diff --git a/epicardium/ble/ble_api.h b/epicardium/ble/ble_api.h index 971ed38e15ae48049feef8a8162183a190adef81..3c50745e91285c782ef6650dfa9c4645c360de64 100644 --- a/epicardium/ble/ble_api.h +++ b/epicardium/ble/ble_api.h @@ -29,6 +29,7 @@ void bleValueUpdate(attEvt_t *pMsg); void bleDiscCback(dmConnId_t connId, uint8_t status); void ble_trigger_event(enum ble_event_type event); void ble_epic_att_api_init(void); +void ble_epic_att_api_event(attEvt_t *att_event); /************************************************************************************************** Data Types diff --git a/epicardium/ble/ble_main.c b/epicardium/ble/ble_main.c index 1992815e416261cd20797ada305a2c448a1e81a6..373f5f37e37bc4633a090c19b63e4335e500f262 100644 --- a/epicardium/ble/ble_main.c +++ b/epicardium/ble/ble_main.c @@ -706,7 +706,6 @@ static void scannerScanReport(dmEvt_t *pMsg) /*************************************************************************************************/ #define ATT_CONNECTION_OPENED 0x81 #define ATT_CONNECTION_CLOSED 0x82 -void send_att_event(attEvt_t *att_event); static void bleProcMsg(bleMsg_t *pMsg) { hciLeConnCmplEvt_t *connOpen; @@ -758,7 +757,7 @@ static void bleProcMsg(bleMsg_t *pMsg) HidProcMsg(&pMsg->hdr); UartProcMsg(pMsg); e.hdr.event = ATT_CONNECTION_OPENED; e.hdr.param = connOpen->hdr.param; - send_att_event(&e); + ble_epic_att_api_event(&e); break; case DM_CONN_CLOSE_IND: @@ -795,7 +794,7 @@ static void bleProcMsg(bleMsg_t *pMsg) advertising_mode = APP_MODE_NONE; AppAdvStop(); e.hdr.param = pMsg->dm.connClose.hdr.param; e.hdr.event = ATT_CONNECTION_CLOSED; - send_att_event(&e); + ble_epic_att_api_event(&e); bleClose(pMsg); break; @@ -936,7 +935,7 @@ static void BleHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg) LOG_INFO("ble", "Ble got evt %d (%s): %d", pMsg->event, att_events[pMsg->event - ATT_CBACK_START], pMsg->status); /* process discovery-related ATT messages */ AppDiscProcAttMsg((attEvt_t *) pMsg); - send_att_event((attEvt_t *)pMsg); + ble_epic_att_api_event((attEvt_t *)pMsg); } else if (pMsg->event >= L2C_COC_CBACK_START && pMsg->event <= L2C_COC_CBACK_CBACK_END) { diff --git a/epicardium/ble/epic_att_api.c b/epicardium/ble/epic_att_api.c index b492d32fbb8cf9232e6eff0803a96c0f24e077d0..c155e80ee9a02585690438a65007ac549d8527bb 100644 --- a/epicardium/ble/epic_att_api.c +++ b/epicardium/ble/epic_att_api.c @@ -6,6 +6,7 @@ #include "util/bstream.h" #include "wsf_msg.h" #include "att_api.h" +#include "wsf_buf.h" #include "FreeRTOS.h" #include "queue.h" @@ -13,29 +14,53 @@ #include <stdio.h> #include <string.h> -#define ATT_QUEUE_SIZE 10 -static QueueHandle_t att_queue; -static uint8_t att_queue_buffer[sizeof(attEvt_t) * ATT_QUEUE_SIZE]; -static StaticQueue_t att_queue_data; +#define ATT_EVENT_QUEUE_SIZE 10 +#define ATT_WRITE_QUEUE_SIZE 10 + +static QueueHandle_t att_event_queue; +static uint8_t att_event_queue_buffer + [sizeof(struct epic_att_event) * ATT_EVENT_QUEUE_SIZE]; +static StaticQueue_t att_event_queue_data; + +static QueueHandle_t att_write_queue; +static uint8_t att_write_queue_buffer + [sizeof(struct epic_att_write) * ATT_WRITE_QUEUE_SIZE]; +static StaticQueue_t att_write_queue_data; int epic_ble_get_att_event(struct epic_att_event *e) { - if (xQueueReceive(att_queue, e, 0) != pdTRUE) { + if (xQueueReceive(att_event_queue, e, 0) != pdTRUE) { return -ENOENT; } - return uxQueueMessagesWaiting(att_queue); + return uxQueueMessagesWaiting(att_event_queue); +} + +void ble_epic_att_api_event(attEvt_t *att_event) +{ + bool enabled; + epic_interrupt_is_enabled(EPIC_INT_BLE, &enabled); + + if (enabled) { + if (xQueueSend(att_event_queue, att_event, 0) != pdTRUE) { + LOG_WARN("ble", "could not queue att event"); + } + ble_trigger_event(BLE_EVENT_ATT_EVENT); + } } -// TODO: make static again once ble_main does not use it anymore -void send_att_event(attEvt_t *att_event) +int epic_ble_get_att_write(struct epic_att_write *w) { - if (xQueueSend(att_queue, att_event, 0) != pdTRUE) { - LOG_WARN("ble", "could not queue att event"); + if (xQueueReceive(att_write_queue, w, 0) != pdTRUE) { + return -ENOENT; } - ble_trigger_event(BLE_EVENT_ATT_EVENT); + return uxQueueMessagesWaiting(att_event_queue); } -#define ATT_WRITE_CALLBACK 0x80 +int epic_ble_free_att_write(struct epic_att_write *w) +{ + WsfBufFree(w->buffer); + return 0; +} static uint8_t DynAttsWriteCback( dmConnId_t connId, @@ -46,16 +71,31 @@ static uint8_t DynAttsWriteCback( uint8_t *pValue, attsAttr_t *pAttr ) { - if (AttsSetAttr(handle, len, pValue) == ATT_SUCCESS) { - attEvt_t att_event; - att_event.hdr.event = ATT_WRITE_CALLBACK; - att_event.hdr.param = connId; - att_event.handle = handle; - att_event.valueLen = len; - send_att_event(&att_event); + printf("DynAttsWriteCback %d, %d, %d\n", handle, len, offset); + struct epic_att_write att_write; + att_write.hdr.param = connId; + att_write.handle = handle; + att_write.valueLen = len; + att_write.operation = operation; + att_write.offset = offset; + + att_write.buffer = WsfBufAlloc(len); + + if (att_write.buffer) { + memcpy(att_write.buffer, pValue, len); + + if (xQueueSend(att_write_queue, &att_write, 0) != pdTRUE) { + LOG_WARN("ble", "could not queue att write"); + epic_ble_free_att_write(&att_write); + } + + ble_trigger_event(BLE_EVENT_ATT_WRITE); + } else { + LOG_WARN("ble", "could allocate att write"); } - return ATT_SUCCESS; + // TODO: handle offset != 0 + return AttsSetAttr(handle, len, pValue); } #define ATTS_DYN_GROUP_COUNT 8 @@ -104,11 +144,17 @@ int epic_ble_atts_dyn_delete_groups(void) void ble_epic_att_api_init(void) { - att_queue = xQueueCreateStatic( - ATT_QUEUE_SIZE, - sizeof(attEvt_t), - att_queue_buffer, - &att_queue_data + att_event_queue = xQueueCreateStatic( + ATT_EVENT_QUEUE_SIZE, + sizeof(struct epic_att_event), + att_event_queue_buffer, + &att_event_queue_data + ); + att_write_queue = xQueueCreateStatic( + ATT_WRITE_QUEUE_SIZE, + sizeof(struct epic_att_write), + att_write_queue_buffer, + &att_write_queue_data ); } @@ -124,3 +170,21 @@ int epic_ble_atts_handle_value_ntf( AttsHandleValueNtf(connId, handle, valueLen, pValue); return 0; } + +int epic_ble_atts_handle_value_ind( + uint8_t connId, uint16_t handle, uint16_t valueLen, uint8_t *pValue +) { + if (!DmConnInUse(connId)) { + return -EIO; + } + + // TODO: There is a race condition here. Ideally AttsHandleValueInd would return an error or + // raise a callback + AttsHandleValueInd(connId, handle, valueLen, pValue); + return 0; +} + +int epic_ble_atts_set_buffer(uint16_t value_handle, size_t len, bool append) +{ + return AttsDynResize(value_handle, len); +} diff --git a/epicardium/epicardium.h b/epicardium/epicardium.h index f56b6c00269f60736edd88d833e00e8d28f8d8d1..ec74d98132d7aae9394d6ec9ecadcc55f3c222c9 100644 --- a/epicardium/epicardium.h +++ b/epicardium/epicardium.h @@ -163,16 +163,20 @@ typedef _Bool bool; #define API_BLE_HID_SEND_REPORT 0x150 #define API_BLE_ATTS_DYN_CREATE_GROUP 0x160 -//#define API_BLE_ATTS_DYN_DELETE_GROUP 0x160 +//#define API_BLE_ATTS_DYN_DELETE_GROUP 0x161 #define API_BLE_ATTS_DYN_REGISTER 0x162 #define API_BLE_ATTS_DYN_ADD_ATTR_DYN 0x163 #define API_BLE_ATTS_DYN_ADD_ATTR 0x164 #define API_BLE_ATTS_SET_ATTR 0x165 #define API_BLE_ATTS_HANDLE_VALUE_NTF 0x166 -#define API_BLE_ATTS_GET_ATTR 0x167 -#define API_BLE_ATT_GET_EVENT 0x168 -#define API_BLE_ATTS_SEND_SERVICE_CHANGED_IND 0x169 -#define API_BLE_ATTS_DYN_DELETE_GROUPS 0x16A +#define API_BLE_ATTS_HANDLE_VALUE_IND 0x167 +#define API_BLE_ATTS_GET_ATTR 0x168 +#define API_BLE_ATT_GET_EVENT 0x169 +#define API_BLE_ATTS_SEND_SERVICE_CHANGED_IND 0x16A +#define API_BLE_ATTS_DYN_DELETE_GROUPS 0x16B +#define API_BLE_ATTS_SET_BUFFER 0x1BC +#define API_BLE_GET_ATT_WRITE 0x1BD +#define API_BLE_FREE_ATT_WRITE 0x1BE /* clang-format on */ @@ -2343,6 +2347,7 @@ enum ble_event_type { /** New scan data is available */ BLE_EVENT_SCAN_REPORT = 4, BLE_EVENT_ATT_EVENT = 5, + BLE_EVENT_ATT_WRITE = 6, }; @@ -2524,7 +2529,8 @@ API(API_BLE_ATTS_SEND_SERVICE_CHANGED_IND, int epic_atts_dyn_send_service_change API(API_BLE_ATTS_SET_ATTR, uint8_t AttsSetAttr(uint16_t handle, uint16_t valueLen, uint8_t *pValue)); API(API_BLE_ATTS_GET_ATTR, uint8_t AttsGetAttr(uint16_t handle, uint16_t *pLen, uint8_t **pValue)); API(API_BLE_ATTS_HANDLE_VALUE_NTF, int epic_ble_atts_handle_value_ntf(uint8_t connId, uint16_t handle, uint16_t valueLen, uint8_t *pValue)); - +API(API_BLE_ATTS_HANDLE_VALUE_IND, int epic_ble_atts_handle_value_ind(uint8_t connId, uint16_t handle, uint16_t valueLen, uint8_t *pValue)); +API(API_BLE_ATTS_SET_BUFFER, int epic_ble_atts_set_buffer(uint16_t value_handle, size_t len, bool append)); struct epic_wsf_header { @@ -2543,9 +2549,21 @@ struct epic_att_event uint16_t mtu; /*!< \brief Negotiated MTU value */ }; - API(API_BLE_ATT_GET_EVENT, int epic_ble_get_att_event(struct epic_att_event *e)); +struct epic_att_write +{ + struct epic_wsf_header hdr; /*!< \brief Header structure */ + uint16_t valueLen; /*!< \brief Value length */ + uint16_t handle; /*!< \brief Attribute handle */ + uint8_t operation; + uint16_t offset; + void *buffer; +}; + +API(API_BLE_GET_ATT_WRITE, int epic_ble_get_att_write(struct epic_att_write *w)); +API(API_BLE_FREE_ATT_WRITE, int epic_ble_free_att_write(struct epic_att_write *w)); + #endif /* _EPICARDIUM_H */ diff --git a/lib/sdk/Libraries/BTLE/stack/ble-host/include/att_api.h b/lib/sdk/Libraries/BTLE/stack/ble-host/include/att_api.h index 0138ea019d14c696078fc62a213537e9be38c893..f50e3a4863d1b169a34e92334934d870b1133794 100644 --- a/lib/sdk/Libraries/BTLE/stack/ble-host/include/att_api.h +++ b/lib/sdk/Libraries/BTLE/stack/ble-host/include/att_api.h @@ -981,6 +981,8 @@ void AttsDynAddAttr(void *pSvcHandle, const uint8_t *pUuid, const uint8_t *pValu /*************************************************************************************************/ void AttsDynAddAttrConst(void *pSvcHandle, const uint8_t *pUuid, const uint8_t *pValue, const uint16_t len, uint8_t settings, uint8_t permissions); + +uint8_t AttsDynResize(uint16_t handle, uint16_t maxLen); /**@}*/ /** \name ATT Server Testing diff --git a/lib/sdk/Libraries/BTLE/stack/ble-host/sources/stack/att/atts_dyn.c b/lib/sdk/Libraries/BTLE/stack/ble-host/sources/stack/att/atts_dyn.c index 0348e2d5de5d43422771fea5a8641d0f8276f27b..ad4ad54e30a0dad6c24de9119654ba0adc15b994 100644 --- a/lib/sdk/Libraries/BTLE/stack/ble-host/sources/stack/att/atts_dyn.c +++ b/lib/sdk/Libraries/BTLE/stack/ble-host/sources/stack/att/atts_dyn.c @@ -421,3 +421,36 @@ void AttsDynAddAttrDyn(void *pSvcHandle, const uint8_t *pUuid, uint8_t uuidLen, AttsAddGroup(&pGroup->group); } } + +uint8_t AttsDynResize(uint16_t handle, uint16_t maxLen) +{ + attsAttr_t *pAttr; + attsGroup_t *pGroup; + void *pValue; + uint8_t err = ATT_SUCCESS; + + /* find attribute */ + if ((pAttr = attsFindByHandle(handle, &pGroup)) != NULL) + { + /* Allocate a buffer for the value of the attribute */ + pValue = attsDynAlloc(maxLen); + WSF_ASSERT(pValue); + + if (pValue == NULL) + { + return ATT_ERR_MEMORY; + } + + pAttr->maxLen = maxLen; + pAttr->pValue = pValue; + memset(pValue, 0, maxLen); + } + /* else attribute not found */ + else + { + err = ATT_ERR_NOT_FOUND; + } + + return err; + +} diff --git a/pycardium/modules/modbluetooth_card10.c b/pycardium/modules/modbluetooth_card10.c index c2dc063e046914422b8c2bd2a4e163b06372d238..5395a68150d9bdf397727e493ea2afc9e5765055 100644 --- a/pycardium/modules/modbluetooth_card10.c +++ b/pycardium/modules/modbluetooth_card10.c @@ -86,7 +86,6 @@ const uint8_t attCliChCfgUuid[] = { UINT16_TO_BYTES( 0x79 /*!< \brief Responsed delayed pending higher layer */ // card10 att interface specific events -#define ATT_WRITE_CALLBACK 0x80 #define ATT_CONNECTION_OPENED 0x81 #define ATT_CONNECTION_CLOSED 0x82 @@ -105,27 +104,31 @@ const char *const not_implemented_message = 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_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) typedef struct { enum notification_status notification_status; -} gatts_db_entry_t; +} gatts_status_entry_t; -static void gatts_db_create_entry(mp_gatts_db_t db, uint16_t handle) +static void gatts_status_create_entry(mp_gatts_db_t db, uint16_t handle) { mp_map_elem_t *elem = mp_map_lookup( db, MP_OBJ_NEW_SMALL_INT(handle), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND ); - gatts_db_entry_t *entry = m_new(gatts_db_entry_t, 1); - entry->notification_status = NOTIFICATION_STATUS_UNKNOWN; - elem->value = MP_OBJ_FROM_PTR(entry); + gatts_status_entry_t *entry = m_new(gatts_status_entry_t, 1); + entry->notification_status = NOTIFICATION_STATUS_UNKNOWN; + elem->value = MP_OBJ_FROM_PTR(entry); } -static gatts_db_entry_t *gatts_db_lookup(mp_gatts_db_t db, uint16_t handle) +static gatts_status_entry_t * +gatts_status_lookup(mp_gatts_db_t db, uint16_t handle) { mp_map_elem_t *elem = mp_map_lookup(db, MP_OBJ_NEW_SMALL_INT(handle), MP_MAP_LOOKUP); @@ -143,82 +146,102 @@ static void raise(void) static void clear_events(void) { struct epic_att_event att_event; + struct epic_att_write att_write; epic_ble_get_event(); while (epic_ble_get_att_event(&att_event) >= 0) ; + while (epic_ble_get_att_write(&att_write) >= 0) + epic_ble_free_att_write(&att_write); +} + +static void handle_att_event(struct epic_att_event *att_event) +{ + printf("MP got att event %d,%d,%d\n", + att_event->hdr.event, + att_event->hdr.status, + att_event->handle); + + if (att_event->hdr.event == ATTS_HANDLE_VALUE_CNF) { + gatts_status_entry_t *e = + gatts_status_lookup(GATTS_STATUS, att_event->handle); + if (att_event->hdr.status == ATT_SUCCESS) { + e->notification_status = NOTIFICATION_STATUS_SUCCESS; + } else if (att_event->hdr.status == ATT_ERR_OVERFLOW) { + e->notification_status = NOTIFICATION_STATUS_OVERFLOW; + } + } else if (att_event->hdr.event == ATT_CONNECTION_OPENED) { + uint8_t event = MP_BLUETOOTH_IRQ_CENTRAL_CONNECT; + uint16_t conn_handle = att_event->hdr.param; + uint8_t addr_type = 0; // TODO + uint8_t addr[8] = {}; // TODO + mp_bluetooth_gap_on_connected_disconnected( + event, conn_handle, addr_type, addr + ); + } else if (att_event->hdr.event == ATT_CONNECTION_CLOSED) { + uint8_t event = MP_BLUETOOTH_IRQ_CENTRAL_DISCONNECT; + uint16_t conn_handle = att_event->hdr.param; + uint8_t addr_type = 0; // TODO + uint8_t addr[8] = {}; // TODO + mp_bluetooth_gap_on_connected_disconnected( + event, conn_handle, addr_type, addr + ); + } +} + +static void handle_att_write(struct epic_att_write *att_write) +{ + printf("MP got att write %d,%d\n", + att_write->handle, + att_write->valueLen); + + mp_bluetooth_gatts_db_entry_t *entry = + mp_bluetooth_gatts_db_lookup(GATTS_DB, att_write->handle); + if (!entry) { + printf("ble: epic_att_write handle not found\n"); + return; + } + + // TODO: Use `offset` arg. + size_t append_offset = 0; + if (entry->append) { + append_offset = entry->data_len; + } + entry->data_len = + MIN(entry->data_alloc, att_write->valueLen + append_offset); + memcpy(entry->data + append_offset, + att_write->buffer, + entry->data_len - append_offset); + + mp_bluetooth_gatts_on_write(att_write->hdr.param, att_write->handle); } static mp_obj_t mp_ble_poll_events(mp_obj_t interrupt_id) { - struct epic_att_event att_event; enum ble_event_type event = epic_ble_get_event(); if (event == BLE_EVENT_ATT_EVENT) { + struct epic_att_event att_event; int ret; do { ret = epic_ble_get_att_event(&att_event); + if (ret >= 0) { + handle_att_event(&att_event); + } + } while (ret >= 0); + } + if (event == BLE_EVENT_ATT_WRITE) { + struct epic_att_write att_write; + int ret; + do { + ret = epic_ble_get_att_write(&att_write); if (ret >= 0) { - printf("MP got att event %d,%d,%d\n", - att_event.hdr.event, - att_event.hdr.status, - att_event.handle); - if (att_event.hdr.event == - ATTS_HANDLE_VALUE_CNF) { - gatts_db_entry_t *e = gatts_db_lookup( - GATTS_DB, att_event.handle - ); - if (att_event.hdr.status == - ATT_SUCCESS) { - e->notification_status = - NOTIFICATION_STATUS_SUCCESS; - } else if ( - att_event.hdr.status == - ATT_ERR_OVERFLOW) { - e->notification_status = - NOTIFICATION_STATUS_OVERFLOW; - } - } else if ( - att_event.hdr.event == - ATT_WRITE_CALLBACK) { - mp_bluetooth_gatts_on_write( - att_event.hdr.param, - att_event.handle - ); - } else if ( - att_event.hdr.event == - ATT_CONNECTION_OPENED) { - uint8_t event = - MP_BLUETOOTH_IRQ_CENTRAL_CONNECT; - uint16_t conn_handle = - att_event.hdr.param; - uint8_t addr_type = 0; // TODO - uint8_t addr[8] = {}; // TODO - mp_bluetooth_gap_on_connected_disconnected( - event, - conn_handle, - addr_type, - addr - ); - } else if ( - att_event.hdr.event == - ATT_CONNECTION_CLOSED) { - uint8_t event = - MP_BLUETOOTH_IRQ_CENTRAL_DISCONNECT; - uint16_t conn_handle = - att_event.hdr.param; - uint8_t addr_type = 0; // TODO - uint8_t addr[8] = {}; // TODO - mp_bluetooth_gap_on_connected_disconnected( - event, - conn_handle, - addr_type, - addr - ); - } + handle_att_write(&att_write); + epic_ble_free_att_write(&att_write); } } while (ret >= 0); } + return mp_const_none; } static MP_DEFINE_CONST_FUN_OBJ_1(ble_event_obj, mp_ble_poll_events); @@ -230,7 +253,10 @@ int mp_bluetooth_init(void) { MP_STATE_PORT(bluetooth_card10_root_pointers) = m_new0(mp_bluetooth_card10_root_pointers_t, 1); + mp_bluetooth_gatts_db_create(&GATTS_DB); + mp_bluetooth_gatts_db_create(&GATTS_STATUS); + mp_interrupt_set_callback( MP_ROM_INT(EPIC_INT_BLE), (mp_obj_t *)&ble_event_obj ); @@ -393,20 +419,29 @@ int mp_bluetooth_gatts_register_service( uuid_len, NULL, 0, - MP_BLUETOOTH_DEFAULT_ATTR_LEN + 10, + MP_BLUETOOTH_DEFAULT_ATTR_LEN, settings, permissions ); handles[handle_index] = currentHandle; - //mp_bluetooth_gatts_db_create_entry(GATTS_DB, currentHandle, MP_BLUETOOTH_DEFAULT_ATTR_LEN); - gatts_db_create_entry(GATTS_DB, currentHandle); + mp_bluetooth_gatts_db_create_entry( + GATTS_DB, currentHandle, MP_BLUETOOTH_DEFAULT_ATTR_LEN + ); + gatts_status_create_entry(GATTS_STATUS, currentHandle); if ((flags & MP_BLUETOOTH_CHARACTERISTIC_FLAG_NOTIFY) || flags & (MP_BLUETOOTH_CHARACTERISTIC_FLAG_INDICATE)) { /* CCCD */ currentHandle++; - //uint8_t initCcc[] = {UINT16_TO_BYTES(0x0000)}; - uint8_t initCcc[] = { UINT16_TO_BYTES(0x0001) }; + uint8_t initCcc[2] = {}; + // TODO: activate notification/indications by default + // Not according to spec + if (flags & MP_BLUETOOTH_CHARACTERISTIC_FLAG_NOTIFY) { + initCcc[0] |= 0x01; + } + if (flags & MP_BLUETOOTH_CHARACTERISTIC_FLAG_INDICATE) { + initCcc[0] |= 0x02; + } // TODO: Handle CCC data // Settings is 0 on purpose. If set to ATTS_SET_CCC the stack starts to try and // manage the CCC data itself. @@ -423,7 +458,7 @@ int mp_bluetooth_gatts_register_service( ); //mp_bluetooth_gatts_db_create_entry(GATTS_DB, handles[handle_index] + 1, MP_BLUETOOTH_CCCB_LEN); - //gatts_db_create_entry(GATTS_DB, handles[handle_index] + 1); + //gatts_status_create_entry(GATTS_STATUS, handles[handle_index] + 1); //int ret = mp_bluetooth_gatts_db_write(GATTS_DB, handles[handle_index] + 1, cccb_buf, sizeof(cccb_buf)); } @@ -443,17 +478,23 @@ int mp_bluetooth_gatts_register_service_end() int mp_bluetooth_gatts_read( uint16_t value_handle, uint8_t **value, size_t *value_len ) { + return mp_bluetooth_gatts_db_read( + GATTS_DB, value_handle, value, value_len + ); +#if 0 uint16_t pLen; uint8_t ret = AttsGetAttr(value_handle, &pLen, value); *value_len = pLen; return ret; +#endif } // Write a value to the local gatts db (ready to be queried by a central). int mp_bluetooth_gatts_write( uint16_t value_handle, const uint8_t *value, size_t value_len ) { - //return mp_bluetooth_gatts_db_write(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, value_handle, value, value_len); + // TODO: which return value to choose? + mp_bluetooth_gatts_db_write(GATTS_DB, value_handle, value, value_len); uint8_t ret = AttsSetAttr(value_handle, value_len, (uint8_t *)value); return ret; } @@ -463,7 +504,8 @@ int mp_bluetooth_gatts_notify(uint16_t conn_handle, uint16_t value_handle) // Note: cordio doesn't appear to support sending a notification without a value, so include the stored value. uint8_t *data = NULL; size_t len = 0; - mp_bluetooth_gatts_read(value_handle, &data, &len); + //mp_bluetooth_gatts_read(value_handle, &data, &len); + mp_bluetooth_gatts_db_read(GATTS_DB, value_handle, &data, &len); return mp_bluetooth_gatts_notify_send( conn_handle, value_handle, data, len ); @@ -475,10 +517,12 @@ int mp_bluetooth_gatts_notify_send( const uint8_t *value, size_t value_len ) { - gatts_db_entry_t *e = gatts_db_lookup(GATTS_DB, value_handle); + gatts_status_entry_t *e = + gatts_status_lookup(GATTS_STATUS, value_handle); e->notification_status = NOTIFICATION_STATUS_PENDING; - int ret = epic_ble_atts_handle_value_ntf( - conn_handle, value_handle, value_len, (uint8_t *)value + + int ret = epic_ble_atts_handle_value_ntf( + conn_handle, value_handle, value_len, (uint8_t *)value ); if (ret < 0) { @@ -498,7 +542,34 @@ int mp_bluetooth_gatts_notify_send( // Indicate the central. int mp_bluetooth_gatts_indicate(uint16_t conn_handle, uint16_t value_handle) { - raise(); + gatts_status_entry_t *e = + gatts_status_lookup(GATTS_STATUS, value_handle); + e->notification_status = NOTIFICATION_STATUS_PENDING; + + // Note: cordio doesn't appear to support sending a notification without a value, so include the stored value. + uint8_t *value = NULL; + size_t value_len = 0; + mp_bluetooth_gatts_read(value_handle, &value, &value_len); + + int ret = epic_ble_atts_handle_value_ind( + conn_handle, value_handle, value_len, (uint8_t *)value + ); + + if (ret < 0) { + return ret; + } + + while (e->notification_status == NOTIFICATION_STATUS_PENDING) { + mp_ble_poll_events(0); + } + + if (e->notification_status != NOTIFICATION_STATUS_SUCCESS) { + // TODO: better error mapping + return -EIO; + } + + // TODO: How does the cordio stack signal that the indication was acked? + // Need to call mp_bluetooth_gatts_on_indicate_complete afterwards return 0; } @@ -506,8 +577,9 @@ int mp_bluetooth_gatts_indicate(uint16_t conn_handle, uint16_t value_handle) // Append-mode means that remote writes will append and local reads will clear after reading. int mp_bluetooth_gatts_set_buffer(uint16_t value_handle, size_t len, bool append) { - raise(); - return 0; + // TODO; which return value to use? + mp_bluetooth_gatts_db_resize(GATTS_DB, value_handle, len, append); + return -epic_ble_atts_set_buffer(value_handle, len, append); } // Disconnect from a central or peripheral.