wip; compiles; much commented out

This commit is contained in:
Dan Halbert 2020-06-26 17:23:20 -04:00
parent 57bac9a1fc
commit 1bc2e979eb
19 changed files with 1340 additions and 1675 deletions

View File

@ -31,9 +31,8 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "bonding.h"
#include "py/gc.h" #include "py/gc.h"
#include "py/mphal.h"
#include "py/objstr.h" #include "py/objstr.h"
#include "py/runtime.h" #include "py/runtime.h"
#include "supervisor/shared/safe_mode.h" #include "supervisor/shared/safe_mode.h"
@ -74,111 +73,111 @@
bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT]; bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT];
STATIC bool adapter_on_ble_evt(ble_evt_t *ble_evt, void *self_in) { // STATIC bool adapter_on_ble_evt(ble_evt_t *ble_evt, void *self_in) {
// bleio_adapter_obj_t *self = (bleio_adapter_obj_t*)self_in; // bleio_adapter_obj_t *self = (bleio_adapter_obj_t*)self_in;
// // For debugging. // // For debugging.
// // mp_printf(&mp_plat_print, "Adapter event: 0x%04x\n", ble_evt->header.evt_id); // // mp_printf(&mp_plat_print, "Adapter event: 0x%04x\n", ble_evt->header.evt_id);
// switch (ble_evt->header.evt_id) { // switch (ble_evt->header.evt_id) {
// case BLE_GAP_EVT_CONNECTED: { // case BLE_GAP_EVT_CONNECTED: {
// // Find an empty connection. One must always be available because the SD has the same // // Find an empty connection. One must always be available because the SD has the same
// // total connection limit. // // total connection limit.
// bleio_connection_internal_t *connection; // bleio_connection_internal_t *connection;
// for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { // for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
// connection = &bleio_connections[i]; // connection = &bleio_connections[i];
// if (connection->conn_handle == BLE_CONN_HANDLE_INVALID) { // if (connection->conn_handle == BLE_CONN_HANDLE_INVALID) {
// break; // break;
// } // }
// } // }
// // Central has connected. // // Central has connected.
// ble_gap_evt_connected_t* connected = &ble_evt->evt.gap_evt.params.connected; // ble_gap_evt_connected_t* connected = &ble_evt->evt.gap_evt.params.connected;
// connection->conn_handle = ble_evt->evt.gap_evt.conn_handle; // connection->conn_handle = ble_evt->evt.gap_evt.conn_handle;
// connection->connection_obj = mp_const_none; // connection->connection_obj = mp_const_none;
// connection->pair_status = PAIR_NOT_PAIRED; // connection->pair_status = PAIR_NOT_PAIRED;
// connection->mtu = 0; // connection->mtu = 0;
// ble_drv_add_event_handler_entry(&connection->handler_entry, connection_on_ble_evt, connection); // ble_drv_add_event_handler_entry(&connection->handler_entry, connection_on_ble_evt, connection);
// self->connection_objs = NULL; // self->connection_objs = NULL;
// // Save the current connection parameters. // // Save the current connection parameters.
// memcpy(&connection->conn_params, &connected->conn_params, sizeof(ble_gap_conn_params_t)); // memcpy(&connection->conn_params, &connected->conn_params, sizeof(ble_gap_conn_params_t));
// #if CIRCUITPY_VERBOSE_BLE // #if CIRCUITPY_VERBOSE_BLE
// ble_gap_conn_params_t *cp = &connected->conn_params; // ble_gap_conn_params_t *cp = &connected->conn_params;
// mp_printf(&mp_plat_print, "conn params: min_ci %d max_ci %d s_l %d sup_timeout %d\n", cp->min_conn_interval, cp->max_conn_interval, cp->slave_latency, cp->conn_sup_timeout); // mp_printf(&mp_plat_print, "conn params: min_ci %d max_ci %d s_l %d sup_timeout %d\n", cp->min_conn_interval, cp->max_conn_interval, cp->slave_latency, cp->conn_sup_timeout);
// #endif // #endif
// // See if connection interval set by Central is out of range. // // See if connection interval set by Central is out of range.
// // If so, negotiate our preferred range. // // If so, negotiate our preferred range.
// ble_gap_conn_params_t conn_params; // ble_gap_conn_params_t conn_params;
// sd_ble_gap_ppcp_get(&conn_params); // sd_ble_gap_ppcp_get(&conn_params);
// if (conn_params.min_conn_interval < connected->conn_params.min_conn_interval || // if (conn_params.min_conn_interval < connected->conn_params.min_conn_interval ||
// conn_params.min_conn_interval > connected->conn_params.max_conn_interval) { // conn_params.min_conn_interval > connected->conn_params.max_conn_interval) {
// sd_ble_gap_conn_param_update(ble_evt->evt.gap_evt.conn_handle, &conn_params); // sd_ble_gap_conn_param_update(ble_evt->evt.gap_evt.conn_handle, &conn_params);
// } // }
// self->current_advertising_data = NULL; // self->current_advertising_data = NULL;
// break; // break;
// } // }
// case BLE_GAP_EVT_DISCONNECTED: { // case BLE_GAP_EVT_DISCONNECTED: {
// // Find the connection that was disconnected. // // Find the connection that was disconnected.
// bleio_connection_internal_t *connection; // bleio_connection_internal_t *connection;
// for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { // for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
// connection = &bleio_connections[i]; // connection = &bleio_connections[i];
// if (connection->conn_handle == ble_evt->evt.gap_evt.conn_handle) { // if (connection->conn_handle == ble_evt->evt.gap_evt.conn_handle) {
// break; // break;
// } // }
// } // }
// ble_drv_remove_event_handler(connection_on_ble_evt, connection); // ble_drv_remove_event_handler(connection_on_ble_evt, connection);
// connection->conn_handle = BLE_CONN_HANDLE_INVALID; // connection->conn_handle = BLE_CONN_HANDLE_INVALID;
// connection->pair_status = PAIR_NOT_PAIRED; // connection->pair_status = PAIR_NOT_PAIRED;
// if (connection->connection_obj != mp_const_none) { // if (connection->connection_obj != mp_const_none) {
// bleio_connection_obj_t* obj = connection->connection_obj; // bleio_connection_obj_t* obj = connection->connection_obj;
// obj->connection = NULL; // obj->connection = NULL;
// obj->disconnect_reason = ble_evt->evt.gap_evt.params.disconnected.reason; // obj->disconnect_reason = ble_evt->evt.gap_evt.params.disconnected.reason;
// } // }
// self->connection_objs = NULL; // self->connection_objs = NULL;
// break; // break;
// } // }
// case BLE_GAP_EVT_ADV_SET_TERMINATED: // case BLE_GAP_EVT_ADV_SET_TERMINATED:
// self->current_advertising_data = NULL; // self->current_advertising_data = NULL;
// break; // break;
// default: // default:
// // For debugging. // // For debugging.
// // mp_printf(&mp_plat_print, "Unhandled adapter event: 0x%04x\n", ble_evt->header.evt_id); // // mp_printf(&mp_plat_print, "Unhandled adapter event: 0x%04x\n", ble_evt->header.evt_id);
// return false; // return false;
// break; // break;
// } // }
return true; // return true;
} // }
STATIC void get_address(bleio_adapter_obj_t *self, ble_gap_addr_t *address) { // STATIC void get_address(bleio_adapter_obj_t *self, ble_gap_addr_t *address) {
// check_nrf_error(sd_ble_gap_addr_get(address)); // check_nrf_error(sd_ble_gap_addr_get(address));
} // }
char default_ble_name[] = { 'C', 'I', 'R', 'C', 'U', 'I', 'T', 'P', 'Y', 0, 0, 0, 0 , 0}; char default_ble_name[] = { 'C', 'I', 'R', 'C', 'U', 'I', 'T', 'P', 'Y', 0, 0, 0, 0 , 0};
STATIC void bleio_adapter_reset_name(bleio_adapter_obj_t *self) { // STATIC void bleio_adapter_reset_name(bleio_adapter_obj_t *self) {
uint8_t len = sizeof(default_ble_name) - 1; // // uint8_t len = sizeof(default_ble_name) - 1;
ble_gap_addr_t local_address; // // ble_gap_addr_t local_address;
get_address(self, &local_address); // // get_address(self, &local_address);
default_ble_name[len - 4] = nibble_to_hex_lower[local_address.addr[1] >> 4 & 0xf]; // // default_ble_name[len - 4] = nibble_to_hex_lower[local_address.addr[1] >> 4 & 0xf];
default_ble_name[len - 3] = nibble_to_hex_lower[local_address.addr[1] & 0xf]; // // default_ble_name[len - 3] = nibble_to_hex_lower[local_address.addr[1] & 0xf];
default_ble_name[len - 2] = nibble_to_hex_lower[local_address.addr[0] >> 4 & 0xf]; // // default_ble_name[len - 2] = nibble_to_hex_lower[local_address.addr[0] >> 4 & 0xf];
default_ble_name[len - 1] = nibble_to_hex_lower[local_address.addr[0] & 0xf]; // // default_ble_name[len - 1] = nibble_to_hex_lower[local_address.addr[0] & 0xf];
default_ble_name[len] = '\0'; // for now we add null for compatibility with C ASCIIZ strings // // default_ble_name[len] = '\0'; // for now we add null for compatibility with C ASCIIZ strings
common_hal_bleio_adapter_set_name(self, (char*) default_ble_name); // common_hal_bleio_adapter_set_name(self, (char*) default_ble_name);
} // }
void common_hal_bleio_adapter_construct(bleio_adapter_obj_t *self, mcu_pin_obj_t *tx, mcu_pin_obj_t *rx, mcu_pin_obj_t *rts, mcu_pin_obj_t *cts, uint32_t baudrate, uint32_t buffer_size, mcu_pin_obj_t* spi_cs, mcu_pin_obj_t* gpio0, mcu_pin_obj_t *reset, bool reset_high) { void common_hal_bleio_adapter_construct(bleio_adapter_obj_t *self, const mcu_pin_obj_t *tx, const mcu_pin_obj_t *rx, const mcu_pin_obj_t *rts, const mcu_pin_obj_t *cts, uint32_t baudrate, uint32_t buffer_size, const mcu_pin_obj_t* spi_cs, const mcu_pin_obj_t* gpio0, const mcu_pin_obj_t *reset, bool reset_high) {
self->tx = tx; self->tx = tx;
self->rx = rx; self->rx = rx;
self->rts = rts; self->rts = rts;
@ -206,9 +205,9 @@ void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enable
// common_hal UART takes rts and cts, but is currently not implemented for many ports. // common_hal UART takes rts and cts, but is currently not implemented for many ports.
// In addition, rts and cts may be pins that are not part of the serial peripheral // In addition, rts and cts may be pins that are not part of the serial peripheral
// used for tx and rx, so use GPIO for them. // used for tx and rx, so use GPIO for them.
common_hal_busio_uart_construct(&self->hci_uart, tx, rx, NULL, NULL, NULL, false, common_hal_busio_uart_construct(&self->hci_uart, self->tx, self->rx, NULL, NULL, NULL, false,
BLEIO_HCI_BAUDRATE, 8, PARITY_NONE, 1, 0.0f, self->baudrate, 8, PARITY_NONE, 1, 0.0f,
BLEIO_HCI_BUFFER_SIZE, NULL, false); self->buffer_size, NULL, false);
// RTS is output, active high // RTS is output, active high
common_hal_digitalio_digitalinout_construct(&self->rts_digitalio, self->rts); common_hal_digitalio_digitalinout_construct(&self->rts_digitalio, self->rts);
@ -220,9 +219,9 @@ void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enable
// SPI_CS and GPI0 are used to signal entering BLE mode. // SPI_CS and GPI0 are used to signal entering BLE mode.
// SPI_CS should be low, and GPI0 should be high // SPI_CS should be low, and GPI0 should be high
common_hal_digitalio_digitalinout_construct(&self->spi_cs_digitalio, self->spi_cs); common_hal_digitalio_digitalinout_construct(&self->spi_cs_digitalio, self->spi_cs);
common_hal_digitalio_digitalinout_construct(&self->gpio0_digitalio, self->gpi0); common_hal_digitalio_digitalinout_construct(&self->gpio0_digitalio, self->gpio0);
common_hal_digitalio_digitalinout_switch_to_output(&self->spi_cs_digitalio, false, DRIVE_MODE_PUSH_PULL); common_hal_digitalio_digitalinout_switch_to_output(&self->spi_cs_digitalio, false, DRIVE_MODE_PUSH_PULL);
common_hal_digitalio_digitalinout_switch_to_output(&self->gpio0_digitalio, true DRIVE_MODE_PUSH_PULL); common_hal_digitalio_digitalinout_switch_to_output(&self->gpio0_digitalio, true, DRIVE_MODE_PUSH_PULL);
// RESET is output, start in non-reset state. // RESET is output, start in non-reset state.
common_hal_digitalio_digitalinout_construct(&self->reset_digitalio, self->reset); common_hal_digitalio_digitalinout_construct(&self->reset_digitalio, self->reset);
@ -252,7 +251,7 @@ void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enable
common_hal_digitalio_digitalinout_deinit(&self->rts_digitalio); common_hal_digitalio_digitalinout_deinit(&self->rts_digitalio);
common_hal_digitalio_digitalinout_deinit(&self->cts_digitalio); common_hal_digitalio_digitalinout_deinit(&self->cts_digitalio);
common_hal_digitalio_digitalinout_deinit(&self->spi_cs_digitalio); common_hal_digitalio_digitalinout_deinit(&self->spi_cs_digitalio);
common_hal_digitalio_digitalinout_deinit(&self->gpi0_digitalio); common_hal_digitalio_digitalinout_deinit(&self->gpio0_digitalio);
common_hal_digitalio_digitalinout_deinit(&self->reset_digitalio); common_hal_digitalio_digitalinout_deinit(&self->reset_digitalio);
} }
@ -263,13 +262,13 @@ bool common_hal_bleio_adapter_get_enabled(bleio_adapter_obj_t *self) {
bleio_address_obj_t *common_hal_bleio_adapter_get_address(bleio_adapter_obj_t *self) { bleio_address_obj_t *common_hal_bleio_adapter_get_address(bleio_adapter_obj_t *self) {
common_hal_bleio_adapter_set_enabled(self, true); common_hal_bleio_adapter_set_enabled(self, true);
ble_gap_addr_t local_address; // ble_gap_addr_t local_address;
get_address(self, &local_address); // get_address(self, &local_address);
bleio_address_obj_t *address = m_new_obj(bleio_address_obj_t); bleio_address_obj_t *address = m_new_obj(bleio_address_obj_t);
address->base.type = &bleio_address_type; address->base.type = &bleio_address_type;
common_hal_bleio_address_construct(address, local_address.addr, local_address.addr_type); // common_hal_bleio_address_construct(address, local_address.addr, local_address.addr_type);
return address; return address;
} }
@ -460,12 +459,12 @@ mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_addre
// sd_ble_gap_data_length_update(conn_handle, NULL, NULL); // sd_ble_gap_data_length_update(conn_handle, NULL, NULL);
// Make the connection object and return it. // Make the connection object and return it.
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { // for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
bleio_connection_internal_t *connection = &bleio_connections[i]; // bleio_connection_internal_t *connection = &bleio_connections[i];
if (connection->conn_handle == conn_handle) { // if (connection->conn_handle == conn_handle) {
return bleio_connection_new_from_internal(connection); // return bleio_connection_new_from_internal(connection);
} // }
} // }
mp_raise_bleio_BluetoothError(translate("Failed to connect: internal error")); mp_raise_bleio_BluetoothError(translate("Failed to connect: internal error"));
@ -473,13 +472,13 @@ mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_addre
} }
// The nRF SD 6.1.0 can only do one concurrent advertisement so share the advertising handle. // The nRF SD 6.1.0 can only do one concurrent advertisement so share the advertising handle.
uint8_t adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET; //FIX uint8_t adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET;
STATIC void check_data_fit(size_t data_len, bool connectable) { STATIC void check_data_fit(size_t data_len, bool connectable) {
if (data_len > BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_MAX_SUPPORTED || //FIX if (data_len > BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_MAX_SUPPORTED ||
(connectable && data_len > BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_CONNECTABLE_MAX_SUPPORTED)) { // (connectable && data_len > BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_CONNECTABLE_MAX_SUPPORTED)) {
mp_raise_ValueError(translate("Data too large for advertisement packet")); // mp_raise_ValueError(translate("Data too large for advertisement packet"));
} // }
} }
// STATIC bool advertising_on_ble_evt(ble_evt_t *ble_evt, void *self_in) { // STATIC bool advertising_on_ble_evt(ble_evt_t *ble_evt, void *self_in) {
@ -607,30 +606,31 @@ void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool
// the same data while cycling the MAC address -- otherwise, what's the // the same data while cycling the MAC address -- otherwise, what's the
// point of randomizing the MAC address? // point of randomizing the MAC address?
if (!timeout) { if (!timeout) {
if (anonymous) { //FIX if (anonymous) {
// The Nordic macro is in units of 10ms. Convert to seconds. // // 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 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; // uint32_t rotate_timeout_max_secs = BLE_GAP_DEFAULT_PRIVATE_ADDR_CYCLE_INTERVAL_S;
timeout = MIN(adv_timeout_max_secs, rotate_timeout_max_secs); // timeout = MIN(adv_timeout_max_secs, rotate_timeout_max_secs);
} // }
else { // else {
timeout = BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED; // timeout = BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED;
} // }
} else { } else {
if (SEC_TO_UNITS(timeout, UNIT_10_MS) > BLE_GAP_ADV_TIMEOUT_LIMITED_MAX) { //FIX 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"), // 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)); // 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. // The advertising data buffers must not move, because the SoftDevice depends on them.
// So make them long-lived and reuse them onwards. // So make them long-lived and reuse them onwards.
if (self->advertising_data == NULL) { //FIX GET CORRECT SIZE
self->advertising_data = (uint8_t *) gc_alloc(BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_MAX_SUPPORTED * sizeof(uint8_t), false, true); // if (self->advertising_data == NULL) {
} // self->advertising_data = (uint8_t *) gc_alloc(BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_MAX_SUPPORTED * sizeof(uint8_t), false, true);
if (self->scan_response_data == NULL) { // }
self->scan_response_data = (uint8_t *) gc_alloc(BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_MAX_SUPPORTED * sizeof(uint8_t), false, true); // if (self->scan_response_data == NULL) {
} // self->scan_response_data = (uint8_t *) gc_alloc(BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_MAX_SUPPORTED * sizeof(uint8_t), false, true);
// }
memcpy(self->advertising_data, advertising_data_bufinfo->buf, advertising_data_bufinfo->len); 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); memcpy(self->scan_response_data, scan_response_data_bufinfo->buf, scan_response_data_bufinfo->len);
@ -690,7 +690,7 @@ mp_obj_t common_hal_bleio_adapter_get_connections(bleio_adapter_obj_t *self) {
} }
void common_hal_bleio_adapter_erase_bonding(bleio_adapter_obj_t *self) { void common_hal_bleio_adapter_erase_bonding(bleio_adapter_obj_t *self) {
bonding_erase_storage(); //FIX bonding_erase_storage();
} }
void bleio_adapter_gc_collect(bleio_adapter_obj_t* adapter) { void bleio_adapter_gc_collect(bleio_adapter_obj_t* adapter) {

View File

@ -52,15 +52,15 @@ typedef struct {
bleio_scanresults_obj_t* scan_results; bleio_scanresults_obj_t* scan_results;
mp_obj_t name; mp_obj_t name;
mp_obj_tuple_t *connection_objs; mp_obj_tuple_t *connection_objs;
mcu_pin_obj_t* tx; const mcu_pin_obj_t* tx;
mcu_pin_obj_t* rx; const mcu_pin_obj_t* rx;
mcu_pin_obj_t* rts; const mcu_pin_obj_t* rts;
mcu_pin_obj_t* cts; const mcu_pin_obj_t* cts;
uint32_t baudrate; uint32_t baudrate;
uint16_t buffer_size; uint16_t buffer_size;
mcu_pin_obj_t* spi_cs; const mcu_pin_obj_t* spi_cs;
mcu_pin_obj_t* gpio0; const mcu_pin_obj_t* gpio0;
mcu_pin_obj_t* reset; const mcu_pin_obj_t* reset;
bool reset_high; bool reset_high;
busio_uart_obj_t hci_uart; busio_uart_obj_t hci_uart;
digitalio_digitalinout_obj_t rts_digitalio; digitalio_digitalinout_obj_t rts_digitalio;

View File

@ -27,34 +27,34 @@
#include "shared-bindings/_bleio/Attribute.h" #include "shared-bindings/_bleio/Attribute.h"
// Convert a _bleio security mode to a ble_gap_conn_sec_mode_t setting. // Convert a _bleio security mode to a ble_gap_conn_sec_mode_t setting.
void bleio_attribute_gatts_set_security_mode(ble_gap_conn_sec_mode_t *perm, bleio_attribute_security_mode_t security_mode) { // void bleio_attribute_gatts_set_security_mode(ble_gap_conn_sec_mode_t *perm, bleio_attribute_security_mode_t security_mode) {
switch (security_mode) { // switch (security_mode) {
case SECURITY_MODE_NO_ACCESS: // case SECURITY_MODE_NO_ACCESS:
BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(perm); // BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(perm);
break; // break;
case SECURITY_MODE_OPEN: // case SECURITY_MODE_OPEN:
BLE_GAP_CONN_SEC_MODE_SET_OPEN(perm); // BLE_GAP_CONN_SEC_MODE_SET_OPEN(perm);
break; // break;
case SECURITY_MODE_ENC_NO_MITM: // case SECURITY_MODE_ENC_NO_MITM:
BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(perm); // BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(perm);
break; // break;
case SECURITY_MODE_ENC_WITH_MITM: // case SECURITY_MODE_ENC_WITH_MITM:
BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(perm); // BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(perm);
break; // break;
case SECURITY_MODE_LESC_ENC_WITH_MITM: // case SECURITY_MODE_LESC_ENC_WITH_MITM:
BLE_GAP_CONN_SEC_MODE_SET_LESC_ENC_WITH_MITM(perm); // BLE_GAP_CONN_SEC_MODE_SET_LESC_ENC_WITH_MITM(perm);
break; // break;
case SECURITY_MODE_SIGNED_NO_MITM: // case SECURITY_MODE_SIGNED_NO_MITM:
BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(perm); // BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(perm);
break; // break;
case SECURITY_MODE_SIGNED_WITH_MITM: // case SECURITY_MODE_SIGNED_WITH_MITM:
BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(perm); // BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(perm);
break; // break;
} // }
} // }

View File

@ -29,6 +29,13 @@
#include "shared-module/_bleio/Attribute.h" #include "shared-module/_bleio/Attribute.h"
extern void bleio_attribute_gatts_set_security_mode(ble_gap_conn_sec_mode_t *perm, bleio_attribute_security_mode_t security_mode); // typedef struct
// {
// uint8_t sm : 4; /**< Security Mode (1 or 2), 0 for no permissions at all. */
// uint8_t lv : 4; /**< Level (1, 2, 3 or 4), 0 for no permissions at all. */
// } ble_gap_conn_sec_mode_t;
// extern void bleio_attribute_gatts_set_security_mode(ble_gap_conn_sec_mode_t *perm, bleio_attribute_security_mode_t security_mode);
#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_ATTRIBUTE_H #endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_ATTRIBUTE_H

View File

@ -33,70 +33,70 @@
#include "shared-bindings/_bleio/Service.h" #include "shared-bindings/_bleio/Service.h"
#include "common-hal/_bleio/Adapter.h" #include "common-hal/_bleio/Adapter.h"
#include "common-hal/_bleio/bonding.h"
STATIC uint16_t characteristic_get_cccd(uint16_t cccd_handle, uint16_t conn_handle) { // STATIC uint16_t characteristic_get_cccd(uint16_t cccd_handle, uint16_t conn_handle) {
uint16_t cccd; // uint16_t cccd;
ble_gatts_value_t value = { // // ble_gatts_value_t value = {
.p_value = (uint8_t*) &cccd, // // .p_value = (uint8_t*) &cccd,
.len = 2, // // .len = 2,
}; // // };
const uint32_t err_code = sd_ble_gatts_value_get(conn_handle, cccd_handle, &value); // // const uint32_t err_code = sd_ble_gatts_value_get(conn_handle, cccd_handle, &value);
if (err_code == BLE_ERROR_GATTS_SYS_ATTR_MISSING) { // // if (err_code == BLE_ERROR_GATTS_SYS_ATTR_MISSING) {
// CCCD is not set, so say that neither Notify nor Indicate is enabled. // // // CCCD is not set, so say that neither Notify nor Indicate is enabled.
cccd = 0; // // cccd = 0;
} else { // // } else {
check_nrf_error(err_code); // // check_nrf_error(err_code);
} // // }
return cccd; // return cccd;
} // }
STATIC void characteristic_gatts_notify_indicate(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, uint16_t hvx_type) { // STATIC void characteristic_gatts_notify_indicate(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, uint16_t hvx_type) {
uint16_t hvx_len = bufinfo->len; // uint16_t hvx_len = bufinfo->len;
ble_gatts_hvx_params_t hvx_params = { // ble_gatts_hvx_params_t hvx_params = {
.handle = handle, // .handle = handle,
.type = hvx_type, // .type = hvx_type,
.offset = 0, // .offset = 0,
.p_len = &hvx_len, // .p_len = &hvx_len,
.p_data = bufinfo->buf, // .p_data = bufinfo->buf,
}; // };
while (1) { // while (1) {
const uint32_t err_code = sd_ble_gatts_hvx(conn_handle, &hvx_params); // const uint32_t err_code = sd_ble_gatts_hvx(conn_handle, &hvx_params);
if (err_code == NRF_SUCCESS) { // if (err_code == NRF_SUCCESS) {
break; // break;
} // }
// TX buffer is full // // TX buffer is full
// We could wait for an event indicating the write is complete, but just retrying is easier. // // We could wait for an event indicating the write is complete, but just retrying is easier.
if (err_code == NRF_ERROR_RESOURCES) { // if (err_code == NRF_ERROR_RESOURCES) {
RUN_BACKGROUND_TASKS; // RUN_BACKGROUND_TASKS;
continue; // continue;
} // }
// Some real error has occurred. // // Some real error has occurred.
check_nrf_error(err_code); // check_nrf_error(err_code);
} // }
} // }
void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, uint16_t handle, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo) { void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, uint16_t handle, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo) {
self->service = service; self->service = service;
self->uuid = uuid; self->uuid = uuid;
self->handle = BLE_GATT_HANDLE_INVALID; //FIX self->handle = BLE_GATT_HANDLE_INVALID;
self->props = props; self->props = props;
self->read_perm = read_perm; self->read_perm = read_perm;
self->write_perm = write_perm; self->write_perm = write_perm;
self->descriptor_list = NULL; self->descriptor_list = NULL;
const mp_int_t max_length_max = fixed_length ? BLE_GATTS_FIX_ATTR_LEN_MAX : BLE_GATTS_VAR_ATTR_LEN_MAX; //FIX
if (max_length < 0 || max_length > max_length_max) { // const mp_int_t max_length_max = fixed_length ? BLE_GATTS_FIX_ATTR_LEN_MAX : BLE_GATTS_VAR_ATTR_LEN_MAX;
mp_raise_ValueError_varg(translate("max_length must be 0-%d when fixed_length is %s"), // if (max_length < 0 || max_length > max_length_max) {
max_length_max, fixed_length ? "True" : "False"); // mp_raise_ValueError_varg(translate("max_length must be 0-%d when fixed_length is %s"),
} // max_length_max, fixed_length ? "True" : "False");
// }
self->max_length = max_length; self->max_length = max_length;
self->fixed_length = fixed_length; self->fixed_length = fixed_length;
@ -159,25 +159,26 @@ void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self,
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
bleio_connection_internal_t *connection = &bleio_connections[i]; bleio_connection_internal_t *connection = &bleio_connections[i];
uint16_t conn_handle = connection->conn_handle; uint16_t conn_handle = connection->conn_handle;
if (connection->conn_handle == BLE_CONN_HANDLE_INVALID) { if (conn_handle == BLE_CONN_HANDLE_INVALID) {
continue; continue;
} }
uint16_t cccd = 0; //FIX
// uint16_t cccd = 0;
const bool notify = self->props & CHAR_PROP_NOTIFY; // const bool notify = self->props & CHAR_PROP_NOTIFY;
const bool indicate = self->props & CHAR_PROP_INDICATE; // const bool indicate = self->props & CHAR_PROP_INDICATE;
if (notify | indicate) { // if (notify | indicate) {
cccd = characteristic_get_cccd(self->cccd_handle, conn_handle); // cccd = characteristic_get_cccd(self->cccd_handle, conn_handle);
} // }
// It's possible that both notify and indicate are set. // // It's possible that both notify and indicate are set.
if (notify && (cccd & BLE_GATT_HVX_NOTIFICATION)) { // if (notify && (cccd & BLE_GATT_HVX_NOTIFICATION)) {
characteristic_gatts_notify_indicate(self->handle, conn_handle, bufinfo, BLE_GATT_HVX_NOTIFICATION); // characteristic_gatts_notify_indicate(self->handle, conn_handle, bufinfo, BLE_GATT_HVX_NOTIFICATION);
} // }
if (indicate && (cccd & BLE_GATT_HVX_INDICATION)) { // if (indicate && (cccd & BLE_GATT_HVX_INDICATION)) {
characteristic_gatts_notify_indicate(self->handle, conn_handle, bufinfo, BLE_GATT_HVX_INDICATION); // characteristic_gatts_notify_indicate(self->handle, conn_handle, bufinfo, BLE_GATT_HVX_INDICATION);
} // }
} }
} }
} }
@ -192,34 +193,35 @@ bleio_characteristic_properties_t common_hal_bleio_characteristic_get_properties
} }
void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t *self, bleio_descriptor_obj_t *descriptor) { void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t *self, bleio_descriptor_obj_t *descriptor) {
ble_uuid_t desc_uuid; //FIX
bleio_uuid_convert_to_nrf_ble_uuid(descriptor->uuid, &desc_uuid); // ble_uuid_t desc_uuid;
// bleio_uuid_convert_to_nrf_ble_uuid(descriptor->uuid, &desc_uuid);
ble_gatts_attr_md_t desc_attr_md = { // ble_gatts_attr_md_t desc_attr_md = {
// Data passed is not in a permanent location and should be copied. // // Data passed is not in a permanent location and should be copied.
.vloc = BLE_GATTS_VLOC_STACK, // .vloc = BLE_GATTS_VLOC_STACK,
.vlen = !descriptor->fixed_length, // .vlen = !descriptor->fixed_length,
}; // };
bleio_attribute_gatts_set_security_mode(&desc_attr_md.read_perm, descriptor->read_perm); // bleio_attribute_gatts_set_security_mode(&desc_attr_md.read_perm, descriptor->read_perm);
bleio_attribute_gatts_set_security_mode(&desc_attr_md.write_perm, descriptor->write_perm); // bleio_attribute_gatts_set_security_mode(&desc_attr_md.write_perm, descriptor->write_perm);
mp_buffer_info_t desc_value_bufinfo; // mp_buffer_info_t desc_value_bufinfo;
mp_get_buffer_raise(descriptor->value, &desc_value_bufinfo, MP_BUFFER_READ); // mp_get_buffer_raise(descriptor->value, &desc_value_bufinfo, MP_BUFFER_READ);
ble_gatts_attr_t desc_attr = { // ble_gatts_attr_t desc_attr = {
.p_uuid = &desc_uuid, // .p_uuid = &desc_uuid,
.p_attr_md = &desc_attr_md, // .p_attr_md = &desc_attr_md,
.init_len = desc_value_bufinfo.len, // .init_len = desc_value_bufinfo.len,
.p_value = desc_value_bufinfo.buf, // .p_value = desc_value_bufinfo.buf,
.init_offs = 0, // .init_offs = 0,
.max_len = descriptor->max_length, // .max_len = descriptor->max_length,
}; // };
check_nrf_error(sd_ble_gatts_descriptor_add(self->handle, &desc_attr, &descriptor->handle)); // check_nrf_error(sd_ble_gatts_descriptor_add(self->handle, &desc_attr, &descriptor->handle));
descriptor->next = self->descriptor_list; // descriptor->next = self->descriptor_list;
self->descriptor_list = descriptor; // self->descriptor_list = descriptor;
} }
void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate) { void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate) {
@ -234,33 +236,34 @@ void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self,
const uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection); const uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection);
common_hal_bleio_check_connected(conn_handle); common_hal_bleio_check_connected(conn_handle);
uint16_t cccd_value = //FIX
(notify ? BLE_GATT_HVX_NOTIFICATION : 0) | // uint16_t cccd_value =
(indicate ? BLE_GATT_HVX_INDICATION : 0); // (notify ? BLE_GATT_HVX_NOTIFICATION : 0) |
// (indicate ? BLE_GATT_HVX_INDICATION : 0);
ble_gattc_write_params_t write_params = { // ble_gattc_write_params_t write_params = {
.write_op = BLE_GATT_OP_WRITE_REQ, // .write_op = BLE_GATT_OP_WRITE_REQ,
.handle = self->cccd_handle, // .handle = self->cccd_handle,
.p_value = (uint8_t *) &cccd_value, // .p_value = (uint8_t *) &cccd_value,
.len = 2, // .len = 2,
}; // };
while (1) { // while (1) {
uint32_t err_code = sd_ble_gattc_write(conn_handle, &write_params); // uint32_t err_code = sd_ble_gattc_write(conn_handle, &write_params);
if (err_code == NRF_SUCCESS) { // if (err_code == NRF_SUCCESS) {
break; // break;
} // }
// Write with response will return NRF_ERROR_BUSY if the response has not been received. // // Write with response will return NRF_ERROR_BUSY if the response has not been received.
// Write without reponse will return NRF_ERROR_RESOURCES if too many writes are pending. // // Write without reponse will return NRF_ERROR_RESOURCES if too many writes are pending.
if (err_code == NRF_ERROR_BUSY || err_code == NRF_ERROR_RESOURCES) { // if (err_code == NRF_ERROR_BUSY || err_code == NRF_ERROR_RESOURCES) {
// We could wait for an event indicating the write is complete, but just retrying is easier. // // We could wait for an event indicating the write is complete, but just retrying is easier.
RUN_BACKGROUND_TASKS; // RUN_BACKGROUND_TASKS;
continue; // continue;
} // }
// Some real error occurred. // // Some real error occurred.
check_nrf_error(err_code); // check_nrf_error(err_code);
} // }
} }

