| 1 | // Copyright (C) 2016 The Qt Company Ltd. | 
| 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only | 
| 3 |  | 
| 4 | #ifndef HCIMANAGER_P_H | 
| 5 | #define HCIMANAGER_P_H | 
| 6 |  | 
| 7 | // | 
| 8 | //  W A R N I N G | 
| 9 | //  ------------- | 
| 10 | // | 
| 11 | // This file is not part of the Qt API.  It exists purely as an | 
| 12 | // implementation detail.  This header file may change from version to | 
| 13 | // version without notice, or even be removed. | 
| 14 | // | 
| 15 | // We mean it. | 
| 16 | // | 
| 17 |  | 
| 18 | #include <QtCore/QObject> | 
| 19 | #include <QtCore/QList> | 
| 20 | #include <QtCore/QSet> | 
| 21 | #include <QtCore/QSocketNotifier> | 
| 22 | #include <QtBluetooth/QBluetoothAddress> | 
| 23 | #include "bluez/bluez_data_p.h" | 
| 24 |  | 
| 25 | QT_BEGIN_NAMESPACE | 
| 26 |  | 
| 27 | class QLowEnergyConnectionParameters; | 
| 28 |  | 
| 29 | class HciManager : public QObject | 
| 30 | { | 
| 31 |     Q_OBJECT | 
| 32 | public: | 
| 33 |     enum class HciEvent { | 
| 34 |         EVT_INQUIRY_COMPLETE                  = 0x01, | 
| 35 |         EVT_INQUIRY_RESULT                    = 0x02, | 
| 36 |         EVT_CONN_COMPLETE                     = 0x03, | 
| 37 |         EVT_CONN_REQUEST                      = 0x04, | 
| 38 |         EVT_DISCONN_COMPLETE                  = 0x05, | 
| 39 |         EVT_AUTH_COMPLETE                     = 0x06, | 
| 40 |         EVT_REMOTE_NAME_REQ_COMPLETE          = 0x07, | 
| 41 |         EVT_ENCRYPT_CHANGE                    = 0x08, | 
| 42 |         EVT_CHANGE_CONN_LINK_KEY_COMPLETE     = 0x09, | 
| 43 |         EVT_MASTER_LINK_KEY_COMPLETE          = 0x0A, | 
| 44 |         EVT_READ_REMOTE_FEATURES_COMPLETE     = 0x0B, | 
| 45 |         EVT_READ_REMOTE_VERSION_COMPLETE      = 0x0C, | 
| 46 |         EVT_QOS_SETUP_COMPLETE                = 0x0D, | 
| 47 |         EVT_CMD_COMPLETE                      = 0x0E, | 
| 48 |         EVT_CMD_STATUS                        = 0x0F, | 
| 49 |         EVT_HARDWARE_ERROR                    = 0x10, | 
| 50 |         EVT_FLUSH_OCCURRED                    = 0x11, | 
| 51 |         EVT_ROLE_CHANGE                       = 0x12, | 
| 52 |         EVT_NUM_COMP_PKTS                     = 0x13, | 
| 53 |         EVT_MODE_CHANGE                       = 0x14, | 
| 54 |         EVT_RETURN_LINK_KEYS                  = 0x15, | 
| 55 |         EVT_PIN_CODE_REQ                      = 0x16, | 
| 56 |         EVT_LINK_KEY_REQ                      = 0x17, | 
| 57 |         EVT_LINK_KEY_NOTIFY                   = 0x18, | 
| 58 |         EVT_LOOPBACK_COMMAND                  = 0x19, | 
| 59 |         EVT_DATA_BUFFER_OVERFLOW              = 0x1A, | 
| 60 |         EVT_MAX_SLOTS_CHANGE                  = 0x1B, | 
| 61 |         EVT_READ_CLOCK_OFFSET_COMPLETE        = 0x1C, | 
| 62 |         EVT_CONN_PTYPE_CHANGED                = 0x1D, | 
| 63 |         EVT_QOS_VIOLATION                     = 0x1E, | 
| 64 |         EVT_PSCAN_REP_MODE_CHANGE             = 0x20, | 
| 65 |         EVT_FLOW_SPEC_COMPLETE                = 0x21, | 
| 66 |                   = 0x22, | 
| 67 |         EVT_READ_REMOTE_EXT_FEATURES_COMPLETE = 0x23, | 
| 68 |         EVT_SYNC_CONN_COMPLETE                = 0x2C, | 
| 69 |         EVT_SYNC_CONN_CHANGED                 = 0x2D, | 
| 70 |         EVT_SNIFF_SUBRATING                   = 0x2E, | 
| 71 |         EVT_EXTENDED_INQUIRY_RESULT           = 0x2F, | 
| 72 |         EVT_ENCRYPTION_KEY_REFRESH_COMPLETE   = 0x30, | 
| 73 |         EVT_IO_CAPABILITY_REQUEST             = 0x31, | 
| 74 |         EVT_IO_CAPABILITY_RESPONSE            = 0x32, | 
| 75 |         EVT_USER_CONFIRM_REQUEST              = 0x33, | 
| 76 |         EVT_USER_PASSKEY_REQUEST              = 0x34, | 
| 77 |         EVT_REMOTE_OOB_DATA_REQUEST           = 0x35, | 
| 78 |         EVT_SIMPLE_PAIRING_COMPLETE           = 0x36, | 
| 79 |         EVT_LINK_SUPERVISION_TIMEOUT_CHANGED  = 0x38, | 
| 80 |         EVT_ENHANCED_FLUSH_COMPLETE           = 0x39, | 
| 81 |         EVT_USER_PASSKEY_NOTIFY               = 0x3B, | 
| 82 |         EVT_KEYPRESS_NOTIFY                   = 0x3C, | 
| 83 |         EVT_REMOTE_HOST_FEATURES_NOTIFY       = 0x3D, | 
| 84 |         EVT_LE_META_EVENT                     = 0x3E, | 
| 85 |         EVT_PHYSICAL_LINK_COMPLETE            = 0x40, | 
| 86 |         EVT_CHANNEL_SELECTED                  = 0x41, | 
| 87 |         EVT_DISCONNECT_PHYSICAL_LINK_COMPLETE = 0x42, | 
| 88 |         EVT_PHYSICAL_LINK_LOSS_EARLY_WARNING  = 0x43, | 
| 89 |         EVT_PHYSICAL_LINK_RECOVERY            = 0x44, | 
| 90 |         EVT_LOGICAL_LINK_COMPLETE             = 0x45, | 
| 91 |         EVT_DISCONNECT_LOGICAL_LINK_COMPLETE  = 0x46, | 
| 92 |         EVT_FLOW_SPEC_MODIFY_COMPLETE         = 0x47, | 
| 93 |         EVT_NUMBER_COMPLETED_BLOCKS           = 0x48, | 
| 94 |         EVT_AMP_STATUS_CHANGE                 = 0x4D, | 
| 95 |         EVT_TESTING                           = 0xFE, | 
| 96 |         EVT_VENDOR                            = 0xFF, | 
| 97 |         EVT_STACK_INTERNAL                    = 0xFD | 
| 98 |     }; | 
| 99 |     Q_ENUM(HciEvent); | 
| 100 |  | 
| 101 |     enum class HciError { | 
| 102 |         HCI_SUCCESS                         = 0x00, // added for convenience, not in bluez code | 
| 103 |         HCI_UNKNOWN_COMMAND                 = 0x01, | 
| 104 |         HCI_NO_CONNECTION                   = 0x02, | 
| 105 |         HCI_HARDWARE_FAILURE                = 0x03, | 
| 106 |         HCI_PAGE_TIMEOUT                    = 0x04, | 
| 107 |         HCI_AUTHENTICATION_FAILURE          = 0x05, | 
| 108 |         HCI_PIN_OR_KEY_MISSING              = 0x06, | 
| 109 |         HCI_MEMORY_FULL                     = 0x07, | 
| 110 |         HCI_CONNECTION_TIMEOUT              = 0x08, | 
| 111 |         HCI_MAX_NUMBER_OF_CONNECTIONS       = 0x09, | 
| 112 |         HCI_MAX_NUMBER_OF_SCO_CONNECTIONS   = 0x0a, | 
| 113 |         HCI_ACL_CONNECTION_EXISTS           = 0x0b, | 
| 114 |         HCI_COMMAND_DISALLOWED              = 0x0c, | 
| 115 |         HCI_REJECTED_LIMITED_RESOURCES      = 0x0d, | 
| 116 |         HCI_REJECTED_SECURITY               = 0x0e, | 
| 117 |         HCI_REJECTED_PERSONAL               = 0x0f, | 
| 118 |         HCI_HOST_TIMEOUT                    = 0x10, | 
| 119 |         HCI_UNSUPPORTED_FEATURE             = 0x11, | 
| 120 |         HCI_INVALID_PARAMETERS              = 0x12, | 
| 121 |         HCI_OE_USER_ENDED_CONNECTION        = 0x13, | 
| 122 |         HCI_OE_LOW_RESOURCES                = 0x14, | 
| 123 |         HCI_OE_POWER_OFF                    = 0x15, | 
| 124 |         HCI_CONNECTION_TERMINATED           = 0x16, | 
| 125 |         HCI_REPEATED_ATTEMPTS               = 0x17, | 
| 126 |         HCI_PAIRING_NOT_ALLOWED             = 0x18, | 
| 127 |         HCI_UNKNOWN_LMP_PDU                 = 0x19, | 
| 128 |         HCI_UNSUPPORTED_REMOTE_FEATURE      = 0x1a, | 
| 129 |         HCI_SCO_OFFSET_REJECTED             = 0x1b, | 
| 130 |         HCI_SCO_INTERVAL_REJECTED           = 0x1c, | 
| 131 |         HCI_AIR_MODE_REJECTED               = 0x1d, | 
| 132 |         HCI_INVALID_LMP_PARAMETERS          = 0x1e, | 
| 133 |         HCI_UNSPECIFIED_ERROR               = 0x1f, | 
| 134 |         HCI_UNSUPPORTED_LMP_PARAMETER_VALUE = 0x20, | 
| 135 |         HCI_ROLE_CHANGE_NOT_ALLOWED         = 0x21, | 
| 136 |         HCI_LMP_RESPONSE_TIMEOUT            = 0x22, | 
| 137 |         HCI_LMP_ERROR_TRANSACTION_COLLISION = 0x23, | 
| 138 |         HCI_LMP_PDU_NOT_ALLOWED             = 0x24, | 
| 139 |         HCI_ENCRYPTION_MODE_NOT_ACCEPTED    = 0x25, | 
| 140 |         HCI_UNIT_LINK_KEY_USED              = 0x26, | 
| 141 |         HCI_QOS_NOT_SUPPORTED               = 0x27, | 
| 142 |         HCI_INSTANT_PASSED                  = 0x28, | 
| 143 |         HCI_PAIRING_NOT_SUPPORTED           = 0x29, | 
| 144 |         HCI_TRANSACTION_COLLISION           = 0x2a, | 
| 145 |         HCI_QOS_UNACCEPTABLE_PARAMETER      = 0x2c, | 
| 146 |         HCI_QOS_REJECTED                    = 0x2d, | 
| 147 |         HCI_CLASSIFICATION_NOT_SUPPORTED    = 0x2e, | 
| 148 |         HCI_INSUFFICIENT_SECURITY           = 0x2f, | 
| 149 |         HCI_PARAMETER_OUT_OF_RANGE          = 0x30, | 
| 150 |         HCI_ROLE_SWITCH_PENDING             = 0x32, | 
| 151 |         HCI_SLOT_VIOLATION                  = 0x34, | 
| 152 |         HCI_ROLE_SWITCH_FAILED              = 0x35, | 
| 153 |         HCI_EIR_TOO_LARGE                   = 0x36, | 
| 154 |         HCI_SIMPLE_PAIRING_NOT_SUPPORTED    = 0x37, | 
| 155 |         HCI_HOST_BUSY_PAIRING               = 0x38 | 
| 156 |     }; | 
| 157 |     Q_ENUM(HciError); | 
| 158 |  | 
| 159 |     explicit HciManager(const QBluetoothAddress &deviceAdapter); | 
| 160 |     ~HciManager(); | 
| 161 |  | 
| 162 |     bool isValid() const; | 
| 163 |     bool monitorEvent(HciManager::HciEvent event); | 
| 164 |     bool monitorAclPackets(); | 
| 165 |     bool sendCommand(QBluezConst::OpCodeGroupField ogf, QBluezConst::OpCodeCommandField ocf, const QByteArray ¶meters); | 
| 166 |  | 
| 167 |     void stopEvents(); | 
| 168 |     QBluetoothAddress addressForConnectionHandle(quint16 handle) const; | 
| 169 |  | 
| 170 |     // active connections | 
| 171 |     QList<quint16> activeLowEnergyConnections() const; | 
| 172 |  | 
| 173 |     bool sendConnectionUpdateCommand(quint16 handle, const QLowEnergyConnectionParameters ¶ms); | 
| 174 |     bool sendConnectionParameterUpdateRequest(quint16 handle, | 
| 175 |                                               const QLowEnergyConnectionParameters ¶ms); | 
| 176 |  | 
| 177 | signals: | 
| 178 |     void encryptionChangedEvent(const QBluetoothAddress &address, bool wasSuccess); | 
| 179 |     void commandCompleted(quint16 opCode, quint8 status, const QByteArray &data); | 
| 180 |     void connectionComplete(quint16 handle); | 
| 181 |     void connectionUpdate(quint16 handle, const QLowEnergyConnectionParameters ¶meters); | 
| 182 |     void signatureResolvingKeyReceived(quint16 connHandle, bool remoteKey, BluezUint128 csrk); | 
| 183 |  | 
| 184 | private slots: | 
| 185 |     void _q_readNotify(); | 
| 186 |  | 
| 187 | private: | 
| 188 |     int hciForAddress(const QBluetoothAddress &deviceAdapter); | 
| 189 |     void handleHciEventPacket(const quint8 *data, int size); | 
| 190 |     void handleHciAclPacket(const quint8 *data, int size); | 
| 191 |     void handleLeMetaEvent(const quint8 *data); | 
| 192 |  | 
| 193 |     int hciSocket; | 
| 194 |     int hciDev; | 
| 195 |     quint8 sigPacketIdentifier = 0; | 
| 196 |     QSocketNotifier *notifier = nullptr; | 
| 197 |     QSet<HciManager::HciEvent> runningEvents; | 
| 198 | }; | 
| 199 |  | 
| 200 | QT_END_NAMESPACE | 
| 201 |  | 
| 202 | #endif // HCIMANAGER_P_H | 
| 203 |  |