diff options
author | Jim Mussared <jim.mussared@gmail.com> | 2019-11-11 17:07:17 +1100 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2019-11-21 12:04:57 +1100 |
commit | 334ba01c9078658d24e06b6ea68b7dc2ec02c506 (patch) | |
tree | 95950ba2a86f98bd5a1ec9fd9690d6c3b2ca0a35 /extmod/modbluetooth.c | |
parent | 4f966892813b1b0c43f7ad1d97a7dcd77c646302 (diff) |
extmod/modbluetooth: Prioritise non-scan-result events.
Remove existing scan result events from the ringbuf if the ringbuf is full
and we're trying to enqueue any other event. This is needed so that events
such as SCAN_COMPLETE are always put on the ringbuf.
Diffstat (limited to 'extmod/modbluetooth.c')
-rw-r--r-- | extmod/modbluetooth.c | 37 |
1 files changed, 32 insertions, 5 deletions
diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index 1e5eafc89..e919a672e 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -792,13 +792,40 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluetooth_ble_invoke_irq_obj, bluetooth_ble_inv STATIC bool enqueue_irq(mp_obj_bluetooth_ble_t *o, size_t len, uint16_t event, bool *sched) { *sched = false; - if (o && ringbuf_free(&o->ringbuf) >= len + 2 && (o->irq_trigger & event) && o->irq_handler != mp_const_none) { - *sched = ringbuf_avail(&o->ringbuf) == 0; - ringbuf_put16(&o->ringbuf, event); - return true; - } else { + if (!o || !(o->irq_trigger & event) || o->irq_handler == mp_const_none) { return false; } + + if (ringbuf_free(&o->ringbuf) < len + 2) { + // Ringbuffer doesn't have room (and is therefore non-empty). + + // If this is another scan result, or the front of the ringbuffer isn't a scan result, then nothing to do. + if (event == MP_BLUETOOTH_IRQ_SCAN_RESULT || ringbuf_peek16(&o->ringbuf) != MP_BLUETOOTH_IRQ_SCAN_RESULT) { + return false; + } + + // Front of the queue is a scan result, remove it. + + // event, addr_type, addr, connectable, rssi + int n = 2 + 1 + 6 + 1 + 1; + for (int i = 0; i < n; ++i) { + ringbuf_get(&o->ringbuf); + } + // adv_data + n = ringbuf_get(&o->ringbuf); + for (int i = 0; i < n; ++i) { + ringbuf_get(&o->ringbuf); + } + + // No need to schedule the handler, as the ringbuffer was non-empty. + } else { + // Schedule the handler only if this is the first thing in the ringbuffer. + *sched = ringbuf_avail(&o->ringbuf) == 0; + } + + // Append this event, the caller will then append the arguments. + ringbuf_put16(&o->ringbuf, event); + return true; } STATIC void schedule_ringbuf(bool sched) { |