void HciManager::handleHciAclPacket(const quint8 *data, int size) { if (size < int(sizeof(AclData))) { qCWarning(QT_BT_BLUEZ) << "Unexpected HCI ACL packet size"; return; } quint16 rawAclData[sizeof(AclData) / sizeof(quint16)]; rawAclData[0] = bt_get_le16(data); rawAclData[1] = bt_get_le16(data + sizeof(quint16)); const AclData *aclData = reinterpret_cast<AclData *>(rawAclData); data += sizeof *aclData; size -= sizeof *aclData; // Consider only directed, complete messages. if ((aclData->pbFlag != 0 && aclData->pbFlag != 2) || aclData->bcFlag != 0) return; if (size < aclData->dataLen) { qCWarning(QT_BT_BLUEZ) << "HCI ACL packet data size" << size << "is smaller than specified size" << aclData->dataLen; return; } // qCDebug(QT_BT_BLUEZ) << "handle:" << aclData->handle << "PB:" << aclData->pbFlag // << "BC:" << aclData->bcFlag << "data len:" << aclData->dataLen; if (size < int(sizeof(L2CapHeader))) { qCWarning(QT_BT_BLUEZ) << "Unexpected HCI ACL packet size"; return; } L2CapHeader l2CapHeader = *reinterpret_cast<const L2CapHeader*>(data); l2CapHeader.channelId = qFromLittleEndian(l2CapHeader.channelId); l2CapHeader.length = qFromLittleEndian(l2CapHeader.length); data += sizeof l2CapHeader; size -= sizeof l2CapHeader; if (size < l2CapHeader.length) { qCWarning(QT_BT_BLUEZ) << "L2Cap payload size" << size << "is smaller than specified size" << l2CapHeader.length; return; } // qCDebug(QT_BT_BLUEZ) << "l2cap channel id:" << l2CapHeader.channelId // << "payload length:" << l2CapHeader.length; if (l2CapHeader.channelId != SECURITY_CHANNEL_ID) return; if (*data != 0xa) // "Signing Information". Spec v4.2, Vol 3, Part H, 3.6.6 return; if (size != 17) { qCWarning(QT_BT_BLUEZ) << "Unexpected key size" << size << "in Signing Information packet"; return; } quint128 csrk; memcpy(&csrk, data + 1, sizeof csrk); const bool isRemoteKey = aclData->pbFlag == 2; emit signatureResolvingKeyReceived(aclData->handle, isRemoteKey, csrk); }
static void events_handler(const uint8_t *pdu, uint16_t len, gpointer user_data) { uint8_t *opdu; uint8_t evt; uint16_t olen; size_t plen; evt = pdu[0]; if ( evt != ATT_OP_HANDLE_NOTIFY && evt != ATT_OP_HANDLE_IND ) { printf("#Invalid opcode %02X in event handler??\n", evt); return; } assert( len >= 3 ); bt_get_le16(&pdu[1]); send_data( pdu+3, len-3 ); if (evt == ATT_OP_HANDLE_NOTIFY) return; opdu = g_attrib_get_buffer(attrib, &plen); olen = enc_confirmation(opdu, plen); if (olen > 0) g_attrib_send(attrib, 0, opdu, olen, NULL, NULL, NULL); }
void HciManager::handleLeMetaEvent(const quint8 *data) { // Spec v4.2, Vol 2, part E, 7.7.65ff switch (*data) { case 0x1: { const quint16 handle = bt_get_le16(data + 2); emit connectionComplete(handle); break; } case 0x3: { // TODO: From little endian! struct ConnectionUpdateData { quint8 status; quint16 handle; quint16 interval; quint16 latency; quint16 timeout; } __attribute((packed)); const auto * const updateData = reinterpret_cast<const ConnectionUpdateData *>(data + 1); if (updateData->status == 0) { QLowEnergyConnectionParameters params; const double interval = qFromLittleEndian(updateData->interval) * 1.25; params.setIntervalRange(interval, interval); params.setLatency(qFromLittleEndian(updateData->latency)); params.setSupervisionTimeout(qFromLittleEndian(updateData->timeout) * 10); emit connectionUpdate(qFromLittleEndian(updateData->handle), params); } break; } default: break; } }
static void char_read_by_uuid_cb(guint8 status, const guint8 *pdu, guint16 plen, gpointer user_data) { struct characteristic_data *char_data = user_data; struct att_data_list *list; int i; if (status == ATT_ECODE_ATTR_NOT_FOUND && char_data->start != char_data->orig_start) { printf("# TODO case in char_read_by_uuid_cb\n"); goto done; } if (status != 0) { resp_error_comm(status); goto done; } list = dec_read_by_type_resp(pdu, plen); resp_begin(rsp_READ); if (list == NULL) goto nolist; for (i = 0; i < list->num; i++) { uint8_t *value = list->data[i]; char_data->start = bt_get_le16(value) + 1; send_uint(tag_HANDLE, bt_get_le16(value)); send_data(value+2, list->len-2); // All the same length?? } att_data_list_free(list); nolist: resp_end(); done: g_free(char_data); }
static uint32_t get_val(uint8_t *ptr, uint8_t len) { switch (len) { case 1: return *ptr; case 2: return bt_get_le16(ptr); case 4: return bt_get_le32(ptr); } return 0; }
static void conf_rfc(void *ptr, int len, int in, uint16_t handle, uint16_t cid) { uint8_t mode; mode = *((uint8_t *) ptr); set_mode(!in, handle, cid, mode); printf("RFC 0x%02x (%s", mode, mode2str(mode)); if (mode >= 0x01 && mode <= 0x04) { uint8_t txwin, maxtrans; uint16_t rto, mto, mps; txwin = *((uint8_t *) (ptr + 1)); maxtrans = *((uint8_t *) (ptr + 2)); rto = bt_get_le16(ptr + 3); mto = bt_get_le16(ptr + 5); mps = bt_get_le16(ptr + 7); printf(", TxWin %d, MaxTx %d, RTo %d, MTo %d, MPS %d", txwin, maxtrans, rto, mto, mps); } printf(")"); }