wip; compiles; much commented out
This commit is contained in:
parent
57bac9a1fc
commit
1bc2e979eb
@ -31,9 +31,8 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bonding.h"
|
||||
|
||||
#include "py/gc.h"
|
||||
#include "py/mphal.h"
|
||||
#include "py/objstr.h"
|
||||
#include "py/runtime.h"
|
||||
#include "supervisor/shared/safe_mode.h"
|
||||
@ -74,111 +73,111 @@
|
||||
|
||||
bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT];
|
||||
|
||||
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;
|
||||
// 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;
|
||||
|
||||
// // For debugging.
|
||||
// // mp_printf(&mp_plat_print, "Adapter event: 0x%04x\n", ble_evt->header.evt_id);
|
||||
// // For debugging.
|
||||
// // mp_printf(&mp_plat_print, "Adapter event: 0x%04x\n", ble_evt->header.evt_id);
|
||||
|
||||
// switch (ble_evt->header.evt_id) {
|
||||
// case BLE_GAP_EVT_CONNECTED: {
|
||||
// // Find an empty connection. One must always be available because the SD has the same
|
||||
// // total connection limit.
|
||||
// bleio_connection_internal_t *connection;
|
||||
// for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
|
||||
// connection = &bleio_connections[i];
|
||||
// if (connection->conn_handle == BLE_CONN_HANDLE_INVALID) {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// switch (ble_evt->header.evt_id) {
|
||||
// case BLE_GAP_EVT_CONNECTED: {
|
||||
// // Find an empty connection. One must always be available because the SD has the same
|
||||
// // total connection limit.
|
||||
// bleio_connection_internal_t *connection;
|
||||
// for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
|
||||
// connection = &bleio_connections[i];
|
||||
// if (connection->conn_handle == BLE_CONN_HANDLE_INVALID) {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Central has connected.
|
||||
// ble_gap_evt_connected_t* connected = &ble_evt->evt.gap_evt.params.connected;
|
||||
// // Central has 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->connection_obj = mp_const_none;
|
||||
// connection->pair_status = PAIR_NOT_PAIRED;
|
||||
// connection->mtu = 0;
|
||||
// connection->conn_handle = ble_evt->evt.gap_evt.conn_handle;
|
||||
// connection->connection_obj = mp_const_none;
|
||||
// connection->pair_status = PAIR_NOT_PAIRED;
|
||||
// connection->mtu = 0;
|
||||
|
||||
// ble_drv_add_event_handler_entry(&connection->handler_entry, connection_on_ble_evt, connection);
|
||||
// self->connection_objs = NULL;
|
||||
// ble_drv_add_event_handler_entry(&connection->handler_entry, connection_on_ble_evt, connection);
|
||||
// self->connection_objs = NULL;
|
||||
|
||||
// // Save the current connection parameters.
|
||||
// memcpy(&connection->conn_params, &connected->conn_params, sizeof(ble_gap_conn_params_t));
|
||||
// // Save the current connection parameters.
|
||||
// memcpy(&connection->conn_params, &connected->conn_params, sizeof(ble_gap_conn_params_t));
|
||||
|
||||
// #if CIRCUITPY_VERBOSE_BLE
|
||||
// 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);
|
||||
// #endif
|
||||
// #if CIRCUITPY_VERBOSE_BLE
|
||||
// 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);
|
||||
// #endif
|
||||
|
||||
// // See if connection interval set by Central is out of range.
|
||||
// // If so, negotiate our preferred range.
|
||||
// ble_gap_conn_params_t conn_params;
|
||||
// sd_ble_gap_ppcp_get(&conn_params);
|
||||
// if (conn_params.min_conn_interval < connected->conn_params.min_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);
|
||||
// }
|
||||
// self->current_advertising_data = NULL;
|
||||
// break;
|
||||
// }
|
||||
// case BLE_GAP_EVT_DISCONNECTED: {
|
||||
// // Find the connection that was disconnected.
|
||||
// bleio_connection_internal_t *connection;
|
||||
// for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
|
||||
// connection = &bleio_connections[i];
|
||||
// if (connection->conn_handle == ble_evt->evt.gap_evt.conn_handle) {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// ble_drv_remove_event_handler(connection_on_ble_evt, connection);
|
||||
// connection->conn_handle = BLE_CONN_HANDLE_INVALID;
|
||||
// connection->pair_status = PAIR_NOT_PAIRED;
|
||||
// if (connection->connection_obj != mp_const_none) {
|
||||
// bleio_connection_obj_t* obj = connection->connection_obj;
|
||||
// obj->connection = NULL;
|
||||
// obj->disconnect_reason = ble_evt->evt.gap_evt.params.disconnected.reason;
|
||||
// }
|
||||
// self->connection_objs = NULL;
|
||||
// // See if connection interval set by Central is out of range.
|
||||
// // If so, negotiate our preferred range.
|
||||
// ble_gap_conn_params_t conn_params;
|
||||
// sd_ble_gap_ppcp_get(&conn_params);
|
||||
// if (conn_params.min_conn_interval < connected->conn_params.min_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);
|
||||
// }
|
||||
// self->current_advertising_data = NULL;
|
||||
// break;
|
||||
// }
|
||||
// case BLE_GAP_EVT_DISCONNECTED: {
|
||||
// // Find the connection that was disconnected.
|
||||
// bleio_connection_internal_t *connection;
|
||||
// for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
|
||||
// connection = &bleio_connections[i];
|
||||
// if (connection->conn_handle == ble_evt->evt.gap_evt.conn_handle) {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// ble_drv_remove_event_handler(connection_on_ble_evt, connection);
|
||||
// connection->conn_handle = BLE_CONN_HANDLE_INVALID;
|
||||
// connection->pair_status = PAIR_NOT_PAIRED;
|
||||
// if (connection->connection_obj != mp_const_none) {
|
||||
// bleio_connection_obj_t* obj = connection->connection_obj;
|
||||
// obj->connection = NULL;
|
||||
// obj->disconnect_reason = ble_evt->evt.gap_evt.params.disconnected.reason;
|
||||
// }
|
||||
// self->connection_objs = NULL;
|
||||
|
||||
// break;
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
|
||||
// case BLE_GAP_EVT_ADV_SET_TERMINATED:
|
||||
// self->current_advertising_data = NULL;
|
||||
// break;
|
||||
// case BLE_GAP_EVT_ADV_SET_TERMINATED:
|
||||
// self->current_advertising_data = NULL;
|
||||
// break;
|
||||
|
||||
// default:
|
||||
// // For debugging.
|
||||
// // mp_printf(&mp_plat_print, "Unhandled adapter event: 0x%04x\n", ble_evt->header.evt_id);
|
||||
// return false;
|
||||
// break;
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
// default:
|
||||
// // For debugging.
|
||||
// // mp_printf(&mp_plat_print, "Unhandled adapter event: 0x%04x\n", ble_evt->header.evt_id);
|
||||
// return false;
|
||||
// break;
|
||||
// }
|
||||
// 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));
|
||||
}
|
||||
// }
|
||||
|
||||
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) {
|
||||
uint8_t len = sizeof(default_ble_name) - 1;
|
||||
// STATIC void bleio_adapter_reset_name(bleio_adapter_obj_t *self) {
|
||||
// // uint8_t len = sizeof(default_ble_name) - 1;
|
||||
|
||||
ble_gap_addr_t local_address;
|
||||
get_address(self, &local_address);
|
||||
// // ble_gap_addr_t 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 - 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 - 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 - 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 - 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] = '\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->rx = rx;
|
||||
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.
|
||||
// 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.
|
||||
common_hal_busio_uart_construct(&self->hci_uart, tx, rx, NULL, NULL, NULL, false,
|
||||
BLEIO_HCI_BAUDRATE, 8, PARITY_NONE, 1, 0.0f,
|
||||
BLEIO_HCI_BUFFER_SIZE, NULL, false);
|
||||
common_hal_busio_uart_construct(&self->hci_uart, self->tx, self->rx, NULL, NULL, NULL, false,
|
||||
self->baudrate, 8, PARITY_NONE, 1, 0.0f,
|
||||
self->buffer_size, NULL, false);
|
||||
|
||||
// RTS is output, active high
|
||||
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 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->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->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.
|
||||
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->cts_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);
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
common_hal_bleio_adapter_set_enabled(self, true);
|
||||
|
||||
ble_gap_addr_t local_address;
|
||||
get_address(self, &local_address);
|
||||
// ble_gap_addr_t local_address;
|
||||
// get_address(self, &local_address);
|
||||
|
||||
bleio_address_obj_t *address = m_new_obj(bleio_address_obj_t);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
// Make the connection object and return it.
|
||||
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
|
||||
bleio_connection_internal_t *connection = &bleio_connections[i];
|
||||
if (connection->conn_handle == conn_handle) {
|
||||
return bleio_connection_new_from_internal(connection);
|
||||
}
|
||||
}
|
||||
// for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
|
||||
// bleio_connection_internal_t *connection = &bleio_connections[i];
|
||||
// if (connection->conn_handle == conn_handle) {
|
||||
// return bleio_connection_new_from_internal(connection);
|
||||
// }
|
||||
// }
|
||||
|
||||
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.
|
||||
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) {
|
||||
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)) {
|
||||
mp_raise_ValueError(translate("Data too large for advertisement packet"));
|
||||
}
|
||||
//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)) {
|
||||
// mp_raise_ValueError(translate("Data too large for advertisement packet"));
|
||||
// }
|
||||
}
|
||||
|
||||
// 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
|
||||
// point of randomizing the MAC address?
|
||||
if (!timeout) {
|
||||
if (anonymous) {
|
||||
// The Nordic macro is in units of 10ms. Convert to seconds.
|
||||
uint32_t adv_timeout_max_secs = UNITS_TO_SEC(BLE_GAP_ADV_TIMEOUT_LIMITED_MAX, UNIT_10_MS);
|
||||
uint32_t rotate_timeout_max_secs = BLE_GAP_DEFAULT_PRIVATE_ADDR_CYCLE_INTERVAL_S;
|
||||
timeout = MIN(adv_timeout_max_secs, rotate_timeout_max_secs);
|
||||
}
|
||||
else {
|
||||
timeout = BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED;
|
||||
}
|
||||
//FIX if (anonymous) {
|
||||
// // The Nordic macro is in units of 10ms. Convert to seconds.
|
||||
// uint32_t adv_timeout_max_secs = UNITS_TO_SEC(BLE_GAP_ADV_TIMEOUT_LIMITED_MAX, UNIT_10_MS);
|
||||
// uint32_t rotate_timeout_max_secs = BLE_GAP_DEFAULT_PRIVATE_ADDR_CYCLE_INTERVAL_S;
|
||||
// timeout = MIN(adv_timeout_max_secs, rotate_timeout_max_secs);
|
||||
// }
|
||||
// else {
|
||||
// timeout = BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED;
|
||||
// }
|
||||
} else {
|
||||
if (SEC_TO_UNITS(timeout, UNIT_10_MS) > BLE_GAP_ADV_TIMEOUT_LIMITED_MAX) {
|
||||
mp_raise_bleio_BluetoothError(translate("Timeout is too long: Maximum timeout length is %d seconds"),
|
||||
UNITS_TO_SEC(BLE_GAP_ADV_TIMEOUT_LIMITED_MAX, UNIT_10_MS));
|
||||
}
|
||||
//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"),
|
||||
// UNITS_TO_SEC(BLE_GAP_ADV_TIMEOUT_LIMITED_MAX, UNIT_10_MS));
|
||||
// }
|
||||
}
|
||||
|
||||
// The advertising data buffers must not move, because the SoftDevice depends on them.
|
||||
// So make them long-lived and reuse them onwards.
|
||||
if (self->advertising_data == NULL) {
|
||||
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);
|
||||
}
|
||||
//FIX GET CORRECT SIZE
|
||||
// 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);
|
||||
// }
|
||||
|
||||
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);
|
||||
@ -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) {
|
||||
bonding_erase_storage();
|
||||
//FIX bonding_erase_storage();
|
||||
}
|
||||
|
||||
void bleio_adapter_gc_collect(bleio_adapter_obj_t* adapter) {
|
||||
|
@ -52,15 +52,15 @@ typedef struct {
|
||||
bleio_scanresults_obj_t* scan_results;
|
||||
mp_obj_t name;
|
||||
mp_obj_tuple_t *connection_objs;
|
||||
mcu_pin_obj_t* tx;
|
||||
mcu_pin_obj_t* rx;
|
||||
mcu_pin_obj_t* rts;
|
||||
mcu_pin_obj_t* cts;
|
||||
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;
|
||||
uint16_t buffer_size;
|
||||
mcu_pin_obj_t* spi_cs;
|
||||
mcu_pin_obj_t* gpio0;
|
||||
mcu_pin_obj_t* reset;
|
||||
const mcu_pin_obj_t* spi_cs;
|
||||
const mcu_pin_obj_t* gpio0;
|
||||
const mcu_pin_obj_t* reset;
|
||||
bool reset_high;
|
||||
busio_uart_obj_t hci_uart;
|
||||
digitalio_digitalinout_obj_t rts_digitalio;
|
||||
|
@ -27,34 +27,34 @@
|
||||
#include "shared-bindings/_bleio/Attribute.h"
|
||||
|
||||
// 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) {
|
||||
switch (security_mode) {
|
||||
case SECURITY_MODE_NO_ACCESS:
|
||||
BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(perm);
|
||||
break;
|
||||
// void bleio_attribute_gatts_set_security_mode(ble_gap_conn_sec_mode_t *perm, bleio_attribute_security_mode_t security_mode) {
|
||||
// switch (security_mode) {
|
||||
// case SECURITY_MODE_NO_ACCESS:
|
||||
// BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(perm);
|
||||
// break;
|
||||
|
||||
case SECURITY_MODE_OPEN:
|
||||
BLE_GAP_CONN_SEC_MODE_SET_OPEN(perm);
|
||||
break;
|
||||
// case SECURITY_MODE_OPEN:
|
||||
// BLE_GAP_CONN_SEC_MODE_SET_OPEN(perm);
|
||||
// break;
|
||||
|
||||
case SECURITY_MODE_ENC_NO_MITM:
|
||||
BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(perm);
|
||||
break;
|
||||
// case SECURITY_MODE_ENC_NO_MITM:
|
||||
// BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(perm);
|
||||
// break;
|
||||
|
||||
case SECURITY_MODE_ENC_WITH_MITM:
|
||||
BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(perm);
|
||||
break;
|
||||
// case SECURITY_MODE_ENC_WITH_MITM:
|
||||
// BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(perm);
|
||||
// break;
|
||||
|
||||
case SECURITY_MODE_LESC_ENC_WITH_MITM:
|
||||
BLE_GAP_CONN_SEC_MODE_SET_LESC_ENC_WITH_MITM(perm);
|
||||
break;
|
||||
// case SECURITY_MODE_LESC_ENC_WITH_MITM:
|
||||
// BLE_GAP_CONN_SEC_MODE_SET_LESC_ENC_WITH_MITM(perm);
|
||||
// break;
|
||||
|
||||
case SECURITY_MODE_SIGNED_NO_MITM:
|
||||
BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(perm);
|
||||
break;
|
||||
// case SECURITY_MODE_SIGNED_NO_MITM:
|
||||
// BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(perm);
|
||||
// break;
|
||||
|
||||
case SECURITY_MODE_SIGNED_WITH_MITM:
|
||||
BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(perm);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// case SECURITY_MODE_SIGNED_WITH_MITM:
|
||||
// BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(perm);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
@ -29,6 +29,13 @@
|
||||
|
||||
#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
|
||||
|
@ -33,70 +33,70 @@
|
||||
#include "shared-bindings/_bleio/Service.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) {
|
||||
uint16_t cccd;
|
||||
ble_gatts_value_t value = {
|
||||
.p_value = (uint8_t*) &cccd,
|
||||
.len = 2,
|
||||
};
|
||||
// STATIC uint16_t characteristic_get_cccd(uint16_t cccd_handle, uint16_t conn_handle) {
|
||||
// uint16_t cccd;
|
||||
// // ble_gatts_value_t value = {
|
||||
// // .p_value = (uint8_t*) &cccd,
|
||||
// // .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) {
|
||||
// CCCD is not set, so say that neither Notify nor Indicate is enabled.
|
||||
cccd = 0;
|
||||
} else {
|
||||
check_nrf_error(err_code);
|
||||
}
|
||||
// // if (err_code == BLE_ERROR_GATTS_SYS_ATTR_MISSING) {
|
||||
// // // CCCD is not set, so say that neither Notify nor Indicate is enabled.
|
||||
// // cccd = 0;
|
||||
// // } else {
|
||||
// // 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) {
|
||||
uint16_t hvx_len = bufinfo->len;
|
||||
// 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;
|
||||
|
||||
ble_gatts_hvx_params_t hvx_params = {
|
||||
.handle = handle,
|
||||
.type = hvx_type,
|
||||
.offset = 0,
|
||||
.p_len = &hvx_len,
|
||||
.p_data = bufinfo->buf,
|
||||
};
|
||||
// ble_gatts_hvx_params_t hvx_params = {
|
||||
// .handle = handle,
|
||||
// .type = hvx_type,
|
||||
// .offset = 0,
|
||||
// .p_len = &hvx_len,
|
||||
// .p_data = bufinfo->buf,
|
||||
// };
|
||||
|
||||
while (1) {
|
||||
const uint32_t err_code = sd_ble_gatts_hvx(conn_handle, &hvx_params);
|
||||
if (err_code == NRF_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
// TX buffer is full
|
||||
// We could wait for an event indicating the write is complete, but just retrying is easier.
|
||||
if (err_code == NRF_ERROR_RESOURCES) {
|
||||
RUN_BACKGROUND_TASKS;
|
||||
continue;
|
||||
}
|
||||
// while (1) {
|
||||
// const uint32_t err_code = sd_ble_gatts_hvx(conn_handle, &hvx_params);
|
||||
// if (err_code == NRF_SUCCESS) {
|
||||
// break;
|
||||
// }
|
||||
// // TX buffer is full
|
||||
// // We could wait for an event indicating the write is complete, but just retrying is easier.
|
||||
// if (err_code == NRF_ERROR_RESOURCES) {
|
||||
// RUN_BACKGROUND_TASKS;
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// Some real error has occurred.
|
||||
check_nrf_error(err_code);
|
||||
}
|
||||
}
|
||||
// // Some real error has occurred.
|
||||
// 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) {
|
||||
self->service = service;
|
||||
self->uuid = uuid;
|
||||
self->handle = BLE_GATT_HANDLE_INVALID;
|
||||
//FIX self->handle = BLE_GATT_HANDLE_INVALID;
|
||||
self->props = props;
|
||||
self->read_perm = read_perm;
|
||||
self->write_perm = write_perm;
|
||||
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;
|
||||
if (max_length < 0 || max_length > max_length_max) {
|
||||
mp_raise_ValueError_varg(translate("max_length must be 0-%d when fixed_length is %s"),
|
||||
max_length_max, fixed_length ? "True" : "False");
|
||||
}
|
||||
//FIX
|
||||
// const mp_int_t max_length_max = fixed_length ? BLE_GATTS_FIX_ATTR_LEN_MAX : BLE_GATTS_VAR_ATTR_LEN_MAX;
|
||||
// if (max_length < 0 || max_length > max_length_max) {
|
||||
// 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->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++) {
|
||||
bleio_connection_internal_t *connection = &bleio_connections[i];
|
||||
uint16_t conn_handle = connection->conn_handle;
|
||||
if (connection->conn_handle == BLE_CONN_HANDLE_INVALID) {
|
||||
if (conn_handle == BLE_CONN_HANDLE_INVALID) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint16_t cccd = 0;
|
||||
//FIX
|
||||
// uint16_t cccd = 0;
|
||||
|
||||
const bool notify = self->props & CHAR_PROP_NOTIFY;
|
||||
const bool indicate = self->props & CHAR_PROP_INDICATE;
|
||||
if (notify | indicate) {
|
||||
cccd = characteristic_get_cccd(self->cccd_handle, conn_handle);
|
||||
}
|
||||
// const bool notify = self->props & CHAR_PROP_NOTIFY;
|
||||
// const bool indicate = self->props & CHAR_PROP_INDICATE;
|
||||
// if (notify | indicate) {
|
||||
// cccd = characteristic_get_cccd(self->cccd_handle, conn_handle);
|
||||
// }
|
||||
|
||||
// It's possible that both notify and indicate are set.
|
||||
if (notify && (cccd & BLE_GATT_HVX_NOTIFICATION)) {
|
||||
characteristic_gatts_notify_indicate(self->handle, conn_handle, bufinfo, BLE_GATT_HVX_NOTIFICATION);
|
||||
}
|
||||
if (indicate && (cccd & BLE_GATT_HVX_INDICATION)) {
|
||||
characteristic_gatts_notify_indicate(self->handle, conn_handle, bufinfo, BLE_GATT_HVX_INDICATION);
|
||||
}
|
||||
// // It's possible that both notify and indicate are set.
|
||||
// if (notify && (cccd & BLE_GATT_HVX_NOTIFICATION)) {
|
||||
// characteristic_gatts_notify_indicate(self->handle, conn_handle, bufinfo, BLE_GATT_HVX_NOTIFICATION);
|
||||
// }
|
||||
// if (indicate && (cccd & 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) {
|
||||
ble_uuid_t desc_uuid;
|
||||
bleio_uuid_convert_to_nrf_ble_uuid(descriptor->uuid, &desc_uuid);
|
||||
//FIX
|
||||
// ble_uuid_t desc_uuid;
|
||||
// bleio_uuid_convert_to_nrf_ble_uuid(descriptor->uuid, &desc_uuid);
|
||||
|
||||
ble_gatts_attr_md_t desc_attr_md = {
|
||||
// Data passed is not in a permanent location and should be copied.
|
||||
.vloc = BLE_GATTS_VLOC_STACK,
|
||||
.vlen = !descriptor->fixed_length,
|
||||
};
|
||||
// ble_gatts_attr_md_t desc_attr_md = {
|
||||
// // Data passed is not in a permanent location and should be copied.
|
||||
// .vloc = BLE_GATTS_VLOC_STACK,
|
||||
// .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.write_perm, descriptor->write_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);
|
||||
|
||||
mp_buffer_info_t desc_value_bufinfo;
|
||||
mp_get_buffer_raise(descriptor->value, &desc_value_bufinfo, MP_BUFFER_READ);
|
||||
// mp_buffer_info_t desc_value_bufinfo;
|
||||
// mp_get_buffer_raise(descriptor->value, &desc_value_bufinfo, MP_BUFFER_READ);
|
||||
|
||||
ble_gatts_attr_t desc_attr = {
|
||||
.p_uuid = &desc_uuid,
|
||||
.p_attr_md = &desc_attr_md,
|
||||
.init_len = desc_value_bufinfo.len,
|
||||
.p_value = desc_value_bufinfo.buf,
|
||||
.init_offs = 0,
|
||||
.max_len = descriptor->max_length,
|
||||
};
|
||||
// ble_gatts_attr_t desc_attr = {
|
||||
// .p_uuid = &desc_uuid,
|
||||
// .p_attr_md = &desc_attr_md,
|
||||
// .init_len = desc_value_bufinfo.len,
|
||||
// .p_value = desc_value_bufinfo.buf,
|
||||
// .init_offs = 0,
|
||||
// .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;
|
||||
self->descriptor_list = descriptor;
|
||||
// descriptor->next = self->descriptor_list;
|
||||
// self->descriptor_list = descriptor;
|
||||
}
|
||||
|
||||
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);
|
||||
common_hal_bleio_check_connected(conn_handle);
|
||||
|
||||
uint16_t cccd_value =
|
||||
(notify ? BLE_GATT_HVX_NOTIFICATION : 0) |
|
||||
(indicate ? BLE_GATT_HVX_INDICATION : 0);
|
||||
//FIX
|
||||
// uint16_t cccd_value =
|
||||
// (notify ? BLE_GATT_HVX_NOTIFICATION : 0) |
|
||||
// (indicate ? BLE_GATT_HVX_INDICATION : 0);
|
||||
|
||||
ble_gattc_write_params_t write_params = {
|
||||
.write_op = BLE_GATT_OP_WRITE_REQ,
|
||||
.handle = self->cccd_handle,
|
||||
.p_value = (uint8_t *) &cccd_value,
|
||||
.len = 2,
|
||||
};
|
||||
// ble_gattc_write_params_t write_params = {
|
||||
// .write_op = BLE_GATT_OP_WRITE_REQ,
|
||||
// .handle = self->cccd_handle,
|
||||
// .p_value = (uint8_t *) &cccd_value,
|
||||
// .len = 2,
|
||||
// };
|
||||
|
||||
while (1) {
|
||||
uint32_t err_code = sd_ble_gattc_write(conn_handle, &write_params);
|
||||
if (err_code == NRF_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
// while (1) {
|
||||
// uint32_t err_code = sd_ble_gattc_write(conn_handle, &write_params);
|
||||
// if (err_code == NRF_SUCCESS) {
|
||||
// break;
|
||||
// }
|
||||
|
||||
// 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.
|
||||
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.
|
||||
RUN_BACKGROUND_TASKS;
|
||||
continue;
|
||||
}
|
||||
// // 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.
|
||||
// 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.
|
||||
// RUN_BACKGROUND_TASKS;
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// Some real error occurred.
|
||||
check_nrf_error(err_code);
|
||||
}
|
||||
// // Some real error occurred.
|
||||
// check_nrf_error(err_code);
|
||||
// }
|
||||
|
||||
}
|
||||
|
@ -37,44 +37,44 @@
|
||||
#include "common-hal/_bleio/CharacteristicBuffer.h"
|
||||
|
||||
// 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) {
|
||||
uint8_t is_nested_critical_region;
|
||||
sd_nvic_critical_region_enter(&is_nested_critical_region);
|
||||
ringbuf_put_n(&self->ringbuf, data, len);
|
||||
sd_nvic_critical_region_exit(is_nested_critical_region);
|
||||
}
|
||||
// STATIC void write_to_ringbuf(bleio_characteristic_buffer_obj_t *self, uint8_t *data, uint16_t len) {
|
||||
// uint8_t is_nested_critical_region;
|
||||
// sd_nvic_critical_region_enter(&is_nested_critical_region);
|
||||
// ringbuf_put_n(&self->ringbuf, data, len);
|
||||
// sd_nvic_critical_region_exit(is_nested_critical_region);
|
||||
// }
|
||||
|
||||
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;
|
||||
switch (ble_evt->header.evt_id) {
|
||||
case BLE_GATTS_EVT_WRITE: {
|
||||
// A client wrote to this server characteristic.
|
||||
// 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;
|
||||
// switch (ble_evt->header.evt_id) {
|
||||
// case BLE_GATTS_EVT_WRITE: {
|
||||
// // A client wrote to this server characteristic.
|
||||
|
||||
ble_gatts_evt_write_t *evt_write = &ble_evt->evt.gatts_evt.params.write;
|
||||
// Event handle must match the handle for my characteristic.
|
||||
if (evt_write->handle == self->characteristic->handle) {
|
||||
write_to_ringbuf(self, evt_write->data, evt_write->len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
// ble_gatts_evt_write_t *evt_write = &ble_evt->evt.gatts_evt.params.write;
|
||||
// // Event handle must match the handle for my characteristic.
|
||||
// if (evt_write->handle == self->characteristic->handle) {
|
||||
// write_to_ringbuf(self, evt_write->data, evt_write->len);
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
|
||||
case BLE_GATTC_EVT_HVX: {
|
||||
// A remote service wrote to this characteristic.
|
||||
// case BLE_GATTC_EVT_HVX: {
|
||||
// // A remote service wrote to this characteristic.
|
||||
|
||||
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.
|
||||
if (evt_hvx->type == BLE_GATT_HVX_NOTIFICATION &&
|
||||
evt_hvx->handle == self->characteristic->handle) {
|
||||
write_to_ringbuf(self, evt_hvx->data, evt_hvx->len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// 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.
|
||||
// if (evt_hvx->type == BLE_GATT_HVX_NOTIFICATION &&
|
||||
// evt_hvx->handle == self->characteristic->handle) {
|
||||
// write_to_ringbuf(self, evt_hvx->data, evt_hvx->len);
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// default:
|
||||
// return false;
|
||||
// break;
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// Assumes that timeout and buffer_size have been validated before call.
|
||||
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.
|
||||
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.
|
||||
uint8_t is_nested_critical_region;
|
||||
sd_nvic_critical_region_enter(&is_nested_critical_region);
|
||||
// FIX uint8_t 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);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
uint32_t common_hal_bleio_characteristic_buffer_rx_characters_available(bleio_characteristic_buffer_obj_t *self) {
|
||||
uint8_t is_nested_critical_region;
|
||||
sd_nvic_critical_region_enter(&is_nested_critical_region);
|
||||
//FIX uint8_t is_nested_critical_region;
|
||||
//FIX sd_nvic_critical_region_enter(&is_nested_critical_region);
|
||||
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;
|
||||
}
|
||||
|
||||
void common_hal_bleio_characteristic_buffer_clear_rx_buffer(bleio_characteristic_buffer_obj_t *self) {
|
||||
// prevent conflict with uart irq
|
||||
uint8_t is_nested_critical_region;
|
||||
sd_nvic_critical_region_enter(&is_nested_critical_region);
|
||||
//FIX uint8_t is_nested_critical_region;
|
||||
//FIX sd_nvic_critical_region_enter(&is_nested_critical_region);
|
||||
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) {
|
||||
@ -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) {
|
||||
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
@ -34,7 +34,6 @@
|
||||
#include "py/objlist.h"
|
||||
|
||||
#include "common-hal/_bleio/__init__.h"
|
||||
#include "common-hal/_bleio/bonding.h"
|
||||
#include "shared-module/_bleio/Address.h"
|
||||
#include "common-hal/_bleio/Service.h"
|
||||
|
||||
|
@ -36,151 +36,152 @@
|
||||
#include "shared-bindings/_bleio/PacketBuffer.h"
|
||||
#include "supervisor/shared/tick.h"
|
||||
|
||||
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)) {
|
||||
// This shouldn't happen.
|
||||
return;
|
||||
}
|
||||
// Push all the data onto the ring buffer.
|
||||
uint8_t is_nested_critical_region;
|
||||
sd_nvic_critical_region_enter(&is_nested_critical_region);
|
||||
// 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)) {
|
||||
uint16_t packet_length;
|
||||
ringbuf_get_n(&self->ringbuf, (uint8_t*) &packet_length, sizeof(uint16_t));
|
||||
for (uint16_t i = 0; i < packet_length; i++) {
|
||||
ringbuf_get(&self->ringbuf);
|
||||
}
|
||||
// set an overflow flag?
|
||||
}
|
||||
ringbuf_put_n(&self->ringbuf, (uint8_t*) &len, sizeof(uint16_t));
|
||||
ringbuf_put_n(&self->ringbuf, data, len);
|
||||
sd_nvic_critical_region_exit(is_nested_critical_region);
|
||||
}
|
||||
// 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)) {
|
||||
// // This shouldn't happen.
|
||||
// return;
|
||||
// }
|
||||
// // Push all the data onto the ring buffer.
|
||||
// //FIX uint8_t 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.
|
||||
// while (ringbuf_capacity(&self->ringbuf) - ringbuf_num_filled(&self->ringbuf) < len + sizeof(uint16_t)) {
|
||||
// uint16_t packet_length;
|
||||
// ringbuf_get_n(&self->ringbuf, (uint8_t*) &packet_length, sizeof(uint16_t));
|
||||
// for (uint16_t i = 0; i < packet_length; i++) {
|
||||
// ringbuf_get(&self->ringbuf);
|
||||
// }
|
||||
// // set an overflow flag?
|
||||
// }
|
||||
// ringbuf_put_n(&self->ringbuf, (uint8_t*) &len, sizeof(uint16_t));
|
||||
// ringbuf_put_n(&self->ringbuf, data, len);
|
||||
// //FIX sd_nvic_critical_region_exit(is_nested_critical_region);
|
||||
// }
|
||||
|
||||
STATIC uint32_t queue_next_write(bleio_packet_buffer_obj_t *self) {
|
||||
// Queue up the next outgoing buffer. We use two, one that has been passed to the SD for
|
||||
// transmission (when packet_queued is true) and the other is `pending` and can still be
|
||||
// modified. By primarily appending to the `pending` buffer we can reduce the protocol overhead
|
||||
// of the lower level link and ATT layers.
|
||||
self->packet_queued = false;
|
||||
if (self->pending_size > 0) {
|
||||
uint16_t conn_handle = self->conn_handle;
|
||||
uint32_t err_code;
|
||||
if (self->client) {
|
||||
ble_gattc_write_params_t write_params = {
|
||||
.write_op = self->write_type,
|
||||
.handle = self->characteristic->handle,
|
||||
.p_value = self->outgoing[self->pending_index],
|
||||
.len = self->pending_size,
|
||||
};
|
||||
//FIX
|
||||
// STATIC uint32_t queue_next_write(bleio_packet_buffer_obj_t *self) {
|
||||
// // Queue up the next outgoing buffer. We use two, one that has been passed to the SD for
|
||||
// // transmission (when packet_queued is true) and the other is `pending` and can still be
|
||||
// // modified. By primarily appending to the `pending` buffer we can reduce the protocol overhead
|
||||
// // of the lower level link and ATT layers.
|
||||
// self->packet_queued = false;
|
||||
// if (self->pending_size > 0) {
|
||||
// uint16_t conn_handle = self->conn_handle;
|
||||
// uint32_t err_code;
|
||||
// if (self->client) {
|
||||
// ble_gattc_write_params_t write_params = {
|
||||
// .write_op = self->write_type,
|
||||
// .handle = self->characteristic->handle,
|
||||
// .p_value = self->outgoing[self->pending_index],
|
||||
// .len = self->pending_size,
|
||||
// };
|
||||
|
||||
err_code = sd_ble_gattc_write(conn_handle, &write_params);
|
||||
} else {
|
||||
uint16_t hvx_len = self->pending_size;
|
||||
// err_code = sd_ble_gattc_write(conn_handle, &write_params);
|
||||
// } else {
|
||||
// uint16_t hvx_len = self->pending_size;
|
||||
|
||||
ble_gatts_hvx_params_t hvx_params = {
|
||||
.handle = self->characteristic->handle,
|
||||
.type = self->write_type,
|
||||
.offset = 0,
|
||||
.p_len = &hvx_len,
|
||||
.p_data = self->outgoing[self->pending_index],
|
||||
};
|
||||
err_code = sd_ble_gatts_hvx(conn_handle, &hvx_params);
|
||||
}
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
// On error, simply skip updating the pending buffers so that the next HVC or WRITE
|
||||
// complete event triggers another attempt.
|
||||
return err_code;
|
||||
}
|
||||
self->pending_size = 0;
|
||||
self->pending_index = (self->pending_index + 1) % 2;
|
||||
self->packet_queued = true;
|
||||
}
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
// ble_gatts_hvx_params_t hvx_params = {
|
||||
// .handle = self->characteristic->handle,
|
||||
// .type = self->write_type,
|
||||
// .offset = 0,
|
||||
// .p_len = &hvx_len,
|
||||
// .p_data = self->outgoing[self->pending_index],
|
||||
// };
|
||||
// err_code = sd_ble_gatts_hvx(conn_handle, &hvx_params);
|
||||
// }
|
||||
// if (err_code != NRF_SUCCESS) {
|
||||
// // On error, simply skip updating the pending buffers so that the next HVC or WRITE
|
||||
// // complete event triggers another attempt.
|
||||
// return err_code;
|
||||
// }
|
||||
// self->pending_size = 0;
|
||||
// self->pending_index = (self->pending_index + 1) % 2;
|
||||
// self->packet_queued = true;
|
||||
// }
|
||||
// return NRF_SUCCESS;
|
||||
// }
|
||||
|
||||
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;
|
||||
// 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) {
|
||||
return false;
|
||||
}
|
||||
// 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;
|
||||
// // 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) {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
uint16_t conn_handle = ble_evt->evt.gattc_evt.conn_handle;
|
||||
bleio_packet_buffer_obj_t *self = (bleio_packet_buffer_obj_t *) param;
|
||||
if (conn_handle != self->conn_handle) {
|
||||
return false;
|
||||
}
|
||||
switch (evt_id) {
|
||||
case BLE_GATTC_EVT_HVX: {
|
||||
// A remote service wrote to this characteristic.
|
||||
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.
|
||||
if (evt_hvx->handle == self->characteristic->handle) {
|
||||
write_to_ringbuf(self, evt_hvx->data, evt_hvx->len);
|
||||
if (evt_hvx->type == BLE_GATT_HVX_INDICATION) {
|
||||
sd_ble_gattc_hv_confirm(conn_handle, evt_hvx->handle);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE: {
|
||||
queue_next_write(self);
|
||||
break;
|
||||
}
|
||||
case BLE_GATTC_EVT_WRITE_RSP: {
|
||||
queue_next_write(self);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// uint16_t conn_handle = ble_evt->evt.gattc_evt.conn_handle;
|
||||
// bleio_packet_buffer_obj_t *self = (bleio_packet_buffer_obj_t *) param;
|
||||
// if (conn_handle != self->conn_handle) {
|
||||
// return false;
|
||||
// }
|
||||
// switch (evt_id) {
|
||||
// case BLE_GATTC_EVT_HVX: {
|
||||
// // A remote service wrote to this characteristic.
|
||||
// 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.
|
||||
// if (evt_hvx->handle == self->characteristic->handle) {
|
||||
// write_to_ringbuf(self, evt_hvx->data, evt_hvx->len);
|
||||
// if (evt_hvx->type == BLE_GATT_HVX_INDICATION) {
|
||||
// sd_ble_gattc_hv_confirm(conn_handle, evt_hvx->handle);
|
||||
// }
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// case BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE: {
|
||||
// queue_next_write(self);
|
||||
// break;
|
||||
// }
|
||||
// case BLE_GATTC_EVT_WRITE_RSP: {
|
||||
// queue_next_write(self);
|
||||
// break;
|
||||
// }
|
||||
// default:
|
||||
// return false;
|
||||
// break;
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
|
||||
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;
|
||||
switch (ble_evt->header.evt_id) {
|
||||
case BLE_GATTS_EVT_WRITE: {
|
||||
uint16_t conn_handle = ble_evt->evt.gatts_evt.conn_handle;
|
||||
// A client wrote to this server characteristic.
|
||||
// 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;
|
||||
// switch (ble_evt->header.evt_id) {
|
||||
// case BLE_GATTS_EVT_WRITE: {
|
||||
// uint16_t conn_handle = ble_evt->evt.gatts_evt.conn_handle;
|
||||
// // 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.
|
||||
if (evt_write->handle == self->characteristic->handle) {
|
||||
if (self->conn_handle == BLE_CONN_HANDLE_INVALID) {
|
||||
self->conn_handle = conn_handle;
|
||||
} else if (self->conn_handle != conn_handle) {
|
||||
return false;
|
||||
}
|
||||
write_to_ringbuf(self, evt_write->data, evt_write->len);
|
||||
} else if (evt_write->handle == self->characteristic->cccd_handle) {
|
||||
uint16_t cccd = *((uint16_t*) evt_write->data);
|
||||
if (cccd & BLE_GATT_HVX_NOTIFICATION) {
|
||||
self->conn_handle = conn_handle;
|
||||
} else {
|
||||
self->conn_handle = BLE_CONN_HANDLE_INVALID;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BLE_GAP_EVT_DISCONNECTED: {
|
||||
if (self->conn_handle == ble_evt->evt.gap_evt.conn_handle) {
|
||||
self->conn_handle = BLE_CONN_HANDLE_INVALID;
|
||||
}
|
||||
}
|
||||
case BLE_GATTS_EVT_HVN_TX_COMPLETE: {
|
||||
queue_next_write(self);
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// // Event handle must match the handle for my characteristic.
|
||||
// if (evt_write->handle == self->characteristic->handle) {
|
||||
// if (self->conn_handle == BLE_CONN_HANDLE_INVALID) {
|
||||
// self->conn_handle = conn_handle;
|
||||
// } else if (self->conn_handle != conn_handle) {
|
||||
// return false;
|
||||
// }
|
||||
// write_to_ringbuf(self, evt_write->data, evt_write->len);
|
||||
// } else if (evt_write->handle == self->characteristic->cccd_handle) {
|
||||
// uint16_t cccd = *((uint16_t*) evt_write->data);
|
||||
// if (cccd & BLE_GATT_HVX_NOTIFICATION) {
|
||||
// self->conn_handle = conn_handle;
|
||||
// } else {
|
||||
// self->conn_handle = BLE_CONN_HANDLE_INVALID;
|
||||
// }
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// case BLE_GAP_EVT_DISCONNECTED: {
|
||||
// if (self->conn_handle == ble_evt->evt.gap_evt.conn_handle) {
|
||||
// self->conn_handle = BLE_CONN_HANDLE_INVALID;
|
||||
// }
|
||||
// }
|
||||
// case BLE_GATTS_EVT_HVN_TX_COMPLETE: {
|
||||
// queue_next_write(self);
|
||||
// }
|
||||
// default:
|
||||
// return false;
|
||||
// break;
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
|
||||
void common_hal_bleio_packet_buffer_construct(
|
||||
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;
|
||||
}
|
||||
|
||||
if (self->client) {
|
||||
ble_drv_add_event_handler(packet_buffer_on_ble_client_evt, self);
|
||||
if (incoming) {
|
||||
// Prefer notify if both are available.
|
||||
if (incoming & CHAR_PROP_NOTIFY) {
|
||||
self->write_type = BLE_GATT_HVX_NOTIFICATION;
|
||||
common_hal_bleio_characteristic_set_cccd(self->characteristic, true, false);
|
||||
} else {
|
||||
common_hal_bleio_characteristic_set_cccd(self->characteristic, false, true);
|
||||
}
|
||||
}
|
||||
if (outgoing) {
|
||||
self->write_type = BLE_GATT_OP_WRITE_REQ;
|
||||
if (outgoing & CHAR_PROP_WRITE_NO_RESPONSE) {
|
||||
self->write_type = BLE_GATT_OP_WRITE_CMD;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ble_drv_add_event_handler(packet_buffer_on_ble_server_evt, self);
|
||||
if (outgoing) {
|
||||
self->write_type = BLE_GATT_HVX_INDICATION;
|
||||
if (outgoing & CHAR_PROP_NOTIFY) {
|
||||
self->write_type = BLE_GATT_HVX_NOTIFICATION;
|
||||
}
|
||||
}
|
||||
}
|
||||
//FIX if (self->client) {
|
||||
// ble_drv_add_event_handler(packet_buffer_on_ble_client_evt, self);
|
||||
// if (incoming) {
|
||||
// // Prefer notify if both are available.
|
||||
// if (incoming & CHAR_PROP_NOTIFY) {
|
||||
// self->write_type = BLE_GATT_HVX_NOTIFICATION;
|
||||
// common_hal_bleio_characteristic_set_cccd(self->characteristic, true, false);
|
||||
// } else {
|
||||
// common_hal_bleio_characteristic_set_cccd(self->characteristic, false, true);
|
||||
// }
|
||||
// }
|
||||
// if (outgoing) {
|
||||
// self->write_type = BLE_GATT_OP_WRITE_REQ;
|
||||
// if (outgoing & CHAR_PROP_WRITE_NO_RESPONSE) {
|
||||
// self->write_type = BLE_GATT_OP_WRITE_CMD;
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// ble_drv_add_event_handler(packet_buffer_on_ble_server_evt, self);
|
||||
// if (outgoing) {
|
||||
// self->write_type = BLE_GATT_HVX_INDICATION;
|
||||
// if (outgoing & CHAR_PROP_NOTIFY) {
|
||||
// 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) {
|
||||
@ -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.
|
||||
uint8_t is_nested_critical_region;
|
||||
sd_nvic_critical_region_enter(&is_nested_critical_region);
|
||||
//FIX uint8_t 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.
|
||||
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.
|
||||
sd_nvic_critical_region_exit(is_nested_critical_region);
|
||||
//FIX sd_nvic_critical_region_exit(is_nested_critical_region);
|
||||
|
||||
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;
|
||||
|
||||
uint8_t is_nested_critical_region;
|
||||
sd_nvic_critical_region_enter(&is_nested_critical_region);
|
||||
//FIX uint8_t is_nested_critical_region;
|
||||
//FIX sd_nvic_critical_region_enter(&is_nested_critical_region);
|
||||
|
||||
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;
|
||||
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 (!self->packet_queued) {
|
||||
queue_next_write(self);
|
||||
//FIX queue_next_write(self);
|
||||
}
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -40,22 +40,24 @@ uint32_t _common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uu
|
||||
self->connection = NULL;
|
||||
self->is_secondary = is_secondary;
|
||||
|
||||
ble_uuid_t nordic_uuid;
|
||||
bleio_uuid_convert_to_nrf_ble_uuid(uuid, &nordic_uuid);
|
||||
//FIX
|
||||
// ble_uuid_t nordic_uuid;
|
||||
// bleio_uuid_convert_to_nrf_ble_uuid(uuid, &nordic_uuid);
|
||||
|
||||
uint8_t service_type = BLE_GATTS_SRVC_TYPE_PRIMARY;
|
||||
if (is_secondary) {
|
||||
service_type = BLE_GATTS_SRVC_TYPE_SECONDARY;
|
||||
}
|
||||
// uint8_t service_type = BLE_GATTS_SRVC_TYPE_PRIMARY;
|
||||
// if (is_secondary) {
|
||||
// service_type = BLE_GATTS_SRVC_TYPE_SECONDARY;
|
||||
// }
|
||||
|
||||
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) {
|
||||
check_nrf_error(_common_hal_bleio_service_construct(self, uuid, is_secondary,
|
||||
mp_obj_new_list(0, NULL)));
|
||||
//FIX check_nrf_error(_common_hal_bleio_service_construct(self, uuid, is_secondary,
|
||||
// mp_obj_new_list(0, NULL)));
|
||||
}
|
||||
|
||||
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,
|
||||
bleio_characteristic_obj_t *characteristic,
|
||||
mp_buffer_info_t *initial_value_bufinfo) {
|
||||
ble_gatts_char_md_t char_md = {
|
||||
.char_props.broadcast = (characteristic->props & CHAR_PROP_BROADCAST) ? 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 = (characteristic->props & CHAR_PROP_WRITE) ? 1 : 0,
|
||||
.char_props.notify = (characteristic->props & CHAR_PROP_NOTIFY) ? 1 : 0,
|
||||
.char_props.indicate = (characteristic->props & CHAR_PROP_INDICATE) ? 1 : 0,
|
||||
};
|
||||
// ble_gatts_char_md_t char_md = {
|
||||
// .char_props.broadcast = (characteristic->props & CHAR_PROP_BROADCAST) ? 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 = (characteristic->props & CHAR_PROP_WRITE) ? 1 : 0,
|
||||
// .char_props.notify = (characteristic->props & CHAR_PROP_NOTIFY) ? 1 : 0,
|
||||
// .char_props.indicate = (characteristic->props & CHAR_PROP_INDICATE) ? 1 : 0,
|
||||
// };
|
||||
|
||||
ble_gatts_attr_md_t cccd_md = {
|
||||
.vloc = BLE_GATTS_VLOC_STACK,
|
||||
};
|
||||
// ble_gatts_attr_md_t cccd_md = {
|
||||
// .vloc = BLE_GATTS_VLOC_STACK,
|
||||
// };
|
||||
|
||||
ble_uuid_t char_uuid;
|
||||
bleio_uuid_convert_to_nrf_ble_uuid(characteristic->uuid, &char_uuid);
|
||||
// ble_uuid_t char_uuid;
|
||||
// bleio_uuid_convert_to_nrf_ble_uuid(characteristic->uuid, &char_uuid);
|
||||
|
||||
ble_gatts_attr_md_t char_attr_md = {
|
||||
.vloc = BLE_GATTS_VLOC_STACK,
|
||||
.vlen = !characteristic->fixed_length,
|
||||
};
|
||||
// ble_gatts_attr_md_t char_attr_md = {
|
||||
// .vloc = BLE_GATTS_VLOC_STACK,
|
||||
// .vlen = !characteristic->fixed_length,
|
||||
// };
|
||||
|
||||
if (char_md.char_props.notify || char_md.char_props.indicate) {
|
||||
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
|
||||
// Make CCCD write permission match characteristic read permission.
|
||||
bleio_attribute_gatts_set_security_mode(&cccd_md.write_perm, characteristic->read_perm);
|
||||
// if (char_md.char_props.notify || char_md.char_props.indicate) {
|
||||
// BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
|
||||
// // Make CCCD write permission match characteristic read permission.
|
||||
// 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.write_perm, characteristic->write_perm);
|
||||
#if CIRCUITPY_VERBOSE_BLE
|
||||
// Turn on read authorization so that we receive an event to print on every read.
|
||||
char_attr_md.rd_auth = true;
|
||||
#endif
|
||||
// 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);
|
||||
// #if CIRCUITPY_VERBOSE_BLE
|
||||
// // Turn on read authorization so that we receive an event to print on every read.
|
||||
// char_attr_md.rd_auth = true;
|
||||
// #endif
|
||||
|
||||
ble_gatts_attr_t char_attr = {
|
||||
.p_uuid = &char_uuid,
|
||||
.p_attr_md = &char_attr_md,
|
||||
.init_len = 0,
|
||||
.p_value = NULL,
|
||||
.init_offs = 0,
|
||||
.max_len = characteristic->max_length,
|
||||
};
|
||||
// ble_gatts_attr_t char_attr = {
|
||||
// .p_uuid = &char_uuid,
|
||||
// .p_attr_md = &char_attr_md,
|
||||
// .init_len = 0,
|
||||
// .p_value = NULL,
|
||||
// .init_offs = 0,
|
||||
// .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->cccd_handle = char_handles.cccd_handle;
|
||||
characteristic->sccd_handle = char_handles.sccd_handle;
|
||||
characteristic->handle = char_handles.value_handle;
|
||||
#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);
|
||||
#endif
|
||||
// characteristic->user_desc_handle = char_handles.user_desc_handle;
|
||||
// characteristic->cccd_handle = char_handles.cccd_handle;
|
||||
// characteristic->sccd_handle = char_handles.sccd_handle;
|
||||
// characteristic->handle = char_handles.value_handle;
|
||||
// #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);
|
||||
// #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));
|
||||
}
|
||||
|
@ -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
|
||||
// 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[]) {
|
||||
self->nrf_ble_uuid.uuid = uuid16;
|
||||
if (uuid128 == NULL) {
|
||||
self->nrf_ble_uuid.type = BLE_UUID_TYPE_BLE;
|
||||
} else {
|
||||
ble_uuid128_t vs_uuid;
|
||||
memcpy(vs_uuid.uuid128, uuid128, sizeof(vs_uuid.uuid128));
|
||||
//FIX self->nrf_ble_uuid.uuid = uuid16;
|
||||
// if (uuid128 == NULL) {
|
||||
// self->nrf_ble_uuid.type = BLE_UUID_TYPE_BLE;
|
||||
// } else {
|
||||
// ble_uuid128_t vs_uuid;
|
||||
// memcpy(vs_uuid.uuid128, uuid128, sizeof(vs_uuid.uuid128));
|
||||
|
||||
// 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));
|
||||
vm_used_ble = true;
|
||||
}
|
||||
// // 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));
|
||||
// vm_used_ble = true;
|
||||
// }
|
||||
}
|
||||
|
||||
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) {
|
||||
// return self->nrf_ble_uuid.uuid;
|
||||
//FIX return self->nrf_ble_uuid.uuid;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void common_hal_bleio_uuid_get_uuid128(bleio_uuid_obj_t *self, uint8_t uuid128[16]) {
|
||||
uint8_t length;
|
||||
// check_nrf_error(sd_ble_uuid_encode(&self->nrf_ble_uuid, &length, uuid128));
|
||||
//FIX uint8_t length;
|
||||
//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) {
|
||||
// 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[1] = self->nrf_ble_uuid.uuid >> 8;
|
||||
// } 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) {
|
||||
// if (nrf_ble_uuid->type == BLE_UUID_TYPE_UNKNOWN) {
|
||||
// mp_raise_bleio_BluetoothError(translate("Unexpected nrfx uuid type"));
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
typedef struct {
|
||||
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.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
|
||||
|
@ -40,52 +40,53 @@
|
||||
|
||||
#include "common-hal/_bleio/__init__.h"
|
||||
|
||||
void check_nrf_error(uint32_t err_code) {
|
||||
if (err_code == NRF_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
switch (err_code) {
|
||||
case NRF_ERROR_TIMEOUT:
|
||||
mp_raise_msg(&mp_type_TimeoutError, NULL);
|
||||
return;
|
||||
case BLE_ERROR_INVALID_CONN_HANDLE:
|
||||
mp_raise_bleio_ConnectionError(translate("Not connected"));
|
||||
return;
|
||||
default:
|
||||
mp_raise_bleio_BluetoothError(translate("Unknown soft device error: %04x"), err_code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
//FIX to check HCI error
|
||||
// void check_nrf_error(uint32_t err_code) {
|
||||
// if (err_code == NRF_SUCCESS) {
|
||||
// return;
|
||||
// }
|
||||
// switch (err_code) {
|
||||
// case NRF_ERROR_TIMEOUT:
|
||||
// mp_raise_msg(&mp_type_TimeoutError, NULL);
|
||||
// return;
|
||||
// case BLE_ERROR_INVALID_CONN_HANDLE:
|
||||
// mp_raise_bleio_ConnectionError(translate("Not connected"));
|
||||
// return;
|
||||
// default:
|
||||
// mp_raise_bleio_BluetoothError(translate("Unknown soft device error: %04x"), err_code);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
void check_gatt_status(uint16_t gatt_status) {
|
||||
if (gatt_status == BLE_GATT_STATUS_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
switch (gatt_status) {
|
||||
case BLE_GATT_STATUS_ATTERR_INSUF_AUTHENTICATION:
|
||||
mp_raise_bleio_SecurityError(translate("Insufficient authentication"));
|
||||
return;
|
||||
case BLE_GATT_STATUS_ATTERR_INSUF_ENCRYPTION:
|
||||
mp_raise_bleio_SecurityError(translate("Insufficient encryption"));
|
||||
return;
|
||||
default:
|
||||
mp_raise_bleio_BluetoothError(translate("Unknown gatt error: 0x%04x"), gatt_status);
|
||||
}
|
||||
}
|
||||
// void check_gatt_status(uint16_t gatt_status) {
|
||||
// if (gatt_status == BLE_GATT_STATUS_SUCCESS) {
|
||||
// return;
|
||||
// }
|
||||
// switch (gatt_status) {
|
||||
// case BLE_GATT_STATUS_ATTERR_INSUF_AUTHENTICATION:
|
||||
// mp_raise_bleio_SecurityError(translate("Insufficient authentication"));
|
||||
// return;
|
||||
// case BLE_GATT_STATUS_ATTERR_INSUF_ENCRYPTION:
|
||||
// mp_raise_bleio_SecurityError(translate("Insufficient encryption"));
|
||||
// return;
|
||||
// default:
|
||||
// mp_raise_bleio_BluetoothError(translate("Unknown gatt error: 0x%04x"), gatt_status);
|
||||
// }
|
||||
// }
|
||||
|
||||
void check_sec_status(uint8_t sec_status) {
|
||||
if (sec_status == BLE_GAP_SEC_STATUS_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
// void check_sec_status(uint8_t sec_status) {
|
||||
// if (sec_status == BLE_GAP_SEC_STATUS_SUCCESS) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
switch (sec_status) {
|
||||
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."));
|
||||
return;
|
||||
default:
|
||||
mp_raise_bleio_SecurityError(translate("Unknown security error: 0x%04x"), sec_status);
|
||||
}
|
||||
}
|
||||
// switch (sec_status) {
|
||||
// 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."));
|
||||
// return;
|
||||
// default:
|
||||
// mp_raise_bleio_SecurityError(translate("Unknown security error: 0x%04x"), sec_status);
|
||||
// }
|
||||
// }
|
||||
|
||||
// Turn off BLE on a reset or reload.
|
||||
void bleio_reset() {
|
||||
@ -98,7 +99,7 @@ void bleio_reset() {
|
||||
return;
|
||||
}
|
||||
common_hal_bleio_adapter_set_enabled(&common_hal_bleio_adapter_obj, false);
|
||||
bonding_reset();
|
||||
//FIX bonding_reset();
|
||||
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.
|
||||
// If we're not connected, that's OK, because we can still read and write the local value.
|
||||
|
||||
ble_gatts_value_t gatts_value = {
|
||||
.p_value = buf,
|
||||
.len = len,
|
||||
};
|
||||
//FIX ble_gatts_value_t gatts_value = {
|
||||
// .p_value = buf,
|
||||
// .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) {
|
||||
// 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.
|
||||
|
||||
ble_gatts_value_t gatts_value = {
|
||||
.p_value = bufinfo->buf,
|
||||
.len = bufinfo->len,
|
||||
};
|
||||
//FIX ble_gatts_value_t gatts_value = {
|
||||
// .p_value = bufinfo->buf,
|
||||
// .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 {
|
||||
uint8_t* buf;
|
||||
size_t len;
|
||||
size_t final_len;
|
||||
uint16_t conn_handle;
|
||||
volatile uint16_t status;
|
||||
volatile bool done;
|
||||
} read_info_t;
|
||||
//FIX
|
||||
// typedef struct {
|
||||
// uint8_t* buf;
|
||||
// size_t len;
|
||||
// size_t final_len;
|
||||
// uint16_t conn_handle;
|
||||
// volatile uint16_t status;
|
||||
// volatile bool done;
|
||||
// } read_info_t;
|
||||
|
||||
STATIC bool _on_gattc_read_rsp_evt(ble_evt_t *ble_evt, void *param) {
|
||||
read_info_t* read = param;
|
||||
switch (ble_evt->header.evt_id) {
|
||||
// STATIC bool _on_gattc_read_rsp_evt(ble_evt_t *ble_evt, void *param) {
|
||||
// read_info_t* read = param;
|
||||
// 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: {
|
||||
ble_gattc_evt_t* evt = &ble_evt->evt.gattc_evt;
|
||||
ble_gattc_evt_read_rsp_t *response = &evt->params.read_rsp;
|
||||
if (read && evt->conn_handle == read->conn_handle) {
|
||||
read->status = evt->gatt_status;
|
||||
size_t len = MIN(read->len, response->len);
|
||||
memcpy(read->buf, response->data, len);
|
||||
read->final_len = len;
|
||||
// Indicate to busy-wait loop that we've read the attribute value.
|
||||
read->done = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// case BLE_GATTC_EVT_READ_RSP: {
|
||||
// ble_gattc_evt_t* evt = &ble_evt->evt.gattc_evt;
|
||||
// ble_gattc_evt_read_rsp_t *response = &evt->params.read_rsp;
|
||||
// if (read && evt->conn_handle == read->conn_handle) {
|
||||
// read->status = evt->gatt_status;
|
||||
// size_t len = MIN(read->len, response->len);
|
||||
// memcpy(read->buf, response->data, len);
|
||||
// read->final_len = len;
|
||||
// // Indicate to busy-wait loop that we've read the attribute value.
|
||||
// read->done = true;
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
|
||||
default:
|
||||
// For debugging.
|
||||
// mp_printf(&mp_plat_print, "Unhandled characteristic event: 0x%04x\n", ble_evt->header.evt_id);
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// default:
|
||||
// // For debugging.
|
||||
// // mp_printf(&mp_plat_print, "Unhandled characteristic event: 0x%04x\n", ble_evt->header.evt_id);
|
||||
// return false;
|
||||
// break;
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
|
||||
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);
|
||||
|
||||
read_info_t read_info;
|
||||
read_info.buf = buf;
|
||||
read_info.len = len;
|
||||
read_info.final_len = 0;
|
||||
read_info.conn_handle = conn_handle;
|
||||
// Set to true by the event handler.
|
||||
read_info.done = false;
|
||||
ble_drv_add_event_handler(_on_gattc_read_rsp_evt, &read_info);
|
||||
//FIX read_info_t read_info;
|
||||
// read_info.buf = buf;
|
||||
// read_info.len = len;
|
||||
// read_info.final_len = 0;
|
||||
// read_info.conn_handle = conn_handle;
|
||||
// // Set to true by the event handler.
|
||||
// read_info.done = false;
|
||||
// ble_drv_add_event_handler(_on_gattc_read_rsp_evt, &read_info);
|
||||
|
||||
uint32_t nrf_error = NRF_ERROR_BUSY;
|
||||
while (nrf_error == NRF_ERROR_BUSY) {
|
||||
nrf_error = sd_ble_gattc_read(conn_handle, handle, 0);
|
||||
}
|
||||
if (nrf_error != NRF_SUCCESS) {
|
||||
ble_drv_remove_event_handler(_on_gattc_read_rsp_evt, &read_info);
|
||||
check_nrf_error(nrf_error);
|
||||
}
|
||||
// uint32_t nrf_error = NRF_ERROR_BUSY;
|
||||
// while (nrf_error == NRF_ERROR_BUSY) {
|
||||
// nrf_error = sd_ble_gattc_read(conn_handle, handle, 0);
|
||||
// }
|
||||
// if (nrf_error != NRF_SUCCESS) {
|
||||
// ble_drv_remove_event_handler(_on_gattc_read_rsp_evt, &read_info);
|
||||
// check_nrf_error(nrf_error);
|
||||
// }
|
||||
|
||||
while (!read_info.done) {
|
||||
RUN_BACKGROUND_TASKS;
|
||||
}
|
||||
// while (!read_info.done) {
|
||||
// RUN_BACKGROUND_TASKS;
|
||||
// }
|
||||
|
||||
ble_drv_remove_event_handler(_on_gattc_read_rsp_evt, &read_info);
|
||||
check_gatt_status(read_info.status);
|
||||
return read_info.final_len;
|
||||
// ble_drv_remove_event_handler(_on_gattc_read_rsp_evt, &read_info);
|
||||
// check_gatt_status(read_info.status);
|
||||
// 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) {
|
||||
common_hal_bleio_check_connected(conn_handle);
|
||||
|
||||
ble_gattc_write_params_t write_params = {
|
||||
.write_op = write_no_response ? BLE_GATT_OP_WRITE_CMD: BLE_GATT_OP_WRITE_REQ,
|
||||
.handle = handle,
|
||||
.p_value = bufinfo->buf,
|
||||
.len = bufinfo->len,
|
||||
};
|
||||
//FIX
|
||||
// ble_gattc_write_params_t write_params = {
|
||||
// .write_op = write_no_response ? BLE_GATT_OP_WRITE_CMD: BLE_GATT_OP_WRITE_REQ,
|
||||
// .handle = handle,
|
||||
// .p_value = bufinfo->buf,
|
||||
// .len = bufinfo->len,
|
||||
// };
|
||||
|
||||
while (1) {
|
||||
uint32_t err_code = sd_ble_gattc_write(conn_handle, &write_params);
|
||||
if (err_code == NRF_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
// while (1) {
|
||||
// uint32_t err_code = sd_ble_gattc_write(conn_handle, &write_params);
|
||||
// if (err_code == NRF_SUCCESS) {
|
||||
// break;
|
||||
// }
|
||||
|
||||
// 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.
|
||||
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.
|
||||
MICROPY_VM_HOOK_LOOP;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Some real error occurred.
|
||||
check_nrf_error(err_code);
|
||||
}
|
||||
// // 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.
|
||||
// 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.
|
||||
// MICROPY_VM_HOOK_LOOP;
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// // Some real error occurred.
|
||||
// check_nrf_error(err_code);
|
||||
// }
|
||||
}
|
||||
|
||||
void common_hal_bleio_gc_collect(void) {
|
||||
|
@ -27,6 +27,8 @@
|
||||
#ifndef MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_INIT_H
|
||||
#define MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_INIT_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
void bleio_reset(void);
|
||||
|
||||
typedef struct {
|
||||
@ -39,6 +41,13 @@ typedef struct {
|
||||
// 20 bytes max (23 - 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.
|
||||
void check_nrf_error(uint32_t err_code);
|
||||
void check_gatt_status(uint16_t gatt_status);
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
@ -317,6 +317,13 @@ SRC_COMMON_HAL_ALL = \
|
||||
watchdog/WatchDogTimer.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))
|
||||
|
||||
# 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 \
|
||||
)
|
||||
|
||||
SRC_COMMON_HAL_INTERNAL = \
|
||||
$(filter $(SRC_PATTERNS), \
|
||||
_bleio/ \
|
||||
)
|
||||
|
||||
ifeq ($(INTERNAL_LIBM),1)
|
||||
SRC_LIBM = \
|
||||
$(addprefix lib/,\
|
||||
|
@ -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_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_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_reset, MP_ARG_KW_ONLY }| MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_reset_high, MP_ARG_KW_ONLY |MP_ARG_BOOL },
|
||||
{ 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_reset, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_reset_high, MP_ARG_KW_ONLY | MP_ARG_BOOL },
|
||||
};
|
||||
|
||||
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 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,
|
||||
args[ARG_baudrate], arg[ARG_buffer_size],
|
||||
baudrate, buffer_size,
|
||||
spi_cs, gpio0,
|
||||
reset, reset_high);
|
||||
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
|
||||
//|
|
||||
|
@ -37,6 +37,10 @@
|
||||
|
||||
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_enabled(bleio_adapter_obj_t *self);
|
||||
extern void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enabled);
|
||||
|
Loading…
x
Reference in New Issue
Block a user