Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-49650

Consecutive BLE characteristic writes without response are concatenated under bluez

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Done
    • Icon: P2: Important P2: Important
    • 5.6.0 RC
    • 5.5.1
    • None
    • Linux 3.16 / Bluez

      When performing consecutive QLowEnergyService::writeCharacteristic calls with the mode being WriteWithoutResponse running in Linux/Bluez, the packets are concatenated into 1 big l2cap packet.

      The main cause is that the l2cpSocket is not opened Unbuffered. Because of this, the writes are buffered/combined in QBluetoothSocket and sent in chunks of 1024 bytes to the socket when control returns to the main event loop.

      The code responsible is in qbluetoothsocket_bluez.cpp in the function QBluetoothSocketPrivate::writeData:

      if (q->openMode() & QIODevice::Unbuffered) {
      if (::write(socket, data, maxSize) != maxSize)

      { errorString = QBluetoothSocket::tr("Network Error"); q->setSocketError(QBluetoothSocket::NetworkError); return -1; }

      emit q->bytesWritten(maxSize);

      return maxSize;
      }
      else {

      if(!connectWriteNotifier)
      return -1;

      if(txBuffer.size() == 0)

      { connectWriteNotifier->setEnabled(true); QMetaObject::invokeMethod(this, "_q_writeNotify", Qt::QueuedConnection); }

      char *txbuf = txBuffer.reserve(maxSize);
      memcpy(txbuf, data, maxSize);

      return maxSize;
      }

      This can be solved in qlowenergycontroller_bluez.cpp in the function void QLowEnergyControllerPrivate::connectToDevice() by replacing
      l2cpSocket->connectToService(remoteDevice, ATTRIBUTE_CHANNEL_ID);
      with
      l2cpSocket->connectToService(remoteDevice, ATTRIBUTE_CHANNEL_ID, QIODevice::ReadWrite | QIODevice::Unbuffered);

      It has been verified that a workaround at the moment is to perform consecutive writes by doing them in a callback of a QTimer::singleShot call with delay 0. This allows the main event loop (and thus the write to the socket) to execute before the next write in the timer callback.

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

            ablasche Alex Blasche
            ThiemoVanEngelen Thiemo van Engelen
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved:

                There are no open Gerrit changes