diff --git a/bt-embedded/drivers/generic.c b/bt-embedded/drivers/generic.c index 09536bd..1852e9d 100644 --- a/bt-embedded/drivers/generic.c +++ b/bt-embedded/drivers/generic.c @@ -32,6 +32,15 @@ static void read_local_features_cb(BteHci *hci, initialization_done(bte_hci_get_client(hci)); } +static void on_bd_addr_done(BteHci *hci, const BteHciReadBdAddrReply *reply, + void *userdata) +{ + STOP_ON_FAILURE(hci, reply); + + /* hci_dev itself saves the result */ + bte_hci_read_local_features(hci, read_local_features_cb, userdata); +} + static void on_buffer_size_done(BteHci *hci, const BteHciReadBufferSizeReply *reply, void *userdata) @@ -47,7 +56,7 @@ static void on_buffer_size_done(BteHci *hci, dev->sco_max_packets = reply->sco_max_packets; dev->info_flags |= BTE_HCI_INFO_GOT_BUFFER_SIZE; - bte_hci_read_local_features(hci, read_local_features_cb, userdata); + bte_hci_read_bd_addr(hci, on_bd_addr_done, userdata); } static void on_reset_done(BteHci *hci, const BteHciReply *reply, diff --git a/bt-embedded/drivers/wii.c b/bt-embedded/drivers/wii.c index 2fd5be4..73b2dda 100644 --- a/bt-embedded/drivers/wii.c +++ b/bt-embedded/drivers/wii.c @@ -131,12 +131,10 @@ static void on_read_local_features(BteHci *hci, static void on_bd_addr_done(BteHci *hci, const BteHciReadBdAddrReply *reply, void *userdata) { - BteHciDev *dev = userdata; - BTE_DEBUG(""); STOP_ON_FAILURE(hci, reply); - dev->address = reply->address; + /* hci_dev itself saves the result */ bte_hci_read_local_features(hci, on_read_local_features, userdata); } diff --git a/bt-embedded/hci.c b/bt-embedded/hci.c index 9fa1ee1..f82e1bb 100644 --- a/bt-embedded/hci.c +++ b/bt-embedded/hci.c @@ -121,6 +121,16 @@ BteHciFeatures bte_hci_get_supported_features(BteHci *) return _bte_hci_dev.supported_features; } +bool bte_hci_get_bd_address(BteHci *hci, BteBdAddr *address) +{ + if (_bte_hci_dev.info_flags & BTE_HCI_INFO_GOT_BD_ADDR) { + *address = _bte_hci_dev.address; + return true; + } else { + return false; + } +} + uint16_t bte_hci_get_acl_mtu(BteHci *hci) { return _bte_hci_dev.acl_mtu; @@ -1840,6 +1850,11 @@ static void read_bd_addr_cb( BteHciReadBdAddrReply reply; reply.status = buffer->data[HCI_CMD_REPLY_POS_STATUS]; memcpy(&reply.address, data, sizeof(reply.address)); + BteHciDev *dev = &_bte_hci_dev; + if (!(dev->info_flags & BTE_HCI_INFO_GOT_BD_ADDR)) { + dev->address = reply.address; + dev->info_flags |= BTE_HCI_INFO_GOT_BD_ADDR; + } BteHciReadBdAddrCb callback = client_cb; callback(hci, &reply, userdata); } diff --git a/bt-embedded/hci.h b/bt-embedded/hci.h index 9c0afad..f4e4cd9 100644 --- a/bt-embedded/hci.h +++ b/bt-embedded/hci.h @@ -88,6 +88,19 @@ typedef uint64_t BteHciFeatures; */ BteHciFeatures bte_hci_get_supported_features(BteHci *hci); +/** + * @brief Get the local host's BD address + * + * Return the host's bluetooth device address. If this function is called + * before the device has been initialized, it will return false and no address + * will be copied into \a address. + * + * @param hci The HCI handle + * @param address Pointer to where the address will be stored + * @return \c true if the address was read, \c false otherwise + */ +bool bte_hci_get_bd_address(BteHci *hci, BteBdAddr *address); + /** * @brief Get the ACL MTU * diff --git a/bt-embedded/internals.h b/bt-embedded/internals.h index fdce429..fb25f96 100644 --- a/bt-embedded/internals.h +++ b/bt-embedded/internals.h @@ -50,6 +50,7 @@ typedef enum { typedef enum { BTE_HCI_INFO_GOT_FEATURES = 1 << 0, BTE_HCI_INFO_GOT_BUFFER_SIZE = 1 << 1, + BTE_HCI_INFO_GOT_BD_ADDR = 1 << 2, } BteHciInfo; typedef struct bte_acl_t BteAcl; diff --git a/example/main.c b/example/main.c index 18a55a7..62de900 100644 --- a/example/main.c +++ b/example/main.c @@ -117,17 +117,6 @@ static void inquiry_cb(BteHci *hci, const BteHciInquiryReply *reply, void *) query_next_name(hci); } -static void read_bd_addr_cb(BteHci *hci, const BteHciReadBdAddrReply *reply, - void *userdata) -{ - static int count = 0; - const uint8_t *b = reply->address.bytes; - printf("%s: (%d), %02x:%02x:%02x:%02x:%02x:%02x\n", __func__, count, b[0], - b[1], b[2], b[3], b[4], b[5]); - count++; - // bte_hci_read_bd_addr(hci, read_bd_addr_cb); -} - static void read_stored_link_key_cb(BteHci *hci, const BteHciReadStoredLinkKeyReply *reply, void *userdata) @@ -148,10 +137,14 @@ static void initialized_cb(BteHci *hci, bool success, void *) printf("ACL MTU=%d, max packets=%d\n", bte_hci_get_acl_mtu(hci), bte_hci_get_acl_max_packets(hci)); - // bte_hci_read_bd_addr(hci, read_bd_addr_cb, NULL); bte_hci_periodic_inquiry(hci, 4, 5, BTE_LAP_GIAC, 3, 0, inquiry_status_cb, inquiry_cb, NULL); //bte_hci_read_stored_link_key(hci, NULL, read_stored_link_key_cb, NULL); + BteBdAddr address; + bte_hci_get_bd_address(hci, &address); + const uint8_t *b = address.bytes; + printf("%s: %02x:%02x:%02x:%02x:%02x:%02x\n", __func__, b[0], + b[1], b[2], b[3], b[4], b[5]); } int main(int argc, char **argv) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 43404b0..1661bdf 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -31,6 +31,7 @@ add_executable(test_commands test_cpp_api.cpp test_data_matcher.cpp test_events.cpp + test_getters.cpp test_hci_dev.cpp test_l2cap_config.cpp test_l2cap_connect.cpp diff --git a/tests/bte_cpp.h b/tests/bte_cpp.h index a57e715..4450af7 100644 --- a/tests/bte_cpp.h +++ b/tests/bte_cpp.h @@ -280,6 +280,10 @@ class Client { bte_hci_on_initialized(m_hci, &Hci::Callbacks::initialized, this); } + bool getBdAddr(BteBdAddr *address) const { + return bte_hci_get_bd_address(m_hci, address); + } + using DoneCb = std::function; void nop(const DoneCb &cb) { bte_hci_nop(m_hci, wrap(cb), this); diff --git a/tests/test_getters.cpp b/tests/test_getters.cpp new file mode 100644 index 0000000..c6f8093 --- /dev/null +++ b/tests/test_getters.cpp @@ -0,0 +1,36 @@ +#include "helpers.h" +#include "mock_backend.h" +#include "type_utils.h" + +#include "bt-embedded/client.h" +#include "bt-embedded/bte.h" +#include "bt-embedded/hci.h" +#include "bt-embedded/internals.h" +#include +#include + +TEST(Getters, BdAddress) { + MockBackend backend; + Bte::Client client; + auto &hci = client.hci(); + + BteBdAddr address; + bool ok = hci.getBdAddr(&address); + ASSERT_FALSE(ok); + + /* Read the BD address manually */ + hci.readBdAddr([&](const BteHciReadBdAddrReply &) {}); + BteBdAddr expectedAddress = {1, 2, 3, 4, 5, 6}; + Buffer reply = Buffer{ + HCI_COMMAND_COMPLETE, 4 + 6, + 1, // packets + 0x9, 0x10, + 0, // status + } + expectedAddress; + backend.sendEvent(reply); + bte_handle_events(); + + ok = hci.getBdAddr(&address); + ASSERT_TRUE(ok); + ASSERT_EQ(address, expectedAddress); +}