From 453b066aeb8acdabfe5a40358b707bee12d2d0b3 Mon Sep 17 00:00:00 2001 From: schneider <schneider@blinkenlichts.net> Date: Sat, 6 Feb 2021 18:59:25 +0100 Subject: [PATCH] feat(mp-ble): add ATTC write queue --- pycardium/modules/modbluetooth_card10.c | 129 ++++++++++++++++++++++-- 1 file changed, 118 insertions(+), 11 deletions(-) diff --git a/pycardium/modules/modbluetooth_card10.c b/pycardium/modules/modbluetooth_card10.c index 55bdb99f7..52f630acf 100644 --- a/pycardium/modules/modbluetooth_card10.c +++ b/pycardium/modules/modbluetooth_card10.c @@ -13,15 +13,29 @@ enum notification_status { NOTIFICATION_STATUS_OVERFLOW }; +typedef struct _pendig_gattc_operation_obj_t { + mp_obj_base_t base; + uint16_t conn_handle; + uint16_t value_handle; + unsigned int mode; + uint16_t value_len; + uint8_t value[]; +} pending_gattc_operation_obj_t; + +STATIC const mp_obj_type_t pending_gattc_operation_type; + typedef struct _mp_bluetooth_card10_root_pointers_t { // Characteristic (and descriptor) value storage. mp_gatts_db_t gatts_db; mp_gatts_db_t gatts_status; + mp_obj_t attc_pending; } mp_bluetooth_card10_root_pointers_t; #define GATTS_DB (MP_STATE_PORT(bluetooth_card10_root_pointers)->gatts_db) #define GATTS_STATUS \ (MP_STATE_PORT(bluetooth_card10_root_pointers)->gatts_status) +#define ATTC_PENDING \ + (MP_STATE_PORT(bluetooth_card10_root_pointers)->attc_pending) typedef struct { enum notification_status notification_status; @@ -266,6 +280,73 @@ static void handle_att_event(struct epic_att_event *att_event) att_event->hdr.status ); } + + bool send_attc = false; + size_t len; + mp_obj_t *items; + + if (att_event->hdr.event == ATTC_WRITE_CMD_RSP) { + mp_obj_list_get(ATTC_PENDING, &len, &items); + for (size_t i = 0; i < len; i++) { + pending_gattc_operation_obj_t *op = + MP_OBJ_TO_PTR(items[i]); + if (op->mode == MP_BLUETOOTH_WRITE_MODE_NO_RESPONSE && + op->conn_handle == 1 && + op->value_handle == att_event->handle) { + mp_obj_subscr( + ATTC_PENDING, + MP_OBJ_NEW_SMALL_INT(i), + MP_OBJ_NULL + ); + send_attc = true; + break; + } + } + } + + if (att_event->hdr.event == ATTC_WRITE_RSP) { + mp_obj_list_get(ATTC_PENDING, &len, &items); + for (size_t i = 0; i < len; i++) { + pending_gattc_operation_obj_t *op = + MP_OBJ_TO_PTR(items[i]); + if (op->mode == MP_BLUETOOTH_WRITE_MODE_WITH_RESPONSE && + op->conn_handle == 1 && + op->value_handle == att_event->handle) { + mp_obj_subscr( + ATTC_PENDING, + MP_OBJ_NEW_SMALL_INT(i), + MP_OBJ_NULL + ); + send_attc = true; + break; + } + } + } + + if (send_attc) { + mp_obj_list_get(ATTC_PENDING, &len, &items); + if (len > 0) { + pending_gattc_operation_obj_t *op = + MP_OBJ_TO_PTR(items[0]); + if (op->mode == MP_BLUETOOTH_WRITE_MODE_NO_RESPONSE) { + epic_ble_attc_write_no_rsp( + op->conn_handle, + op->value_handle, + op->value, + op->value_len + ); + } else if ( + op->mode == + MP_BLUETOOTH_WRITE_MODE_WITH_RESPONSE) { + epic_ble_attc_write( + op->conn_handle, + op->value_handle, + op->value, + op->value_len + ); + } + } + } #endif } @@ -351,6 +432,7 @@ int mp_bluetooth_init(void) mp_bluetooth_gatts_db_create(&GATTS_DB); mp_bluetooth_gatts_db_create(&GATTS_STATUS); + ATTC_PENDING = mp_obj_new_list(0, NULL); mp_interrupt_set_callback( MP_ROM_INT(EPIC_INT_BLE), (mp_obj_t *)&ble_event_obj @@ -623,6 +705,8 @@ int mp_bluetooth_gatts_notify_send( const uint8_t *value, size_t value_len ) { + // TODO: We could make use of a list similar to GATTC operations to + // avoid polling for the return value in this function gatts_status_entry_t *e = gatts_status_lookup(GATTS_STATUS, value_handle); e->notification_status = NOTIFICATION_STATUS_PENDING; @@ -648,6 +732,8 @@ int mp_bluetooth_gatts_notify_send( // Indicate the central. int mp_bluetooth_gatts_indicate(uint16_t conn_handle, uint16_t value_handle) { + // TODO: We could make use of a list similar to GATTC operations to + // avoid polling for the return value in this function gatts_status_entry_t *e = gatts_status_lookup(GATTS_STATUS, value_handle); e->notification_status = NOTIFICATION_STATUS_PENDING; @@ -781,6 +867,7 @@ int mp_bluetooth_gattc_discover_descriptors( // Initiate read of a value from the remote peripheral. int mp_bluetooth_gattc_read(uint16_t conn_handle, uint16_t value_handle) { + // TODO: Make use of ATTC_PENDING list return epic_ble_attc_read(conn_handle, value_handle); } @@ -792,17 +879,37 @@ int mp_bluetooth_gattc_write( size_t *value_len, unsigned int mode ) { - int err; - if (mode == MP_BLUETOOTH_WRITE_MODE_NO_RESPONSE) { - err = epic_ble_attc_write_no_rsp( - conn_handle, value_handle, value, *value_len - ); - } else if (mode == MP_BLUETOOTH_WRITE_MODE_WITH_RESPONSE) { - err = epic_ble_attc_write( - conn_handle, value_handle, value, *value_len - ); - } else { - err = MP_EINVAL; + int err = 0; + + if (mode != MP_BLUETOOTH_WRITE_MODE_WITH_RESPONSE && + mode != MP_BLUETOOTH_WRITE_MODE_NO_RESPONSE) { + return MP_EINVAL; + } + pending_gattc_operation_obj_t *op = m_new_obj_var( + pending_gattc_operation_obj_t, uint8_t, *value_len + ); + op->base.type = &pending_gattc_operation_type; + op->conn_handle = conn_handle; + op->value_handle = value_handle; + op->mode = mode; + op->value_len = *value_len; + memcpy(op->value, value, *value_len); + mp_obj_list_append(ATTC_PENDING, MP_OBJ_FROM_PTR(op)); + + size_t len; + mp_obj_t *items; + mp_obj_list_get(ATTC_PENDING, &len, &items); + + if (len == 1) { + if (mode == MP_BLUETOOTH_WRITE_MODE_NO_RESPONSE) { + err = epic_ble_attc_write_no_rsp( + conn_handle, value_handle, value, *value_len + ); + } else if (mode == MP_BLUETOOTH_WRITE_MODE_WITH_RESPONSE) { + err = epic_ble_attc_write( + conn_handle, value_handle, value, *value_len + ); + } } return err; } -- GitLab