diff options
Diffstat (limited to 'src/bluetooth/qlowenergycontroller_p.h')
-rw-r--r-- | src/bluetooth/qlowenergycontroller_p.h | 424 |
1 files changed, 17 insertions, 407 deletions
diff --git a/src/bluetooth/qlowenergycontroller_p.h b/src/bluetooth/qlowenergycontroller_p.h index 6e866144..54a49b53 100644 --- a/src/bluetooth/qlowenergycontroller_p.h +++ b/src/bluetooth/qlowenergycontroller_p.h @@ -51,452 +51,62 @@ // We mean it. // -#if defined(QT_OSX_BLUETOOTH) || defined(QT_IOS_BLUETOOTH) - -#include <QtCore/qglobal.h> -#include <QtCore/qobject.h> - -QT_BEGIN_NAMESPACE - -class QLowEnergyControllerPrivate : public QObject -{ -public: - // This class is required to make shared pointer machinery and - // moc (== Obj-C syntax) happy on both OS X and iOS. -}; - -QT_END_NAMESPACE - -#else - #include <qglobal.h> #include <QtCore/QQueue> #include <QtCore/QVector> #include <QtBluetooth/qbluetooth.h> #include <QtBluetooth/qlowenergycharacteristic.h> #include "qlowenergycontroller.h" -#include "qlowenergyserviceprivate_p.h" - -#if QT_CONFIG(bluez) && !defined(QT_BLUEZ_NO_BTLE) -#include <QtBluetooth/QBluetoothSocket> -#elif defined(QT_ANDROID_BLUETOOTH) -#include <QtAndroidExtras/QAndroidJniObject> -#include "android/lowenergynotificationhub_p.h" -#elif defined(QT_WINRT_BLUETOOTH) -#include <wrl.h> -#include <windows.devices.bluetooth.h> -#endif - -#include <functional> +#include "qlowenergycontrollerbase_p.h" QT_BEGIN_NAMESPACE class QLowEnergyServiceData; -class QTimer; - -#if QT_CONFIG(bluez) && !defined(QT_BLUEZ_NO_BTLE) -class HciManager; -class LeCmacCalculator; -class QSocketNotifier; -class RemoteDeviceManager; -#elif defined(QT_ANDROID_BLUETOOTH) -class LowEnergyNotificationHub; -#elif defined(QT_WINRT_BLUETOOTH) -class QWinRTLowEnergyServiceHandler; -#endif extern void registerQLowEnergyControllerMetaType(); -typedef QMap<QBluetoothUuid, QSharedPointer<QLowEnergyServicePrivate> > ServiceDataMap; -class QLeAdvertiser; - -class QLowEnergyControllerPrivate : public QObject +class QLowEnergyControllerPrivateCommon final : public QLowEnergyControllerPrivate { Q_OBJECT - Q_DECLARE_PUBLIC(QLowEnergyController) public: - QLowEnergyControllerPrivate(); - ~QLowEnergyControllerPrivate(); + QLowEnergyControllerPrivateCommon(); + ~QLowEnergyControllerPrivateCommon() override; - void init(); + void init() override; - void setError(QLowEnergyController::Error newError); - bool isValidLocalAdapter(); + void connectToDevice() override; + void disconnectFromDevice() override; - void setState(QLowEnergyController::ControllerState newState); - - void connectToDevice(); - void disconnectFromDevice(); - - void discoverServices(); - void invalidateServices(); - - void discoverServiceDetails(const QBluetoothUuid &service); + void discoverServices() override; + void discoverServiceDetails(const QBluetoothUuid &service) override; void startAdvertising(const QLowEnergyAdvertisingParameters ¶ms, const QLowEnergyAdvertisingData &advertisingData, - const QLowEnergyAdvertisingData &scanResponseData); - void stopAdvertising(); - - void requestConnectionUpdate(const QLowEnergyConnectionParameters ¶ms); + const QLowEnergyAdvertisingData &scanResponseData) override; + void stopAdvertising() override; - // misc helpers - QSharedPointer<QLowEnergyServicePrivate> serviceForHandle( - QLowEnergyHandle handle); - QLowEnergyCharacteristic characteristicForHandle( - QLowEnergyHandle handle); - QLowEnergyDescriptor descriptorForHandle( - QLowEnergyHandle handle); - QLowEnergyService *addServiceHelper(const QLowEnergyServiceData &service); - - - quint16 updateValueOfCharacteristic(QLowEnergyHandle charHandle, - const QByteArray &value, - bool appendValue); - quint16 updateValueOfDescriptor(QLowEnergyHandle charHandle, - QLowEnergyHandle descriptorHandle, - const QByteArray &value, - bool appendValue); + void requestConnectionUpdate(const QLowEnergyConnectionParameters ¶ms) override; // read data void readCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service, - const QLowEnergyHandle charHandle); + const QLowEnergyHandle charHandle) override; void readDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service, const QLowEnergyHandle charHandle, - const QLowEnergyHandle descriptorHandle); + const QLowEnergyHandle descriptorHandle) override; // write data void writeCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service, const QLowEnergyHandle charHandle, - const QByteArray &newValue, QLowEnergyService::WriteMode mode); + const QByteArray &newValue, QLowEnergyService::WriteMode mode) override; void writeDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service, const QLowEnergyHandle charHandle, const QLowEnergyHandle descriptorHandle, - const QByteArray &newValue); + const QByteArray &newValue) override; void addToGenericAttributeList(const QLowEnergyServiceData &service, - QLowEnergyHandle startHandle); - - QBluetoothAddress remoteDevice; - QBluetoothAddress localAdapter; - QLowEnergyController::Role role; - - QString remoteName; - - QLowEnergyController::ControllerState state; - QLowEnergyController::Error error; - QString errorString; - - // list of all found service uuids on remote device - ServiceDataMap serviceList; - - QLowEnergyHandle lastLocalHandle; - // list of all service uuids on local peripheral device - ServiceDataMap localServices; - - struct Attribute { - Attribute() : handle(0) {} - - QLowEnergyHandle handle; - QLowEnergyHandle groupEndHandle; - QLowEnergyCharacteristic::PropertyTypes properties; - QBluetooth::AttAccessConstraints readConstraints; - QBluetooth::AttAccessConstraints writeConstraints; - QBluetoothUuid type; - QByteArray value; - int minLength; - int maxLength; - }; - QVector<Attribute> localAttributes; - - QLowEnergyController::RemoteAddressType addressType; - -private: -#if QT_CONFIG(bluez) && !defined(QT_BLUEZ_NO_BTLE) - quint16 connectionHandle = 0; - QBluetoothSocket *l2cpSocket; - struct Request { - quint8 command; - QByteArray payload; - // TODO reference below is ugly but until we know all commands and their - // requirements this is WIP - QVariant reference; - QVariant reference2; - }; - QQueue<Request> openRequests; - - struct WriteRequest { - WriteRequest() {} - WriteRequest(quint16 h, quint16 o, const QByteArray &v) - : handle(h), valueOffset(o), value(v) {} - quint16 handle; - quint16 valueOffset; - QByteArray value; - }; - QVector<WriteRequest> openPrepareWriteRequests; - - // Invariant: !scheduledIndications.isEmpty => indicationInFlight == true - QVector<QLowEnergyHandle> scheduledIndications; - bool indicationInFlight = false; - - struct TempClientConfigurationData { - TempClientConfigurationData(QLowEnergyServicePrivate::DescData *dd = nullptr, - QLowEnergyHandle chHndl = 0, QLowEnergyHandle coHndl = 0) - : descData(dd), charValueHandle(chHndl), configHandle(coHndl) {} - - QLowEnergyServicePrivate::DescData *descData; - QLowEnergyHandle charValueHandle; - QLowEnergyHandle configHandle; - }; - - struct ClientConfigurationData { - ClientConfigurationData(QLowEnergyHandle chHndl = 0, QLowEnergyHandle coHndl = 0, - quint16 val = 0) - : charValueHandle(chHndl), configHandle(coHndl), configValue(val) {} - - QLowEnergyHandle charValueHandle; - QLowEnergyHandle configHandle; - quint16 configValue; - bool charValueWasUpdated = false; - }; - QHash<quint64, QVector<ClientConfigurationData>> clientConfigData; - - struct SigningData { - SigningData() = default; - SigningData(const quint128 &csrk, quint32 signCounter = quint32(-1)) - : key(csrk), counter(signCounter) {} - - quint128 key; - quint32 counter = quint32(-1); - }; - QHash<quint64, SigningData> signingData; - LeCmacCalculator *cmacCalculator = nullptr; - - bool requestPending; - quint16 mtuSize; - int securityLevelValue; - bool encryptionChangePending; - bool receivedMtuExchangeRequest = false; - - HciManager *hciManager; - QLeAdvertiser *advertiser; - QSocketNotifier *serverSocketNotifier; - QTimer *requestTimer = nullptr; - RemoteDeviceManager* device1Manager = nullptr; - - /* - Defines the maximum number of milliseconds the implementation will - wait for requests that require a response. - - This addresses the problem that some non-conformant BTLE devices - do not implement the request/response system properly. In such cases - the queue system would hang forever. - - Once timeout has been triggered we gracefully continue with the next request. - Depending on the type of the timed out ATT command we either ignore it - or artifically trigger an error response to ensure the API gives the - appropriate response. Potentially this can cause problems when the - response for the dropped requests arrives very late. That's why a big warning - is printed about the compromised state when a timeout is triggered. - */ - int gattRequestTimeout = 20000; - - void handleConnectionRequest(); - void closeServerSocket(); - - bool isBonded() const; - QVector<TempClientConfigurationData> gatherClientConfigData(); - void storeClientConfigurations(); - void restoreClientConfigurations(); - - enum SigningKeyType { LocalSigningKey, RemoteSigningKey }; - void loadSigningDataIfNecessary(SigningKeyType keyType); - void storeSignCounter(SigningKeyType keyType) const; - QString signingKeySettingsGroup(SigningKeyType keyType) const; - QString keySettingsFilePath() const; - - void sendPacket(const QByteArray &packet); - void sendNextPendingRequest(); - void processReply(const Request &request, const QByteArray &reply); - - void sendReadByGroupRequest(QLowEnergyHandle start, QLowEnergyHandle end, - quint16 type); - void sendReadByTypeRequest(QSharedPointer<QLowEnergyServicePrivate> serviceData, - QLowEnergyHandle nextHandle, quint16 attributeType); - void sendReadValueRequest(QLowEnergyHandle attributeHandle, bool isDescriptor); - void readServiceValues(const QBluetoothUuid &service, - bool readCharacteristics); - void readServiceValuesByOffset(uint handleData, quint16 offset, - bool isLastValue); - - void discoverServiceDescriptors(const QBluetoothUuid &serviceUuid); - void discoverNextDescriptor(QSharedPointer<QLowEnergyServicePrivate> serviceData, - const QList<QLowEnergyHandle> pendingCharHandles, - QLowEnergyHandle startingHandle); - void processUnsolicitedReply(const QByteArray &msg); - void exchangeMTU(); - bool setSecurityLevel(int level); - int securityLevel() const; - void sendExecuteWriteRequest(const QLowEnergyHandle attrHandle, - const QByteArray &newValue, - bool isCancelation); - void sendNextPrepareWriteRequest(const QLowEnergyHandle handle, - const QByteArray &newValue, quint16 offset); - bool increaseEncryptLevelfRequired(quint8 errorCode); - - void resetController(); - - void handleAdvertisingError(); - - bool checkPacketSize(const QByteArray &packet, int minSize, int maxSize = -1); - bool checkHandle(const QByteArray &packet, QLowEnergyHandle handle); - bool checkHandlePair(quint8 request, QLowEnergyHandle startingHandle, - QLowEnergyHandle endingHandle); - - void handleExchangeMtuRequest(const QByteArray &packet); - void handleFindInformationRequest(const QByteArray &packet); - void handleFindByTypeValueRequest(const QByteArray &packet); - void handleReadByTypeRequest(const QByteArray &packet); - void handleReadRequest(const QByteArray &packet); - void handleReadBlobRequest(const QByteArray &packet); - void handleReadMultipleRequest(const QByteArray &packet); - void handleReadByGroupTypeRequest(const QByteArray &packet); - void handleWriteRequestOrCommand(const QByteArray &packet); - void handlePrepareWriteRequest(const QByteArray &packet); - void handleExecuteWriteRequest(const QByteArray &packet); - - void sendErrorResponse(quint8 request, quint16 handle, quint8 code); - - using ElemWriter = std::function<void(const Attribute &, char *&)>; - void sendListResponse(const QByteArray &packetStart, int elemSize, - const QVector<Attribute> &attributes, const ElemWriter &elemWriter); - - void sendNotification(QLowEnergyHandle handle); - void sendIndication(QLowEnergyHandle handle); - void sendNotificationOrIndication(quint8 opCode, QLowEnergyHandle handle); - void sendNextIndication(); - - void ensureUniformAttributes(QVector<Attribute> &attributes, const std::function<int(const Attribute &)> &getSize); - void ensureUniformUuidSizes(QVector<Attribute> &attributes); - void ensureUniformValueSizes(QVector<Attribute> &attributes); - - using AttributePredicate = std::function<bool(const Attribute &)>; - QVector<Attribute> getAttributes(QLowEnergyHandle startHandle, QLowEnergyHandle endHandle, - const AttributePredicate &attributePredicate = [](const Attribute &) { return true; }); - - int checkPermissions(const Attribute &attr, QLowEnergyCharacteristic::PropertyType type); - int checkReadPermissions(const Attribute &attr); - int checkReadPermissions(QVector<Attribute> &attributes); - - bool verifyMac(const QByteArray &message, const quint128 &csrk, quint32 signCounter, - quint64 expectedMac); - - void updateLocalAttributeValue( - QLowEnergyHandle handle, - const QByteArray &value, - QLowEnergyCharacteristic &characteristic, - QLowEnergyDescriptor &descriptor); - - void writeCharacteristicForPeripheral( - QLowEnergyServicePrivate::CharData &charData, - const QByteArray &newValue); - void writeCharacteristicForCentral(const QSharedPointer<QLowEnergyServicePrivate> &service, - QLowEnergyHandle charHandle, - QLowEnergyHandle valueHandle, - const QByteArray &newValue, - QLowEnergyService::WriteMode mode); - - void writeDescriptorForPeripheral( - const QSharedPointer<QLowEnergyServicePrivate> &service, - const QLowEnergyHandle charHandle, - const QLowEnergyHandle descriptorHandle, - const QByteArray &newValue); - void writeDescriptorForCentral( - const QLowEnergyHandle charHandle, - const QLowEnergyHandle descriptorHandle, - const QByteArray &newValue); - - void restartRequestTimer(); - void establishL2cpClientSocket(); - void createServicesForCentralIfRequired(); - -private slots: - void l2cpConnected(); - void l2cpDisconnected(); - void l2cpErrorChanged(QBluetoothSocket::SocketError); - void l2cpReadyRead(); - void encryptionChangedEvent(const QBluetoothAddress&, bool); - void handleGattRequestTimeout(); - void activeConnectionTerminationDone(); -#elif defined(QT_ANDROID_BLUETOOTH) - LowEnergyNotificationHub *hub; - -private slots: - void connectionUpdated(QLowEnergyController::ControllerState newState, - QLowEnergyController::Error errorCode); - void servicesDiscovered(QLowEnergyController::Error errorCode, - const QString &foundServices); - void serviceDetailsDiscoveryFinished(const QString& serviceUuid, - int startHandle, int endHandle); - void characteristicRead(const QBluetoothUuid &serviceUuid, int handle, - const QBluetoothUuid &charUuid, int properties, - const QByteArray& data); - void descriptorRead(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid, - int handle, const QBluetoothUuid &descUuid, const QByteArray &data); - void characteristicWritten(int charHandle, const QByteArray &data, - QLowEnergyService::ServiceError errorCode); - void descriptorWritten(int descHandle, const QByteArray &data, - QLowEnergyService::ServiceError errorCode); - void serverDescriptorWritten(const QAndroidJniObject &jniDesc, const QByteArray &newValue); - void characteristicChanged(int charHandle, const QByteArray &data); - void serverCharacteristicChanged(const QAndroidJniObject &jniChar, const QByteArray &newValue); - void serviceError(int attributeHandle, QLowEnergyService::ServiceError errorCode); - void advertisementError(int errorCode); - -private: - void peripheralConnectionUpdated(QLowEnergyController::ControllerState newState, - QLowEnergyController::Error errorCode); - void centralConnectionUpdated(QLowEnergyController::ControllerState newState, - QLowEnergyController::Error errorCode); - -#elif defined(QT_WINRT_BLUETOOTH) -private slots: - void characteristicChanged(int charHandle, const QByteArray &data); - -private: - Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::IBluetoothLEDevice> mDevice; - EventRegistrationToken mStatusChangedToken; - struct ValueChangedEntry { - ValueChangedEntry() {} - ValueChangedEntry(Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattCharacteristic> c, - EventRegistrationToken t) - : characteristic(c) - , token(t) - { - } - - Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattCharacteristic> characteristic; - EventRegistrationToken token; - }; - QVector<ValueChangedEntry> mValueChangedTokens; - - Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattDeviceService> getNativeService(const QBluetoothUuid &serviceUuid); - Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattCharacteristic> getNativeCharacteristic(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid); - - void registerForValueChanges(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid); - - void obtainIncludedServices(QSharedPointer<QLowEnergyServicePrivate> servicePointer, - Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattDeviceService> nativeService); -#endif -private: - QLowEnergyController *q_ptr; - + QLowEnergyHandle startHandle) override; }; -Q_DECLARE_TYPEINFO(QLowEnergyControllerPrivate::Attribute, Q_MOVABLE_TYPE); - QT_END_NAMESPACE -#endif // QT_OSX_BLUETOOTH || QT_IOS_BLUETOOTH - #endif // QLOWENERGYCONTROLLERPRIVATE_P_H |