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 | |