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