summaryrefslogtreecommitdiff
path: root/extmod/nimble/modbluetooth_nimble.c
diff options
context:
space:
mode:
authorJim Mussared <jim.mussared@gmail.com>2020-08-14 15:47:21 +1000
committerDamien George <damien@micropython.org>2020-09-08 12:53:24 +1000
commitc4af714d58213bb23b81f3736f785d897e60ac77 (patch)
tree62fae24743bf5e80dac4d81bb256b6399bc44cac /extmod/nimble/modbluetooth_nimble.c
parent1b1b22905e1aa7676c51078f75b1bd73d8383a4a (diff)
extmod/modbluetooth: Implement configuration of address modes.
Changes `BLE.config('mac')` to return a tuple (addr_mode, addr). Adds `BLE.config(addr_mode=...)` to set the addressing mode.
Diffstat (limited to 'extmod/nimble/modbluetooth_nimble.c')
-rw-r--r--extmod/nimble/modbluetooth_nimble.c127
1 files changed, 83 insertions, 44 deletions
diff --git a/extmod/nimble/modbluetooth_nimble.c b/extmod/nimble/modbluetooth_nimble.c
index 61ba3a3ab..1c782943a 100644
--- a/extmod/nimble/modbluetooth_nimble.c
+++ b/extmod/nimble/modbluetooth_nimble.c
@@ -50,6 +50,8 @@
#define ERRNO_BLUETOOTH_NOT_ACTIVE MP_ENODEV
+STATIC uint8_t nimble_address_mode = BLE_OWN_ADDR_RANDOM;
+
// Any BLE_HS_xxx code not in this table will default to MP_EIO.
STATIC int8_t ble_hs_err_to_errno_table[] = {
[BLE_HS_EAGAIN] = MP_EAGAIN,
@@ -148,9 +150,26 @@ STATIC void reset_cb(int reason) {
(void)reason;
}
-STATIC void sync_cb(void) {
+STATIC bool has_public_address(void) {
+ return ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, NULL, NULL) == 0;
+}
+
+STATIC void set_random_address(bool nrpa) {
int rc;
+ (void)rc;
+ DEBUG_printf("sync_cb: Generating random static address\n");
ble_addr_t addr;
+ rc = ble_hs_id_gen_rnd(nrpa ? 1 : 0, &addr);
+ assert(rc == 0);
+ rc = ble_hs_id_set_rnd(addr.val);
+ assert(rc == 0);
+ rc = ble_hs_util_ensure_addr(1);
+ assert(rc == 0);
+}
+
+STATIC void sync_cb(void) {
+ int rc;
+ (void)rc;
DEBUG_printf("sync_cb: state=%d\n", mp_bluetooth_nimble_ble_state);
@@ -158,25 +177,11 @@ STATIC void sync_cb(void) {
return;
}
- rc = ble_hs_util_ensure_addr(0); // prefer public address
- if (rc != 0) {
- // https://mynewt.apache.org/latest/tutorials/ble/eddystone.html#configure-the-nimble-stack-with-an-address
- #if MICROPY_PY_BLUETOOTH_RANDOM_ADDR
- rc = ble_hs_id_gen_rnd(1, &addr);
- assert(rc == 0);
- rc = ble_hs_id_set_rnd(addr.val);
- assert(rc == 0);
- #else
- uint8_t addr_be[6];
- mp_hal_get_mac(MP_HAL_MAC_BDADDR, addr_be);
- reverse_addr_byte_order(addr.val, addr_be);
- // ble_hs_id_set_pub(addr.val);
- rc = ble_hs_id_set_rnd(addr.val);
- assert(rc == 0);
- #endif
-
- rc = ble_hs_util_ensure_addr(0); // prefer public address
- assert(rc == 0);
+ if (has_public_address()) {
+ nimble_address_mode = BLE_OWN_ADDR_PUBLIC;
+ } else {
+ nimble_address_mode = BLE_OWN_ADDR_RANDOM;
+ set_random_address(false);
}
if (MP_BLUETOOTH_DEFAULT_ATTR_LEN > 20) {
@@ -412,19 +417,65 @@ bool mp_bluetooth_is_active(void) {
return mp_bluetooth_nimble_ble_state == MP_BLUETOOTH_NIMBLE_BLE_STATE_ACTIVE;
}
-void mp_bluetooth_get_device_addr(uint8_t *addr) {
- #if MICROPY_PY_BLUETOOTH_RANDOM_ADDR
+void mp_bluetooth_get_current_address(uint8_t *addr_type, uint8_t *addr) {
+ if (!mp_bluetooth_is_active()) {
+ mp_raise_OSError(ERRNO_BLUETOOTH_NOT_ACTIVE);
+ }
+
uint8_t addr_le[6];
- int rc = ble_hs_id_copy_addr(BLE_ADDR_RANDOM, addr_le, NULL);
+
+ switch (nimble_address_mode) {
+ case BLE_OWN_ADDR_PUBLIC:
+ *addr_type = BLE_ADDR_PUBLIC;
+ break;
+ case BLE_OWN_ADDR_RANDOM:
+ *addr_type = BLE_ADDR_RANDOM;
+ break;
+ case BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT:
+ case BLE_OWN_ADDR_RPA_RANDOM_DEFAULT:
+ default:
+ // TODO: If RPA/NRPA in use, get the current value.
+ // Is this even possible in NimBLE?
+ mp_raise_OSError(MP_EINVAL);
+ }
+
+ int rc = ble_hs_id_copy_addr(*addr_type, addr_le, NULL);
if (rc != 0) {
- // Even with MICROPY_PY_BLUETOOTH_RANDOM_ADDR enabled the public address may
- // be used instead, in which case there is no random address.
- ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, addr_le, NULL);
+ mp_raise_OSError(MP_EINVAL);
}
reverse_addr_byte_order(addr, addr_le);
- #else
- mp_hal_get_mac(MP_HAL_MAC_BDADDR, addr);
- #endif
+}
+
+void mp_bluetooth_set_address_mode(uint8_t addr_mode) {
+ switch (addr_mode) {
+ case MP_BLUETOOTH_ADDRESS_MODE_PUBLIC:
+ if (!has_public_address()) {
+ // No public address available.
+ mp_raise_OSError(MP_EINVAL);
+ }
+ nimble_address_mode = BLE_OWN_ADDR_PUBLIC;
+ break;
+ case MP_BLUETOOTH_ADDRESS_MODE_RANDOM:
+ // Generate an static random address.
+ set_random_address(false);
+ nimble_address_mode = BLE_OWN_ADDR_RANDOM;
+ break;
+ case MP_BLUETOOTH_ADDRESS_MODE_RPA:
+ if (has_public_address()) {
+ nimble_address_mode = BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT;
+ } else {
+ // Generate an static random address to use as the identity address.
+ set_random_address(false);
+ nimble_address_mode = BLE_OWN_ADDR_RPA_RANDOM_DEFAULT;
+ }
+ break;
+ case MP_BLUETOOTH_ADDRESS_MODE_NRPA:
+ // Generate an NRPA.
+ set_random_address(true);
+ // In NimBLE, NRPA is treated like a static random address that happens to be an NRPA.
+ nimble_address_mode = BLE_OWN_ADDR_RANDOM;
+ break;
+ }
}
size_t mp_bluetooth_gap_get_device_name(const uint8_t **buf) {
@@ -473,19 +524,7 @@ int mp_bluetooth_gap_advertise_start(bool connectable, int32_t interval_us, cons
.channel_map = 7, // all 3 channels.
};
- ret = ble_gap_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, BLE_HS_FOREVER, &adv_params, gap_event_cb, NULL);
- if (ret == 0) {
- return 0;
- }
- ret = ble_gap_adv_start(BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT, NULL, BLE_HS_FOREVER, &adv_params, gap_event_cb, NULL);
- if (ret == 0) {
- return 0;
- }
- ret = ble_gap_adv_start(BLE_OWN_ADDR_RPA_RANDOM_DEFAULT, NULL, BLE_HS_FOREVER, &adv_params, gap_event_cb, NULL);
- if (ret == 0) {
- return 0;
- }
- ret = ble_gap_adv_start(BLE_OWN_ADDR_RANDOM, NULL, BLE_HS_FOREVER, &adv_params, gap_event_cb, NULL);
+ ret = ble_gap_adv_start(nimble_address_mode, NULL, BLE_HS_FOREVER, &adv_params, gap_event_cb, NULL);
if (ret == 0) {
return 0;
}
@@ -756,7 +795,7 @@ int mp_bluetooth_gap_scan_start(int32_t duration_ms, int32_t interval_us, int32_
.passive = active_scan ? 0 : 1,
.filter_duplicates = 0,
};
- int err = ble_gap_disc(BLE_OWN_ADDR_PUBLIC, duration_ms, &discover_params, gap_scan_cb, NULL);
+ int err = ble_gap_disc(nimble_address_mode, duration_ms, &discover_params, gap_scan_cb, NULL);
return ble_hs_err_to_errno(err);
}
@@ -847,7 +886,7 @@ int mp_bluetooth_gap_peripheral_connect(uint8_t addr_type, const uint8_t *addr,
};
ble_addr_t addr_nimble = create_nimble_addr(addr_type, addr);
- int err = ble_gap_connect(BLE_OWN_ADDR_PUBLIC, &addr_nimble, duration_ms, &params, &peripheral_gap_event_cb, NULL);
+ int err = ble_gap_connect(nimble_address_mode, &addr_nimble, duration_ms, &params, &peripheral_gap_event_cb, NULL);
return ble_hs_err_to_errno(err);
}