| 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, int size); |
| 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 | |