diff options
Diffstat (limited to 'src/bluetooth/qlowenergycontroller_bluez.cpp')
-rw-r--r-- | src/bluetooth/qlowenergycontroller_bluez.cpp | 313 |
1 files changed, 202 insertions, 111 deletions
diff --git a/src/bluetooth/qlowenergycontroller_bluez.cpp b/src/bluetooth/qlowenergycontroller_bluez.cpp index ca3f7760..502f42ad 100644 --- a/src/bluetooth/qlowenergycontroller_bluez.cpp +++ b/src/bluetooth/qlowenergycontroller_bluez.cpp @@ -39,15 +39,21 @@ ****************************************************************************/ #include "lecmaccalculator_p.h" -#include "qlowenergycontroller_p.h" -#include "qbluetoothsocket_p.h" +#include "qlowenergycontroller_bluez_p.h" +#include "qbluetoothsocketbase_p.h" #include "qleadvertiser_p.h" #include "bluez/bluez_data_p.h" #include "bluez/hcimanager_p.h" +#include "bluez/objectmanager_p.h" #include "bluez/remotedevicemanager_p.h" #include "bluez/bluez5_helper_p.h" #include "bluez/bluetoothmanagement_p.h" +// Bluez 4 +#include "bluez/adapter_p.h" +#include "bluez/device_p.h" +#include "bluez/manager_p.h" + #include <QtCore/QFileInfo> #include <QtCore/QLoggingCategory> #include <QtCore/QSettings> @@ -263,11 +269,8 @@ template<> void putDataAndIncrement(const QByteArray &value, char *&dst) dst += value.count(); } -QLowEnergyControllerPrivate::QLowEnergyControllerPrivate() - : QObject(), - state(QLowEnergyController::UnconnectedState), - error(QLowEnergyController::NoError), - lastLocalHandle(0), +QLowEnergyControllerPrivateBluez::QLowEnergyControllerPrivateBluez() + : QLowEnergyControllerPrivate(), l2cpSocket(0), requestPending(false), mtuSize(ATT_DEFAULT_LE_MTU), securityLevelValue(-1), @@ -280,7 +283,7 @@ QLowEnergyControllerPrivate::QLowEnergyControllerPrivate() qRegisterMetaType<QList<QLowEnergyHandle> >(); } -void QLowEnergyControllerPrivate::init() +void QLowEnergyControllerPrivateBluez::init() { hciManager = new HciManager(localAdapter, this); if (!hciManager->isValid()) @@ -331,12 +334,12 @@ void QLowEnergyControllerPrivate::init() requestTimer->setSingleShot(true); requestTimer->setInterval(gattRequestTimeout); connect(requestTimer, &QTimer::timeout, - this, &QLowEnergyControllerPrivate::handleGattRequestTimeout); + this, &QLowEnergyControllerPrivateBluez::handleGattRequestTimeout); } } } -void QLowEnergyControllerPrivate::handleGattRequestTimeout() +void QLowEnergyControllerPrivateBluez::handleGattRequestTimeout() { // antyhing open that might require cancellation or a warning? if (encryptionChangePending) { @@ -346,8 +349,8 @@ void QLowEnergyControllerPrivate::handleGattRequestTimeout() } if (!openRequests.isEmpty() && requestPending) { - requestPending = false; // reset pending flag const Request currentRequest = openRequests.dequeue(); + requestPending = false; // reset pending flag qCWarning(QT_BT_BLUEZ).nospace() << "****** Request type 0x" << hex << currentRequest.command << " to server/peripheral timed out"; @@ -372,7 +375,6 @@ void QLowEnergyControllerPrivate::handleGattRequestTimeout() case ATT_OP_EXCHANGE_MTU_REQUEST: // MTU change request // never received reply to MTU request // it is safe to skip and go to next request - sendNextPendingRequest(); break; case ATT_OP_READ_BY_GROUP_REQUEST: // primary or secondary service discovery case ATT_OP_READ_BY_TYPE_REQUEST: // characteristic or included service discovery @@ -406,12 +408,17 @@ void QLowEnergyControllerPrivate::handleGattRequestTimeout() break; default: // not a command used by central role implementation - return; + qCWarning(QT_BT_BLUEZ) << "Missing response for ATT peripheral command: " + << hex << command; + break; } + + // spin openRequest queue further + sendNextPendingRequest(); } } -QLowEnergyControllerPrivate::~QLowEnergyControllerPrivate() +QLowEnergyControllerPrivateBluez::~QLowEnergyControllerPrivateBluez() { closeServerSocket(); delete cmacCalculator; @@ -467,7 +474,7 @@ private: }; -void QLowEnergyControllerPrivate::startAdvertising(const QLowEnergyAdvertisingParameters ¶ms, +void QLowEnergyControllerPrivateBluez::startAdvertising(const QLowEnergyAdvertisingParameters ¶ms, const QLowEnergyAdvertisingData &advertisingData, const QLowEnergyAdvertisingData &scanResponseData) { @@ -476,7 +483,7 @@ void QLowEnergyControllerPrivate::startAdvertising(const QLowEnergyAdvertisingPa advertiser = new QLeAdvertiserBluez(params, advertisingData, scanResponseData, *hciManager, this); connect(advertiser, &QLeAdvertiser::errorOccurred, this, - &QLowEnergyControllerPrivate::handleAdvertisingError); + &QLowEnergyControllerPrivateBluez::handleAdvertisingError); } setState(QLowEnergyController::AdvertisingState); advertiser->startAdvertising(); @@ -497,16 +504,16 @@ void QLowEnergyControllerPrivate::startAdvertising(const QLowEnergyAdvertisingPa const int socketFd = serverSocket.takeSocket(); serverSocketNotifier = new QSocketNotifier(socketFd, QSocketNotifier::Read, this); connect(serverSocketNotifier, &QSocketNotifier::activated, this, - &QLowEnergyControllerPrivate::handleConnectionRequest); + &QLowEnergyControllerPrivateBluez::handleConnectionRequest); } -void QLowEnergyControllerPrivate::stopAdvertising() +void QLowEnergyControllerPrivateBluez::stopAdvertising() { setState(QLowEnergyController::UnconnectedState); advertiser->stopAdvertising(); } -void QLowEnergyControllerPrivate::requestConnectionUpdate(const QLowEnergyConnectionParameters ¶ms) +void QLowEnergyControllerPrivateBluez::requestConnectionUpdate(const QLowEnergyConnectionParameters ¶ms) { // The spec says that the connection update command can be used by both slave and master // devices, but BlueZ allows it only for master devices. So for slave devices, we have to use a @@ -518,7 +525,7 @@ void QLowEnergyControllerPrivate::requestConnectionUpdate(const QLowEnergyConnec hciManager->sendConnectionParameterUpdateRequest(connectionHandle, params); } -void QLowEnergyControllerPrivate::connectToDevice() +void QLowEnergyControllerPrivateBluez::connectToDevice() { if (remoteDevice.isNull()) { qCWarning(QT_BT_BLUEZ) << "Invalid/null remote device address"; @@ -527,8 +534,10 @@ void QLowEnergyControllerPrivate::connectToDevice() } setState(QLowEnergyController::ConnectingState); - if (l2cpSocket) + if (l2cpSocket) { delete l2cpSocket; + l2cpSocket = nullptr; + } createServicesForCentralIfRequired(); @@ -550,7 +559,7 @@ void QLowEnergyControllerPrivate::connectToDevice() if (!device1Manager) { device1Manager = new RemoteDeviceManager(localAdapter, this); connect(device1Manager, &RemoteDeviceManager::finished, - this, &QLowEnergyControllerPrivate::activeConnectionTerminationDone); + this, &QLowEnergyControllerPrivateBluez::activeConnectionTerminationDone); } QVector<QBluetoothAddress> connectedAddresses; @@ -568,7 +577,7 @@ void QLowEnergyControllerPrivate::connectToDevice() /*! * Handles outcome of attempts to close external connections. */ -void QLowEnergyControllerPrivate::activeConnectionTerminationDone() +void QLowEnergyControllerPrivateBluez::activeConnectionTerminationDone() { if (!device1Manager) return; @@ -581,6 +590,7 @@ void QLowEnergyControllerPrivate::activeConnectionTerminationDone() qCWarning(QT_BT_BLUEZ) << "Cannot close pending external BTLE connections. Aborting connect attempt"; setError(QLowEnergyController::ConnectionError); setState(QLowEnergyController::UnconnectedState); + l2cpDisconnected(); return; } else { establishL2cpClientSocket(); @@ -590,7 +600,7 @@ void QLowEnergyControllerPrivate::activeConnectionTerminationDone() /*! * Establishes the L2CP client socket. */ -void QLowEnergyControllerPrivate::establishL2cpClientSocket() +void QLowEnergyControllerPrivateBluez::establishL2cpClientSocket() { //we are already in Connecting state @@ -646,7 +656,7 @@ void QLowEnergyControllerPrivate::establishL2cpClientSocket() loadSigningDataIfNecessary(LocalSigningKey); } -void QLowEnergyControllerPrivate::createServicesForCentralIfRequired() +void QLowEnergyControllerPrivateBluez::createServicesForCentralIfRequired() { bool ok = false; int value = qEnvironmentVariableIntValue("QT_DEFAULT_CENTRAL_SERVICES", &ok); @@ -712,7 +722,7 @@ void QLowEnergyControllerPrivate::createServicesForCentralIfRequired() service->setParent(q); } -void QLowEnergyControllerPrivate::l2cpConnected() +void QLowEnergyControllerPrivateBluez::l2cpConnected() { Q_Q(QLowEnergyController); @@ -723,26 +733,37 @@ void QLowEnergyControllerPrivate::l2cpConnected() emit q->connected(); } -void QLowEnergyControllerPrivate::disconnectFromDevice() +void QLowEnergyControllerPrivateBluez::disconnectFromDevice() { setState(QLowEnergyController::ClosingState); - l2cpSocket->close(); + if (l2cpSocket) + l2cpSocket->close(); resetController(); + + // this may happen when RemoteDeviceManager::JobType::JobDisconnectDevice + // is pending. + if (!l2cpSocket) { + qWarning(QT_BT_BLUEZ) << "Unexpected closure of device. Cleaning up internal states."; + l2cpDisconnected(); + } } -void QLowEnergyControllerPrivate::l2cpDisconnected() +void QLowEnergyControllerPrivateBluez::l2cpDisconnected() { Q_Q(QLowEnergyController); - if (role == QLowEnergyController::PeripheralRole) + if (role == QLowEnergyController::PeripheralRole) { storeClientConfigurations(); + remoteDevice.clear(); + remoteName.clear(); + } invalidateServices(); resetController(); setState(QLowEnergyController::UnconnectedState); emit q->disconnected(); } -void QLowEnergyControllerPrivate::l2cpErrorChanged(QBluetoothSocket::SocketError e) +void QLowEnergyControllerPrivateBluez::l2cpErrorChanged(QBluetoothSocket::SocketError e) { switch (e) { case QBluetoothSocket::HostNotFoundError: @@ -775,7 +796,7 @@ void QLowEnergyControllerPrivate::l2cpErrorChanged(QBluetoothSocket::SocketError } -void QLowEnergyControllerPrivate::resetController() +void QLowEnergyControllerPrivateBluez::resetController() { openRequests.clear(); openPrepareWriteRequests.clear(); @@ -784,15 +805,19 @@ void QLowEnergyControllerPrivate::resetController() requestPending = false; encryptionChangePending = false; receivedMtuExchangeRequest = false; + mtuSize = ATT_DEFAULT_LE_MTU; securityLevelValue = -1; connectionHandle = 0; - // public API behavior requires stop of advertisement - if (role == QLowEnergyController::PeripheralRole && advertiser) - advertiser->stopAdvertising(); + if (role == QLowEnergyController::PeripheralRole) { + // public API behavior requires stop of advertisement + if (advertiser) + advertiser->stopAdvertising(); + localAttributes.clear(); + } } -void QLowEnergyControllerPrivate::restartRequestTimer() +void QLowEnergyControllerPrivateBluez::restartRequestTimer() { if (!requestTimer) return; @@ -801,7 +826,7 @@ void QLowEnergyControllerPrivate::restartRequestTimer() requestTimer->start(gattRequestTimeout); } -void QLowEnergyControllerPrivate::l2cpReadyRead() +void QLowEnergyControllerPrivateBluez::l2cpReadyRead() { const QByteArray incomingPacket = l2cpSocket->readAll(); qCDebug(QT_BT_BLUEZ) << "Received size:" << incomingPacket.size() << "data:" @@ -899,7 +924,7 @@ void QLowEnergyControllerPrivate::l2cpReadyRead() * callback is called. The first pending request in the queue is the request * that triggered the encryption request. */ -void QLowEnergyControllerPrivate::encryptionChangedEvent( +void QLowEnergyControllerPrivateBluez::encryptionChangedEvent( const QBluetoothAddress &address, bool wasSuccess) { if (!encryptionChangePending) // somebody else caused change event @@ -948,7 +973,7 @@ void QLowEnergyControllerPrivate::encryptionChangedEvent( sendNextPendingRequest(); } -void QLowEnergyControllerPrivate::sendPacket(const QByteArray &packet) +void QLowEnergyControllerPrivateBluez::sendPacket(const QByteArray &packet) { qint64 result = l2cpSocket->write(packet.constData(), packet.size()); @@ -967,7 +992,7 @@ void QLowEnergyControllerPrivate::sendPacket(const QByteArray &packet) } -void QLowEnergyControllerPrivate::sendNextPendingRequest() +void QLowEnergyControllerPrivateBluez::sendNextPendingRequest() { if (openRequests.isEmpty() || requestPending || encryptionChangePending) return; @@ -1032,7 +1057,7 @@ QLowEnergyHandle parseReadByTypeIncludeDiscovery( return attributeHandle; } -void QLowEnergyControllerPrivate::processReply( +void QLowEnergyControllerPrivateBluez::processReply( const Request &request, const QByteArray &response) { Q_Q(QLowEnergyController); @@ -1233,9 +1258,9 @@ void QLowEnergyControllerPrivate::processReply( } else if (!isServiceDiscoveryRun) { // not encryption problem -> abort readCharacteristic()/readDescriptor() run if (!descriptorHandle) - emit service->error(QLowEnergyService::CharacteristicReadError); + service->setError(QLowEnergyService::CharacteristicReadError); else - emit service->error(QLowEnergyService::DescriptorReadError); + service->setError(QLowEnergyService::DescriptorReadError); } } else { if (!descriptorHandle) @@ -1570,12 +1595,12 @@ void QLowEnergyControllerPrivate::processReply( } } -void QLowEnergyControllerPrivate::discoverServices() +void QLowEnergyControllerPrivateBluez::discoverServices() { sendReadByGroupRequest(0x0001, 0xFFFF, GATT_PRIMARY_SERVICE); } -void QLowEnergyControllerPrivate::sendReadByGroupRequest( +void QLowEnergyControllerPrivateBluez::sendReadByGroupRequest( QLowEnergyHandle start, QLowEnergyHandle end, quint16 type) { //call for primary and secondary services @@ -1600,7 +1625,7 @@ void QLowEnergyControllerPrivate::sendReadByGroupRequest( sendNextPendingRequest(); } -void QLowEnergyControllerPrivate::discoverServiceDetails(const QBluetoothUuid &service) +void QLowEnergyControllerPrivateBluez::discoverServiceDetails(const QBluetoothUuid &service) { if (!serviceList.contains(service)) { qCWarning(QT_BT_BLUEZ) << "Discovery of unknown service" << service.toString() @@ -1613,7 +1638,7 @@ void QLowEnergyControllerPrivate::discoverServiceDetails(const QBluetoothUuid &s sendReadByTypeRequest(serviceData, serviceData->startHandle, GATT_INCLUDED_SERVICE); } -void QLowEnergyControllerPrivate::sendReadByTypeRequest( +void QLowEnergyControllerPrivateBluez::sendReadByTypeRequest( QSharedPointer<QLowEnergyServicePrivate> serviceData, QLowEnergyHandle nextHandle, quint16 attributeType) { @@ -1649,7 +1674,7 @@ void QLowEnergyControllerPrivate::sendReadByTypeRequest( \a readCharacteristics determines whether we intend to read a characteristic; otherwise we read a descriptor. */ -void QLowEnergyControllerPrivate::readServiceValues( +void QLowEnergyControllerPrivateBluez::readServiceValues( const QBluetoothUuid &serviceUuid, bool readCharacteristics) { quint8 packet[READ_REQUEST_HEADER_SIZE]; @@ -1743,7 +1768,7 @@ void QLowEnergyControllerPrivate::readServiceValues( open requests to finish the current value read up before starting the next read request. */ -void QLowEnergyControllerPrivate::readServiceValuesByOffset( +void QLowEnergyControllerPrivateBluez::readServiceValuesByOffset( uint handleData, quint16 offset, bool isLastValue) { const QLowEnergyHandle charHandle = (handleData & 0xffff); @@ -1782,7 +1807,7 @@ void QLowEnergyControllerPrivate::readServiceValuesByOffset( openRequests.prepend(request); } -void QLowEnergyControllerPrivate::discoverServiceDescriptors( +void QLowEnergyControllerPrivateBluez::discoverServiceDescriptors( const QBluetoothUuid &serviceUuid) { qCDebug(QT_BT_BLUEZ) << "Discovering descriptor values for" @@ -1802,7 +1827,7 @@ void QLowEnergyControllerPrivate::discoverServiceDescriptors( discoverNextDescriptor(service, keys, keys[0]); } -void QLowEnergyControllerPrivate::processUnsolicitedReply(const QByteArray &payload) +void QLowEnergyControllerPrivateBluez::processUnsolicitedReply(const QByteArray &payload) { const char *data = payload.constData(); bool isNotification = (data[0] == ATT_OP_HANDLE_VAL_NOTIFICATION); @@ -1826,7 +1851,7 @@ void QLowEnergyControllerPrivate::processUnsolicitedReply(const QByteArray &payl } } -void QLowEnergyControllerPrivate::exchangeMTU() +void QLowEnergyControllerPrivateBluez::exchangeMTU() { qCDebug(QT_BT_BLUEZ) << "Exchanging MTU"; @@ -1845,7 +1870,7 @@ void QLowEnergyControllerPrivate::exchangeMTU() sendNextPendingRequest(); } -int QLowEnergyControllerPrivate::securityLevel() const +int QLowEnergyControllerPrivateBluez::securityLevel() const { int socket = l2cpSocket->socketDescriptor(); if (socket < 0) { @@ -1884,7 +1909,7 @@ int QLowEnergyControllerPrivate::securityLevel() const return -1; } -bool QLowEnergyControllerPrivate::setSecurityLevel(int level) +bool QLowEnergyControllerPrivateBluez::setSecurityLevel(int level) { if (level > BT_SECURITY_HIGH || level < BT_SECURITY_LOW) return false; @@ -1931,7 +1956,7 @@ bool QLowEnergyControllerPrivate::setSecurityLevel(int level) return false; } -void QLowEnergyControllerPrivate::discoverNextDescriptor( +void QLowEnergyControllerPrivateBluez::discoverNextDescriptor( QSharedPointer<QLowEnergyServicePrivate> serviceData, const QList<QLowEnergyHandle> pendingCharHandles, const QLowEnergyHandle startingHandle) @@ -1968,7 +1993,7 @@ void QLowEnergyControllerPrivate::discoverNextDescriptor( sendNextPendingRequest(); } -void QLowEnergyControllerPrivate::sendNextPrepareWriteRequest( +void QLowEnergyControllerPrivateBluez::sendNextPrepareWriteRequest( const QLowEnergyHandle handle, const QByteArray &newValue, quint16 offset) { @@ -2023,7 +2048,7 @@ void QLowEnergyControllerPrivate::sendNextPrepareWriteRequest( Otherwise this function sends an execute request for all pending prepare write requests. */ -void QLowEnergyControllerPrivate::sendExecuteWriteRequest( +void QLowEnergyControllerPrivateBluez::sendExecuteWriteRequest( const QLowEnergyHandle attrHandle, const QByteArray &newValue, bool isCancelation) { @@ -2055,7 +2080,7 @@ void QLowEnergyControllerPrivate::sendExecuteWriteRequest( TODO Reliable/prepare write across multiple characteristics is not supported */ -void QLowEnergyControllerPrivate::writeCharacteristic( +void QLowEnergyControllerPrivateBluez::writeCharacteristic( const QSharedPointer<QLowEnergyServicePrivate> service, const QLowEnergyHandle charHandle, const QByteArray &newValue, @@ -2073,7 +2098,7 @@ void QLowEnergyControllerPrivate::writeCharacteristic( writeCharacteristicForCentral(service, charHandle, charData.valueHandle, newValue, mode); } -void QLowEnergyControllerPrivate::writeDescriptor( +void QLowEnergyControllerPrivateBluez::writeDescriptor( const QSharedPointer<QLowEnergyServicePrivate> service, const QLowEnergyHandle charHandle, const QLowEnergyHandle descriptorHandle, @@ -2092,7 +2117,7 @@ void QLowEnergyControllerPrivate::writeDescriptor( Reads the value of one specific characteristic. */ -void QLowEnergyControllerPrivate::readCharacteristic( +void QLowEnergyControllerPrivateBluez::readCharacteristic( const QSharedPointer<QLowEnergyServicePrivate> service, const QLowEnergyHandle charHandle) { @@ -2130,7 +2155,7 @@ void QLowEnergyControllerPrivate::readCharacteristic( sendNextPendingRequest(); } -void QLowEnergyControllerPrivate::readDescriptor( +void QLowEnergyControllerPrivateBluez::readDescriptor( const QSharedPointer<QLowEnergyServicePrivate> service, const QLowEnergyHandle charHandle, const QLowEnergyHandle descriptorHandle) @@ -2169,7 +2194,7 @@ void QLowEnergyControllerPrivate::readDescriptor( * Returns true if the encryption change was successfully requested. * The request is triggered if we got a related ATT error. */ -bool QLowEnergyControllerPrivate::increaseEncryptLevelfRequired(quint8 errorCode) +bool QLowEnergyControllerPrivateBluez::increaseEncryptLevelfRequired(quint8 errorCode) { if (securityLevelValue == BT_SECURITY_HIGH) return false; @@ -2197,14 +2222,14 @@ bool QLowEnergyControllerPrivate::increaseEncryptLevelfRequired(quint8 errorCode return false; } -void QLowEnergyControllerPrivate::handleAdvertisingError() +void QLowEnergyControllerPrivateBluez::handleAdvertisingError() { qCWarning(QT_BT_BLUEZ) << "received advertising error"; setError(QLowEnergyController::AdvertisingError); setState(QLowEnergyController::UnconnectedState); } -bool QLowEnergyControllerPrivate::checkPacketSize(const QByteArray &packet, int minSize, +bool QLowEnergyControllerPrivateBluez::checkPacketSize(const QByteArray &packet, int minSize, int maxSize) { if (maxSize == -1) @@ -2217,7 +2242,7 @@ bool QLowEnergyControllerPrivate::checkPacketSize(const QByteArray &packet, int return false; } -bool QLowEnergyControllerPrivate::checkHandle(const QByteArray &packet, QLowEnergyHandle handle) +bool QLowEnergyControllerPrivateBluez::checkHandle(const QByteArray &packet, QLowEnergyHandle handle) { if (handle != 0 && handle <= lastLocalHandle) return true; @@ -2225,7 +2250,7 @@ bool QLowEnergyControllerPrivate::checkHandle(const QByteArray &packet, QLowEner return false; } -bool QLowEnergyControllerPrivate::checkHandlePair(quint8 request, QLowEnergyHandle startingHandle, +bool QLowEnergyControllerPrivateBluez::checkHandlePair(quint8 request, QLowEnergyHandle startingHandle, QLowEnergyHandle endingHandle) { if (startingHandle == 0 || startingHandle > endingHandle) { @@ -2236,7 +2261,7 @@ bool QLowEnergyControllerPrivate::checkHandlePair(quint8 request, QLowEnergyHand return true; } -void QLowEnergyControllerPrivate::handleExchangeMtuRequest(const QByteArray &packet) +void QLowEnergyControllerPrivateBluez::handleExchangeMtuRequest(const QByteArray &packet) { // Spec v4.2, Vol 3, Part F, 3.4.2 @@ -2263,7 +2288,7 @@ void QLowEnergyControllerPrivate::handleExchangeMtuRequest(const QByteArray &pac qCDebug(QT_BT_BLUEZ) << "Sending server RX MTU" << ATT_MAX_LE_MTU; } -void QLowEnergyControllerPrivate::handleFindInformationRequest(const QByteArray &packet) +void QLowEnergyControllerPrivateBluez::handleFindInformationRequest(const QByteArray &packet) { // Spec v4.2, Vol 3, Part F, 3.4.3.1-2 @@ -2296,7 +2321,7 @@ void QLowEnergyControllerPrivate::handleFindInformationRequest(const QByteArray } -void QLowEnergyControllerPrivate::handleFindByTypeValueRequest(const QByteArray &packet) +void QLowEnergyControllerPrivateBluez::handleFindByTypeValueRequest(const QByteArray &packet) { // Spec v4.2, Vol 3, Part F, 3.4.3.3-4 @@ -2331,7 +2356,7 @@ void QLowEnergyControllerPrivate::handleFindByTypeValueRequest(const QByteArray sendListResponse(responsePrefix, elemSize, results, elemWriter); } -void QLowEnergyControllerPrivate::handleReadByTypeRequest(const QByteArray &packet) +void QLowEnergyControllerPrivateBluez::handleReadByTypeRequest(const QByteArray &packet) { // Spec v4.2, Vol 3, Part F, 3.4.4.1-2 @@ -2384,7 +2409,7 @@ void QLowEnergyControllerPrivate::handleReadByTypeRequest(const QByteArray &pack sendListResponse(responsePrefix, elementSize, results, elemWriter); } -void QLowEnergyControllerPrivate::handleReadRequest(const QByteArray &packet) +void QLowEnergyControllerPrivateBluez::handleReadRequest(const QByteArray &packet) { // Spec v4.2, Vol 3, Part F, 3.4.4.3-4 @@ -2411,7 +2436,7 @@ void QLowEnergyControllerPrivate::handleReadRequest(const QByteArray &packet) sendPacket(response); } -void QLowEnergyControllerPrivate::handleReadBlobRequest(const QByteArray &packet) +void QLowEnergyControllerPrivateBluez::handleReadBlobRequest(const QByteArray &packet) { // Spec v4.2, Vol 3, Part F, 3.4.4.5-6 @@ -2450,7 +2475,7 @@ void QLowEnergyControllerPrivate::handleReadBlobRequest(const QByteArray &packet sendPacket(response); } -void QLowEnergyControllerPrivate::handleReadMultipleRequest(const QByteArray &packet) +void QLowEnergyControllerPrivateBluez::handleReadMultipleRequest(const QByteArray &packet) { // Spec v4.2, Vol 3, Part F, 3.4.4.7-8 @@ -2486,7 +2511,7 @@ void QLowEnergyControllerPrivate::handleReadMultipleRequest(const QByteArray &pa sendPacket(response); } -void QLowEnergyControllerPrivate::handleReadByGroupTypeRequest(const QByteArray &packet) +void QLowEnergyControllerPrivateBluez::handleReadByGroupTypeRequest(const QByteArray &packet) { // Spec v4.2, Vol 3, Part F, 3.4.4.9-10 @@ -2545,7 +2570,7 @@ void QLowEnergyControllerPrivate::handleReadByGroupTypeRequest(const QByteArray sendListResponse(responsePrefix, elementSize, results, elemWriter); } -void QLowEnergyControllerPrivate::updateLocalAttributeValue( +void QLowEnergyControllerPrivateBluez::updateLocalAttributeValue( QLowEnergyHandle handle, const QByteArray &value, QLowEnergyCharacteristic &characteristic, @@ -2579,7 +2604,7 @@ void QLowEnergyControllerPrivate::updateLocalAttributeValue( static bool isNotificationEnabled(quint16 clientConfigValue) { return clientConfigValue & 0x1; } static bool isIndicationEnabled(quint16 clientConfigValue) { return clientConfigValue & 0x2; } -void QLowEnergyControllerPrivate::writeCharacteristicForPeripheral( +void QLowEnergyControllerPrivateBluez::writeCharacteristicForPeripheral( QLowEnergyServicePrivate::CharData &charData, const QByteArray &newValue) { @@ -2636,7 +2661,7 @@ void QLowEnergyControllerPrivate::writeCharacteristicForPeripheral( } } -void QLowEnergyControllerPrivate::writeCharacteristicForCentral(const QSharedPointer<QLowEnergyServicePrivate> &service, +void QLowEnergyControllerPrivateBluez::writeCharacteristicForCentral(const QSharedPointer<QLowEnergyServicePrivate> &service, QLowEnergyHandle charHandle, QLowEnergyHandle valueHandle, const QByteArray &newValue, @@ -2710,7 +2735,7 @@ void QLowEnergyControllerPrivate::writeCharacteristicForCentral(const QSharedPoi sendNextPendingRequest(); } -void QLowEnergyControllerPrivate::writeDescriptorForPeripheral( +void QLowEnergyControllerPrivateBluez::writeDescriptorForPeripheral( const QSharedPointer<QLowEnergyServicePrivate> &service, const QLowEnergyHandle charHandle, const QLowEnergyHandle descriptorHandle, @@ -2727,7 +2752,7 @@ void QLowEnergyControllerPrivate::writeDescriptorForPeripheral( service->characteristicList[charHandle].descriptorList[descriptorHandle].value = newValue; } -void QLowEnergyControllerPrivate::writeDescriptorForCentral( +void QLowEnergyControllerPrivateBluez::writeDescriptorForCentral( const QLowEnergyHandle charHandle, const QLowEnergyHandle descriptorHandle, const QByteArray &newValue) @@ -2760,7 +2785,7 @@ void QLowEnergyControllerPrivate::writeDescriptorForCentral( sendNextPendingRequest(); } -void QLowEnergyControllerPrivate::handleWriteRequestOrCommand(const QByteArray &packet) +void QLowEnergyControllerPrivateBluez::handleWriteRequestOrCommand(const QByteArray &packet) { // Spec v4.2, Vol 3, Part F, 3.4.5.1-3 @@ -2854,7 +2879,7 @@ void QLowEnergyControllerPrivate::handleWriteRequestOrCommand(const QByteArray & } } -void QLowEnergyControllerPrivate::handlePrepareWriteRequest(const QByteArray &packet) +void QLowEnergyControllerPrivateBluez::handlePrepareWriteRequest(const QByteArray &packet) { // Spec v4.2, Vol 3, Part F, 3.4.6.1 @@ -2885,7 +2910,7 @@ void QLowEnergyControllerPrivate::handlePrepareWriteRequest(const QByteArray &pa sendPacket(response); } -void QLowEnergyControllerPrivate::handleExecuteWriteRequest(const QByteArray &packet) +void QLowEnergyControllerPrivateBluez::handleExecuteWriteRequest(const QByteArray &packet) { // Spec v4.2, Vol 3, Part F, 3.4.6.3 @@ -2933,7 +2958,7 @@ void QLowEnergyControllerPrivate::handleExecuteWriteRequest(const QByteArray &pa emit descriptor.d_ptr->descriptorWritten(descriptor, descriptor.value()); } -void QLowEnergyControllerPrivate::sendErrorResponse(quint8 request, quint16 handle, quint8 code) +void QLowEnergyControllerPrivateBluez::sendErrorResponse(quint8 request, quint16 handle, quint8 code) { // An ATT command never receives an error response. if (request == ATT_OP_WRITE_COMMAND || request == ATT_OP_SIGNED_WRITE_COMMAND) @@ -2949,7 +2974,7 @@ void QLowEnergyControllerPrivate::sendErrorResponse(quint8 request, quint16 hand sendPacket(packet); } -void QLowEnergyControllerPrivate::sendListResponse(const QByteArray &packetStart, int elemSize, +void QLowEnergyControllerPrivateBluez::sendListResponse(const QByteArray &packetStart, int elemSize, const QVector<Attribute> &attributes, const ElemWriter &elemWriter) { const int offset = packetStart.count(); @@ -2965,19 +2990,19 @@ void QLowEnergyControllerPrivate::sendListResponse(const QByteArray &packetStart sendPacket(response); } -void QLowEnergyControllerPrivate::sendNotification(QLowEnergyHandle handle) +void QLowEnergyControllerPrivateBluez::sendNotification(QLowEnergyHandle handle) { sendNotificationOrIndication(ATT_OP_HANDLE_VAL_NOTIFICATION, handle); } -void QLowEnergyControllerPrivate::sendIndication(QLowEnergyHandle handle) +void QLowEnergyControllerPrivateBluez::sendIndication(QLowEnergyHandle handle) { Q_ASSERT(!indicationInFlight); indicationInFlight = true; sendNotificationOrIndication(ATT_OP_HANDLE_VAL_INDICATION, handle); } -void QLowEnergyControllerPrivate::sendNotificationOrIndication( +void QLowEnergyControllerPrivateBluez::sendNotificationOrIndication( quint8 opCode, QLowEnergyHandle handle) { @@ -2993,13 +3018,76 @@ void QLowEnergyControllerPrivate::sendNotificationOrIndication( sendPacket(packet); } -void QLowEnergyControllerPrivate::sendNextIndication() +void QLowEnergyControllerPrivateBluez::sendNextIndication() { if (!scheduledIndications.isEmpty()) sendIndication(scheduledIndications.takeFirst()); } -void QLowEnergyControllerPrivate::handleConnectionRequest() +static QString nameOfRemoteCentral(const QBluetoothAddress &peerAddress, const QBluetoothAddress &localAdapter) +{ + const QString peerAddressString = peerAddress.toString(); + if (isBluez5()) { + OrgFreedesktopDBusObjectManagerInterface manager(QStringLiteral("org.bluez"), + QStringLiteral("/"), + QDBusConnection::systemBus()); + QDBusPendingReply<ManagedObjectList> reply = manager.GetManagedObjects(); + reply.waitForFinished(); + if (reply.isError()) + return QString(); + + ManagedObjectList managedObjectList = reply.value(); + for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) { + const InterfaceList &ifaceList = it.value(); + + for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) { + const QString &iface = jt.key(); + const QVariantMap &ifaceValues = jt.value(); + + if (iface == QStringLiteral("org.bluez.Device1")) { + if (ifaceValues.value(QStringLiteral("Address")).toString() == peerAddressString) + return ifaceValues.value(QStringLiteral("Alias")).toString(); + } + } + } + return QString(); + } else { + OrgBluezManagerInterface manager(QStringLiteral("org.bluez"), QStringLiteral("/"), + QDBusConnection::systemBus()); + + QDBusPendingReply<QDBusObjectPath> reply = manager.FindAdapter(localAdapter.toString()); + reply.waitForFinished(); + if (reply.isError()) + return QString(); + + OrgBluezAdapterInterface adapter(QStringLiteral("org.bluez"), reply.value().path(), + QDBusConnection::systemBus()); + + QDBusPendingReply<QDBusObjectPath> deviceObjectPath = adapter.FindDevice(peerAddressString); + deviceObjectPath.waitForFinished(); + if (deviceObjectPath.isError()) { + if (deviceObjectPath.error().name() != QStringLiteral("org.bluez.Error.DoesNotExist")) + return QString(); + + deviceObjectPath = adapter.CreateDevice(peerAddressString); + deviceObjectPath.waitForFinished(); + if (deviceObjectPath.isError()) + return QString(); + } + + OrgBluezDeviceInterface device(QStringLiteral("org.bluez"), deviceObjectPath.value().path(), + QDBusConnection::systemBus()); + + QDBusPendingReply<QVariantMap> properties = device.GetProperties(); + properties.waitForFinished(); + if (properties.isError()) + return QString(); + + return properties.value().value(QStringLiteral("Alias")).toString(); + } +} + +void QLowEnergyControllerPrivateBluez::handleConnectionRequest() { if (state != QLowEnergyController::AdvertisingState) { qCWarning(QT_BT_BLUEZ) << "Incoming connection request in unexpected state" << state; @@ -3017,18 +3105,21 @@ void QLowEnergyControllerPrivate::handleConnectionRequest() serverSocketNotifier->setEnabled(true); return; } + remoteDevice = QBluetoothAddress(convertAddress(clientAddr.l2_bdaddr.b)); - qCDebug(QT_BT_BLUEZ) << "GATT connection from device" << remoteDevice; + remoteName = nameOfRemoteCentral(remoteDevice, localAdapter); + qCDebug(QT_BT_BLUEZ) << "GATT connection from device" << remoteDevice << remoteName; + if (connectionHandle == 0) qCWarning(QT_BT_BLUEZ) << "Received client connection, but no connection complete event"; closeServerSocket(); l2cpSocket = new QBluetoothSocket(QBluetoothServiceInfo::L2capProtocol, this); connect(l2cpSocket, &QBluetoothSocket::disconnected, - this, &QLowEnergyControllerPrivate::l2cpDisconnected); + this, &QLowEnergyControllerPrivateBluez::l2cpDisconnected); connect(l2cpSocket, static_cast<void (QBluetoothSocket::*)(QBluetoothSocket::SocketError)> - (&QBluetoothSocket::error), this, &QLowEnergyControllerPrivate::l2cpErrorChanged); - connect(l2cpSocket, &QIODevice::readyRead, this, &QLowEnergyControllerPrivate::l2cpReadyRead); + (&QBluetoothSocket::error), this, &QLowEnergyControllerPrivateBluez::l2cpErrorChanged); + connect(l2cpSocket, &QIODevice::readyRead, this, &QLowEnergyControllerPrivateBluez::l2cpReadyRead); l2cpSocket->d_ptr->lowEnergySocketType = addressType == QLowEnergyController::PublicAddress ? BDADDR_LE_PUBLIC : BDADDR_LE_RANDOM; l2cpSocket->setSocketDescriptor(clientSocket, QBluetoothServiceInfo::L2capProtocol, @@ -3041,7 +3132,7 @@ void QLowEnergyControllerPrivate::handleConnectionRequest() emit q->connected(); } -void QLowEnergyControllerPrivate::closeServerSocket() +void QLowEnergyControllerPrivateBluez::closeServerSocket() { if (!serverSocketNotifier) return; @@ -3051,7 +3142,7 @@ void QLowEnergyControllerPrivate::closeServerSocket() serverSocketNotifier = nullptr; } -bool QLowEnergyControllerPrivate::isBonded() const +bool QLowEnergyControllerPrivateBluez::isBonded() const { // Pairing does not necessarily imply bonding, but we don't know whether the // bonding flag was set in the original pairing request. @@ -3059,7 +3150,7 @@ bool QLowEnergyControllerPrivate::isBonded() const != QBluetoothLocalDevice::Unpaired; } -QVector<QLowEnergyControllerPrivate::TempClientConfigurationData> QLowEnergyControllerPrivate::gatherClientConfigData() +QVector<QLowEnergyControllerPrivateBluez::TempClientConfigurationData> QLowEnergyControllerPrivateBluez::gatherClientConfigData() { QVector<TempClientConfigurationData> data; foreach (const auto &service, localServices) { @@ -3080,7 +3171,7 @@ QVector<QLowEnergyControllerPrivate::TempClientConfigurationData> QLowEnergyCont return data; } -void QLowEnergyControllerPrivate::storeClientConfigurations() +void QLowEnergyControllerPrivateBluez::storeClientConfigurations() { if (!isBonded()) { clientConfigData.remove(remoteDevice.toUInt64()); @@ -3099,7 +3190,7 @@ void QLowEnergyControllerPrivate::storeClientConfigurations() clientConfigData.insert(remoteDevice.toUInt64(), clientConfigs); } -void QLowEnergyControllerPrivate::restoreClientConfigurations() +void QLowEnergyControllerPrivateBluez::restoreClientConfigurations() { const QVector<TempClientConfigurationData> &tempConfigList = gatherClientConfigData(); const QVector<ClientConfigurationData> &restoredClientConfigs = isBonded() @@ -3133,7 +3224,7 @@ void QLowEnergyControllerPrivate::restoreClientConfigurations() sendNextIndication(); } -void QLowEnergyControllerPrivate::loadSigningDataIfNecessary(SigningKeyType keyType) +void QLowEnergyControllerPrivateBluez::loadSigningDataIfNecessary(SigningKeyType keyType) { const auto signingDataIt = signingData.constFind(remoteDevice.toUInt64()); if (signingDataIt != signingData.constEnd()) @@ -3165,7 +3256,7 @@ void QLowEnergyControllerPrivate::loadSigningDataIfNecessary(SigningKeyType keyT signingData.insert(remoteDevice.toUInt64(), SigningData(csrk, counter - 1)); } -void QLowEnergyControllerPrivate::storeSignCounter(SigningKeyType keyType) const +void QLowEnergyControllerPrivateBluez::storeSignCounter(SigningKeyType keyType) const { const auto signingDataIt = signingData.constFind(remoteDevice.toUInt64()); if (signingDataIt == signingData.constEnd()) @@ -3186,12 +3277,12 @@ void QLowEnergyControllerPrivate::storeSignCounter(SigningKeyType keyType) const settings.setValue(counterKey, counterValue); } -QString QLowEnergyControllerPrivate::signingKeySettingsGroup(SigningKeyType keyType) const +QString QLowEnergyControllerPrivateBluez::signingKeySettingsGroup(SigningKeyType keyType) const { return QLatin1String(keyType == LocalSigningKey ? "LocalSignatureKey" : "RemoteSignatureKey"); } -QString QLowEnergyControllerPrivate::keySettingsFilePath() const +QString QLowEnergyControllerPrivateBluez::keySettingsFilePath() const { return QString::fromLatin1("/var/lib/bluetooth/%1/%2/info") .arg(localAdapter.toString(), remoteDevice.toString()); @@ -3213,7 +3304,7 @@ static QByteArray uuidToByteArray(const QBluetoothUuid &uuid) return ba; } -void QLowEnergyControllerPrivate::addToGenericAttributeList(const QLowEnergyServiceData &service, +void QLowEnergyControllerPrivateBluez::addToGenericAttributeList(const QLowEnergyServiceData &service, QLowEnergyHandle startHandle) { // Construct generic attribute data for the service with handles as keys. @@ -3323,7 +3414,7 @@ void QLowEnergyControllerPrivate::addToGenericAttributeList(const QLowEnergyServ localAttributes[serviceAttribute.handle] = serviceAttribute; } -void QLowEnergyControllerPrivate::ensureUniformAttributes(QVector<Attribute> &attributes, +void QLowEnergyControllerPrivateBluez::ensureUniformAttributes(QVector<Attribute> &attributes, const std::function<int (const Attribute &)> &getSize) { if (attributes.isEmpty()) @@ -3336,19 +3427,19 @@ void QLowEnergyControllerPrivate::ensureUniformAttributes(QVector<Attribute> &at } -void QLowEnergyControllerPrivate::ensureUniformUuidSizes(QVector<Attribute> &attributes) +void QLowEnergyControllerPrivateBluez::ensureUniformUuidSizes(QVector<Attribute> &attributes) { ensureUniformAttributes(attributes, [](const Attribute &attr) { return getUuidSize(attr.type); }); } -void QLowEnergyControllerPrivate::ensureUniformValueSizes(QVector<Attribute> &attributes) +void QLowEnergyControllerPrivateBluez::ensureUniformValueSizes(QVector<Attribute> &attributes) { ensureUniformAttributes(attributes, [](const Attribute &attr) { return attr.value.count(); }); } -QVector<QLowEnergyControllerPrivate::Attribute> QLowEnergyControllerPrivate::getAttributes(QLowEnergyHandle startHandle, +QVector<QLowEnergyControllerPrivateBluez::Attribute> QLowEnergyControllerPrivateBluez::getAttributes(QLowEnergyHandle startHandle, QLowEnergyHandle endHandle, const AttributePredicate &attributePredicate) { QVector<Attribute> results; @@ -3367,7 +3458,7 @@ QVector<QLowEnergyControllerPrivate::Attribute> QLowEnergyControllerPrivate::get return results; } -int QLowEnergyControllerPrivate::checkPermissions(const Attribute &attr, +int QLowEnergyControllerPrivateBluez::checkPermissions(const Attribute &attr, QLowEnergyCharacteristic::PropertyType type) { const bool isReadAccess = type == QLowEnergyCharacteristic::Read; @@ -3401,12 +3492,12 @@ int QLowEnergyControllerPrivate::checkPermissions(const Attribute &attr, return 0; } -int QLowEnergyControllerPrivate::checkReadPermissions(const Attribute &attr) +int QLowEnergyControllerPrivateBluez::checkReadPermissions(const Attribute &attr) { return checkPermissions(attr, QLowEnergyCharacteristic::Read); } -int QLowEnergyControllerPrivate::checkReadPermissions(QVector<Attribute> &attributes) +int QLowEnergyControllerPrivateBluez::checkReadPermissions(QVector<Attribute> &attributes) { if (attributes.isEmpty()) return 0; @@ -3426,7 +3517,7 @@ int QLowEnergyControllerPrivate::checkReadPermissions(QVector<Attribute> &attrib return 0; } -bool QLowEnergyControllerPrivate::verifyMac(const QByteArray &message, const quint128 &csrk, +bool QLowEnergyControllerPrivateBluez::verifyMac(const QByteArray &message, const quint128 &csrk, quint32 signCounter, quint64 expectedMac) { if (!cmacCalculator) |