Commit Graph

53 Commits

Author SHA1 Message Date
Jim Mussared
0e8af2b370 extmod/modbluetooth: Add API for L2CAP channels.
Also known as L2CAP "connection oriented channels". This provides a
socket-like data transfer mechanism for BLE.

Currently only implemented for NimBLE on STM32 / Unix.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2020-11-24 01:07:17 +11:00
Jim Mussared
81e92d3d6e extmod/modbluetooth: Re-instate optional no-ringbuf modbluetooth.
This requires that the event handlers are called from non-interrupt context
(i.e. the MicroPython scheduler).

This will allow the BLE stack (e.g. NimBLE) to run from the scheduler
rather than an IRQ like PENDSV, and therefore be able to invoke Python
callbacks directly/synchronously.  This allows writing Python BLE handlers
for events that require immediate response such as _IRQ_READ_REQUEST (which
was previous a hard IRQ) and future events relating to pairing/bonding.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2020-11-13 17:19:05 +11:00
Jim Mussared
c398e46b29 extmod/modbluetooth: Combine gattc-data-available callbacks into one.
Instead of having the stack indicate a "start", "data"..., "end", pass
through the data in one callback as an array of chunks of data.

This is because the upcoming non-ringbuffer modbluetooth implementation
cannot buffer the data in the ringbuffer and requires instead a single
callback with all the data, to pass to the Python callback.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2020-11-13 17:19:05 +11:00
Jim Mussared
3d890e7ab4 extmod/modbluetooth: Make UUID type accessible outside modbluetooth.c.
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2020-11-13 17:19:05 +11:00
Damien George
81f2162ca0 extmod/modbluetooth: Change module-owned bytes objects to memoryview.
A read-only memoryview object is a better representation of the data, which
is owned by the ubluetooth module and may change between calls to the
user's irq callback function.

Signed-off-by: Damien George <damien@micropython.org>
2020-09-25 12:23:11 +10:00
Jim Mussared
857e2c8fd5 extmod/modbluetooth: Implement MTU. 2020-09-18 12:51:21 +10:00
Jim Mussared
5be3bfcb7e extmod/modbluetooth: Print UUIDs correctly.
In particular, the printed string can now be re-evaluated to construct the
same UUID object.
2020-09-15 15:29:13 +10:00
Jim Mussared
6a6a5f9e15 extmod/modbluetooth: Make BLE.irq() method positional only.
Simplifcation now that the trigger arg has been removed.
2020-09-15 15:28:45 +10:00
Jim Mussared
504522bd02 extmod/modbluetooth: Fix handling of optional data/uuid args.
For the following 3 functions, previously the code relied on whether the
arg was passed at all, to make it optional.  Now it allows them to be
explicitly `None` to indicate they are not used:

- gatts_notify(..., [data])
- gattc_discover_services(..., [uuid])
- gattc_discover_characteristics(..., [uuid])

Also ensure that the uuid arguments are actually instances of the uuid
type, and fix handling of the 5th arg in gattc_discover_characteristics().
2020-09-15 15:23:51 +10:00
Jim Mussared
c4af714d58 extmod/modbluetooth: Implement configuration of address modes.
Changes `BLE.config('mac')` to return a tuple (addr_mode, addr).

Adds `BLE.config(addr_mode=...)` to set the addressing mode.
2020-09-08 12:53:24 +10:00
Andrew Leech
a80a146858 extmod/bluetooth: Support active scanning in BLE.gap_scan().
This adds an additional optional parameter to gap_scan() to select active
scanning, where scan responses are returned as well as normal scan results.
This parameter is False by default which retains the existing behaviour.
2020-08-26 15:00:11 +10:00
Jim Mussared
0bc2c1c105 extmod/modbluetooth: Fix race between READ_REQUEST and other IRQs.
The READ_REQUEST callback is handled as a hard interrupt (because the BLE
stack needs an immediate response from it so it can continue) and so calls
to Python require extra protection:

- the caller-owned tuple passed into the callback must be separate from the
  tuple used by other callback events (which are soft interrupts);

- the GC and scheduler must be locked during callback execution.
2020-08-26 14:57:36 +10:00
Jim Mussared
9d823a5d9a extmod/modbluetooth: Add event for "indicate acknowledgement".
This commit adds the IRQ_GATTS_INDICATE_DONE BLE event which will be raised
with the status of gatts_indicate (unlike notify, indications require
acknowledgement).

