| 1 | // Copyright (C) 2021 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 BLUEZ_DATA_P_H | 
| 5 | #define BLUEZ_DATA_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/private/qglobal_p.h> | 
| 19 | #include <QtCore/qendian.h> | 
| 20 | #include <sys/socket.h> | 
| 21 | #include <QtBluetooth/QBluetoothUuid> | 
| 22 | #include <QtCore/qtmetamacros.h> | 
| 23 |  | 
| 24 | QT_BEGIN_NAMESPACE | 
| 25 |  | 
| 26 | #define ATTRIBUTE_CHANNEL_ID 4 | 
| 27 | #define SIGNALING_CHANNEL_ID 5 | 
| 28 | #define SECURITY_CHANNEL_ID 6 | 
| 29 |  | 
| 30 | #define BTPROTO_L2CAP   0 | 
| 31 | #define BTPROTO_HCI     1 | 
| 32 | #define BTPROTO_RFCOMM  3 | 
| 33 |  | 
| 34 | #define SOL_HCI     0 | 
| 35 | #define SOL_L2CAP   6 | 
| 36 | #define SOL_RFCOMM  18 | 
| 37 | #ifndef SOL_BLUETOOTH | 
| 38 | #define SOL_BLUETOOTH   274 | 
| 39 | #endif | 
| 40 |  | 
| 41 | #define RFCOMM_LM   0x03 | 
| 42 |  | 
| 43 | #define RFCOMM_LM_AUTH      0x0002 | 
| 44 | #define RFCOMM_LM_ENCRYPT   0x0004 | 
| 45 | #define RFCOMM_LM_TRUSTED   0x0008 | 
| 46 | #define RFCOMM_LM_SECURE    0x0020 | 
| 47 |  | 
| 48 | #define L2CAP_LM            0x03 | 
| 49 | #define L2CAP_LM_AUTH       0x0002 | 
| 50 | #define L2CAP_LM_ENCRYPT    0x0004 | 
| 51 | #define L2CAP_LM_TRUSTED    0x0008 | 
| 52 | #define L2CAP_LM_SECURE     0x0020 | 
| 53 |  | 
| 54 | #define BT_SECURITY 4 | 
| 55 | struct bt_security { | 
| 56 |     quint8 level; | 
| 57 |     quint8 key_size; | 
| 58 | }; | 
| 59 | #define BT_SECURITY_SDP     0 | 
| 60 | #define BT_SECURITY_LOW     1 | 
| 61 | #define BT_SECURITY_MEDIUM  2 | 
| 62 | #define BT_SECURITY_HIGH    3 | 
| 63 |  | 
| 64 | #define BDADDR_LE_PUBLIC    0x01 | 
| 65 | #define BDADDR_LE_RANDOM    0x02 | 
| 66 |  | 
| 67 | #define SCO_LINK    0x00 | 
| 68 | #define ACL_LINK    0x01 | 
| 69 | #define ESCO_LINK   0x02 | 
| 70 | #define LE_LINK     0x80    // based on hcitool.c -> no fixed constant available | 
| 71 |  | 
| 72 | /* Byte order conversions */ | 
| 73 | #if __BYTE_ORDER == __LITTLE_ENDIAN | 
| 74 | #define htobs(d)  (d) | 
| 75 | #define htobl(d)  (d) | 
| 76 | #define htobll(d) (d) | 
| 77 | #define btohs(d)  (d) | 
| 78 | #define btohl(d)  (d) | 
| 79 | #define btohll(d) (d) | 
| 80 | #elif __BYTE_ORDER == __BIG_ENDIAN | 
| 81 | #define htobs(d)  qbswap((quint16)(d)) | 
| 82 | #define htobl(d)  qbswap((quint32)(d)) | 
| 83 | #define htobll(d) qbswap((quint64)(d)) | 
| 84 | #define btohs(d)  qbswap((quint16)(d)) | 
| 85 | #define btohl(d)  qbswap((quint32)(d)) | 
| 86 | #define btohll(d) qbswap((quint64)(d)) | 
| 87 | #else | 
| 88 | #error "Unknown byte order" | 
| 89 | #endif | 
| 90 |  | 
| 91 | #define HCIGETCONNLIST  _IOR('H', 212, int) | 
| 92 | #define HCIGETDEVINFO   _IOR('H', 211, int) | 
| 93 | #define HCIGETDEVLIST   _IOR('H', 210, int) | 
| 94 |  | 
| 95 | // Generic 128 bits of data | 
| 96 | typedef QUuid::Id128Bytes BluezUint128; | 
| 97 |  | 
| 98 | // Bluetooth address | 
| 99 | typedef struct { | 
| 100 |     quint8 b[6]; | 
| 101 | } __attribute__((packed)) bdaddr_t; | 
| 102 |  | 
| 103 | // L2CP socket | 
| 104 | struct sockaddr_l2 { | 
| 105 |     sa_family_t     l2_family; | 
| 106 |     unsigned short  l2_psm; | 
| 107 |     bdaddr_t        l2_bdaddr; | 
| 108 |     unsigned short  l2_cid; | 
| 109 | #if !defined(QT_BLUEZ_NO_BTLE) | 
| 110 |     quint8          l2_bdaddr_type; | 
| 111 | #endif | 
| 112 | }; | 
| 113 |  | 
| 114 | // RFCOMM socket | 
| 115 | struct sockaddr_rc { | 
| 116 |     sa_family_t rc_family; | 
| 117 |     bdaddr_t    rc_bdaddr; | 
| 118 |     quint8      rc_channel; | 
| 119 | }; | 
| 120 |  | 
| 121 | // Bt Low Energy related | 
| 122 |  | 
| 123 | template<typename T> inline T getBtData(const void *ptr) | 
| 124 | { | 
| 125 |     return qFromLittleEndian<T>(reinterpret_cast<const uchar *>(ptr)); | 
| 126 | } | 
| 127 |  | 
| 128 | static inline quint16 bt_get_le16(const void *ptr) | 
| 129 | { | 
| 130 |     return getBtData<quint16>(ptr); | 
| 131 | } | 
| 132 |  | 
| 133 | template<typename T> inline void putBtData(T src, void *dst) | 
| 134 | { | 
| 135 |     qToLittleEndian(src, reinterpret_cast<uchar *>(dst)); | 
| 136 | } | 
| 137 |  | 
| 138 | // HCI related | 
| 139 |  | 
| 140 | #define HCI_MAX_DEV     16 | 
| 141 | #define HCI_DEV_NONE    0xffff | 
| 142 |  | 
| 143 | #define HCI_CHANNEL_CONTROL     0x3 | 
| 144 |  | 
| 145 | #define HCI_MAX_EVENT_SIZE 260 | 
| 146 |  | 
| 147 | // HCI sockopts | 
| 148 | #define HCI_FILTER 2 | 
| 149 |  | 
| 150 | // HCI packet types | 
| 151 | #define HCI_COMMAND_PKT 0x01 | 
| 152 | #define HCI_ACL_PKT     0x02 | 
| 153 | #define HCI_EVENT_PKT   0x04 | 
| 154 | #define HCI_VENDOR_PKT  0xff | 
| 155 |  | 
| 156 | #define HCI_FLT_TYPE_BITS  31 | 
| 157 | #define HCI_FLT_EVENT_BITS 63 | 
| 158 |  | 
| 159 |  | 
| 160 | struct sockaddr_hci { | 
| 161 |     sa_family_t hci_family; | 
| 162 |     unsigned short hci_dev; | 
| 163 |     unsigned short hci_channel; | 
| 164 | }; | 
| 165 |  | 
| 166 | struct hci_dev_req { | 
| 167 |     quint16 dev_id; | 
| 168 |     quint32 dev_opt; | 
| 169 | }; | 
| 170 |  | 
| 171 | struct hci_dev_list_req { | 
| 172 |     quint16 dev_num; | 
| 173 |     struct hci_dev_req dev_req[0]; | 
| 174 | }; | 
| 175 |  | 
| 176 | struct hci_dev_stats { | 
| 177 |     quint32 err_rx; | 
| 178 |     quint32 err_tx; | 
| 179 |     quint32 cmd_tx; | 
| 180 |     quint32 evt_rx; | 
| 181 |     quint32 acl_tx; | 
| 182 |     quint32 acl_rx; | 
| 183 |     quint32 sco_tx; | 
| 184 |     quint32 sco_rx; | 
| 185 |     quint32 byte_rx; | 
| 186 |     quint32 byte_tx; | 
| 187 | }; | 
| 188 |  | 
| 189 | struct hci_dev_info { | 
| 190 |     quint16 dev_id; | 
| 191 |     char     name[8]; | 
| 192 |  | 
| 193 |     bdaddr_t bdaddr; | 
| 194 |  | 
| 195 |     quint32 flags; | 
| 196 |     quint8  type; | 
| 197 |  | 
| 198 |     quint8  features[8]; | 
| 199 |  | 
| 200 |     quint32 pkt_type; | 
| 201 |     quint32 link_policy; | 
| 202 |     quint32 link_mode; | 
| 203 |  | 
| 204 |     quint16 acl_mtu; | 
| 205 |     quint16 acl_pkts; | 
| 206 |     quint16 sco_mtu; | 
| 207 |     quint16 sco_pkts; | 
| 208 |  | 
| 209 |     struct   hci_dev_stats stat; | 
| 210 | }; | 
| 211 |  | 
| 212 | struct hci_conn_info { | 
| 213 |     quint16 handle; | 
| 214 |     bdaddr_t bdaddr; | 
| 215 |     quint8  type; | 
| 216 |     quint8  out; | 
| 217 |     quint16 state; | 
| 218 |     quint32 link_mode; | 
| 219 | }; | 
| 220 |  | 
| 221 | struct hci_conn_list_req { | 
| 222 |     quint16 dev_id; | 
| 223 |     quint16 conn_num; | 
| 224 |     struct hci_conn_info conn_info[0]; | 
| 225 | }; | 
| 226 |  | 
| 227 | struct hci_filter { | 
| 228 |     quint32 type_mask; | 
| 229 |     quint32 event_mask[2]; | 
| 230 |     quint16 opcode; | 
| 231 | }; | 
| 232 |  | 
| 233 | static inline void hci_set_bit(int nr, void *addr) | 
| 234 | { | 
| 235 |     *((quint32 *) addr + (nr >> 5)) |= (1 << (nr & 31)); | 
| 236 | } | 
| 237 | static inline void hci_clear_bit(int nr, void *addr) | 
| 238 | { | 
| 239 |     *((quint32 *) addr + (nr >> 5)) &= ~(1 << (nr & 31)); | 
| 240 | } | 
| 241 | static inline void hci_filter_clear(struct hci_filter *f) | 
| 242 | { | 
| 243 |     memset(s: f, c: 0, n: sizeof(*f)); | 
| 244 | } | 
| 245 | static inline void hci_filter_set_ptype(int t, struct hci_filter *f) | 
| 246 | { | 
| 247 |     hci_set_bit(nr: (t == HCI_VENDOR_PKT) ? 0 : (t & HCI_FLT_TYPE_BITS), addr: &f->type_mask); | 
| 248 | } | 
| 249 | static inline void hci_filter_clear_ptype(int t, struct hci_filter *f) | 
| 250 | { | 
| 251 |     hci_clear_bit(nr: (t == HCI_VENDOR_PKT) ? 0 : (t & HCI_FLT_TYPE_BITS), addr: &f->type_mask); | 
| 252 | } | 
| 253 | static inline void hci_filter_set_event(int e, struct hci_filter *f) | 
| 254 | { | 
| 255 |     hci_set_bit(nr: (e & HCI_FLT_EVENT_BITS), addr: &f->event_mask); | 
| 256 | } | 
| 257 | static inline void hci_filter_clear_event(int e, struct hci_filter *f) | 
| 258 | { | 
| 259 |     hci_clear_bit(nr: (e & HCI_FLT_EVENT_BITS), addr: &f->event_mask); | 
| 260 | } | 
| 261 | static inline void hci_filter_all_ptypes(struct hci_filter *f) | 
| 262 | { | 
| 263 |     memset(s: (void *) &f->type_mask, c: 0xff, n: sizeof(f->type_mask)); | 
| 264 | } | 
| 265 | static inline void hci_filter_all_events(struct hci_filter *f) | 
| 266 | { | 
| 267 |     memset(s: (void *) f->event_mask, c: 0xff, n: sizeof(f->event_mask)); | 
| 268 | } | 
| 269 |  | 
| 270 | typedef struct { | 
| 271 |     quint8 evt; | 
| 272 |     quint8 plen; | 
| 273 | } __attribute__ ((packed)) hci_event_hdr; | 
| 274 | #define HCI_EVENT_HDR_SIZE 2 | 
| 275 |  | 
| 276 | typedef struct { | 
| 277 |     quint8  status; | 
| 278 |     quint16 handle; | 
| 279 |     quint8  encrypt; | 
| 280 | } __attribute__ ((packed)) evt_encrypt_change; | 
| 281 | #define EVT_ENCRYPT_CHANGE_SIZE 4 | 
| 282 |  | 
| 283 | struct evt_cmd_complete { | 
| 284 |     quint8 ncmd; | 
| 285 |     quint16 opcode; | 
| 286 | } __attribute__ ((packed)); | 
| 287 |  | 
| 288 | struct AclData { | 
| 289 |     quint16 handle: 12; | 
| 290 |     quint16 pbFlag: 2; | 
| 291 |     quint16 bcFlag: 2; | 
| 292 |     quint16 dataLen; | 
| 293 | }; | 
| 294 |  | 
| 295 | struct  { | 
| 296 |     quint16 ; | 
| 297 |     quint16 ; | 
| 298 | }; | 
| 299 |  | 
| 300 | struct hci_command_hdr { | 
| 301 |     quint16 opcode;         /* OCF & OGF */ | 
| 302 |     quint8 plen; | 
| 303 | } __attribute__ ((packed)); | 
| 304 |  | 
| 305 | namespace QBluezConst { | 
| 306 |     Q_NAMESPACE | 
| 307 |     enum OpCodeGroupField { | 
| 308 |         OgfLinkControl = 0x8, | 
| 309 |     }; | 
| 310 |     Q_ENUM_NS(OpCodeGroupField) | 
| 311 |  | 
| 312 |     enum OpCodeCommandField { | 
| 313 |         OcfLeSetAdvParams = 0x6, | 
| 314 |         OcfLeReadTxPowerLevel = 0x7, | 
| 315 |         OcfLeSetAdvData = 0x8, | 
| 316 |         OcfLeSetScanResponseData = 0x9, | 
| 317 |         OcfLeSetAdvEnable = 0xa, | 
| 318 |         OcfLeClearWhiteList = 0x10, | 
| 319 |         OcfLeAddToWhiteList = 0x11, | 
| 320 |         OcfLeConnectionUpdate = 0x13, | 
| 321 |     }; | 
| 322 |     Q_ENUM_NS(OpCodeCommandField) | 
| 323 |  | 
| 324 |     enum class AttCommand : quint8 { | 
| 325 |         ATT_OP_ERROR_RESPONSE              = 0x01, | 
| 326 |         ATT_OP_EXCHANGE_MTU_REQUEST        = 0x02, //send own mtu | 
| 327 |         ATT_OP_EXCHANGE_MTU_RESPONSE       = 0x03, //receive server MTU | 
| 328 |         ATT_OP_FIND_INFORMATION_REQUEST    = 0x04, //discover individual attribute info | 
| 329 |         ATT_OP_FIND_INFORMATION_RESPONSE   = 0x05, | 
| 330 |         ATT_OP_FIND_BY_TYPE_VALUE_REQUEST  = 0x06, | 
| 331 |         ATT_OP_FIND_BY_TYPE_VALUE_RESPONSE = 0x07, | 
| 332 |         ATT_OP_READ_BY_TYPE_REQUEST        = 0x08, //discover characteristics | 
| 333 |         ATT_OP_READ_BY_TYPE_RESPONSE       = 0x09, | 
| 334 |         ATT_OP_READ_REQUEST                = 0x0A, //read characteristic & descriptor values | 
| 335 |         ATT_OP_READ_RESPONSE               = 0x0B, | 
| 336 |         ATT_OP_READ_BLOB_REQUEST           = 0x0C, //read values longer than MTU-1 | 
| 337 |         ATT_OP_READ_BLOB_RESPONSE          = 0x0D, | 
| 338 |         ATT_OP_READ_MULTIPLE_REQUEST       = 0x0E, | 
| 339 |         ATT_OP_READ_MULTIPLE_RESPONSE      = 0x0F, | 
| 340 |         ATT_OP_READ_BY_GROUP_REQUEST       = 0x10, //discover services | 
| 341 |         ATT_OP_READ_BY_GROUP_RESPONSE      = 0x11, | 
| 342 |         ATT_OP_WRITE_REQUEST               = 0x12, //write characteristic with response | 
| 343 |         ATT_OP_WRITE_RESPONSE              = 0x13, | 
| 344 |         ATT_OP_PREPARE_WRITE_REQUEST       = 0x16, //write values longer than MTU-3 -> queueing | 
| 345 |         ATT_OP_PREPARE_WRITE_RESPONSE      = 0x17, | 
| 346 |         ATT_OP_EXECUTE_WRITE_REQUEST       = 0x18, //write values longer than MTU-3 -> execute queue | 
| 347 |         ATT_OP_EXECUTE_WRITE_RESPONSE      = 0x19, | 
| 348 |         ATT_OP_HANDLE_VAL_NOTIFICATION     = 0x1b, //informs about value change | 
| 349 |         ATT_OP_HANDLE_VAL_INDICATION       = 0x1d, //informs about value change -> requires reply | 
| 350 |         ATT_OP_HANDLE_VAL_CONFIRMATION     = 0x1e, //answer for ATT_OP_HANDLE_VAL_INDICATION | 
| 351 |         ATT_OP_WRITE_COMMAND               = 0x52, //write characteristic without response | 
| 352 |         ATT_OP_SIGNED_WRITE_COMMAND        = 0xD2 | 
| 353 |     }; | 
| 354 |     Q_ENUM_NS(AttCommand) | 
| 355 |  | 
| 356 |     enum class AttError : quint8 { | 
| 357 |         ATT_ERROR_NO_ERROR              = 0x00, | 
| 358 |         ATT_ERROR_INVALID_HANDLE        = 0x01, | 
| 359 |         ATT_ERROR_READ_NOT_PERM         = 0x02, | 
| 360 |         ATT_ERROR_WRITE_NOT_PERM        = 0x03, | 
| 361 |         ATT_ERROR_INVALID_PDU           = 0x04, | 
| 362 |         ATT_ERROR_INSUF_AUTHENTICATION  = 0x05, | 
| 363 |         ATT_ERROR_REQUEST_NOT_SUPPORTED = 0x06, | 
| 364 |         ATT_ERROR_INVALID_OFFSET        = 0x07, | 
| 365 |         ATT_ERROR_INSUF_AUTHORIZATION   = 0x08, | 
| 366 |         ATT_ERROR_PREPARE_QUEUE_FULL    = 0x09, | 
| 367 |         ATT_ERROR_ATTRIBUTE_NOT_FOUND   = 0x0A, | 
| 368 |         ATT_ERROR_ATTRIBUTE_NOT_LONG    = 0x0B, | 
| 369 |         ATT_ERROR_INSUF_ENCR_KEY_SIZE   = 0x0C, | 
| 370 |         ATT_ERROR_INVAL_ATTR_VALUE_LEN  = 0x0D, | 
| 371 |         ATT_ERROR_UNLIKELY              = 0x0E, | 
| 372 |         ATT_ERROR_INSUF_ENCRYPTION      = 0x0F, | 
| 373 |         ATT_ERROR_UNSUPPRTED_GROUP_TYPE = 0x10, | 
| 374 |         ATT_ERROR_INSUF_RESOURCES       = 0x11, | 
| 375 |         ATT_ERROR_APPLICATION_START     = 0x80, | 
| 376 |         //------------------------------------------ | 
| 377 |         // The error codes in this block are | 
| 378 |         // implementation specific errors | 
| 379 |  | 
| 380 |         ATT_ERROR_REQUEST_STALLED       = 0x81, | 
| 381 |  | 
| 382 |         //------------------------------------------ | 
| 383 |         ATT_ERROR_APPLICATION_END       = 0x9f | 
| 384 |     }; | 
| 385 |     Q_ENUM_NS(AttError) | 
| 386 | } | 
| 387 | /* Command opcode pack/unpack */ | 
| 388 | #define opCodePack(ogf, ocf) (quint16(((ocf) & 0x03ff)|((ogf) << 10))) | 
| 389 | #define ogfFromOpCode(op) ((op) >> 10) | 
| 390 | #define ocfFromOpCode(op) ((op) & 0x03ff) | 
| 391 |  | 
| 392 | QT_END_NAMESPACE | 
| 393 |  | 
| 394 | #endif // BLUEZ_DATA_P_H | 
| 395 |  |