extmod/modbluetooth: Remove limit on data coming from gattc data input.

This removes the limit on data coming in from a BLE.gattc_read() request,
or a notify with payload (coming in to a central).  In both cases the data
coming in to the BLE callback is now limited only by the available data in
the ringbuf, whereas before it was capped at (default hard coded) 20 bytes.
This commit is contained in:
Damien George 2019-11-29 12:36:32 +11:00
parent d6e051082a
commit 8ce69288e9
3 changed files with 44 additions and 27 deletions

View File

@ -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) {

View File

@ -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);

View File

@ -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;
}