summaryrefslogtreecommitdiff
path: root/ports/nrf
diff options
context:
space:
mode:
authorScott Shawcroft <scott@tannewt.org>2020-05-20 10:48:27 -0700
committerScott Shawcroft <scott@tannewt.org>2020-05-20 10:48:27 -0700
commitba724fffb4e67dc37159c1371352e42e0bab7b4a (patch)
tree502847224bc9ef6e292e3d5529e8fda30918a935 /ports/nrf
parentfd0420d43209a533f4896adae36952d9a11dc49c (diff)
parent916ca9f8a635d20c299326a955d4ca51dae055e1 (diff)
Merge remote-tracking branch 'adafruit/master' into esp32s2_digitalio
Diffstat (limited to 'ports/nrf')
-rw-r--r--ports/nrf/bluetooth/ble_drv.h1
-rw-r--r--ports/nrf/common-hal/_bleio/Adapter.c82
-rw-r--r--ports/nrf/common-hal/busio/UART.c3
3 files changed, 79 insertions, 7 deletions
diff --git a/ports/nrf/bluetooth/ble_drv.h b/ports/nrf/bluetooth/ble_drv.h
index ece4b2436..d69f83e6e 100644
--- a/ports/nrf/bluetooth/ble_drv.h
+++ b/ports/nrf/bluetooth/ble_drv.h
@@ -41,6 +41,7 @@
#define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION))
#define SEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000000) / (RESOLUTION))
+#define UNITS_TO_SEC(TIME, RESOLUTION) (((TIME) * (RESOLUTION)) / 1000000)
// 0.625 msecs (625 usecs)
#define ADV_INTERVAL_UNIT_FLOAT_SECS (0.000625)
// Microseconds is the base unit. The macros above know that.
diff --git a/ports/nrf/common-hal/_bleio/Adapter.c b/ports/nrf/common-hal/_bleio/Adapter.c
index 36c79e88e..0b23bb7bf 100644
--- a/ports/nrf/common-hal/_bleio/Adapter.c
+++ b/ports/nrf/common-hal/_bleio/Adapter.c
@@ -26,6 +26,7 @@
* THE SOFTWARE.
*/
+#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
@@ -594,7 +595,25 @@ 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) {
+STATIC bool advertising_on_ble_evt(ble_evt_t *ble_evt, void *self_in) {
+ bleio_adapter_obj_t *self = (bleio_adapter_obj_t*)self_in;
+
+ switch (ble_evt->header.evt_id) {
+ case BLE_GAP_EVT_ADV_SET_TERMINATED:
+ common_hal_bleio_adapter_stop_advertising(self);
+ ble_drv_remove_event_handler(advertising_on_ble_evt, self_in);
+ break;
+
+ default:
+ // For debugging.
+ // mp_printf(&mp_plat_print, "Unhandled advertising event: 0x%04x\n", ble_evt->header.evt_id);
+ return false;
+ break;
+ }
+ return true;
+}
+
+uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, bool anonymous, uint32_t timeout, 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 +624,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,11 +645,35 @@ 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,
+ // Rotate the keys one second after we're scheduled to stop
+ // advertising. This prevents a potential race condition where we
+ // fire off a beacon with the same advertising data but a new MAC
+ // address just as we tear down the connection.
+ .private_addr_cycle_s = timeout + 1,
+ .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,
- .duration = BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED,
+ .duration = SEC_TO_UNITS(timeout, UNIT_10_MS),
.filter_policy = BLE_GAP_ADV_FP_ANY,
.primary_phy = BLE_GAP_PHY_1MBPS,
};
@@ -647,6 +690,8 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
return err_code;
}
+ ble_drv_add_event_handler(advertising_on_ble_evt, self);
+
vm_used_ble = true;
err_code = sd_ble_gap_adv_start(adv_handle, BLE_CONN_CFG_TAG_CUSTOM);
if (err_code != NRF_SUCCESS) {
@@ -657,7 +702,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, uint32_t timeout, 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."));
}
@@ -669,6 +714,27 @@ void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool
if (advertising_data_bufinfo->len > 31 && scan_response_data_bufinfo->len > 0) {
mp_raise_bleio_BluetoothError(translate("Extended advertisements with scan response not supported."));
}
+
+ // Anonymous mode requires a timeout so that we don't continue to broadcast
+ // the same data while cycling the MAC address -- otherwise, what's the
+ // point of randomizing the MAC address?
+ if (!timeout) {
+ if (anonymous) {
+ // The Nordic macro is in units of 10ms. Convert to seconds.
+ uint32_t adv_timeout_max_secs = UNITS_TO_SEC(BLE_GAP_ADV_TIMEOUT_LIMITED_MAX, UNIT_10_MS);
+ uint32_t rotate_timeout_max_secs = BLE_GAP_DEFAULT_PRIVATE_ADDR_CYCLE_INTERVAL_S;
+ timeout = MIN(adv_timeout_max_secs, rotate_timeout_max_secs);
+ }
+ else {
+ timeout = BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED;
+ }
+ } else {
+ if (SEC_TO_UNITS(timeout, UNIT_10_MS) > BLE_GAP_ADV_TIMEOUT_LIMITED_MAX) {
+ mp_raise_bleio_BluetoothError(translate("Timeout is too long: Maximum timeout length is %d seconds"),
+ UNITS_TO_SEC(BLE_GAP_ADV_TIMEOUT_LIMITED_MAX, UNIT_10_MS));
+ }
+ }
+
// The advertising data buffers must not move, because the SoftDevice depends on them.
// So make them long-lived and reuse them onwards.
if (self->advertising_data == NULL) {
@@ -681,7 +747,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, timeout, interval,
self->advertising_data,
advertising_data_bufinfo->len,
self->scan_response_data,
@@ -701,6 +767,10 @@ void common_hal_bleio_adapter_stop_advertising(bleio_adapter_obj_t *self) {
}
}
+bool common_hal_bleio_adapter_get_advertising(bleio_adapter_obj_t *self) {
+ return self->current_advertising_data != NULL;
+}
+
bool common_hal_bleio_adapter_get_connected(bleio_adapter_obj_t *self) {
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
bleio_connection_internal_t *connection = &bleio_connections[i];
diff --git a/ports/nrf/common-hal/busio/UART.c b/ports/nrf/common-hal/busio/UART.c
index dbf40ea51..89f3c9f32 100644
--- a/ports/nrf/common-hal/busio/UART.c
+++ b/ports/nrf/common-hal/busio/UART.c
@@ -134,7 +134,8 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
const mcu_pin_obj_t * rts, const mcu_pin_obj_t * cts,
const mcu_pin_obj_t * rs485_dir, bool rs485_invert,
uint32_t baudrate, uint8_t bits, uart_parity_t parity, uint8_t stop,
- mp_float_t timeout, uint16_t receiver_buffer_size) {
+ mp_float_t timeout, uint16_t receiver_buffer_size, byte* receiver_buffer,
+ bool sigint_enabled) {
if ((rts != NULL) || (cts != NULL) || (rs485_dir != NULL) || (rs485_invert)) {
mp_raise_ValueError(translate("RTS/CTS/RS485 Not yet supported on this device"));