aboutsummaryrefslogtreecommitdiffstats
path: root/src/direct_bt/HCIHandler.cpp
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2023-10-23 08:19:24 +0200
committerSven Gothel <[email protected]>2023-10-23 08:19:24 +0200
commitd17582e5dc9e380a12ac54ea6ba154f46c468a21 (patch)
tree156535a769c492dea832520dc0694a156e990b7c /src/direct_bt/HCIHandler.cpp
parent5363ea9c9c540d3e432a2813f1356b6249e9bf47 (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/HCIHandler.cpp')
-rw-r--r--src/direct_bt/HCIHandler.cpp106
1 files changed, 106 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) ) {