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

Consecutive BLE characteristic writes without response are concatenated under bluez

    XMLWordPrintable

Details

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

    Description

      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.

      Attachments

        Issue Links

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

          Activity

            People

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

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews

                  There are no open Gerrit changes