-
Bug
-
Resolution: Done
-
P2: Important
-
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)
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.
- is duplicated by
-
QTBUG-50258 Bluetooth socket writes may get coalesced (bluez)
-
- Closed
-