View File

@ -37,44 +37,44 @@
#include "common-hal/_bleio/CharacteristicBuffer.h" #include "common-hal/_bleio/CharacteristicBuffer.h"
// Push all the data onto the ring buffer. When the buffer is full, new bytes will be dropped. // Push all the data onto the ring buffer. When the buffer is full, new bytes will be dropped.
STATIC void write_to_ringbuf(bleio_characteristic_buffer_obj_t *self, uint8_t *data, uint16_t len) { // STATIC void write_to_ringbuf(bleio_characteristic_buffer_obj_t *self, uint8_t *data, uint16_t len) {
uint8_t is_nested_critical_region; // uint8_t is_nested_critical_region;
sd_nvic_critical_region_enter(&is_nested_critical_region); // sd_nvic_critical_region_enter(&is_nested_critical_region);
ringbuf_put_n(&self->ringbuf, data, len); // ringbuf_put_n(&self->ringbuf, data, len);
sd_nvic_critical_region_exit(is_nested_critical_region); // sd_nvic_critical_region_exit(is_nested_critical_region);
} // }
STATIC bool characteristic_buffer_on_ble_evt(ble_evt_t *ble_evt, void *param) { // STATIC bool characteristic_buffer_on_ble_evt(ble_evt_t *ble_evt, void *param) {
bleio_characteristic_buffer_obj_t *self = (bleio_characteristic_buffer_obj_t *) param; // bleio_characteristic_buffer_obj_t *self = (bleio_characteristic_buffer_obj_t *) param;
switch (ble_evt->header.evt_id) { // switch (ble_evt->header.evt_id) {
case BLE_GATTS_EVT_WRITE: { // case BLE_GATTS_EVT_WRITE: {
// A client wrote to this server characteristic. // // A client wrote to this server characteristic.
ble_gatts_evt_write_t *evt_write = &ble_evt->evt.gatts_evt.params.write; // ble_gatts_evt_write_t *evt_write = &ble_evt->evt.gatts_evt.params.write;
// Event handle must match the handle for my characteristic. // // Event handle must match the handle for my characteristic.
if (evt_write->handle == self->characteristic->handle) { // if (evt_write->handle == self->characteristic->handle) {
write_to_ringbuf(self, evt_write->data, evt_write->len); // write_to_ringbuf(self, evt_write->data, evt_write->len);
} // }
break; // break;
} // }
case BLE_GATTC_EVT_HVX: { // case BLE_GATTC_EVT_HVX: {
// A remote service wrote to this characteristic. // // A remote service wrote to this characteristic.
ble_gattc_evt_hvx_t* evt_hvx = &ble_evt->evt.gattc_evt.params.hvx; // ble_gattc_evt_hvx_t* evt_hvx = &ble_evt->evt.gattc_evt.params.hvx;
// Must be a notification, and event handle must match the handle for my characteristic. // // Must be a notification, and event handle must match the handle for my characteristic.
if (evt_hvx->type == BLE_GATT_HVX_NOTIFICATION && // if (evt_hvx->type == BLE_GATT_HVX_NOTIFICATION &&
evt_hvx->handle == self->characteristic->handle) { // evt_hvx->handle == self->characteristic->handle) {
write_to_ringbuf(self, evt_hvx->data, evt_hvx->len); // write_to_ringbuf(self, evt_hvx->data, evt_hvx->len);
} // }
break; // break;
} // }
default: // default:
return false; // return false;
break; // break;
} // }
return true; // return true;
} // }
// Assumes that timeout and buffer_size have been validated before call. // Assumes that timeout and buffer_size have been validated before call.
void common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffer_obj_t *self, void common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffer_obj_t *self,
@ -88,7 +88,7 @@ void common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffe
// true means long-lived, so it won't be moved. // true means long-lived, so it won't be moved.
ringbuf_alloc(&self->ringbuf, buffer_size, true); ringbuf_alloc(&self->ringbuf, buffer_size, true);
ble_drv_add_event_handler(characteristic_buffer_on_ble_evt, self); // FIX ble_drv_add_event_handler(characteristic_buffer_on_ble_evt, self);
} }
@ -105,31 +105,31 @@ uint32_t common_hal_bleio_characteristic_buffer_read(bleio_characteristic_buffer
} }
// Copy received data. Lock out write interrupt handler while copying. // Copy received data. Lock out write interrupt handler while copying.
uint8_t is_nested_critical_region; // FIX uint8_t is_nested_critical_region;
sd_nvic_critical_region_enter(&is_nested_critical_region); // FIX sd_nvic_critical_region_enter(&is_nested_critical_region);
uint32_t num_bytes_read = ringbuf_get_n(&self->ringbuf, data, len); uint32_t num_bytes_read = ringbuf_get_n(&self->ringbuf, data, len);
// Writes now OK. // Writes now OK.
sd_nvic_critical_region_exit(is_nested_critical_region); // FIX sd_nvic_critical_region_exit(is_nested_critical_region);
return num_bytes_read; return num_bytes_read;
} }
uint32_t common_hal_bleio_characteristic_buffer_rx_characters_available(bleio_characteristic_buffer_obj_t *self) { uint32_t common_hal_bleio_characteristic_buffer_rx_characters_available(bleio_characteristic_buffer_obj_t *self) {
uint8_t is_nested_critical_region; //FIX uint8_t is_nested_critical_region;
sd_nvic_critical_region_enter(&is_nested_critical_region); //FIX sd_nvic_critical_region_enter(&is_nested_critical_region);
uint16_t count = ringbuf_num_filled(&self->ringbuf); uint16_t count = ringbuf_num_filled(&self->ringbuf);
sd_nvic_critical_region_exit(is_nested_critical_region); //FIX sd_nvic_critical_region_exit(is_nested_critical_region);
return count; return count;
} }
void common_hal_bleio_characteristic_buffer_clear_rx_buffer(bleio_characteristic_buffer_obj_t *self) { void common_hal_bleio_characteristic_buffer_clear_rx_buffer(bleio_characteristic_buffer_obj_t *self) {
// prevent conflict with uart irq // prevent conflict with uart irq
uint8_t is_nested_critical_region; //FIX uint8_t is_nested_critical_region;
sd_nvic_critical_region_enter(&is_nested_critical_region); //FIX sd_nvic_critical_region_enter(&is_nested_critical_region);
ringbuf_clear(&self->ringbuf); ringbuf_clear(&self->ringbuf);
sd_nvic_critical_region_exit(is_nested_critical_region); //FIX sd_nvic_critical_region_exit(is_nested_critical_region);
} }
bool common_hal_bleio_characteristic_buffer_deinited(bleio_characteristic_buffer_obj_t *self) { bool common_hal_bleio_characteristic_buffer_deinited(bleio_characteristic_buffer_obj_t *self) {
@ -138,7 +138,7 @@ bool common_hal_bleio_characteristic_buffer_deinited(bleio_characteristic_buffer
void common_hal_bleio_characteristic_buffer_deinit(bleio_characteristic_buffer_obj_t *self) { void common_hal_bleio_characteristic_buffer_deinit(bleio_characteristic_buffer_obj_t *self) {
if (!common_hal_bleio_characteristic_buffer_deinited(self)) { if (!common_hal_bleio_characteristic_buffer_deinited(self)) {
ble_drv_remove_event_handler(characteristic_buffer_on_ble_evt, self); //FIX ble_drv_remove_event_handler(characteristic_buffer_on_ble_evt, self);
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -34,7 +34,6 @@
#include "py/objlist.h" #include "py/objlist.h"
#include "common-hal/_bleio/__init__.h" #include "common-hal/_bleio/__init__.h"
#include "common-hal/_bleio/bonding.h"
#include "shared-module/_bleio/Address.h" #include "shared-module/_bleio/Address.h"
#include "common-hal/_bleio/Service.h" #include "common-hal/_bleio/Service.h"

View File

@ -36,151 +36,152 @@
#include "shared-bindings/_bleio/PacketBuffer.h" #include "shared-bindings/_bleio/PacketBuffer.h"
#include "supervisor/shared/tick.h" #include "supervisor/shared/tick.h"
STATIC void write_to_ringbuf(bleio_packet_buffer_obj_t *self, uint8_t *data, uint16_t len) { // STATIC void write_to_ringbuf(bleio_packet_buffer_obj_t *self, uint8_t *data, uint16_t len) {
if (len + sizeof(uint16_t) > ringbuf_capacity(&self->ringbuf)) { // if (len + sizeof(uint16_t) > ringbuf_capacity(&self->ringbuf)) {
// This shouldn't happen. // // This shouldn't happen.
return; // return;
} // }
// Push all the data onto the ring buffer. // // Push all the data onto the ring buffer.
uint8_t is_nested_critical_region; // //FIX uint8_t is_nested_critical_region;
sd_nvic_critical_region_enter(&is_nested_critical_region); // //FIX sd_nvic_critical_region_enter(&is_nested_critical_region);
// Make room for the new value by dropping the oldest packets first. // // Make room for the new value by dropping the oldest packets first.
while (ringbuf_capacity(&self->ringbuf) - ringbuf_num_filled(&self->ringbuf) < len + sizeof(uint16_t)) { // while (ringbuf_capacity(&self->ringbuf) - ringbuf_num_filled(&self->ringbuf) < len + sizeof(uint16_t)) {
uint16_t packet_length; // uint16_t packet_length;
ringbuf_get_n(&self->ringbuf, (uint8_t*) &packet_length, sizeof(uint16_t)); // ringbuf_get_n(&self->ringbuf, (uint8_t*) &packet_length, sizeof(uint16_t));
for (uint16_t i = 0; i < packet_length; i++) { // for (uint16_t i = 0; i < packet_length; i++) {
ringbuf_get(&self->ringbuf); // ringbuf_get(&self->ringbuf);
} // }
// set an overflow flag? // // set an overflow flag?
} // }
ringbuf_put_n(&self->ringbuf, (uint8_t*) &len, sizeof(uint16_t)); // ringbuf_put_n(&self->ringbuf, (uint8_t*) &len, sizeof(uint16_t));
ringbuf_put_n(&self->ringbuf, data, len); // ringbuf_put_n(&self->ringbuf, data, len);
sd_nvic_critical_region_exit(is_nested_critical_region); // //FIX sd_nvic_critical_region_exit(is_nested_critical_region);
} // }
STATIC uint32_t queue_next_write(bleio_packet_buffer_obj_t *self) { //FIX
// Queue up the next outgoing buffer. We use two, one that has been passed to the SD for // STATIC uint32_t queue_next_write(bleio_packet_buffer_obj_t *self) {
// transmission (when packet_queued is true) and the other is `pending` and can still be // // Queue up the next outgoing buffer. We use two, one that has been passed to the SD for
// modified. By primarily appending to the `pending` buffer we can reduce the protocol overhead // // transmission (when packet_queued is true) and the other is `pending` and can still be
// of the lower level link and ATT layers. // // modified. By primarily appending to the `pending` buffer we can reduce the protocol overhead
self->packet_queued = false; // // of the lower level link and ATT layers.
if (self->pending_size > 0) { // self->packet_queued = false;
uint16_t conn_handle = self->conn_handle; // if (self->pending_size > 0) {
uint32_t err_code; // uint16_t conn_handle = self->conn_handle;
if (self->client) { // uint32_t err_code;
ble_gattc_write_params_t write_params = { // if (self->client) {
.write_op = self->write_type, // ble_gattc_write_params_t write_params = {
.handle = self->characteristic->handle, // .write_op = self->write_type,
.p_value = self->outgoing[self->pending_index], // .handle = self->characteristic->handle,
.len = self->pending_size, // .p_value = self->outgoing[self->pending_index],
}; // .len = self->pending_size,
// };
err_code = sd_ble_gattc_write(conn_handle, &write_params); // err_code = sd_ble_gattc_write(conn_handle, &write_params);
} else { // } else {
uint16_t hvx_len = self->pending_size; // uint16_t hvx_len = self->pending_size;
ble_gatts_hvx_params_t hvx_params = { // ble_gatts_hvx_params_t hvx_params = {
.handle = self->characteristic->handle, // .handle = self->characteristic->handle,
.type = self->write_type, // .type = self->write_type,
.offset = 0, // .offset = 0,
.p_len = &hvx_len, // .p_len = &hvx_len,
.p_data = self->outgoing[self->pending_index], // .p_data = self->outgoing[self->pending_index],
}; // };
err_code = sd_ble_gatts_hvx(conn_handle, &hvx_params); // err_code = sd_ble_gatts_hvx(conn_handle, &hvx_params);
} // }
if (err_code != NRF_SUCCESS) { // if (err_code != NRF_SUCCESS) {
// On error, simply skip updating the pending buffers so that the next HVC or WRITE // // On error, simply skip updating the pending buffers so that the next HVC or WRITE
// complete event triggers another attempt. // // complete event triggers another attempt.
return err_code; // return err_code;
} // }
self->pending_size = 0; // self->pending_size = 0;
self->pending_index = (self->pending_index + 1) % 2; // self->pending_index = (self->pending_index + 1) % 2;
self->packet_queued = true; // self->packet_queued = true;
} // }
return NRF_SUCCESS; // return NRF_SUCCESS;
} // }
STATIC bool packet_buffer_on_ble_client_evt(ble_evt_t *ble_evt, void *param) { // STATIC bool packet_buffer_on_ble_client_evt(ble_evt_t *ble_evt, void *param) {
const uint16_t evt_id = ble_evt->header.evt_id; // const uint16_t evt_id = ble_evt->header.evt_id;
// Check if this is a GATTC event so we can make sure the conn_handle is valid. // // Check if this is a GATTC event so we can make sure the conn_handle is valid.
if (evt_id < BLE_GATTC_EVT_BASE || evt_id > BLE_GATTC_EVT_LAST) { // if (evt_id < BLE_GATTC_EVT_BASE || evt_id > BLE_GATTC_EVT_LAST) {
return false; // return false;
} // }
uint16_t conn_handle = ble_evt->evt.gattc_evt.conn_handle; // uint16_t conn_handle = ble_evt->evt.gattc_evt.conn_handle;
bleio_packet_buffer_obj_t *self = (bleio_packet_buffer_obj_t *) param; // bleio_packet_buffer_obj_t *self = (bleio_packet_buffer_obj_t *) param;
if (conn_handle != self->conn_handle) { // if (conn_handle != self->conn_handle) {
return false; // return false;
} // }
switch (evt_id) { // switch (evt_id) {
case BLE_GATTC_EVT_HVX: { // case BLE_GATTC_EVT_HVX: {
// A remote service wrote to this characteristic. // // A remote service wrote to this characteristic.
ble_gattc_evt_hvx_t* evt_hvx = &ble_evt->evt.gattc_evt.params.hvx; // ble_gattc_evt_hvx_t* evt_hvx = &ble_evt->evt.gattc_evt.params.hvx;
// Must be a notification, and event handle must match the handle for my characteristic. // // Must be a notification, and event handle must match the handle for my characteristic.
if (evt_hvx->handle == self->characteristic->handle) { // if (evt_hvx->handle == self->characteristic->handle) {
write_to_ringbuf(self, evt_hvx->data, evt_hvx->len); // write_to_ringbuf(self, evt_hvx->data, evt_hvx->len);
if (evt_hvx->type == BLE_GATT_HVX_INDICATION) { // if (evt_hvx->type == BLE_GATT_HVX_INDICATION) {
sd_ble_gattc_hv_confirm(conn_handle, evt_hvx->handle); // sd_ble_gattc_hv_confirm(conn_handle, evt_hvx->handle);
} // }
} // }
break; // break;
} // }
case BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE: { // case BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE: {
queue_next_write(self); // queue_next_write(self);
break; // break;
} // }
case BLE_GATTC_EVT_WRITE_RSP: { // case BLE_GATTC_EVT_WRITE_RSP: {
queue_next_write(self); // queue_next_write(self);
break; // break;
} // }
default: // default:
return false; // return false;
break; // break;
} // }
return true; // return true;
} // }
STATIC bool packet_buffer_on_ble_server_evt(ble_evt_t *ble_evt, void *param) { // STATIC bool packet_buffer_on_ble_server_evt(ble_evt_t *ble_evt, void *param) {
bleio_packet_buffer_obj_t *self = (bleio_packet_buffer_obj_t *) param; // bleio_packet_buffer_obj_t *self = (bleio_packet_buffer_obj_t *) param;
switch (ble_evt->header.evt_id) { // switch (ble_evt->header.evt_id) {
case BLE_GATTS_EVT_WRITE: { // case BLE_GATTS_EVT_WRITE: {
uint16_t conn_handle = ble_evt->evt.gatts_evt.conn_handle; // uint16_t conn_handle = ble_evt->evt.gatts_evt.conn_handle;
// A client wrote to this server characteristic. // // A client wrote to this server characteristic.
ble_gatts_evt_write_t *evt_write = &ble_evt->evt.gatts_evt.params.write; // ble_gatts_evt_write_t *evt_write = &ble_evt->evt.gatts_evt.params.write;
// Event handle must match the handle for my characteristic. // // Event handle must match the handle for my characteristic.
if (evt_write->handle == self->characteristic->handle) { // if (evt_write->handle == self->characteristic->handle) {
if (self->conn_handle == BLE_CONN_HANDLE_INVALID) { // if (self->conn_handle == BLE_CONN_HANDLE_INVALID) {
self->conn_handle = conn_handle; // self->conn_handle = conn_handle;
} else if (self->conn_handle != conn_handle) { // } else if (self->conn_handle != conn_handle) {
return false; // return false;
} // }
write_to_ringbuf(self, evt_write->data, evt_write->len); // write_to_ringbuf(self, evt_write->data, evt_write->len);
} else if (evt_write->handle == self->characteristic->cccd_handle) { // } else if (evt_write->handle == self->characteristic->cccd_handle) {
uint16_t cccd = *((uint16_t*) evt_write->data); // uint16_t cccd = *((uint16_t*) evt_write->data);
if (cccd & BLE_GATT_HVX_NOTIFICATION) { // if (cccd & BLE_GATT_HVX_NOTIFICATION) {
self->conn_handle = conn_handle; // self->conn_handle = conn_handle;
} else { // } else {
self->conn_handle = BLE_CONN_HANDLE_INVALID; // self->conn_handle = BLE_CONN_HANDLE_INVALID;
} // }
} // }
break; // break;
} // }
case BLE_GAP_EVT_DISCONNECTED: { // case BLE_GAP_EVT_DISCONNECTED: {
if (self->conn_handle == ble_evt->evt.gap_evt.conn_handle) { // if (self->conn_handle == ble_evt->evt.gap_evt.conn_handle) {
self->conn_handle = BLE_CONN_HANDLE_INVALID; // self->conn_handle = BLE_CONN_HANDLE_INVALID;
} // }
} // }
case BLE_GATTS_EVT_HVN_TX_COMPLETE: { // case BLE_GATTS_EVT_HVN_TX_COMPLETE: {
queue_next_write(self); // queue_next_write(self);
} // }
default: // default:
return false; // return false;
break; // break;
} // }
return true; // return true;
} // }
void common_hal_bleio_packet_buffer_construct( void common_hal_bleio_packet_buffer_construct(
bleio_packet_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic, bleio_packet_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic,
@ -218,32 +219,32 @@ void common_hal_bleio_packet_buffer_construct(
self->outgoing[1] = NULL; self->outgoing[1] = NULL;
} }
if (self->client) { //FIX if (self->client) {
ble_drv_add_event_handler(packet_buffer_on_ble_client_evt, self); // ble_drv_add_event_handler(packet_buffer_on_ble_client_evt, self);
if (incoming) { // if (incoming) {
// Prefer notify if both are available. // // Prefer notify if both are available.
if (incoming & CHAR_PROP_NOTIFY) { // if (incoming & CHAR_PROP_NOTIFY) {
self->write_type = BLE_GATT_HVX_NOTIFICATION; // self->write_type = BLE_GATT_HVX_NOTIFICATION;
common_hal_bleio_characteristic_set_cccd(self->characteristic, true, false); // common_hal_bleio_characteristic_set_cccd(self->characteristic, true, false);
} else { // } else {
common_hal_bleio_characteristic_set_cccd(self->characteristic, false, true); // common_hal_bleio_characteristic_set_cccd(self->characteristic, false, true);
} // }
} // }
if (outgoing) { // if (outgoing) {
self->write_type = BLE_GATT_OP_WRITE_REQ; // self->write_type = BLE_GATT_OP_WRITE_REQ;
if (outgoing & CHAR_PROP_WRITE_NO_RESPONSE) { // if (outgoing & CHAR_PROP_WRITE_NO_RESPONSE) {
self->write_type = BLE_GATT_OP_WRITE_CMD; // self->write_type = BLE_GATT_OP_WRITE_CMD;
} // }
} // }
} else { // } else {
ble_drv_add_event_handler(packet_buffer_on_ble_server_evt, self); // ble_drv_add_event_handler(packet_buffer_on_ble_server_evt, self);
if (outgoing) { // if (outgoing) {
self->write_type = BLE_GATT_HVX_INDICATION; // self->write_type = BLE_GATT_HVX_INDICATION;
if (outgoing & CHAR_PROP_NOTIFY) { // if (outgoing & CHAR_PROP_NOTIFY) {
self->write_type = BLE_GATT_HVX_NOTIFICATION; // self->write_type = BLE_GATT_HVX_NOTIFICATION;
} // }
} // }
} // }
} }
mp_int_t common_hal_bleio_packet_buffer_readinto(bleio_packet_buffer_obj_t *self, uint8_t *data, size_t len) { mp_int_t common_hal_bleio_packet_buffer_readinto(bleio_packet_buffer_obj_t *self, uint8_t *data, size_t len) {
@ -252,8 +253,8 @@ mp_int_t common_hal_bleio_packet_buffer_readinto(bleio_packet_buffer_obj_t *self
} }
// Copy received data. Lock out write interrupt handler while copying. // Copy received data. Lock out write interrupt handler while copying.
uint8_t is_nested_critical_region; //FIX uint8_t is_nested_critical_region;
sd_nvic_critical_region_enter(&is_nested_critical_region); //FIX sd_nvic_critical_region_enter(&is_nested_critical_region);
// Get packet length, which is in first two bytes of packet. // Get packet length, which is in first two bytes of packet.
uint16_t packet_length; uint16_t packet_length;
@ -274,7 +275,7 @@ mp_int_t common_hal_bleio_packet_buffer_readinto(bleio_packet_buffer_obj_t *self
} }
// Writes now OK. // Writes now OK.
sd_nvic_critical_region_exit(is_nested_critical_region); //FIX sd_nvic_critical_region_exit(is_nested_critical_region);
return ret; return ret;
} }
@ -306,8 +307,8 @@ mp_int_t common_hal_bleio_packet_buffer_write(bleio_packet_buffer_obj_t *self, u
size_t num_bytes_written = 0; size_t num_bytes_written = 0;
uint8_t is_nested_critical_region; //FIX uint8_t is_nested_critical_region;
sd_nvic_critical_region_enter(&is_nested_critical_region); //FIX sd_nvic_critical_region_enter(&is_nested_critical_region);
uint8_t* pending = self->outgoing[self->pending_index]; uint8_t* pending = self->outgoing[self->pending_index];
@ -320,11 +321,11 @@ mp_int_t common_hal_bleio_packet_buffer_write(bleio_packet_buffer_obj_t *self, u
self->pending_size += len; self->pending_size += len;
num_bytes_written += len; num_bytes_written += len;
sd_nvic_critical_region_exit(is_nested_critical_region); //FIX sd_nvic_critical_region_exit(is_nested_critical_region);
// If no writes are queued then sneak in this data. // If no writes are queued then sneak in this data.
if (!self->packet_queued) { if (!self->packet_queued) {
queue_next_write(self); //FIX queue_next_write(self);
} }
return num_bytes_written; return num_bytes_written;
} }
@ -397,6 +398,6 @@ bool common_hal_bleio_packet_buffer_deinited(bleio_packet_buffer_obj_t *self) {
void common_hal_bleio_packet_buffer_deinit(bleio_packet_buffer_obj_t *self) { void common_hal_bleio_packet_buffer_deinit(bleio_packet_buffer_obj_t *self) {
if (!common_hal_bleio_packet_buffer_deinited(self)) { if (!common_hal_bleio_packet_buffer_deinited(self)) {
ble_drv_remove_event_handler(packet_buffer_on_ble_client_evt, self); //FIX ble_drv_remove_event_handler(packet_buffer_on_ble_client_evt, self);
} }
} }

View File

@ -40,22 +40,24 @@ uint32_t _common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uu
self->connection = NULL; self->connection = NULL;
self->is_secondary = is_secondary; self->is_secondary = is_secondary;
ble_uuid_t nordic_uuid; //FIX
bleio_uuid_convert_to_nrf_ble_uuid(uuid, &nordic_uuid); // ble_uuid_t nordic_uuid;
// bleio_uuid_convert_to_nrf_ble_uuid(uuid, &nordic_uuid);
uint8_t service_type = BLE_GATTS_SRVC_TYPE_PRIMARY; // uint8_t service_type = BLE_GATTS_SRVC_TYPE_PRIMARY;
if (is_secondary) { // if (is_secondary) {
service_type = BLE_GATTS_SRVC_TYPE_SECONDARY; // service_type = BLE_GATTS_SRVC_TYPE_SECONDARY;
} // }
vm_used_ble = true; vm_used_ble = true;
return sd_ble_gatts_service_add(service_type, &nordic_uuid, &self->handle); //FIX return sd_ble_gatts_service_add(service_type, &nordic_uuid, &self->handle);
return 0;
} }
void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary) { void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary) {
check_nrf_error(_common_hal_bleio_service_construct(self, uuid, is_secondary, //FIX check_nrf_error(_common_hal_bleio_service_construct(self, uuid, is_secondary,
mp_obj_new_list(0, NULL))); // mp_obj_new_list(0, NULL)));
} }
void bleio_service_from_connection(bleio_service_obj_t *self, mp_obj_t connection) { void bleio_service_from_connection(bleio_service_obj_t *self, mp_obj_t connection) {
@ -86,62 +88,62 @@ bool common_hal_bleio_service_get_is_secondary(bleio_service_obj_t *self) {
void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self,
bleio_characteristic_obj_t *characteristic, bleio_characteristic_obj_t *characteristic,
mp_buffer_info_t *initial_value_bufinfo) { mp_buffer_info_t *initial_value_bufinfo) {
ble_gatts_char_md_t char_md = { // ble_gatts_char_md_t char_md = {
.char_props.broadcast = (characteristic->props & CHAR_PROP_BROADCAST) ? 1 : 0, // .char_props.broadcast = (characteristic->props & CHAR_PROP_BROADCAST) ? 1 : 0,
.char_props.read = (characteristic->props & CHAR_PROP_READ) ? 1 : 0, // .char_props.read = (characteristic->props & CHAR_PROP_READ) ? 1 : 0,
.char_props.write_wo_resp = (characteristic->props & CHAR_PROP_WRITE_NO_RESPONSE) ? 1 : 0, // .char_props.write_wo_resp = (characteristic->props & CHAR_PROP_WRITE_NO_RESPONSE) ? 1 : 0,
.char_props.write = (characteristic->props & CHAR_PROP_WRITE) ? 1 : 0, // .char_props.write = (characteristic->props & CHAR_PROP_WRITE) ? 1 : 0,
.char_props.notify = (characteristic->props & CHAR_PROP_NOTIFY) ? 1 : 0, // .char_props.notify = (characteristic->props & CHAR_PROP_NOTIFY) ? 1 : 0,
.char_props.indicate = (characteristic->props & CHAR_PROP_INDICATE) ? 1 : 0, // .char_props.indicate = (characteristic->props & CHAR_PROP_INDICATE) ? 1 : 0,
}; // };
ble_gatts_attr_md_t cccd_md = { // ble_gatts_attr_md_t cccd_md = {
.vloc = BLE_GATTS_VLOC_STACK, // .vloc = BLE_GATTS_VLOC_STACK,
}; // };
ble_uuid_t char_uuid; // ble_uuid_t char_uuid;
bleio_uuid_convert_to_nrf_ble_uuid(characteristic->uuid, &char_uuid); // bleio_uuid_convert_to_nrf_ble_uuid(characteristic->uuid, &char_uuid);
ble_gatts_attr_md_t char_attr_md = { // ble_gatts_attr_md_t char_attr_md = {
.vloc = BLE_GATTS_VLOC_STACK, // .vloc = BLE_GATTS_VLOC_STACK,
.vlen = !characteristic->fixed_length, // .vlen = !characteristic->fixed_length,
}; // };
if (char_md.char_props.notify || char_md.char_props.indicate) { // if (char_md.char_props.notify || char_md.char_props.indicate) {
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm); // BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
// Make CCCD write permission match characteristic read permission. // // Make CCCD write permission match characteristic read permission.
bleio_attribute_gatts_set_security_mode(&cccd_md.write_perm, characteristic->read_perm); // bleio_attribute_gatts_set_security_mode(&cccd_md.write_perm, characteristic->read_perm);
char_md.p_cccd_md = &cccd_md; // char_md.p_cccd_md = &cccd_md;
} // }
bleio_attribute_gatts_set_security_mode(&char_attr_md.read_perm, characteristic->read_perm); // bleio_attribute_gatts_set_security_mode(&char_attr_md.read_perm, characteristic->read_perm);
bleio_attribute_gatts_set_security_mode(&char_attr_md.write_perm, characteristic->write_perm); // bleio_attribute_gatts_set_security_mode(&char_attr_md.write_perm, characteristic->write_perm);
#if CIRCUITPY_VERBOSE_BLE // #if CIRCUITPY_VERBOSE_BLE
// Turn on read authorization so that we receive an event to print on every read. // // Turn on read authorization so that we receive an event to print on every read.
char_attr_md.rd_auth = true; // char_attr_md.rd_auth = true;
#endif // #endif
ble_gatts_attr_t char_attr = { // ble_gatts_attr_t char_attr = {
.p_uuid = &char_uuid, // .p_uuid = &char_uuid,
.p_attr_md = &char_attr_md, // .p_attr_md = &char_attr_md,
.init_len = 0, // .init_len = 0,
.p_value = NULL, // .p_value = NULL,
.init_offs = 0, // .init_offs = 0,
.max_len = characteristic->max_length, // .max_len = characteristic->max_length,
}; // };
ble_gatts_char_handles_t char_handles; // ble_gatts_char_handles_t char_handles;
check_nrf_error(sd_ble_gatts_characteristic_add(self->handle, &char_md, &char_attr, &char_handles)); // check_nrf_error(sd_ble_gatts_characteristic_add(self->handle, &char_md, &char_attr, &char_handles));
characteristic->user_desc_handle = char_handles.user_desc_handle; // characteristic->user_desc_handle = char_handles.user_desc_handle;
characteristic->cccd_handle = char_handles.cccd_handle; // characteristic->cccd_handle = char_handles.cccd_handle;
characteristic->sccd_handle = char_handles.sccd_handle; // characteristic->sccd_handle = char_handles.sccd_handle;
characteristic->handle = char_handles.value_handle; // characteristic->handle = char_handles.value_handle;
#if CIRCUITPY_VERBOSE_BLE // #if CIRCUITPY_VERBOSE_BLE
mp_printf(&mp_plat_print, "Char handle %x user %x cccd %x sccd %x\n", characteristic->handle, characteristic->user_desc_handle, characteristic->cccd_handle, characteristic->sccd_handle); // mp_printf(&mp_plat_print, "Char handle %x user %x cccd %x sccd %x\n", characteristic->handle, characteristic->user_desc_handle, characteristic->cccd_handle, characteristic->sccd_handle);
#endif // #endif
mp_obj_list_append(self->characteristic_list, MP_OBJ_FROM_PTR(characteristic)); // mp_obj_list_append(self->characteristic_list, MP_OBJ_FROM_PTR(characteristic));
} }

View File

@ -37,35 +37,36 @@
// If uuid128 is not NULL, it's a 128-bit (16-byte) UUID, with bytes 12 and 13 zero'd out, where // If uuid128 is not NULL, it's a 128-bit (16-byte) UUID, with bytes 12 and 13 zero'd out, where
// the 16-bit part goes. Those 16 bits are passed in uuid16. // the 16-bit part goes. Those 16 bits are passed in uuid16.
void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, uint32_t uuid16, const uint8_t uuid128[]) { void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, uint32_t uuid16, const uint8_t uuid128[]) {
self->nrf_ble_uuid.uuid = uuid16; //FIX self->nrf_ble_uuid.uuid = uuid16;
if (uuid128 == NULL) { // if (uuid128 == NULL) {
self->nrf_ble_uuid.type = BLE_UUID_TYPE_BLE; // self->nrf_ble_uuid.type = BLE_UUID_TYPE_BLE;
} else { // } else {
ble_uuid128_t vs_uuid; // ble_uuid128_t vs_uuid;
memcpy(vs_uuid.uuid128, uuid128, sizeof(vs_uuid.uuid128)); // memcpy(vs_uuid.uuid128, uuid128, sizeof(vs_uuid.uuid128));
// Register this vendor-specific UUID. Bytes 12 and 13 will be zero. // // Register this vendor-specific UUID. Bytes 12 and 13 will be zero.
check_nrf_error(sd_ble_uuid_vs_add(&vs_uuid, &self->nrf_ble_uuid.type)); // check_nrf_error(sd_ble_uuid_vs_add(&vs_uuid, &self->nrf_ble_uuid.type));
vm_used_ble = true; // vm_used_ble = true;
} // }
} }
uint32_t common_hal_bleio_uuid_get_size(bleio_uuid_obj_t *self) { uint32_t common_hal_bleio_uuid_get_size(bleio_uuid_obj_t *self) {
// return self->nrf_ble_uuid.type == BLE_UUID_TYPE_BLE ? 16 : 128; //FIX return self->nrf_ble_uuid.type == BLE_UUID_TYPE_BLE ? 16 : 128;
return 0;
} }
uint32_t common_hal_bleio_uuid_get_uuid16(bleio_uuid_obj_t *self) { uint32_t common_hal_bleio_uuid_get_uuid16(bleio_uuid_obj_t *self) {
// return self->nrf_ble_uuid.uuid; //FIX return self->nrf_ble_uuid.uuid;
return 0; return 0;
} }
void common_hal_bleio_uuid_get_uuid128(bleio_uuid_obj_t *self, uint8_t uuid128[16]) { void common_hal_bleio_uuid_get_uuid128(bleio_uuid_obj_t *self, uint8_t uuid128[16]) {
uint8_t length; //FIX uint8_t length;
// check_nrf_error(sd_ble_uuid_encode(&self->nrf_ble_uuid, &length, uuid128)); //FIX check_nrf_error(sd_ble_uuid_encode(&self->nrf_ble_uuid, &length, uuid128));
} }
void common_hal_bleio_uuid_pack_into(bleio_uuid_obj_t *self, uint8_t* buf) { void common_hal_bleio_uuid_pack_into(bleio_uuid_obj_t *self, uint8_t* buf) {
// if (self->nrf_ble_uuid.type == BLE_UUID_TYPE_BLE) { //FIX if (self->nrf_ble_uuid.type == BLE_UUID_TYPE_BLE) {
// buf[0] = self->nrf_ble_uuid.uuid & 0xff; // buf[0] = self->nrf_ble_uuid.uuid & 0xff;
// buf[1] = self->nrf_ble_uuid.uuid >> 8; // buf[1] = self->nrf_ble_uuid.uuid >> 8;
// } else { // } else {
@ -73,6 +74,7 @@ void common_hal_bleio_uuid_pack_into(bleio_uuid_obj_t *self, uint8_t* buf) {
// } // }
} }
//FIX
// void bleio_uuid_construct_from_nrf_ble_uuid(bleio_uuid_obj_t *self, ble_uuid_t *nrf_ble_uuid) { // void bleio_uuid_construct_from_nrf_ble_uuid(bleio_uuid_obj_t *self, ble_uuid_t *nrf_ble_uuid) {
// if (nrf_ble_uuid->type == BLE_UUID_TYPE_UNKNOWN) { // if (nrf_ble_uuid->type == BLE_UUID_TYPE_UNKNOWN) {
// mp_raise_bleio_BluetoothError(translate("Unexpected nrfx uuid type")); // mp_raise_bleio_BluetoothError(translate("Unexpected nrfx uuid type"));

View File

@ -33,7 +33,7 @@
typedef struct { typedef struct {
mp_obj_base_t base; mp_obj_base_t base;
// Use the native way of storing UUID's: //FIX Use the native way of storing UUID's:
// - ble_uuid_t.uuid is a 16-bit uuid. // - ble_uuid_t.uuid is a 16-bit uuid.
// - ble_uuid_t.type is BLE_UUID_TYPE_BLE if it's a 16-bit Bluetooth SIG UUID. // - ble_uuid_t.type is BLE_UUID_TYPE_BLE if it's a 16-bit Bluetooth SIG UUID.
// or is BLE_UUID_TYPE_VENDOR_BEGIN and higher, which indexes into a table of registered // or is BLE_UUID_TYPE_VENDOR_BEGIN and higher, which indexes into a table of registered

View File

@ -40,52 +40,53 @@
#include "common-hal/_bleio/__init__.h" #include "common-hal/_bleio/__init__.h"
void check_nrf_error(uint32_t err_code) { //FIX to check HCI error
if (err_code == NRF_SUCCESS) { // void check_nrf_error(uint32_t err_code) {
return; // if (err_code == NRF_SUCCESS) {
} // return;
switch (err_code) { // }
case NRF_ERROR_TIMEOUT: // switch (err_code) {
mp_raise_msg(&mp_type_TimeoutError, NULL); // case NRF_ERROR_TIMEOUT:
return; // mp_raise_msg(&mp_type_TimeoutError, NULL);
case BLE_ERROR_INVALID_CONN_HANDLE: // return;
mp_raise_bleio_ConnectionError(translate("Not connected")); // case BLE_ERROR_INVALID_CONN_HANDLE:
return; // mp_raise_bleio_ConnectionError(translate("Not connected"));
default: // return;
mp_raise_bleio_BluetoothError(translate("Unknown soft device error: %04x"), err_code); // default:
break; // mp_raise_bleio_BluetoothError(translate("Unknown soft device error: %04x"), err_code);
} // break;
} // }
// }
void check_gatt_status(uint16_t gatt_status) { // void check_gatt_status(uint16_t gatt_status) {
if (gatt_status == BLE_GATT_STATUS_SUCCESS) { // if (gatt_status == BLE_GATT_STATUS_SUCCESS) {
return; // return;
} // }
switch (gatt_status) { // switch (gatt_status) {
case BLE_GATT_STATUS_ATTERR_INSUF_AUTHENTICATION: // case BLE_GATT_STATUS_ATTERR_INSUF_AUTHENTICATION:
mp_raise_bleio_SecurityError(translate("Insufficient authentication")); // mp_raise_bleio_SecurityError(translate("Insufficient authentication"));
return; // return;
case BLE_GATT_STATUS_ATTERR_INSUF_ENCRYPTION: // case BLE_GATT_STATUS_ATTERR_INSUF_ENCRYPTION:
mp_raise_bleio_SecurityError(translate("Insufficient encryption")); // mp_raise_bleio_SecurityError(translate("Insufficient encryption"));
return; // return;
default: // default:
mp_raise_bleio_BluetoothError(translate("Unknown gatt error: 0x%04x"), gatt_status); // mp_raise_bleio_BluetoothError(translate("Unknown gatt error: 0x%04x"), gatt_status);
} // }
} // }
void check_sec_status(uint8_t sec_status) { // void check_sec_status(uint8_t sec_status) {
if (sec_status == BLE_GAP_SEC_STATUS_SUCCESS) { // if (sec_status == BLE_GAP_SEC_STATUS_SUCCESS) {
return; // return;
} // }
switch (sec_status) { // switch (sec_status) {
case BLE_GAP_SEC_STATUS_UNSPECIFIED: // case BLE_GAP_SEC_STATUS_UNSPECIFIED:
mp_raise_bleio_SecurityError(translate("Unspecified issue. Can be that the pairing prompt on the other device was declined or ignored.")); // mp_raise_bleio_SecurityError(translate("Unspecified issue. Can be that the pairing prompt on the other device was declined or ignored."));
return; // return;
default: // default:
mp_raise_bleio_SecurityError(translate("Unknown security error: 0x%04x"), sec_status); // mp_raise_bleio_SecurityError(translate("Unknown security error: 0x%04x"), sec_status);
} // }
} // }
// Turn off BLE on a reset or reload. // Turn off BLE on a reset or reload.
void bleio_reset() { void bleio_reset() {
@ -98,7 +99,7 @@ void bleio_reset() {
return; return;
} }
common_hal_bleio_adapter_set_enabled(&common_hal_bleio_adapter_obj, false); common_hal_bleio_adapter_set_enabled(&common_hal_bleio_adapter_obj, false);
bonding_reset(); //FIX bonding_reset();
supervisor_start_bluetooth(); supervisor_start_bluetooth();
} }
@ -121,124 +122,127 @@ size_t common_hal_bleio_gatts_read(uint16_t handle, uint16_t conn_handle, uint8_
// conn_handle is ignored unless this is a system attribute. // conn_handle is ignored unless this is a system attribute.
// If we're not connected, that's OK, because we can still read and write the local value. // If we're not connected, that's OK, because we can still read and write the local value.
ble_gatts_value_t gatts_value = { //FIX ble_gatts_value_t gatts_value = {
.p_value = buf, // .p_value = buf,
.len = len, // .len = len,
}; // };
check_nrf_error(sd_ble_gatts_value_get(conn_handle, handle, &gatts_value)); // check_nrf_error(sd_ble_gatts_value_get(conn_handle, handle, &gatts_value));
return gatts_value.len; // return gatts_value.len;
return 0;
} }
void common_hal_bleio_gatts_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo) { void common_hal_bleio_gatts_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo) {
// conn_handle is ignored unless this is a system attribute. // conn_handle is ignored unless this is a system attribute.
// If we're not connected, that's OK, because we can still read and write the local value. // If we're not connected, that's OK, because we can still read and write the local value.
ble_gatts_value_t gatts_value = { //FIX ble_gatts_value_t gatts_value = {
.p_value = bufinfo->buf, // .p_value = bufinfo->buf,
.len = bufinfo->len, // .len = bufinfo->len,
}; // };
check_nrf_error(sd_ble_gatts_value_set(conn_handle, handle, &gatts_value)); // check_nrf_error(sd_ble_gatts_value_set(conn_handle, handle, &gatts_value));
} }
typedef struct { //FIX
uint8_t* buf; // typedef struct {
size_t len; // uint8_t* buf;
size_t final_len; // size_t len;
uint16_t conn_handle; // size_t final_len;
volatile uint16_t status; // uint16_t conn_handle;
volatile bool done; // volatile uint16_t status;
} read_info_t; // volatile bool done;
// } read_info_t;
STATIC bool _on_gattc_read_rsp_evt(ble_evt_t *ble_evt, void *param) { // STATIC bool _on_gattc_read_rsp_evt(ble_evt_t *ble_evt, void *param) {
read_info_t* read = param; // read_info_t* read = param;
switch (ble_evt->header.evt_id) { // switch (ble_evt->header.evt_id) {
// More events may be handled later, so keep this as a switch. // // More events may be handled later, so keep this as a switch.
case BLE_GATTC_EVT_READ_RSP: { // case BLE_GATTC_EVT_READ_RSP: {
ble_gattc_evt_t* evt = &ble_evt->evt.gattc_evt; // ble_gattc_evt_t* evt = &ble_evt->evt.gattc_evt;
ble_gattc_evt_read_rsp_t *response = &evt->params.read_rsp; // ble_gattc_evt_read_rsp_t *response = &evt->params.read_rsp;
if (read && evt->conn_handle == read->conn_handle) { // if (read && evt->conn_handle == read->conn_handle) {
read->status = evt->gatt_status; // read->status = evt->gatt_status;
size_t len = MIN(read->len, response->len); // size_t len = MIN(read->len, response->len);
memcpy(read->buf, response->data, len); // memcpy(read->buf, response->data, len);
read->final_len = len; // read->final_len = len;
// Indicate to busy-wait loop that we've read the attribute value. // // Indicate to busy-wait loop that we've read the attribute value.
read->done = true; // read->done = true;
} // }
break; // break;
} // }
default: // default:
// For debugging. // // For debugging.
// mp_printf(&mp_plat_print, "Unhandled characteristic event: 0x%04x\n", ble_evt->header.evt_id); // // mp_printf(&mp_plat_print, "Unhandled characteristic event: 0x%04x\n", ble_evt->header.evt_id);
return false; // return false;
break; // break;
} // }
return true; // return true;
} // }
size_t common_hal_bleio_gattc_read(uint16_t handle, uint16_t conn_handle, uint8_t* buf, size_t len) { size_t common_hal_bleio_gattc_read(uint16_t handle, uint16_t conn_handle, uint8_t* buf, size_t len) {
common_hal_bleio_check_connected(conn_handle); common_hal_bleio_check_connected(conn_handle);
read_info_t read_info; //FIX read_info_t read_info;
read_info.buf = buf; // read_info.buf = buf;
read_info.len = len; // read_info.len = len;
read_info.final_len = 0; // read_info.final_len = 0;
read_info.conn_handle = conn_handle; // read_info.conn_handle = conn_handle;
// Set to true by the event handler. // // Set to true by the event handler.
read_info.done = false; // read_info.done = false;
ble_drv_add_event_handler(_on_gattc_read_rsp_evt, &read_info); // ble_drv_add_event_handler(_on_gattc_read_rsp_evt, &read_info);
uint32_t nrf_error = NRF_ERROR_BUSY; // uint32_t nrf_error = NRF_ERROR_BUSY;
while (nrf_error == NRF_ERROR_BUSY) { // while (nrf_error == NRF_ERROR_BUSY) {
nrf_error = sd_ble_gattc_read(conn_handle, handle, 0); // nrf_error = sd_ble_gattc_read(conn_handle, handle, 0);
} // }
if (nrf_error != NRF_SUCCESS) { // if (nrf_error != NRF_SUCCESS) {
ble_drv_remove_event_handler(_on_gattc_read_rsp_evt, &read_info); // ble_drv_remove_event_handler(_on_gattc_read_rsp_evt, &read_info);
check_nrf_error(nrf_error); // check_nrf_error(nrf_error);
} // }
while (!read_info.done) { // while (!read_info.done) {
RUN_BACKGROUND_TASKS; // RUN_BACKGROUND_TASKS;
} // }
ble_drv_remove_event_handler(_on_gattc_read_rsp_evt, &read_info); // ble_drv_remove_event_handler(_on_gattc_read_rsp_evt, &read_info);
check_gatt_status(read_info.status); // check_gatt_status(read_info.status);
return read_info.final_len; // return read_info.final_len;
return 0;
} }
void common_hal_bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, bool write_no_response) { void common_hal_bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, bool write_no_response) {
common_hal_bleio_check_connected(conn_handle); common_hal_bleio_check_connected(conn_handle);
ble_gattc_write_params_t write_params = { //FIX
.write_op = write_no_response ? BLE_GATT_OP_WRITE_CMD: BLE_GATT_OP_WRITE_REQ, // ble_gattc_write_params_t write_params = {
.handle = handle, // .write_op = write_no_response ? BLE_GATT_OP_WRITE_CMD: BLE_GATT_OP_WRITE_REQ,
.p_value = bufinfo->buf, // .handle = handle,
.len = bufinfo->len, // .p_value = bufinfo->buf,
}; // .len = bufinfo->len,
// };
while (1) { // while (1) {
uint32_t err_code = sd_ble_gattc_write(conn_handle, &write_params); // uint32_t err_code = sd_ble_gattc_write(conn_handle, &write_params);
if (err_code == NRF_SUCCESS) { // if (err_code == NRF_SUCCESS) {
break; // break;
} // }
// Write with response will return NRF_ERROR_BUSY if the response has not been received. // // Write with response will return NRF_ERROR_BUSY if the response has not been received.
// Write without reponse will return NRF_ERROR_RESOURCES if too many writes are pending. // // Write without reponse will return NRF_ERROR_RESOURCES if too many writes are pending.
if (err_code == NRF_ERROR_BUSY || err_code == NRF_ERROR_RESOURCES) { // if (err_code == NRF_ERROR_BUSY || err_code == NRF_ERROR_RESOURCES) {
// We could wait for an event indicating the write is complete, but just retrying is easier. // // We could wait for an event indicating the write is complete, but just retrying is easier.
MICROPY_VM_HOOK_LOOP; // MICROPY_VM_HOOK_LOOP;
continue; // continue;
} // }
// Some real error occurred.
check_nrf_error(err_code);
}
// // Some real error occurred.
// check_nrf_error(err_code);
// }
} }
void common_hal_bleio_gc_collect(void) { void common_hal_bleio_gc_collect(void) {

View File

@ -27,6 +27,8 @@
#ifndef MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_INIT_H #ifndef MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_INIT_H
#define MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_INIT_H #define MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_INIT_H
#include <stdbool.h>
void bleio_reset(void); void bleio_reset(void);
typedef struct { typedef struct {
@ -39,6 +41,13 @@ typedef struct {
// 20 bytes max (23 - 3). // 20 bytes max (23 - 3).
#define GATT_MAX_DATA_LENGTH (BLE_GATT_ATT_MTU_DEFAULT - 3) #define GATT_MAX_DATA_LENGTH (BLE_GATT_ATT_MTU_DEFAULT - 3)
//FIX
#define BLE_GATT_HANDLE_INVALID 0x0000
#define BLE_CONN_HANDLE_INVALID 0xFFFF
#define BLE_GATTS_FIX_ATTR_LEN_MAX (510) /**< Maximum length for fixed length Attribute Values. */
#define BLE_GATTS_VAR_ATTR_LEN_MAX (512) /**< Maximum length for variable length Attribute Values. */
// These helpers raise the appropriate exceptions if the code doesn't equal success. // These helpers raise the appropriate exceptions if the code doesn't equal success.
void check_nrf_error(uint32_t err_code); void check_nrf_error(uint32_t err_code);
void check_gatt_status(uint16_t gatt_status); void check_gatt_status(uint16_t gatt_status);

View File

@ -1,306 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Dan Halbert for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "shared-bindings/_bleio/__init__.h"
#include "shared-bindings/_bleio/Adapter.h"
#include "shared-bindings/nvm/ByteArray.h"
#include "supervisor/shared/tick.h"
#include "bonding.h"
// Internal flash area reserved for bonding storage.
#define BONDING_PAGES_START_ADDR CIRCUITPY_BLE_CONFIG_START_ADDR
#define BONDING_PAGES_END_ADDR (CIRCUITPY_BLE_CONFIG_START_ADDR + CIRCUITPY_BLE_CONFIG_SIZE)
// First and last four bytes are magic bytes for id and version. Data is in between.
// 'BD01'
const uint32_t BONDING_FLAG = ('1' | '0' << 8 | 'D' << 16 | 'B' << 24);
#define BONDING_DATA_START_ADDR (BONDING_PAGES_START_ADDR + sizeof(BONDING_FLAG))
#define BONDING_DATA_END_ADDR (BONDING_PAGES_END_ADDR - sizeof(BONDING_FLAG))
#define BONDING_START_FLAG_ADDR BONDING_PAGES_START_ADDR
#define BONDING_END_FLAG_ADDR BONDING_DATA_END_ADDR
// Save both system and user service info.
#define SYS_ATTR_FLAGS (BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS | BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS)
#if BONDING_DEBUG
void bonding_print_block(bonding_block_t *block) {
printf("at 0x%08lx: is_central: %1d, type: 0x%x, ediv: 0x%04x, data_length: %d\n",
(uint32_t) block, block->is_central, block->type, block->ediv, block->data_length);
}
void bonding_print_keys(bonding_keys_t *keys) {
for (size_t i = 0; i < sizeof(bonding_keys_t); i ++) {
printf("%x", ((uint8_t*) keys)[i]);
}
printf("\n");
}
#endif
STATIC size_t compute_block_size(uint16_t data_length) {
// Round data size up to the nearest 32-bit address.
return sizeof(bonding_block_t) + ((data_length + 3) & ~0x3);
}
void bonding_erase_storage(void) {
// Erase all pages in the bonding area.
for(uint32_t page_address = BONDING_PAGES_START_ADDR;
page_address < BONDING_PAGES_END_ADDR;
page_address += FLASH_PAGE_SIZE) {
// Argument is page number, not address.
sd_flash_page_erase_sync(page_address / FLASH_PAGE_SIZE);
}
// Write marker words at the beginning and the end of the bonding area.
uint32_t flag = BONDING_FLAG;
sd_flash_write_sync((uint32_t *) BONDING_START_FLAG_ADDR, &flag, 1);
sd_flash_write_sync((uint32_t *) BONDING_END_FLAG_ADDR, &flag, 1);
}
// Given NULL to start or block address, return the address of the next valid block.
// The last block returned is the unused block at the end.
// Return NULL if we have run off the end of the bonding space.
STATIC bonding_block_t *next_block(bonding_block_t *block) {
while (1) {
// Advance to next block.
if (block == NULL) {
return (bonding_block_t *) BONDING_DATA_START_ADDR;
} else if (block->type == BLOCK_UNUSED) {
// Already at last block (the unused block).
return NULL;
}
// Advance to next block.
block = (bonding_block_t *) ((uint8_t *) block + compute_block_size(block->data_length));
if (block >= (bonding_block_t *) BONDING_DATA_END_ADDR) {
// Went past end of bonding space.
return NULL;
}
if (block->type != BLOCK_INVALID) {
// Found an empty or a valid block.
return block;
}
// Invalid block (was erased); try again.
}
}
// Find the block with given is_central, type and ediv value.
// If type == BLOCK_UNUSED, ediv is ignored and the the sole unused block at the end is returned.
// If not found, return NULL.
STATIC bonding_block_t *find_existing_block(bool is_central, bonding_block_type_t type, uint16_t ediv) {
bonding_block_t *block = NULL;
while (1) {
block = next_block(block);
if (block == NULL) {
return NULL;
}
// If types match, and block is unused, just return it.
// Otherwise check that is_central and ediv match.
if (type == block->type) {
if (type == BLOCK_UNUSED ||
(is_central == block->is_central && ediv == block->ediv)) {
return block;
}
}
}
}
// Get an empty block large enough to store data_length data.
STATIC bonding_block_t* find_unused_block(uint16_t data_length) {
bonding_block_t *unused_block = find_existing_block(true, BLOCK_UNUSED, EDIV_INVALID);
// If no more room, erase all existing blocks and start over.
if (!unused_block ||
(uint8_t *) unused_block + compute_block_size(data_length) >= (uint8_t *) BONDING_DATA_END_ADDR) {
bonding_erase_storage();
unused_block = (bonding_block_t *) BONDING_DATA_START_ADDR;
}
return unused_block;
}
// Set the header word to all 0's, to mark the block as invalid.
// We don't change data_length, so we can still skip over this block.
STATIC void invalidate_block(bonding_block_t *block) {
uint32_t zero = 0;
sd_flash_write_sync((uint32_t *) block, &zero, 1);
}
// Write bonding block header.
STATIC void write_block_header(bonding_block_t *dest_block, bonding_block_t *source_block_header) {
sd_flash_write_sync((uint32_t *) dest_block, (uint32_t *) source_block_header, sizeof(bonding_block_t) / 4);
}
// Write variable-length data at end of bonding block.
STATIC void write_block_data(bonding_block_t *dest_block, uint8_t *data, uint16_t data_length) {
// Minimize the number of writes. Datasheet says no more than two writes per word before erasing again.
// Start writing after the current header.
uint32_t *flash_word_p = (uint32_t *) ((uint8_t *) dest_block + sizeof(bonding_block_t));
while (1) {
uint32_t word = 0xffffffff;
memcpy(&word, data, data_length >= 4 ? 4 : data_length);
sd_flash_write_sync(flash_word_p, &word, 1);
if (data_length <= 4) {
break;
}
data_length -= 4;
data += 4;
// Increment by word size.
flash_word_p++;
}
}
STATIC void write_sys_attr_block(bleio_connection_internal_t *connection) {
uint16_t length = 0;
// First find out how big a buffer we need, then fetch the data.
if(sd_ble_gatts_sys_attr_get(connection->conn_handle, NULL, &length, SYS_ATTR_FLAGS) != NRF_SUCCESS) {
return;
}
uint8_t sys_attr[length];
if(sd_ble_gatts_sys_attr_get(connection->conn_handle, sys_attr, &length, SYS_ATTR_FLAGS) != NRF_SUCCESS) {
return;
}
// Is there an existing sys_attr block that matches the current sys_attr data?
bonding_block_t *existing_block =
find_existing_block(connection->is_central, BLOCK_SYS_ATTR, connection->ediv);
if (existing_block) {
if (length == existing_block->data_length &&
memcmp(sys_attr, existing_block->data, length) == 0) {
// Identical block found. No need to store again.
return;
}
// Data doesn't match. Invalidate block and store a new one.
invalidate_block(existing_block);
}
bonding_block_t block_header = {
.is_central = connection->is_central,
.type = BLOCK_SYS_ATTR,
.ediv = connection->ediv,
.conn_handle = connection->conn_handle,
.data_length = length,
};
bonding_block_t *new_block = find_unused_block(length);
write_block_header(new_block, &block_header);
write_block_data(new_block, sys_attr, length);
return;
}
STATIC void write_keys_block(bleio_connection_internal_t *connection) {
uint16_t const ediv = connection->is_central
? connection->bonding_keys.peer_enc.master_id.ediv
: connection->bonding_keys.own_enc.master_id.ediv;
// Is there an existing keys block that matches?
bonding_block_t *existing_block = find_existing_block(connection->is_central, BLOCK_KEYS, ediv);
if (existing_block) {
if (existing_block->data_length == sizeof(bonding_keys_t) &&
memcmp(existing_block->data, &connection->bonding_keys, sizeof(bonding_keys_t)) == 0) {
// Identical block found. No need to store again.
return;
}
// Data doesn't match. Invalidate block and store a new one.
invalidate_block(existing_block);
}
bonding_block_t block_header = {
.is_central = connection->is_central,
.type = BLOCK_KEYS,
.ediv = ediv,
.conn_handle = connection->conn_handle,
.data_length = sizeof(bonding_keys_t),
};
bonding_block_t *new_block = find_unused_block(sizeof(bonding_keys_t));
write_block_header(new_block, &block_header);
write_block_data(new_block, (uint8_t *) &connection->bonding_keys, sizeof(bonding_keys_t));
}
void bonding_clear_keys(bonding_keys_t *bonding_keys) {
memset((uint8_t*) bonding_keys, 0, sizeof(bonding_keys_t));
}
void bonding_reset(void) {
if (BONDING_FLAG != *((uint32_t *) BONDING_START_FLAG_ADDR) ||
BONDING_FLAG != *((uint32_t *) BONDING_END_FLAG_ADDR)) {
bonding_erase_storage();
}
}
// Write bonding blocks to flash. Requests have been queued during evt handlers.
void bonding_background(void) {
// A paired connection will request that its keys and CCCD values be stored.
// The CCCD store whenever a CCCD value is written.
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
bleio_connection_internal_t *connection = &bleio_connections[i];
// Wait at least one second before saving CCCD, to consolidate
// writes that involve multiple CCCDs. For instance, for HID,
// three CCCD's are set in short succession by the HID client.
if (connection->do_bond_cccds) {
uint64_t current_ticks_ms = supervisor_ticks_ms64();
if (current_ticks_ms - connection->do_bond_cccds_request_time >= 1000) {
write_sys_attr_block(connection);
connection->do_bond_cccds = false;
}
}
if (connection->do_bond_keys) {
write_keys_block(connection);
connection->do_bond_keys = false;
}
}
}
bool bonding_load_cccd_info(bool is_central, uint16_t conn_handle, uint16_t ediv) {
bonding_block_t *block = find_existing_block(is_central, BLOCK_SYS_ATTR, ediv);
if (block == NULL) {
return false;
}
return NRF_SUCCESS ==
sd_ble_gatts_sys_attr_set(conn_handle, block->data, block->data_length, SYS_ATTR_FLAGS);
}
bool bonding_load_keys(bool is_central, uint16_t ediv, bonding_keys_t *bonding_keys) {
bonding_block_t *block = find_existing_block(is_central, BLOCK_KEYS, ediv);
if (block == NULL) {
return false;
}
if (sizeof(bonding_keys_t) != block->data_length) {
// bonding_keys_t is a fixed length, so lengths should match.
return false;
}
memcpy(bonding_keys, block->data, block->data_length);
return true;
}

View File

@ -1,83 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Dan Halbert for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_BONDING_H
#define MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_BONDING_H
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "common-hal/_bleio/__init__.h"
#define EDIV_INVALID (0xffff)
#define BONDING_DEBUG (1)
#if BONDING_DEBUG
#define BONDING_DEBUG_PRINTF(...) printf(__VA_ARGS__)
#define BONDING_DEBUG_PRINT_BLOCK(block) bonding_print_block(block)
#define BONDING_DEBUG_PRINT_KEYS(keys) bonding_print_keys(keys)
#else
#define BONDING_DEBUG_PRINTF(...)
#define BONDING_DEBUG_PRINT_BLOCK(block)
#define BONDING_DEBUG_PRINT_KEYS(keys)
#endif
// Bonding data is stored in variable-length blocks consecutively in
// erased flash (all 1's). The blocks are 32-bit aligned, though the
// data may be any number of bytes. We hop through the blocks using
// the size field to find the next block. When we hit a word that is
// all 1's, we have reached the end of the blocks. We can write a new
// block there.
typedef enum {
BLOCK_INVALID = 0, // Ignore this block
BLOCK_KEYS = 1, // Block contains bonding keys.
BLOCK_SYS_ATTR = 2, // Block contains sys_attr values (CCCD settings, etc.).
BLOCK_UNUSED = 0xff, // Initial erased value.
} bonding_block_type_t;
typedef struct {
bool is_central: 1; // 1 if data is for a central role.
uint16_t reserved: 7; // Not currently used
bonding_block_type_t type: 8; // What kind of data is stored in.
uint16_t ediv; // ediv value; used as a lookup key.
uint16_t conn_handle; // Connection handle: used when a BLOCK_SYS_ATTR is queued to write.
// Not used as a key, etc.
uint16_t data_length; // Length of data in bytes, including ediv, not including padding.
// End of block header. 32-bit boundary here.
uint8_t data[]; // Rest of data in the block. Needs to be 32-bit aligned.
// Block is padded to 32-bit alignment.
} bonding_block_t;
void bonding_background(void);
void bonding_erase_storage(void);
void bonding_reset(void);
void bonding_clear_keys(bonding_keys_t *bonding_keys);
bool bonding_load_cccd_info(bool is_central, uint16_t conn_handle, uint16_t ediv);
bool bonding_load_keys(bool is_central, uint16_t ediv, bonding_keys_t *bonding_keys);
#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_BONDING_H

View File

@ -317,6 +317,13 @@ SRC_COMMON_HAL_ALL = \
watchdog/WatchDogTimer.c \ watchdog/WatchDogTimer.c \
watchdog/__init__.c \ watchdog/__init__.c \
ifeq ($(CIRCUITPY_BLEIO_HCI),1)
SRC_C +=\
common_hal/_bleio/hci.c \
endif
SRC_COMMON_HAL = $(filter $(SRC_PATTERNS), $(SRC_COMMON_HAL_ALL)) SRC_COMMON_HAL = $(filter $(SRC_PATTERNS), $(SRC_COMMON_HAL_ALL))
# These don't have corresponding files in each port but are still located in # These don't have corresponding files in each port but are still located in
@ -463,6 +470,11 @@ $(filter $(SRC_PATTERNS), \
displayio/display_core.c \ displayio/display_core.c \
) )
SRC_COMMON_HAL_INTERNAL = \
$(filter $(SRC_PATTERNS), \
_bleio/ \
)
ifeq ($(INTERNAL_LIBM),1) ifeq ($(INTERNAL_LIBM),1)
SRC_LIBM = \ SRC_LIBM = \
$(addprefix lib/,\ $(addprefix lib/,\

View File

@ -90,10 +90,10 @@ STATIC mp_obj_t bleio_adapter_make_new(const mp_obj_type_t *type, size_t n_args,
{ MP_QSTR_cts, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_cts, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 115200 } }, { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 115200 } },
{ MP_QSTR_buffer_size, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 256 } }, { MP_QSTR_buffer_size, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 256 } },
{ MP_QSTR_spi_cs, MP_ARG_KW_ONLY }| MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_spi_cs, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_gpio0, MP_ARG_KW_ONLY }| MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_gpio0, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_reset, MP_ARG_KW_ONLY }| MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_reset, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_reset_high, MP_ARG_KW_ONLY |MP_ARG_BOOL }, { MP_QSTR_reset_high, MP_ARG_KW_ONLY | MP_ARG_BOOL },
}; };
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
@ -108,13 +108,23 @@ STATIC mp_obj_t bleio_adapter_make_new(const mp_obj_type_t *type, size_t n_args,
const mcu_pin_obj_t *reset = validate_obj_is_free_pin(args[ARG_reset].u_obj); const mcu_pin_obj_t *reset = validate_obj_is_free_pin(args[ARG_reset].u_obj);
const bool reset_high = args[ARG_reset_high].u_bool; const bool reset_high = args[ARG_reset_high].u_bool;
if (args[ARG_baudrate].u_int <= 0) {
mp_raise_ValueError(translate("baudrate must be > 0"));
}
const uint32_t baudrate = args[ARG_baudrate].u_int;
if (args[ARG_buffer_size].u_int <= 1) {
mp_raise_ValueError(translate("buffer_size must be >= 1"));
}
const uint32_t buffer_size = args[ARG_buffer_size].u_int;
common_hal_bleio_adapter_construct(&common_hal_bleio_adapter_obj, tx, rx, rts, cts, common_hal_bleio_adapter_construct(&common_hal_bleio_adapter_obj, tx, rx, rts, cts,
args[ARG_baudrate], arg[ARG_buffer_size], baudrate, buffer_size,
spi_cs, gpio0, spi_cs, gpio0,
reset, reset_high); reset, reset_high);
common_hal_bleio_adapter_set_enabled(&common_hal_bleio_adapter_obj, true); common_hal_bleio_adapter_set_enabled(&common_hal_bleio_adapter_obj, true);
return MP_OBJ_FROM_PTR(service); return MP_OBJ_FROM_PTR(&common_hal_bleio_adapter_obj);
} }
#endif #endif
//| //|

View File

@ -37,6 +37,10 @@
const mp_obj_type_t bleio_adapter_type; const mp_obj_type_t bleio_adapter_type;
#if CIRCUITPY_BLEIO_HCI
void common_hal_bleio_adapter_construct(bleio_adapter_obj_t *self, const mcu_pin_obj_t *tx, const mcu_pin_obj_t *rx, const mcu_pin_obj_t *rts, const mcu_pin_obj_t *cts, uint32_t baudrate, uint32_t buffer_size, const mcu_pin_obj_t* spi_cs, const mcu_pin_obj_t* gpio0, const mcu_pin_obj_t *reset, bool reset_high);
#endif
extern bool common_hal_bleio_adapter_get_advertising(bleio_adapter_obj_t *self); extern bool common_hal_bleio_adapter_get_advertising(bleio_adapter_obj_t *self);
extern bool common_hal_bleio_adapter_get_enabled(bleio_adapter_obj_t *self); extern bool common_hal_bleio_adapter_get_enabled(bleio_adapter_obj_t *self);
extern void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enabled); extern void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enabled);