An example of its use is added to ble_temperature.py, and to the multitests
in ble_characteristic.py.

Implemented for btstack and nimble bindings, tested in both directions
between unix/btstack and pybd/nimble.
2020-07-20 23:26:41 +10:00
Jim Mussared
3c7ca2004c extmod/modbluetooth: Fix so it builds in peripheral-only mode. 2020-07-20 23:25:56 +10:00
Jim Mussared
43ceadac55 extmod/modbluetooth: Ignore unused self_in in ble_gatts_indicate. 2020-07-20 23:25:22 +10:00
Jim Mussared
e152d0c197 extmod/btstack: Schedule notify/indicate/write ops for bg completion.
The goal of this commit is to allow using ble.gatts_notify() at any time,
even if the stack is not ready to send the notification right now.  It also
addresses the same issue for ble.gatts_indicate() and ble.gattc_write()
(without response).  In addition this commit fixes the case where the
buffer passed to write-with-response wasn't copied, meaning it could be
modified by the caller, affecting the in-progress write.

The changes are:

- gatts_notify/indicate will now run in the background if the ACL buffer is
  currently full, meaning that notify/indicate can be called at any time.

- gattc_write(mode=0) (no response) will now allow for one outstanding
  write.

- gattc_write(mode=1) (with response) will now copy the buffer so that it
  can't be modified by the caller while the write is in progress.

All four paths also now track the buffer while the operation is in
progress, which prevents the GC free'ing the buffer while it's still
needed.
2020-07-18 14:23:47 +10:00
Jim Mussared
8b7ae4e099 extmod/modbluetooth: Support bigger characteristic values.
The ring buffer previously used a single unsigned byte field to save the
length, meaning that it would overflow for large characteristic value
responses.

With this commit it now use a 16-bit length instead and has code to
explicitly truncate at UINT16_MAX (although this should be impossible to
achieve in practice).
2020-06-05 14:11:46 +10:00
Jim Mussared
c07ea3e4c2 extmod/modbluetooth: Implement read done event.
On btstack there's no status associated with the read result, it comes
through as a separate event.  This allows you to detect read failures or
timeouts.
2020-06-05 14:08:15 +10:00
Jim Mussared
919d640aec extmod/modbluetooth: Allow discovery of svc/char by uuid.
In most situations this is a more efficient way of going straight to the
service and characteristic you need.
2020-06-05 14:08:07 +10:00
Jim Mussared
6a3c89d584 extmod/modbluetooth: Add discover complete events for svc/char/desc.
Without this it's difficult to implement a state machine correctly if the
desired services are not found.
2020-06-05 14:07:52 +10:00
Jim Mussared
e6881f0829 extmod/modbluetooth: Make modbluetooth event not a bitfield.
There doesn't appear to be any use for only triggering on specific events,
so it's just easier to number them sequentially.  This makes them smaller
values so they take up only 1 byte in the ringbuf, only 1 byte for the
opcode in the bytecode, and makes room for more events.

Also add a couple of new event types that need to be implemented (to avoid
re-numbering later).

And rename _COMPLETE and _STATUS to _DONE for consistency.

In the future the "trigger" keyword argument can be reinstated by requiring
the user to compute the bitmask, eg:

    ble.irq(handler, 1 << _IRQ_SCAN_RESULT | 1 << _IRQ_SCAN_DONE)
2020-06-05 14:04:20 +10:00
Damien George
3b6c9119eb extmod/modbluetooth: Add support for changing the GAP device name.
This commit allows the user to set/get the GAP device name used by service
0x1800, characteristic 0x2a00.  The usage is:

    BLE.config(gap_name="myname")
    print(BLE.config("gap_name"))

