diff options
-rw-r--r-- | extmod/modbluetooth.c | 26 | ||||
-rw-r--r-- | extmod/modbluetooth.h | 12 | ||||
-rw-r--r-- | extmod/modbluetooth_nimble.c | 33 |
3 files changed, 44 insertions, 27 deletions
diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index cb014bd9e..96cd41ae4 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -42,12 +42,6 @@ #error modbluetooth requires MICROPY_ENABLE_SCHEDULER #endif -// This is used to protect the ringbuffer. -#ifndef MICROPY_PY_BLUETOOTH_ENTER -#define MICROPY_PY_BLUETOOTH_ENTER mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); -#define MICROPY_PY_BLUETOOTH_EXIT MICROPY_END_ATOMIC_SECTION(atomic_state); -#endif - #define MP_BLUETOOTH_CONNECT_DEFAULT_SCAN_DURATION_MS 2000 #define MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_TUPLE_LEN 5 @@ -961,20 +955,28 @@ void mp_bluetooth_gattc_on_descriptor_result(uint16_t conn_handle, uint16_t hand MICROPY_PY_BLUETOOTH_EXIT } -void mp_bluetooth_gattc_on_data_available(uint16_t event, uint16_t conn_handle, uint16_t value_handle, const uint8_t *data, size_t data_len) { - MICROPY_PY_BLUETOOTH_ENTER +size_t mp_bluetooth_gattc_on_data_available_start(uint16_t event, uint16_t conn_handle, uint16_t value_handle, size_t data_len) { mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); data_len = MIN(MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN, data_len); if (enqueue_irq(o, 2 + 2 + 1 + data_len, event)) { ringbuf_put16(&o->ringbuf, conn_handle); ringbuf_put16(&o->ringbuf, value_handle); ringbuf_put(&o->ringbuf, data_len); - for (int i = 0; i < data_len; ++i) { - ringbuf_put(&o->ringbuf, data[i]); - } + return data_len; + } else { + return 0; } +} + +void mp_bluetooth_gattc_on_data_available_chunk(const uint8_t *data, size_t data_len) { + mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); + for (int i = 0; i < data_len; ++i) { + ringbuf_put(&o->ringbuf, data[i]); + } +} + +void mp_bluetooth_gattc_on_data_available_end(void) { schedule_ringbuf(); - MICROPY_PY_BLUETOOTH_EXIT } void mp_bluetooth_gattc_on_write_status(uint16_t conn_handle, uint16_t value_handle, uint16_t status) { diff --git a/extmod/modbluetooth.h b/extmod/modbluetooth.h index bce28a6d1..8a3ab414f 100644 --- a/extmod/modbluetooth.h +++ b/extmod/modbluetooth.h @@ -47,6 +47,12 @@ #define MICROPY_PY_BLUETOOTH_GATTS_ON_READ_CALLBACK (0) #endif +// This is used to protect the ringbuffer. +#ifndef MICROPY_PY_BLUETOOTH_ENTER +#define MICROPY_PY_BLUETOOTH_ENTER mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); +#define MICROPY_PY_BLUETOOTH_EXIT MICROPY_END_ATOMIC_SECTION(atomic_state); +#endif + // Common constants. #ifndef MP_BLUETOOTH_MAX_ATTR_SIZE #define MP_BLUETOOTH_MAX_ATTR_SIZE (20) @@ -247,7 +253,11 @@ void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t void mp_bluetooth_gattc_on_descriptor_result(uint16_t conn_handle, uint16_t handle, mp_obj_bluetooth_uuid_t *descriptor_uuid); // Notify modbluetooth that a read has completed with data (or notify/indicate data available, use `event` to disambiguate). -void mp_bluetooth_gattc_on_data_available(uint16_t event, uint16_t conn_handle, uint16_t value_handle, const uint8_t *data, size_t data_len); +// Note: these functions are to be called in a group protected by MICROPY_PY_BLUETOOTH_ENTER/EXIT. +// _start returns the number of bytes to submit to the calls to _chunk, followed by a call to _end. +size_t mp_bluetooth_gattc_on_data_available_start(uint16_t event, uint16_t conn_handle, uint16_t value_handle, size_t data_len); +void mp_bluetooth_gattc_on_data_available_chunk(const uint8_t *data, size_t data_len); +void mp_bluetooth_gattc_on_data_available_end(void); // Notify modbluetooth that a write has completed. void mp_bluetooth_gattc_on_write_status(uint16_t conn_handle, uint16_t value_handle, uint16_t status); diff --git a/extmod/modbluetooth_nimble.c b/extmod/modbluetooth_nimble.c index f86ab70bf..83eb4b88a 100644 --- a/extmod/modbluetooth_nimble.c +++ b/extmod/modbluetooth_nimble.c @@ -616,6 +616,20 @@ int mp_bluetooth_gatts_set_buffer(uint16_t value_handle, size_t len, bool append #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE +STATIC void gattc_on_data_available(uint16_t event, uint16_t conn_handle, uint16_t value_handle, const struct os_mbuf *om) { + MICROPY_PY_BLUETOOTH_ENTER + size_t len = OS_MBUF_PKTLEN(om); + len = mp_bluetooth_gattc_on_data_available_start(event, conn_handle, value_handle, len); + while (len > 0 && om != NULL) { + size_t n = MIN(om->om_len, len); + mp_bluetooth_gattc_on_data_available_chunk(OS_MBUF_DATA(om, const uint8_t*), n); + len -= n; + om = SLIST_NEXT(om, om_next); + } + mp_bluetooth_gattc_on_data_available_end(); + MICROPY_PY_BLUETOOTH_EXIT +} + STATIC int gap_scan_cb(struct ble_gap_event *event, void *arg) { DEBUG_EVENT_printf("gap_scan_cb: event=%d type=%d\n", event->type, event->type == BLE_GAP_EVENT_DISC ? event->disc.event_type : -1); @@ -674,8 +688,6 @@ int mp_bluetooth_gap_scan_stop(void) { STATIC int peripheral_gap_event_cb(struct ble_gap_event *event, void *arg) { DEBUG_EVENT_printf("peripheral_gap_event_cb: event=%d\n", event->type); struct ble_gap_conn_desc desc; - uint8_t buf[MP_BLUETOOTH_MAX_ATTR_SIZE]; - size_t len; uint8_t addr[6] = {0}; switch (event->type) { @@ -698,15 +710,11 @@ STATIC int peripheral_gap_event_cb(struct ble_gap_event *event, void *arg) { break; - case BLE_GAP_EVENT_NOTIFY_RX: - len = MIN(MP_BLUETOOTH_MAX_ATTR_SIZE, OS_MBUF_PKTLEN(event->notify_rx.om)); - os_mbuf_copydata(event->notify_rx.om, 0, len, buf); - if (event->notify_rx.indication == 0) { - mp_bluetooth_gattc_on_data_available(MP_BLUETOOTH_IRQ_GATTC_NOTIFY, event->notify_rx.conn_handle, event->notify_rx.attr_handle, buf, len); - } else { - mp_bluetooth_gattc_on_data_available(MP_BLUETOOTH_IRQ_GATTC_INDICATE, event->notify_rx.conn_handle, event->notify_rx.attr_handle, buf, len); - } + case BLE_GAP_EVENT_NOTIFY_RX: { + uint16_t ev = event->notify_rx.indication == 0 ? MP_BLUETOOTH_IRQ_GATTC_NOTIFY : MP_BLUETOOTH_IRQ_GATTC_INDICATE; + gattc_on_data_available(ev, event->notify_rx.conn_handle, event->notify_rx.attr_handle, event->notify_rx.om); break; + } case BLE_GAP_EVENT_CONN_UPDATE: // TODO @@ -790,10 +798,7 @@ STATIC int ble_gatt_attr_read_cb(uint16_t conn_handle, const struct ble_gatt_err DEBUG_EVENT_printf("ble_gatt_attr_read_cb: conn_handle=%d status=%d handle=%d\n", conn_handle, error->status, attr ? attr->handle : -1); // TODO: Maybe send NULL if error->status non-zero. if (error->status == 0) { - uint8_t buf[MP_BLUETOOTH_MAX_ATTR_SIZE]; - size_t len = MIN(MP_BLUETOOTH_MAX_ATTR_SIZE, OS_MBUF_PKTLEN(attr->om)); - os_mbuf_copydata(attr->om, 0, len, buf); - mp_bluetooth_gattc_on_data_available(MP_BLUETOOTH_IRQ_GATTC_READ_RESULT, conn_handle, attr->handle, buf, len); + gattc_on_data_available(MP_BLUETOOTH_IRQ_GATTC_READ_RESULT, conn_handle, attr->handle, attr->om); } return 0; } |