private void setConnectionParameters() {
   // Make sure connection interval is long enough for OAD
   byte[] value = {
     Conversion.loUint16(OAD_CONN_INTERVAL),
     Conversion.hiUint16(OAD_CONN_INTERVAL),
     Conversion.loUint16(OAD_CONN_INTERVAL),
     Conversion.hiUint16(OAD_CONN_INTERVAL),
     0,
     0,
     Conversion.loUint16(OAD_SUPERVISION_TIMEOUT),
     Conversion.hiUint16(OAD_SUPERVISION_TIMEOUT)
   };
   mCharConnReq.setValue(value);
   boolean ok = mLeService.writeCharacteristic(mCharConnReq);
   if (ok) ok = mLeService.waitIdle(GATT_WRITE_TIMEOUT);
 }
  private void startProgramming() {
    mLog.append("Programming started\n");
    mProgramming = true;
    updateGui();

    // Prepare image notification
    byte[] buf = new byte[OAD_IMG_HDR_SIZE + 2 + 2];
    buf[0] = Conversion.loUint16(mFileImgHdr.ver);
    buf[1] = Conversion.hiUint16(mFileImgHdr.ver);
    buf[2] = Conversion.loUint16(mFileImgHdr.len);
    buf[3] = Conversion.hiUint16(mFileImgHdr.len);
    System.arraycopy(mFileImgHdr.uid, 0, buf, 4, 4);

    // Send image notification
    mCharIdentify.setValue(buf);
    mLeService.writeCharacteristic(mCharIdentify);

    // Initialize stats
    mProgInfo.reset();

    // Start the packet timer
    mTimer = null;
    mTimer = new Timer();
    mTimerTask = new ProgTimerTask();
    mTimer.scheduleAtFixedRate(mTimerTask, 0, PKT_INTERVAL);
  }
  private void onBlockTimer() {

    if (mProgInfo.iBlocks < mProgInfo.nBlocks) {
      mProgramming = true;

      // Prepare block
      mOadBuffer[0] = Conversion.loUint16(mProgInfo.iBlocks);
      mOadBuffer[1] = Conversion.hiUint16(mProgInfo.iBlocks);
      System.arraycopy(mFileBuffer, mProgInfo.iBytes, mOadBuffer, 2, OAD_BLOCK_SIZE);

      // Send block
      mCharBlock.setValue(mOadBuffer);
      boolean success = mLeService.writeCharacteristic(mCharBlock);

      if (success) {
        // Update stats
        mProgInfo.iBlocks++;
        mProgInfo.iBytes += OAD_BLOCK_SIZE;
        mProgressBar.setProgress((mProgInfo.iBlocks * 100) / mProgInfo.nBlocks);
      } else {
        // Check if the device has been prematurely disconnected
        if (BluetoothLeService.getBtGatt() == null) mProgramming = false;
      }
    } else {
      mProgramming = false;
    }
    mProgInfo.iTimeElapsed += PKT_INTERVAL;

    if (!mProgramming) {
      runOnUiThread(
          new Runnable() {
            public void run() {
              displayStats();
              stopProgramming();
            }
          });
    }
  }
  public FwUpdateActivity() {
    Log.d(TAG, "construct");
    mDeviceActivity = DeviceActivity.getInstance();

    // BLE Gatt Service
    mLeService = BluetoothLeService.getInstance();

    // Service information
    mOadService = mDeviceActivity.getOadService();
    mConnControlService = mDeviceActivity.getConnControlService();

    // Characteristics list
    mCharListOad = mOadService.getCharacteristics();
    mCharListCc = mConnControlService.getCharacteristics();

    mServiceOk = mCharListOad.size() == 2 && mCharListCc.size() >= 3;
    if (mServiceOk) {
      mCharIdentify = mCharListOad.get(0);
      mCharBlock = mCharListOad.get(1);
      mCharConnReq = mCharListCc.get(1);
    }
  }
 private boolean enableNotification(BluetoothGattCharacteristic c, boolean enable) {
   boolean ok = mLeService.setCharacteristicNotification(c, enable);
   if (ok) ok = mLeService.waitIdle(GATT_WRITE_TIMEOUT);
   return ok;
 }
 private boolean writeCharacteristic(BluetoothGattCharacteristic c, byte v) {
   boolean ok = mLeService.writeCharacteristic(c, v);
   if (ok) ok = mLeService.waitIdle(GATT_WRITE_TIMEOUT);
   return ok;
 }