As part of this change the compile-time setting
MICROPY_PY_BLUETOOTH_DEFAULT_NAME is renamed to
MICROPY_PY_BLUETOOTH_DEFAULT_GAP_NAME to emphasise its link to GAP and this
new "gap_name" config value.  And the default value of this for the NimBLE
bindings is changed from "PYBD" to "MPY NIMBLE" to be more generic.
2020-05-11 21:30:41 +10:00
Jim Mussared
ebfd9ff2e6 extmod/modbluetooth: Fix sign compare and unused variable warnings. 2020-04-29 16:54:12 +10:00
Jim Mussared
8119ec0765 extmod/modbluetooth: Don't hold atomic section during mp_sched_schedule.
Because, for example, on unix the atomic section isn't re-entrant, and
mp_sched_schedule() will try to re-acquire the atomic section.
2020-04-29 16:45:40 +10:00
Damien George
c5a21a94f8 extmod/modbluetooth: Provide FLAG_WRITE_NO_RESPONSE for characteristics.
This flag is supported and needs to be set if characteristics are write-
without-response.
2020-04-07 13:46:56 +10:00
Jim Mussared
def76fe4d9 all: Use MP_ERROR_TEXT for all error messages. 2020-04-05 15:02:06 +10:00
Damien George
dd0bc26e65 extmod/modbluetooth: Change scan result's "connectable" to "adv_type".
This commit changes the BLE _IRQ_SCAN_RESULT data from:

    addr_type, addr, connectable, rssi, adv_data

to:

    addr_type, addr, adv_type, rssi, adv_data

This allows _IRQ_SCAN_RESULT to handle all scan result types (not just
connectable and non-connectable passive scans), and to distinguish between
them using adv_type which is an integer taking values 0x00-0x04 per the BT
specification.

This is a breaking change to the API, albeit a very minor one: the existing
connectable value was a boolean and True now becomes 0x00, False becomes
0x02.

Documentation is updated and a test added.

Fixes #5738.
2020-03-11 14:00:44 +11:00
Thomas Friebel
41a9f1dec8 extmod/modbluetooth: Unify error handling in remaining places.
Most error handling is done via `bluetooth_handle_errno()` already.
Replace the remaining few manual checks with calls to that function.
2020-03-11 13:01:35 +11:00
Jim Mussared
1937fb22ab extmod/nimble: Clarify active state and check for active in all methods.
This commit ensures that the BLE stack is active before allowing operations
that may otherwise crash if it's not active.  It also clarifies the state
better (adding the "stopping" state) and renames mp_bluetooth_is_enabled to
the more self-explanatory mp_bluetooth_is_active.
2020-03-11 13:01:35 +11:00
Damien George
0ac06a510a extmod/modbluetooth: Extract out gatts_db functionality from nimble.
For use by other stacks, if they need it.

Work done in collaboration with Jim Mussared aka @jimmo.
2020-03-10 01:53:42 +11:00
Damien George
69661f3343 all: Reformat C and Python source code with tools/codeformat.py.
This is run with uncrustify 0.70.1, and black 19.10b0.
2020-02-28 10:33:03 +11:00
Thomas Friebel
f4726735cf extmod/modbluetooth: Implement config getter for BLE rxbuf size.
Knowing the buffer size can be important, to ensure that valid data will be
received.
2020-02-18 13:37:50 +11:00
Damien George
6f872f81d6 extmod: Fix modbluetooth and modwebrepl to build in nanbox mode. 2019-12-27 22:54:53 +11:00
Damien George
84958a8fe1 extmod/modbluetooth: Allow setting ringbuf size via BLE.config(rxbuf=).
The size of the event ringbuf was previously fixed to compile-time config
value, but it's necessary to sometimes increase this for applications that
have large characteristic buffers to read, or many events at once.

With this commit the size can be set via BLE.config(rxbuf=512), for
example.  This also resizes the internal event data buffer which sets the
maximum size of incoming data passed to the event handler.
2019-12-05 11:30:35 +11:00
Damien George
7aeafe2ae9 extmod/modbluetooth: Add optional 4th arg to gattc_write for write mode.
This allows the user to explicitly select the behaviour of the write to the
remote peripheral.  This is needed for peripherals that have
characteristics with WRITE_NO_RESPONSE set (instead of normal WRITE).  The
function's signature is now:

    BLE.gattc_write(conn_handle, value_handle, data, mode=0)

mode=0 means write without response, while mode=1 means write with
response.  The latter was the original behaviour so this commit is a change
in behaviour of this method, and one should specify 1 as the 4th argument
to get back the old behaviour.

