extmod/modbluetooth: Add support for bonding (key persistence).
This adds `_IRQ_GET_SECRET` and `_IRQ_SET_SECRET` events to allow the BT stack to request the Python code retrive/store/delete secret key data. The actual keys and values are opaque to Python and stack-specific. Only NimBLE is implemented (pending moving btstack to sync events). The secret store is designed to be compatible with BlueKitchen's TLV store API. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
This commit is contained in:
parent
fff634e031
commit
c4d08aa4e3
|
@ -1081,14 +1081,15 @@ STATIC mp_obj_t invoke_irq_handler(uint16_t event,
|
|||
const uint8_t *addr,
|
||||
const int8_t *i8, size_t n_i8,
|
||||
const mp_obj_bluetooth_uuid_t *uuid,
|
||||
const uint8_t *data, size_t data_len) {
|
||||
const uint8_t **data, size_t *data_len, size_t n_data) {
|
||||
mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth));
|
||||
if (o->irq_handler == mp_const_none) {
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_array_t mv_addr;
|
||||
mp_obj_array_t mv_data;
|
||||
mp_obj_array_t mv_data[2];
|
||||
assert(n_data <= 2);
|
||||
|
||||
mp_obj_tuple_t *data_tuple = mp_local_alloc(sizeof(mp_obj_tuple_t) + sizeof(mp_obj_t) * MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_TUPLE_LEN);
|
||||
data_tuple->base.type = &mp_type_tuple;
|
||||
|
@ -1112,9 +1113,13 @@ STATIC mp_obj_t invoke_irq_handler(uint16_t event,
|
|||
data_tuple->items[data_tuple->len++] = MP_OBJ_FROM_PTR(uuid);
|
||||
}
|
||||
#endif
|
||||
if (data) {
|
||||
mp_obj_memoryview_init(&mv_data, 'B', 0, data_len, (void *)data);
|
||||
data_tuple->items[data_tuple->len++] = MP_OBJ_FROM_PTR(&mv_data);
|
||||
for (size_t i = 0; i < n_data; ++i) {
|
||||
if (data[i]) {
|
||||
mp_obj_memoryview_init(&mv_data[i], 'B', 0, data_len[i], (void *)data[i]);
|
||||
data_tuple->items[data_tuple->len++] = MP_OBJ_FROM_PTR(&mv_data[i]);
|
||||
} else {
|
||||
data_tuple->items[data_tuple->len++] = mp_const_none;
|
||||
}
|
||||
}
|
||||
assert(data_tuple->len <= MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_TUPLE_LEN);
|
||||
|
||||
|
@ -1131,36 +1136,57 @@ STATIC mp_obj_t invoke_irq_handler(uint16_t event,
|
|||
#define NULL_I8 NULL
|
||||
#define NULL_UUID NULL
|
||||
#define NULL_DATA NULL
|
||||
#define NULL_DATA_LEN NULL
|
||||
|
||||
void mp_bluetooth_gap_on_connected_disconnected(uint8_t event, uint16_t conn_handle, uint8_t addr_type, const uint8_t *addr) {
|
||||
invoke_irq_handler(event, &conn_handle, 1, &addr_type, 1, addr, NULL_I8, 0, NULL_UUID, NULL_DATA, 0);
|
||||
invoke_irq_handler(event, &conn_handle, 1, &addr_type, 1, addr, NULL_I8, 0, NULL_UUID, NULL_DATA, NULL_DATA_LEN, 0);
|
||||
}
|
||||
|
||||
void mp_bluetooth_gap_on_connection_update(uint16_t conn_handle, uint16_t conn_interval, uint16_t conn_latency, uint16_t supervision_timeout, uint16_t status) {
|
||||
uint16_t args[] = {conn_handle, conn_interval, conn_latency, supervision_timeout, status};
|
||||
invoke_irq_handler(MP_BLUETOOTH_IRQ_CONNECTION_UPDATE, args, 5, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, 0);
|
||||
invoke_irq_handler(MP_BLUETOOTH_IRQ_CONNECTION_UPDATE, args, 5, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, NULL_DATA_LEN, 0);
|
||||
}
|
||||
|
||||
#if MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING
|
||||
void mp_bluetooth_gatts_on_encryption_update(uint16_t conn_handle, bool encrypted, bool authenticated, bool bonded, uint8_t key_size) {
|
||||
uint8_t args[] = {encrypted, authenticated, bonded, key_size};
|
||||
invoke_irq_handler(MP_BLUETOOTH_IRQ_ENCRYPTION_UPDATE, &conn_handle, 1, args, 4, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, 0);
|
||||
invoke_irq_handler(MP_BLUETOOTH_IRQ_ENCRYPTION_UPDATE, &conn_handle, 1, args, 4, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, NULL_DATA_LEN, 0);
|
||||
}
|
||||
|
||||
bool mp_bluetooth_gap_on_get_secret(uint8_t type, uint8_t index, const uint8_t *key, size_t key_len, const uint8_t **value, size_t *value_len) {
|
||||
uint8_t args[] = {type, index};
|
||||
mp_obj_t result = invoke_irq_handler(MP_BLUETOOTH_IRQ_GET_SECRET, NULL_U16, 0, args, 2, NULL_ADDR, NULL_I8, 0, NULL_UUID, &key, &key_len, 1);
|
||||
if (result == mp_const_none) {
|
||||
return false;
|
||||
}
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(result, &bufinfo, MP_BUFFER_READ);
|
||||
*value = bufinfo.buf;
|
||||
*value_len = bufinfo.len;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mp_bluetooth_gap_on_set_secret(uint8_t type, const uint8_t *key, size_t key_len, const uint8_t *value, size_t value_len) {
|
||||
const uint8_t *data[] = {key, value};
|
||||
size_t data_len[] = {key_len, value_len};
|
||||
mp_obj_t result = invoke_irq_handler(MP_BLUETOOTH_IRQ_SET_SECRET, NULL_U16, 0, &type, 1, NULL_ADDR, NULL_I8, 0, NULL_UUID, data, data_len, 2);
|
||||
return mp_obj_is_true(result);
|
||||
}
|
||||
#endif // MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING
|
||||
|
||||
void mp_bluetooth_gatts_on_write(uint16_t conn_handle, uint16_t value_handle) {
|
||||
uint16_t args[] = {conn_handle, value_handle};
|
||||
invoke_irq_handler(MP_BLUETOOTH_IRQ_GATTS_WRITE, args, 2, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, 0);
|
||||
invoke_irq_handler(MP_BLUETOOTH_IRQ_GATTS_WRITE, args, 2, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, NULL_DATA_LEN, 0);
|
||||
}
|
||||
|
||||
void mp_bluetooth_gatts_on_indicate_complete(uint16_t conn_handle, uint16_t value_handle, uint8_t status) {
|
||||
uint16_t args[] = {conn_handle, value_handle};
|
||||
invoke_irq_handler(MP_BLUETOOTH_IRQ_GATTS_INDICATE_DONE, args, 2, &status, 1, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, 0);
|
||||
invoke_irq_handler(MP_BLUETOOTH_IRQ_GATTS_INDICATE_DONE, args, 2, &status, 1, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, NULL_DATA_LEN, 0);
|
||||
}
|
||||
|
||||
mp_int_t mp_bluetooth_gatts_on_read_request(uint16_t conn_handle, uint16_t value_handle) {
|
||||
uint16_t args[] = {conn_handle, value_handle};
|
||||
mp_obj_t result = invoke_irq_handler(MP_BLUETOOTH_IRQ_GATTS_READ_REQUEST, args, 2, NULL, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, 0);
|
||||
mp_obj_t result = invoke_irq_handler(MP_BLUETOOTH_IRQ_GATTS_READ_REQUEST, args, 2, NULL, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, NULL_DATA_LEN, 0);
|
||||
// Return non-zero from IRQ handler to fail the read.
|
||||
mp_int_t ret = 0;
|
||||
mp_obj_get_int_maybe(result, &ret);
|
||||
|
@ -1169,13 +1195,13 @@ mp_int_t mp_bluetooth_gatts_on_read_request(uint16_t conn_handle, uint16_t value
|
|||
|
||||
void mp_bluetooth_gatts_on_mtu_exchanged(uint16_t conn_handle, uint16_t value) {
|
||||
uint16_t args[] = {conn_handle, value};
|
||||
invoke_irq_handler(MP_BLUETOOTH_IRQ_MTU_EXCHANGED, args, 2, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, 0);
|
||||
invoke_irq_handler(MP_BLUETOOTH_IRQ_MTU_EXCHANGED, args, 2, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, NULL_DATA_LEN, 0);
|
||||
}
|
||||
|
||||
#if MICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS
|
||||
mp_int_t mp_bluetooth_gattc_on_l2cap_accept(uint16_t conn_handle, uint16_t cid, uint16_t psm, uint16_t our_mtu, uint16_t peer_mtu) {
|
||||
uint16_t args[] = {conn_handle, cid, psm, our_mtu, peer_mtu};
|
||||
mp_obj_t result = invoke_irq_handler(MP_BLUETOOTH_IRQ_L2CAP_ACCEPT, args, 5, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, 0);
|
||||
mp_obj_t result = invoke_irq_handler(MP_BLUETOOTH_IRQ_L2CAP_ACCEPT, args, 5, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, NULL_DATA_LEN, 0);
|
||||
// Return non-zero from IRQ handler to fail the accept.
|
||||
mp_int_t ret = 0;
|
||||
mp_obj_get_int_maybe(result, &ret);
|
||||
|
@ -1184,58 +1210,58 @@ mp_int_t mp_bluetooth_gattc_on_l2cap_accept(uint16_t conn_handle, uint16_t cid,
|
|||
|
||||
void mp_bluetooth_gattc_on_l2cap_connect(uint16_t conn_handle, uint16_t cid, uint16_t psm, uint16_t our_mtu, uint16_t peer_mtu) {
|
||||
uint16_t args[] = {conn_handle, cid, psm, our_mtu, peer_mtu};
|
||||
invoke_irq_handler(MP_BLUETOOTH_IRQ_L2CAP_CONNECT, args, 5, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, 0);
|
||||
invoke_irq_handler(MP_BLUETOOTH_IRQ_L2CAP_CONNECT, args, 5, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, NULL_DATA_LEN, 0);
|
||||
}
|
||||
|
||||
void mp_bluetooth_gattc_on_l2cap_disconnect(uint16_t conn_handle, uint16_t cid, uint16_t psm, uint16_t status) {
|
||||
uint16_t args[] = {conn_handle, cid, psm, status};
|
||||
invoke_irq_handler(MP_BLUETOOTH_IRQ_L2CAP_DISCONNECT, args, 4, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, 0);
|
||||
invoke_irq_handler(MP_BLUETOOTH_IRQ_L2CAP_DISCONNECT, args, 4, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, NULL_DATA_LEN, 0);
|
||||
}
|
||||
|
||||
void mp_bluetooth_gattc_on_l2cap_send_ready(uint16_t conn_handle, uint16_t cid, uint8_t status) {
|
||||
uint16_t args[] = {conn_handle, cid};
|
||||
invoke_irq_handler(MP_BLUETOOTH_IRQ_L2CAP_SEND_READY, args, 2, &status, 1, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, 0);
|
||||
invoke_irq_handler(MP_BLUETOOTH_IRQ_L2CAP_SEND_READY, args, 2, &status, 1, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, NULL_DATA_LEN, 0);
|
||||
}
|
||||
|
||||
void mp_bluetooth_gattc_on_l2cap_recv(uint16_t conn_handle, uint16_t cid) {
|
||||
uint16_t args[] = {conn_handle, cid};
|
||||
invoke_irq_handler(MP_BLUETOOTH_IRQ_L2CAP_RECV, args, 2, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, 0);
|
||||
invoke_irq_handler(MP_BLUETOOTH_IRQ_L2CAP_RECV, args, 2, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, NULL_DATA_LEN, 0);
|
||||
}
|
||||
#endif // MICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS
|
||||
|
||||
#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
|
||||
void mp_bluetooth_gap_on_scan_complete(void) {
|
||||
invoke_irq_handler(MP_BLUETOOTH_IRQ_SCAN_DONE, NULL_U16, 0, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, 0);
|
||||
invoke_irq_handler(MP_BLUETOOTH_IRQ_SCAN_DONE, NULL_U16, 0, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, NULL_DATA_LEN, 0);
|
||||
}
|
||||
|
||||
void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, uint8_t adv_type, const int8_t rssi, const uint8_t *data, size_t data_len) {
|
||||
int8_t args[] = {adv_type, rssi};
|
||||
invoke_irq_handler(MP_BLUETOOTH_IRQ_SCAN_RESULT, NULL_U16, 0, &addr_type, 1, addr, args, 2, NULL_UUID, data, data_len);
|
||||
invoke_irq_handler(MP_BLUETOOTH_IRQ_SCAN_RESULT, NULL_U16, 0, &addr_type, 1, addr, args, 2, NULL_UUID, &data, &data_len, 1);
|
||||
}
|
||||
|
||||
void mp_bluetooth_gattc_on_primary_service_result(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, mp_obj_bluetooth_uuid_t *service_uuid) {
|
||||
uint16_t args[] = {conn_handle, start_handle, end_handle};
|
||||
invoke_irq_handler(MP_BLUETOOTH_IRQ_GATTC_SERVICE_RESULT, args, 3, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, service_uuid, NULL_DATA, 0);
|
||||
invoke_irq_handler(MP_BLUETOOTH_IRQ_GATTC_SERVICE_RESULT, args, 3, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, service_uuid, NULL_DATA, NULL_DATA_LEN, 0);
|
||||
}
|
||||
|
||||
void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t def_handle, uint16_t value_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid) {
|
||||
uint16_t args[] = {conn_handle, def_handle, value_handle};
|
||||
invoke_irq_handler(MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_RESULT, args, 3, &properties, 1, NULL_ADDR, NULL_I8, 0, characteristic_uuid, NULL_DATA, 0);
|
||||
invoke_irq_handler(MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_RESULT, args, 3, &properties, 1, NULL_ADDR, NULL_I8, 0, characteristic_uuid, NULL_DATA, NULL_DATA_LEN, 0);
|
||||
}
|
||||
|
||||
void mp_bluetooth_gattc_on_descriptor_result(uint16_t conn_handle, uint16_t handle, mp_obj_bluetooth_uuid_t *descriptor_uuid) {
|
||||
uint16_t args[] = {conn_handle, handle};
|
||||
invoke_irq_handler(MP_BLUETOOTH_IRQ_GATTC_DESCRIPTOR_RESULT, args, 2, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, descriptor_uuid, NULL_DATA, 0);
|
||||
invoke_irq_handler(MP_BLUETOOTH_IRQ_GATTC_DESCRIPTOR_RESULT, args, 2, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, descriptor_uuid, NULL_DATA, NULL_DATA_LEN, 0);
|
||||
}
|
||||
|
||||
void mp_bluetooth_gattc_on_discover_complete(uint8_t event, uint16_t conn_handle, uint16_t status) {
|
||||
uint16_t args[] = {conn_handle, status};
|
||||
invoke_irq_handler(event, args, 2, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, 0);
|
||||
invoke_irq_handler(event, args, 2, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, NULL_DATA_LEN, 0);
|
||||
}
|
||||
|
||||
void mp_bluetooth_gattc_on_data_available(uint8_t event, uint16_t conn_handle, uint16_t value_handle, const uint8_t **data, uint16_t *data_len, size_t num) {
|
||||
const uint8_t *combined_data;
|
||||
uint16_t total_len;
|
||||
size_t total_len;
|
||||
|
||||
if (num > 1) {
|
||||
// Fragmented buffer, need to combine into a new heap-allocated buffer
|
||||
|
@ -1258,7 +1284,7 @@ void mp_bluetooth_gattc_on_data_available(uint8_t event, uint16_t conn_handle, u
|
|||
}
|
||||
|
||||
uint16_t args[] = {conn_handle, value_handle};
|
||||
invoke_irq_handler(event, args, 2, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, combined_data, total_len);
|
||||
invoke_irq_handler(event, args, 2, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, &combined_data, &total_len, 1);
|
||||
|
||||
if (num > 1) {
|
||||
m_del(uint8_t, (uint8_t *)combined_data, total_len);
|
||||
|
@ -1267,7 +1293,7 @@ void mp_bluetooth_gattc_on_data_available(uint8_t event, uint16_t conn_handle, u
|
|||
|
||||
void mp_bluetooth_gattc_on_read_write_status(uint8_t event, uint16_t conn_handle, uint16_t value_handle, uint16_t status) {
|
||||
uint16_t args[] = {conn_handle, value_handle, status};
|
||||
invoke_irq_handler(event, args, 3, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, 0);
|
||||
invoke_irq_handler(event, args, 3, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, NULL_DATA_LEN, 0);
|
||||
}
|
||||
|
||||
#endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
|
||||
|
|
|
@ -146,6 +146,8 @@
|
|||
#define MP_BLUETOOTH_IRQ_L2CAP_SEND_READY (26)
|
||||
#define MP_BLUETOOTH_IRQ_CONNECTION_UPDATE (27)
|
||||
#define MP_BLUETOOTH_IRQ_ENCRYPTION_UPDATE (28)
|
||||
#define MP_BLUETOOTH_IRQ_GET_SECRET (29)
|
||||
#define MP_BLUETOOTH_IRQ_SET_SECRET (30)
|
||||
|
||||
#define MP_BLUETOOTH_ADDRESS_MODE_PUBLIC (0)
|
||||
#define MP_BLUETOOTH_ADDRESS_MODE_RANDOM (1)
|
||||
|
@ -159,6 +161,12 @@
|
|||
#define MP_BLUETOOTH_IO_CAPABILITY_NO_INPUT_OUTPUT (3)
|
||||
#define MP_BLUETOOTH_IO_CAPABILITY_KEYBOARD_DISPLAY (4)
|
||||
|
||||
// These match NimBLE BLE_SM_IOACT_.
|
||||
#define MP_BLUETOOTH_PASSKEY_ACTION_NONE (0)
|
||||
#define MP_BLUETOOTH_PASSKEY_ACTION_INPUT (2)
|
||||
#define MP_BLUETOOTH_PASSKEY_ACTION_DISPLAY (3)
|
||||
#define MP_BLUETOOTH_PASSKEY_ACTION_NUMERIC_COMPARISON (4)
|
||||
|
||||
/*
|
||||
These aren't included in the module for space reasons, but can be used
|
||||
in your Python code if necessary.
|
||||
|
@ -192,6 +200,8 @@ _IRQ_L2CAP_RECV = const(25)
|
|||
_IRQ_L2CAP_SEND_READY = const(26)
|
||||
_IRQ_CONNECTION_UPDATE = const(27)
|
||||
_IRQ_ENCRYPTION_UPDATE = const(28)
|
||||
_IRQ_GET_SECRET = const(29)
|
||||
_IRQ_SET_SECRET = const(30)
|
||||
|
||||
_FLAG_BROADCAST = const(0x0001)
|
||||
_FLAG_READ = const(0x0002)
|
||||
|
@ -373,7 +383,13 @@ void mp_bluetooth_gap_on_connection_update(uint16_t conn_handle, uint16_t conn_i
|
|||
#if MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING
|
||||
// Call this when any connection encryption has been changed (e.g. during pairing).
|
||||
void mp_bluetooth_gatts_on_encryption_update(uint16_t conn_handle, bool encrypted, bool authenticated, bool bonded, uint8_t key_size);
|
||||
#endif
|
||||
|
||||
// Call this when you need the application to manage persistent key data.
|
||||
// For get, if key is NULL, then the implementation must return the index'th matching key. Otherwise it should return a specific key.
|
||||
// For set, if value is NULL, then delete.
|
||||
bool mp_bluetooth_gap_on_get_secret(uint8_t type, uint8_t index, const uint8_t *key, size_t key_len, const uint8_t **value, size_t *value_len);
|
||||
bool mp_bluetooth_gap_on_set_secret(uint8_t type, const uint8_t *key, size_t key_len, const uint8_t *value, size_t value_len);
|
||||
#endif // MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING
|
||||
|
||||
// Call this when a characteristic is written to.
|
||||
void mp_bluetooth_gatts_on_write(uint16_t conn_handle, uint16_t value_handle);
|
||||
|
|
|
@ -269,6 +269,7 @@ STATIC int gap_event_cb(struct ble_gap_event *event, void *arg) {
|
|||
|
||||
switch (event->type) {
|
||||
case BLE_GAP_EVENT_CONNECT:
|
||||
DEBUG_printf("gap_event_cb: connect: status=%d\n", event->connect.status);
|
||||
if (event->connect.status == 0) {
|
||||
// Connection established.
|
||||
ble_gap_conn_find(event->connect.conn_handle, &desc);
|
||||
|
@ -282,6 +283,7 @@ STATIC int gap_event_cb(struct ble_gap_event *event, void *arg) {
|
|||
|
||||
case BLE_GAP_EVENT_DISCONNECT:
|
||||
// Disconnect.
|
||||
DEBUG_printf("gap_event_cb: disconnect: reason=%d\n", event->disconnect.reason);
|
||||
reverse_addr_byte_order(addr, event->disconnect.conn.peer_id_addr.val);
|
||||
mp_bluetooth_gap_on_connected_disconnected(MP_BLUETOOTH_IRQ_CENTRAL_DISCONNECT, event->disconnect.conn.conn_handle, event->disconnect.conn.peer_id_addr.type, addr);
|
||||
break;
|
||||
|
@ -310,7 +312,6 @@ STATIC int gap_event_cb(struct ble_gap_event *event, void *arg) {
|
|||
|
||||
case BLE_GAP_EVENT_CONN_UPDATE: {
|
||||
DEBUG_printf("gap_event_cb: connection update: status=%d\n", event->conn_update.status);
|
||||
struct ble_gap_conn_desc desc;
|
||||
if (ble_gap_conn_find(event->conn_update.conn_handle, &desc) == 0) {
|
||||
mp_bluetooth_gap_on_connection_update(event->conn_update.conn_handle, desc.conn_itvl, desc.conn_latency, desc.supervision_timeout, event->conn_update.status == 0 ? 0 : 1);
|
||||
}
|
||||
|
@ -320,7 +321,6 @@ STATIC int gap_event_cb(struct ble_gap_event *event, void *arg) {
|
|||
case BLE_GAP_EVENT_ENC_CHANGE: {
|
||||
DEBUG_printf("gap_event_cb: enc change: status=%d\n", event->enc_change.status);
|
||||
#if MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING
|
||||
struct ble_gap_conn_desc desc;
|
||||
if (ble_gap_conn_find(event->enc_change.conn_handle, &desc) == 0) {
|
||||
mp_bluetooth_gatts_on_encryption_update(event->conn_update.conn_handle,
|
||||
desc.sec_state.encrypted, desc.sec_state.authenticated,
|
||||
|
@ -329,6 +329,27 @@ STATIC int gap_event_cb(struct ble_gap_event *event, void *arg) {
|
|||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
case BLE_GAP_EVENT_REPEAT_PAIRING: {
|
||||
// We recognized this peer but the peer doesn't recognize us.
|
||||
DEBUG_printf("gap_event_cb: repeat pairing: conn_handle=%d\n", event->repeat_pairing.conn_handle);
|
||||
|
||||
// TODO: Consider returning BLE_GAP_REPEAT_PAIRING_IGNORE (and
|
||||
// possibly an API to configure this).
|
||||
|
||||
// Delete the old bond.
|
||||
int rc = ble_gap_conn_find(event->repeat_pairing.conn_handle, &desc);
|
||||
if (rc == 0) {
|
||||
ble_store_util_delete_peer(&desc.peer_id_addr);
|
||||
}
|
||||
|
||||
// Allow re-pairing.
|
||||
return BLE_GAP_REPEAT_PAIRING_RETRY;
|
||||
}
|
||||
|
||||
default:
|
||||
DEBUG_printf("gap_event_cb: unknown type %d\n", event->type);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -969,6 +990,7 @@ STATIC int peripheral_gap_event_cb(struct ble_gap_event *event, void *arg) {
|
|||
|
||||
switch (event->type) {
|
||||
case BLE_GAP_EVENT_CONNECT:
|
||||
DEBUG_printf("peripheral_gap_event_cb: status=%d\n", event->connect.status);
|
||||
if (event->connect.status == 0) {
|
||||
// Connection established.
|
||||
ble_gap_conn_find(event->connect.conn_handle, &desc);
|
||||
|
@ -982,6 +1004,7 @@ STATIC int peripheral_gap_event_cb(struct ble_gap_event *event, void *arg) {
|
|||
|
||||
case BLE_GAP_EVENT_DISCONNECT:
|
||||
// Disconnect.
|
||||
DEBUG_printf("peripheral_gap_event_cb: reason=%d\n", event->disconnect.reason);
|
||||
reverse_addr_byte_order(addr, event->disconnect.conn.peer_id_addr.val);
|
||||
mp_bluetooth_gap_on_connected_disconnected(MP_BLUETOOTH_IRQ_PERIPHERAL_DISCONNECT, event->disconnect.conn.conn_handle, event->disconnect.conn.peer_id_addr.type, addr);
|
||||
|
||||
|
@ -1020,9 +1043,12 @@ STATIC int peripheral_gap_event_cb(struct ble_gap_event *event, void *arg) {
|
|||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
DEBUG_printf("peripheral_gap_event_cb: unknown type %d\n", event->type);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1514,4 +1540,146 @@ int mp_bluetooth_l2cap_recvinto(uint16_t conn_handle, uint16_t cid, uint8_t *buf
|
|||
|
||||
#endif // MICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS
|
||||
|
||||
#if MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING
|
||||
|
||||
STATIC int ble_store_ram_read(int obj_type, const union ble_store_key *key, union ble_store_value *value) {
|
||||
DEBUG_printf("ble_store_ram_read: %d\n", obj_type);
|
||||
const uint8_t *key_data;
|
||||
size_t key_data_len;
|
||||
|
||||
switch (obj_type) {
|
||||
case BLE_STORE_OBJ_TYPE_PEER_SEC: {
|
||||
if (ble_addr_cmp(&key->sec.peer_addr, BLE_ADDR_ANY)) {
|
||||
// <type=peer,addr,*> (single)
|
||||
// Find the entry for this specific peer.
|
||||
assert(key->sec.idx == 0);
|
||||
assert(!key->sec.ediv_rand_present);
|
||||
key_data = (const uint8_t *)&key->sec.peer_addr;
|
||||
key_data_len = sizeof(ble_addr_t);
|
||||
} else {
|
||||
// <type=peer,*> (with index)
|
||||
// Iterate all known peers.
|
||||
assert(!key->sec.ediv_rand_present);
|
||||
key_data = NULL;
|
||||
key_data_len = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BLE_STORE_OBJ_TYPE_OUR_SEC: {
|
||||
// <type=our,addr,ediv_rand>
|
||||
// Find our secret for this remote device, matching this ediv/rand key.
|
||||
assert(ble_addr_cmp(&key->sec.peer_addr, BLE_ADDR_ANY)); // Must have address.
|
||||
assert(key->sec.idx == 0);
|
||||
assert(key->sec.ediv_rand_present);
|
||||
key_data = (const uint8_t *)&key->sec.peer_addr;
|
||||
key_data_len = sizeof(ble_addr_t);
|
||||
break;
|
||||
}
|
||||
case BLE_STORE_OBJ_TYPE_CCCD: {
|
||||
// TODO: Implement CCCD persistence.
|
||||
DEBUG_printf("ble_store_ram_read: CCCD not supported.\n");
|
||||
return -1;
|
||||
}
|
||||
default:
|
||||
return BLE_HS_ENOTSUP;
|
||||
}
|
||||
|
||||
const uint8_t *value_data;
|
||||
size_t value_data_len;
|
||||
if (!mp_bluetooth_gap_on_get_secret(obj_type, key->sec.idx, key_data, key_data_len, &value_data, &value_data_len)) {
|
||||
DEBUG_printf("ble_store_ram_read: Key not found: type=%d, index=%u, key=0x%p, len=" UINT_FMT "\n", obj_type, key->sec.idx, key_data, key_data_len);
|
||||
return BLE_HS_ENOENT;
|
||||
}
|
||||
|
||||
if (value_data_len != sizeof(struct ble_store_value_sec)) {
|
||||
DEBUG_printf("ble_store_ram_read: Invalid key data: actual=" UINT_FMT " expected=" UINT_FMT "\n", value_data_len, sizeof(struct ble_store_value_sec));
|
||||
return BLE_HS_ENOENT;
|
||||
}
|
||||
|
||||
memcpy((uint8_t *)&value->sec, value_data, sizeof(struct ble_store_value_sec));
|
||||
|
||||
DEBUG_printf("ble_store_ram_read: found secret\n");
|
||||
|
||||
if (obj_type == BLE_STORE_OBJ_TYPE_OUR_SEC) {
|
||||
// TODO: Verify ediv_rand matches.
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC int ble_store_ram_write(int obj_type, const union ble_store_value *val) {
|
||||
DEBUG_printf("ble_store_ram_write: %d\n", obj_type);
|
||||
switch (obj_type) {
|
||||
case BLE_STORE_OBJ_TYPE_PEER_SEC:
|
||||
case BLE_STORE_OBJ_TYPE_OUR_SEC: {
|
||||
// <type=peer,addr,edivrand>
|
||||
|
||||
struct ble_store_key_sec key_sec;
|
||||
const struct ble_store_value_sec *value_sec = &val->sec;
|
||||
ble_store_key_from_value_sec(&key_sec, value_sec);
|
||||
|
||||
assert(ble_addr_cmp(&key_sec.peer_addr, BLE_ADDR_ANY)); // Must have address.
|
||||
assert(key_sec.ediv_rand_present);
|
||||
|
||||
if (!mp_bluetooth_gap_on_set_secret(obj_type, (const uint8_t *)&key_sec.peer_addr, sizeof(ble_addr_t), (const uint8_t *)value_sec, sizeof(struct ble_store_value_sec))) {
|
||||
DEBUG_printf("Failed to write key: type=%d\n", obj_type);
|
||||
return BLE_HS_ESTORE_CAP;
|
||||
}
|
||||
|
||||
DEBUG_printf("ble_store_ram_write: wrote secret\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
case BLE_STORE_OBJ_TYPE_CCCD: {
|
||||
// TODO: Implement CCCD persistence.
|
||||
DEBUG_printf("ble_store_ram_write: CCCD not supported.\n");
|
||||
// Just pretend we wrote it.
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
return BLE_HS_ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC int ble_store_ram_delete(int obj_type, const union ble_store_key *key) {
|
||||
DEBUG_printf("ble_store_ram_delete: %d\n", obj_type);
|
||||
switch (obj_type) {
|
||||
case BLE_STORE_OBJ_TYPE_PEER_SEC:
|
||||
case BLE_STORE_OBJ_TYPE_OUR_SEC: {
|
||||
// <type=peer,addr,*>
|
||||
|
||||
assert(ble_addr_cmp(&key->sec.peer_addr, BLE_ADDR_ANY)); // Must have address.
|
||||
// ediv_rand is optional (will not be present for delete).
|
||||
|
||||
if (!mp_bluetooth_gap_on_set_secret(obj_type, (const uint8_t *)&key->sec.peer_addr, sizeof(ble_addr_t), NULL, 0)) {
|
||||
DEBUG_printf("Failed to delete key: type=%d\n", obj_type);
|
||||
return BLE_HS_ENOENT;
|
||||
}
|
||||
|
||||
DEBUG_printf("ble_store_ram_delete: deleted secret\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
case BLE_STORE_OBJ_TYPE_CCCD: {
|
||||
// TODO: Implement CCCD persistence.
|
||||
DEBUG_printf("ble_store_ram_delete: CCCD not supported.\n");
|
||||
// Just pretend it wasn't there.
|
||||
return BLE_HS_ENOENT;
|
||||
}
|
||||
default:
|
||||
return BLE_HS_ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
// nimble_port_init always calls ble_store_ram_init. We provide this alternative
|
||||
// implementation rather than the one in nimble/store/ram/src/ble_store_ram.c.
|
||||
// TODO: Consider re-implementing nimble_port_init instead.
|
||||
void ble_store_ram_init(void) {
|
||||
ble_hs_cfg.store_read_cb = ble_store_ram_read;
|
||||
ble_hs_cfg.store_write_cb = ble_store_ram_write;
|
||||
ble_hs_cfg.store_delete_cb = ble_store_ram_delete;
|
||||
}
|
||||
|
||||
#endif // MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING
|
||||
|
||||
#endif // MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE
|
||||
|
|
|
@ -83,7 +83,6 @@ LIB_SRC_C += $(addprefix $(NIMBLE_LIB_DIR)/, \
|
|||
ble_store_util.c \
|
||||
ble_uuid.c \
|
||||
) \
|
||||
nimble/host/store/ram/src/ble_store_ram.c \
|
||||
nimble/host/util/src/addr.c \
|
||||
nimble/transport/uart/src/ble_hci_uart.c \
|
||||
$(addprefix porting/nimble/src/, \
|
||||
|
@ -95,6 +94,7 @@ LIB_SRC_C += $(addprefix $(NIMBLE_LIB_DIR)/, \
|
|||
os_msys_init.c \
|
||||
) \
|
||||
)
|
||||
# nimble/host/store/ram/src/ble_store_ram.c \
|
||||
|
||||
EXTMOD_SRC_C += $(addprefix $(NIMBLE_EXTMOD_DIR)/, \
|
||||
nimble/nimble_npl_os.c \
|
||||
|
|
Loading…
Reference in New Issue