diff options
author | Sven Gothel <[email protected]> | 2023-10-23 08:19:24 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2023-10-23 08:19:24 +0200 |
commit | d17582e5dc9e380a12ac54ea6ba154f46c468a21 (patch) | |
tree | 156535a769c492dea832520dc0694a156e990b7c /src/direct_bt | |
parent | 5363ea9c9c540d3e432a2813f1356b6249e9bf47 (diff) |
HCIHandler: Add support for HCI resolvable functions: add, del, clear, read.., set..
NOTE that the following seem not to be supported in Linux/BlueZ:
- LE_READ_PEER_RESOLV_ADDR
- LE_READ_LOCAL_RESOLV_ADDR
The others are coded within BlueZ,
but I received 0x01 UNKNOWN_COMMAND as a HCIStatusCode
Used kernel for analysis:
- bluetooth-next 2022-04-01
- 38a1944deda4d96ca04b9aaa51ee5ae879b61aa0
Diffstat (limited to 'src/direct_bt')
-rw-r--r-- | src/direct_bt/HCIHandler.cpp | 106 | ||||
-rw-r--r-- | src/direct_bt/HCITypes.cpp | 7 |
2 files changed, 113 insertions, 0 deletions
diff --git a/src/direct_bt/HCIHandler.cpp b/src/direct_bt/HCIHandler.cpp index 21f3c573..c99539b8 100644 --- a/src/direct_bt/HCIHandler.cpp +++ b/src/direct_bt/HCIHandler.cpp @@ -749,6 +749,7 @@ HCIHandler::HCIHandler(const uint16_t dev_id_, const BTMode btMode_) noexcept HCIComm::filter_set_event(number(HCIEventType::CMD_STATUS), &filter_mask); HCIComm::filter_set_event(number(HCIEventType::HARDWARE_ERROR), &filter_mask); HCIComm::filter_set_event(number(HCIEventType::ENCRYPT_KEY_REFRESH_COMPLETE), &filter_mask); + // HCIComm::filter_set_event(number(HCIEventType::IO_CAPABILITY_REQUEST), &filter_mask); // HCIComm::filter_set_event(number(HCIEventType::IO_CAPABILITY_RESPONSE), &filter_mask); HCIComm::filter_set_event(number(HCIEventType::LE_META), &filter_mask); @@ -1499,6 +1500,111 @@ HCIStatusCode HCIHandler::disconnect(const uint16_t conn_handle, const BDAddress return status; } +HCIStatusCode HCIHandler::le_add_to_resolv_list(const BDAddressAndType& peerIdentityAddressAndType, + jau::uint128_t& peer_irk, jau::uint128_t& local_irk) noexcept { + HCIStatusCode status; + HCIStructCommand<hci_cp_le_add_to_resolv_list> req0(HCIOpcode::LE_ADD_TO_RESOLV_LIST); + hci_cp_le_add_to_resolv_list * cp = req0.getWStruct(); + cp->bdaddr_type = static_cast<uint8_t>(peerIdentityAddressAndType.type); + cp->bdaddr = jau::cpu_to_le(peerIdentityAddressAndType.address); + jau::put_uint128(cp->peer_irk, 0, peer_irk, true /* le */); + jau::put_uint128(cp->local_irk, 0, local_irk, true /* le */); + const hci_rp_status * ev_res; + std::unique_ptr<HCIEvent> ev = processCommandComplete(req0, &ev_res, &status, true /* quiet */); + if( nullptr == ev || nullptr == ev_res || HCIStatusCode::SUCCESS != status ) { + ERR_PRINT("%s: 0x%x (%s) - %s", to_string(req0.getOpcode()), number(status), to_string(status).c_str(), toString().c_str()); + } + return status; +} + +HCIStatusCode HCIHandler::le_del_from_resolv_list(const BDAddressAndType& peerIdentityAddressAndType) noexcept { + HCIStatusCode status; + HCIStructCommand<hci_cp_le_del_from_resolv_list> req0(HCIOpcode::LE_DEL_FROM_RESOLV_LIST); + hci_cp_le_del_from_resolv_list * cp = req0.getWStruct(); + cp->bdaddr_type = static_cast<uint8_t>(peerIdentityAddressAndType.type); + cp->bdaddr = jau::cpu_to_le(peerIdentityAddressAndType.address); + const hci_rp_status * ev_res; + std::unique_ptr<HCIEvent> ev = processCommandComplete(req0, &ev_res, &status, true /* quiet */); + if( nullptr == ev || nullptr == ev_res || HCIStatusCode::SUCCESS != status ) { + ERR_PRINT("%s: 0x%x (%s) - %s", to_string(req0.getOpcode()), number(status), to_string(status).c_str(), toString().c_str()); + } + return status; +} + +HCIStatusCode HCIHandler::le_clear_resolv_list() noexcept { + HCIStatusCode status; + HCICommand req0(HCIOpcode::LE_CLEAR_RESOLV_LIST, 0); + const hci_rp_status * ev_res; + std::unique_ptr<HCIEvent> ev = processCommandComplete(req0, &ev_res, &status, true /* quiet */); + if( nullptr == ev || nullptr == ev_res || HCIStatusCode::SUCCESS != status ) { + ERR_PRINT("%s: 0x%x (%s) - %s", to_string(req0.getOpcode()), number(status), to_string(status).c_str(), toString().c_str()); + } + return status; +} + +HCIStatusCode HCIHandler::le_read_resolv_list_size(uint32_t& size_res) noexcept { + size_res = 0; + HCIStatusCode status; + HCICommand req0(HCIOpcode::LE_READ_RESOLV_LIST_SIZE, 0); + const hci_rp_le_read_resolv_list_size * ev_res; + std::unique_ptr<HCIEvent> ev = processCommandComplete(req0, &ev_res, &status, true /* quiet */); + if( nullptr == ev || nullptr == ev_res || HCIStatusCode::SUCCESS != status ) { + ERR_PRINT("%s: 0x%x (%s) - %s", to_string(req0.getOpcode()), number(status), to_string(status).c_str(), toString().c_str()); + } else if( nullptr != ev_res && HCIStatusCode::SUCCESS != status ) { + size_res = ev_res->size; + } + return status; +} + +HCIStatusCode HCIHandler::le_read_peer_resolv_addr(const BDAddressAndType& peerIdentityAddressAndType, + jau::EUI48& peerResolvableAddress) noexcept { + peerResolvableAddress.clear(); + HCIStatusCode status; + HCIStructCommand<hci_cp_le_read_peer_resolv_addr> req0(HCIOpcode::LE_READ_PEER_RESOLV_ADDR); + hci_cp_le_read_peer_resolv_addr * cp = req0.getWStruct(); + cp->peer_id_addr_type = static_cast<uint8_t>(peerIdentityAddressAndType.type); + cp->peer_id_addr = jau::cpu_to_le(peerIdentityAddressAndType.address); + const hci_rp_le_read_peer_resolv_addr * ev_res; + std::unique_ptr<HCIEvent> ev = processCommandComplete(req0, &ev_res, &status, true /* quiet */); + if( nullptr == ev || nullptr == ev_res || HCIStatusCode::SUCCESS != status ) { + ERR_PRINT("%s: 0x%x (%s) - %s", to_string(req0.getOpcode()), number(status), to_string(status).c_str(), toString().c_str()); + } else if( nullptr != ev_res && HCIStatusCode::SUCCESS != status ) { + peerResolvableAddress = jau::le_to_cpu(ev_res->peer_resolv_addr); + } + return status; +} + +HCIStatusCode HCIHandler::le_read_local_resolv_addr(const BDAddressAndType& peerIdentityAddressAndType, + jau::EUI48& localResolvableAddress) noexcept { + localResolvableAddress.clear(); + HCIStatusCode status; + HCIStructCommand<hci_cp_le_read_local_resolv_addr> req0(HCIOpcode::LE_READ_LOCAL_RESOLV_ADDR); + hci_cp_le_read_local_resolv_addr * cp = req0.getWStruct(); + cp->peer_id_addr_type = static_cast<uint8_t>(peerIdentityAddressAndType.type); + cp->peer_id_addr = jau::cpu_to_le(peerIdentityAddressAndType.address); + const hci_rp_le_read_local_resolv_addr * ev_res; + std::unique_ptr<HCIEvent> ev = processCommandComplete(req0, &ev_res, &status, true /* quiet */); + if( nullptr == ev || nullptr == ev_res || HCIStatusCode::SUCCESS != status ) { + ERR_PRINT("%s: 0x%x (%s) - %s", to_string(req0.getOpcode()), number(status), to_string(status).c_str(), toString().c_str()); + } else if( nullptr != ev_res && HCIStatusCode::SUCCESS != status ) { + localResolvableAddress = jau::le_to_cpu(ev_res->local_resolv_addr); + } + return status; +} + +HCIStatusCode HCIHandler::le_set_addr_resolv_enable(const bool enable) noexcept { + HCIStatusCode status; + HCIStructCommand<hci_cp_le_set_addr_resolv_enable> req0(HCIOpcode::LE_SET_ADDR_RESOLV_ENABLE); + hci_cp_le_set_addr_resolv_enable * cp = req0.getWStruct(); + cp->enable = enable ? 0x01 : 0x00; + const hci_rp_status * ev_res; + std::unique_ptr<HCIEvent> ev = processCommandComplete(req0, &ev_res, &status, true /* quiet */); + if( nullptr == ev || nullptr == ev_res || HCIStatusCode::SUCCESS != status ) { + ERR_PRINT("%s: 0x%x (%s) - %s", to_string(req0.getOpcode()), number(status), to_string(status).c_str(), toString().c_str()); + } + return status; +} + HCIStatusCode HCIHandler::le_read_phy(const uint16_t conn_handle, const BDAddressAndType& peerAddressAndType, LE_PHYs& resTx, LE_PHYs& resRx) noexcept { if( !is_set(le_ll_feats, LE_Features::LE_2M_PHY) ) { diff --git a/src/direct_bt/HCITypes.cpp b/src/direct_bt/HCITypes.cpp index 63c69c7f..d4a78381 100644 --- a/src/direct_bt/HCITypes.cpp +++ b/src/direct_bt/HCITypes.cpp @@ -199,6 +199,13 @@ std::string to_string(const HCIOGF op) noexcept { X(LE_ENABLE_ENC) \ X(LE_LTK_REPLY_ACK) \ X(LE_LTK_REPLY_REJ) \ + X(LE_ADD_TO_RESOLV_LIST) \ + X(LE_DEL_FROM_RESOLV_LIST) \ + X(LE_CLEAR_RESOLV_LIST) \ + X(LE_READ_RESOLV_LIST_SIZE) \ + X(LE_READ_PEER_RESOLV_ADDR) \ + X(LE_READ_LOCAL_RESOLV_ADDR) \ + X(LE_SET_ADDR_RESOLV_ENABLE) \ X(LE_READ_PHY) \ X(LE_SET_DEFAULT_PHY) \ X(LE_SET_PHY) \ |