Commit Graph

43 Commits

Author SHA1 Message Date
Jim Mussared
a76604afba extmod/modbluetooth: Separate enabling of "client" from "central".
Previously, the MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE macro
controlled enabling both the central mode and the GATT client
functionality (because usually the two go together).

This commits adds a new MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
macro that separately enables the GATT client functionality.
This defaults to MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE.

This also fixes a bug in the NimBLE bindings where a notification
or indication would not be received by a peripheral (acting as client)
as gap_event_cb wasn't handling it. Now both central_gap_event_cb
and peripheral_gap_event_cb share the same common handler for these
events.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2021-02-19 17:53:43 +11:00
Jim Mussared
aa136b4d78 extmod/modbluetooth: Add ble.hci_cmd(ogf, ocf, req, resp) function.
This allows sending arbitrary HCI commands and getting the response.  The
return value of the function is the status of the command.

This is intended for debugging and not to be a part of the public API, and
must be enabled via mpconfigboard.h.  It's currently only implemented for
NimBLE bindings.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2021-01-22 18:15:12 +11:00
Jim Mussared
e4f27cbee7 extmod/modbluetooth: Add support for passkey authentication.
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2020-12-02 14:43:32 +11:00
Jim Mussared
c4d08aa4e3 extmod/modbluetooth: Add support for bonding (key persistence).
This adds `_IRQ_GET_SECRET` and `_IRQ_SET_SECRET` events to allow the BT
stack to request the Python code retrive/store/delete secret key data.  The
actual keys and values are opaque to Python and stack-specific.

Only NimBLE is implemented (pending moving btstack to sync events).  The
secret store is designed to be compatible with BlueKitchen's TLV store API.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2020-12-02 14:41:41 +11:00
Jim Mussared
801e8ffacf extmod/modbluetooth: Add gap_pair(conn_handle) func to intiate pairing.
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2020-12-02 14:41:26 +11:00
Jim Mussared
a1fcf30121 extmod/modbluetooth: Allow configuration of pairing/bonding parameters.
This allows setting the security and MITM-protection requirements.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2020-12-02 14:40:49 +11:00
Andrew Leech
05fef8c6a4 extmod/modbluetooth: Add _IRQ_ENCRYPTION_UPDATE event.
This allows the application to be notified if any of encrypted,
authenticated and bonded state change, as well as the encryption key size.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2020-12-02 14:40:15 +11:00
Jim Mussared
ac89267fef extmod/modbluetooth: Add compile-config flag to enable pairing/bonding.
Enable it on STM32/Unix NimBLE only (pairing/bonding requires synchronous
events and full bindings).

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2020-12-02 14:39:41 +11:00
Jim Mussared
60830bcba4 extmod/modbluetooth: Allow user-specified reason in read request IRQ.
Instead of returning None/bool from the IRQ, return None/int (where a zero
value means success).  This mirrors how the L2CAP_ACCEPT return value
works.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2020-12-02 14:37:55 +11:00
Andrew Leech
1697ff335d extmod/modbluetooth: Allow setting char/desc enc/auth options.
This widens the characteristic/descriptor flags to 16-bit, to allow setting
encryption/authentication requirements.

Sets the required flags for NimBLE and btstack implementations.

The BLE.FLAG_* constants will eventually be deprecated in favour of copy
and paste Python constants (like the IRQs).

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2020-12-02 14:36:50 +11:00
Andrew Leech
c70665fb0b extmod/modbluetooth: Add _IRQ_CONNECTION_UPDATE event.
This allows the application to be notified of changes to the connection
interval, connection latency and supervision timeout.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2020-12-02 14:35:39 +11:00
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
61d1e4b01b extmod/nimble: Make stm32 and unix NimBLE ports use synchronous events.
This changes stm32 from using PENDSV to run NimBLE to use the MicroPython
scheduler instead.  This allows Python BLE callbacks to be invoked directly
(and therefore synchronously) rather than via the ringbuffer.

The NimBLE UART HCI and event processing now happens in a scheduled task
every 128ms.  When RX IRQ idle events arrive, it will also schedule this
task to improve latency.

There is a similar change for the unix port where the background thread now
queues the scheduled task.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2020-11-13 17:19:05 +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
Jim Mussared
857e2c8fd5 extmod/modbluetooth: Implement MTU. 2020-09-18 12:51:21 +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
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
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
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
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
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
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
86c26db3ff extmod/btstack: Implement service registration.
Work done in collaboration with Jim Mussared aka @jimmo.
2020-03-10 01:53:42 +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
Jim Mussared
66ac2e1fc0 extmod/modbluetooth.h: Fix typo in comment about registering services. 2020-02-18 16:36:37 +11:00
Yonatan Goldschmidt
aca8873bb8 extmod/modbluetooth: Fix func prototype, empty args should be (void).
This fixes a -Wstrict-prototypes error.
2019-12-27 23:57:46 +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
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
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
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
Jim Mussared
76f474129e extmod/modbluetooth: Use us instead of ms for advertising interval.
This is to more accurately match the BLE spec, where intervals are
configured in units of channel hop time (625us). When it was
specified in ms, not all "valid" intervals were able to be
specified.

Now that we're also allowing configuration of scan interval, this
commit updates advertising to match.
2019-10-11 13:51:07 +11:00
Jim Mussared
b65cc387cd extmod/modbluetooth: Allow config of scan interval/window.
This adds two additional optional kwargs to `gap_scan()`:
  - `interval_us`: How long between scans.
  - `window_us`: How long to scan for during a scan.

The default with NimBLE is a 11.25ms window with a 1.28s interval.

Changing these parameters is important for detecting low-frequency
advertisements (e.g. beacons).

Note: these params are in microseconds, not milliseconds in order
to allow the 625us granularity offered by the spec.
2019-10-11 13:51:07 +11:00
Andrew Leech
eb1b6858a2 extmod/modbluetooth: Allow MP_BLUETOOTH_MAX_ATTR_SIZE in board config. 2019-10-01 09:51:02 +10:00
Jim Mussared
16f8ceeaaa extmod/modbluetooth: Add low-level Python BLE API. 2019-10-01 09:51:02 +10:00