_bleio: support anonymous advertising

Add a new parameter to the `start_advertising()` function to enable
anonymous advertising.  This forces a call to `sd_ble_gap_privacy_set()`
with `privacy_mode` set to `BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY` and
`private_addr_type` set to
`BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE`.

With this, addresses will cycle at a predefined rate (currently once
every 15 minutes).

Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
Sean Cross 2020-05-17 22:06:21 +08:00
parent 2c2b53303d
commit cfe65742a3
4 changed files with 33 additions and 9 deletions

View File

@ -594,7 +594,7 @@ STATIC void check_data_fit(size_t data_len, bool connectable) {
}
}
uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, float interval, uint8_t *advertising_data, uint16_t advertising_data_len, uint8_t *scan_response_data, uint16_t scan_response_data_len) {
uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, bool anonymous, float interval, uint8_t *advertising_data, uint16_t advertising_data_len, uint8_t *scan_response_data, uint16_t scan_response_data_len) {
if (self->current_advertising_data != NULL && self->current_advertising_data == self->advertising_data) {
return NRF_ERROR_BUSY;
}
@ -605,7 +605,7 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
common_hal_bleio_adapter_stop_advertising(self);
}
uint32_t err_code;
bool extended = advertising_data_len > BLE_GAP_ADV_SET_DATA_SIZE_MAX ||
scan_response_data_len > BLE_GAP_ADV_SET_DATA_SIZE_MAX;
@ -626,7 +626,27 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
adv_type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED;
}
uint32_t err_code;
if (anonymous) {
ble_gap_privacy_params_t privacy = {
.privacy_mode = BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY,
.private_addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE,
.private_addr_cycle_s = 0,
.p_device_irk = NULL,
};
err_code = sd_ble_gap_privacy_set(&privacy);
} else {
ble_gap_privacy_params_t privacy = {
.privacy_mode = BLE_GAP_PRIVACY_MODE_OFF,
.private_addr_type = BLE_GAP_ADDR_TYPE_PUBLIC,
.private_addr_cycle_s = 0,
.p_device_irk = NULL,
};
err_code = sd_ble_gap_privacy_set(&privacy);
}
if (err_code != NRF_SUCCESS) {
return err_code;
}
ble_gap_adv_params_t adv_params = {
.interval = SEC_TO_UNITS(interval, UNIT_0_625_MS),
.properties.type = adv_type,
@ -657,7 +677,7 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
}
void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, mp_float_t interval, mp_buffer_info_t *advertising_data_bufinfo, mp_buffer_info_t *scan_response_data_bufinfo) {
void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, bool anonymous, mp_float_t interval, mp_buffer_info_t *advertising_data_bufinfo, mp_buffer_info_t *scan_response_data_bufinfo) {
if (self->current_advertising_data != NULL && self->current_advertising_data == self->advertising_data) {
mp_raise_bleio_BluetoothError(translate("Already advertising."));
}
@ -681,7 +701,7 @@ void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool
memcpy(self->advertising_data, advertising_data_bufinfo->buf, advertising_data_bufinfo->len);
memcpy(self->scan_response_data, scan_response_data_bufinfo->buf, scan_response_data_bufinfo->len);
check_nrf_error(_common_hal_bleio_adapter_start_advertising(self, connectable, interval,
check_nrf_error(_common_hal_bleio_adapter_start_advertising(self, connectable, anonymous, interval,
self->advertising_data,
advertising_data_bufinfo->len,
self->scan_response_data,

View File

@ -145,17 +145,19 @@ const mp_obj_property_t bleio_adapter_name_obj = {
//| :param buf data: advertising data packet bytes
//| :param buf scan_response: scan response data packet bytes. ``None`` if no scan response is needed.
//| :param bool connectable: If `True` then other devices are allowed to connect to this peripheral.
//| :param bool anonymous: If `True` then this device's MAC address is randomized regularly.
//| :param float interval: advertising interval, in seconds"""
//| ...
//|
STATIC mp_obj_t bleio_adapter_start_advertising(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
enum { ARG_data, ARG_scan_response, ARG_connectable, ARG_interval };
enum { ARG_data, ARG_scan_response, ARG_connectable, ARG_anonymous, ARG_interval };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_scan_response, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_connectable, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
{ MP_QSTR_anonymous, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
{ MP_QSTR_interval, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
};
@ -182,11 +184,12 @@ STATIC mp_obj_t bleio_adapter_start_advertising(mp_uint_t n_args, const mp_obj_t
}
bool connectable = args[ARG_connectable].u_bool;
bool anonymous = args[ARG_anonymous].u_bool;
if (data_bufinfo.len > 31 && connectable && scan_response_bufinfo.len > 0) {
mp_raise_bleio_BluetoothError(translate("Cannot have scan responses for extended, connectable advertisements."));
}
common_hal_bleio_adapter_start_advertising(self, connectable, interval,
common_hal_bleio_adapter_start_advertising(self, connectable, anonymous, interval,
&data_bufinfo, &scan_response_bufinfo);
return mp_const_none;

View File

@ -45,9 +45,9 @@ extern bleio_address_obj_t *common_hal_bleio_adapter_get_address(bleio_adapter_o
extern mp_obj_str_t* common_hal_bleio_adapter_get_name(bleio_adapter_obj_t *self);
extern void common_hal_bleio_adapter_set_name(bleio_adapter_obj_t *self, const char* name);
extern uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, float interval, uint8_t *advertising_data, uint16_t advertising_data_len, uint8_t *scan_response_data, uint16_t scan_response_data_len);
extern uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, bool anonymous, float interval, uint8_t *advertising_data, uint16_t advertising_data_len, uint8_t *scan_response_data, uint16_t scan_response_data_len);
extern void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, mp_float_t interval, mp_buffer_info_t *advertising_data_bufinfo, mp_buffer_info_t *scan_response_data_bufinfo);
extern void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, bool anonymous, mp_float_t interval, mp_buffer_info_t *advertising_data_bufinfo, mp_buffer_info_t *scan_response_data_bufinfo);
extern void common_hal_bleio_adapter_stop_advertising(bleio_adapter_obj_t *self);
extern mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t* prefixes, size_t prefix_length, bool extended, mp_int_t buffer_size, mp_float_t timeout, mp_float_t interval, mp_float_t window, mp_int_t minimum_rssi, bool active);

View File

@ -74,6 +74,7 @@ void supervisor_bluetooth_start_advertising(void) {
// TODO: switch to Adafruit short UUID for the advertisement and add manufacturing data to distinguish ourselves from arduino.
_common_hal_bleio_adapter_start_advertising(&common_hal_bleio_adapter_obj,
true,
false,
1.0,
circuitpython_advertising_data,
sizeof(circuitpython_advertising_data),