In the future there could be more modes supported, such as long writes.
2019-12-04 23:23:07 +11:00
Damien George
40cc7ec677 stm32/mpconfigport.h: Use IRQ_PRI_PENDSV to protect bluetooth ringbuf.
The default protection for the BLE ringbuf is to use
MICROPY_BEGIN_ATOMIC_SECTION, which disables all interrupts. On stm32 it
only needs to disable the lowest priority IRQ, pendsv, because that's the
IRQ level at which the BLE stack is driven.
2019-12-04 13:39:22 +11:00
Damien George
8ce69288e9 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.
2019-12-02 23:27:25 +11:00
Damien George
d6e051082a extmod/modbluetooth: Simplify how BLE IRQ callback is scheduled.
Instead of enqueue_irq() inspecting the ringbuf to decide whether to
schedule the IRQ callback (if ringbuf is empty), maintain a flag that knows
if the callback is on the schedule queue or not.  This saves about 150
bytes of code (for stm32 builds), and simplifies all uses of enqueue_irq()
and schedule_ringbuf().
2019-12-02 23:25:36 +11:00
Jim Mussared
e873d352ad extmod/modbluetooth: Simplify management of pre-allocated event data.
The address, adv payload and uuid fields of the event are pre-allocated by
modbluetooth, and reused in the IRQ handler.  Simplify this and move all
storage into the `mp_obj_bluetooth_ble_t` instance.

This now allows users to hold on to a reference to these instances without
crashes, although they may be overwritten by future events.  If they want
to hold onto the values longer term they need to copy them.
2019-11-25 17:32:10 +11:00
Jim Mussared
d19c6d0519 extmod/modbluetooth: Create UUID from bytes and allow comparison ops.
This allows construction of UUID objects from advertising data payloads and
matching against known UUIDs.
2019-11-25 17:20:51 +11:00
Jim Mussared
334ba01c90 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.
2019-11-21 12:04:57 +11:00
Jim Mussared
d16a27da51 extmod/modbluetooth: Add gatts_set_buffer.
- Adds an explicit way to set the size of a value's internal buffer,
  replacing `ble.gatts_write(handle, bytes(size))` (although that
  still works).
- Add an "append" mode for values, which means that remote writes
  will append to the buffer.
2019-10-29 23:09:02 +11:00
Jim Mussared
b02d7e612d extmod/modbluetooth: Rename module to "ubluetooth".
For consistency with "umachine". Now that weak links are enabled
by default for built-in modules, this should be a no-op, but allows
extension of the bluetooth module by user code.

Also move registration of ubluetooth to objmodule rather than
port-specific.
2019-10-22 21:58:05 +11:00
Jim Mussared
f34e16dbc6 extmod/modbluetooth: Persist reference to NimBLE service instances.
NimBLE doesn't actually copy this data, it requires it to stay live.
Only dereference when we register a new set of services.

Fixes #5226

This will allow incrementally adding services in the future, so
rename `reset` to `append` to make it clearer.
2019-10-22 14:30:23 +11:00
Jim Mussared
56fc3edf98 extmod/modbluetooth: Make UUID support the buffer protocol.
Internally change the representation of UUIDs to LE uint8* to simplify this.

This allows UUIDs to be easily used in BLE payloads (such as advertising).

Ref: #5186
2019-10-22 13:54:05 +11:00
Damien George
8f7f671236 extmod/modbluetooth: In gap_advertise only accept None to stop adv.
To match the docs, and interval=0 may be used in the future to indicate
something else.
2019-10-15 17:29:27 +11:00
Jim Mussared
36502bdfdc extmod/modbluetooth: Make gap_disconnect not raise when disconnected.
Previously it raised OSError(MP_ENOTCONN) if the conn_handle was already
disconnected.  Now it returns True/False.
2019-10-15 17:22:53 +11:00
Jim Mussared
423e67d0a0 extmod/modbluetooth: Improve ringbuf handling.
No need to share the irq_data buffer with addresses.  Split them into two
separate buffers and manage their max length independently.
2019-10-15 17:22:07 +11:00
Jim Mussared
cb73103f57 extmod/modbluetooth: Fix order of params to IRQ_GATTS_WRITE event. 2019-10-15 17:22:01 +11:00
Jim Mussared
ba16a22991 extmod/modbluetooth: Clear gap_advertise payload when data is empty.
Also fix default adv interval to 500ms.
2019-10-15 17:21:17 +11:00