Skip to content

Commit

Permalink
Merge 577579f into 9883d8e
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewleech committed Aug 4, 2020
2 parents 9883d8e + 577579f commit c0bded6
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 3 deletions.
7 changes: 7 additions & 0 deletions docs/library/ubluetooth.rst
Expand Up @@ -63,6 +63,9 @@ Configuration
example scan results) and the ability for a central role to receive
larger characteristic values.

- ``'mtu'``: Set only. Allows configuring the default max MTU used for
subsequent new connections.

Event Handling
--------------

Expand Down Expand Up @@ -152,6 +155,9 @@ Event Handling
# A central has acknowledged the indication.
# Note: Status will be zero on successful acknowledgment, implementation-specific value otherwise.
conn_handle, value_handle, status = data
elif event == _IRQ_GATTS_MTU_UPDATE:
# Connection MTU has been negotiated.
conn_handle, mtu_length = data

The event codes are::

Expand All @@ -176,6 +182,7 @@ The event codes are::
_IRQ_GATTC_NOTIFY = const(18)
_IRQ_GATTC_INDICATE = const(19)
_IRQ_GATTS_INDICATE_DONE = const(20)
_IRQ_GATTS_MTU_UPDATE = const(21)

In order to save space in the firmware, these constants are not included on the
:mod:`ubluetooth` module. Add the ones that you need from the list above to your
Expand Down
17 changes: 16 additions & 1 deletion extmod/btstack/modbluetooth_btstack.c
Expand Up @@ -316,8 +316,17 @@ STATIC void btstack_packet_handler(uint8_t packet_type, uint8_t *packet, uint8_t
DEBUG_EVENT_printf(" --> btstack # conns changed\n");
} else if (event_type == HCI_EVENT_VENDOR_SPECIFIC) {
DEBUG_EVENT_printf(" --> hci vendor specific\n");
} else if (event_type == ATT_EVENT_MTU_EXCHANGE_COMPLETE) {
uint16_t conn_handle = gatt_event_mtu_get_handle(packet);
uint16_t mtu = gatt_event_mtu_get_MTU(packet);
printf(" --> att MTU: %d\n", mtu);
mp_bluetooth_gatts_on_mtu_update(conn_handle, mtu);

} else if (event_type == GATT_EVENT_MTU) {
DEBUG_EVENT_printf(" --> hci MTU\n");
uint16_t conn_handle = gatt_event_mtu_get_handle(packet);
uint16_t mtu = gatt_event_mtu_get_MTU(packet);
printf(" --> gatt MTU: %d\n", mtu);
mp_bluetooth_gatts_on_mtu_update(conn_handle, mtu);
} else if (event_type == HCI_EVENT_DISCONNECTION_COMPLETE) {
DEBUG_EVENT_printf(" --> hci disconnect complete\n");
uint16_t conn_handle = hci_event_disconnection_complete_get_connection_handle(packet);
Expand All @@ -332,6 +341,7 @@ STATIC void btstack_packet_handler(uint8_t packet_type, uint8_t *packet, uint8_t
}
uint8_t addr[6] = {0};
mp_bluetooth_gap_on_connected_disconnected(irq_event, conn_handle, 0xff, addr);

#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
} else if (event_type == GAP_EVENT_ADVERTISING_REPORT) {
DEBUG_EVENT_printf(" --> gap advertising report\n");
Expand Down Expand Up @@ -617,6 +627,11 @@ int mp_bluetooth_gap_set_device_name(const uint8_t *buf, size_t len) {
return mp_bluetooth_gatts_db_write(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, BTSTACK_GAP_DEVICE_NAME_HANDLE, buf, len);
}

int mp_bluetooth_gap_set_mtu(int len) {
l2cap_set_max_le_mtu(len);
return 0;
}

int mp_bluetooth_gap_advertise_start(bool connectable, int32_t interval_us, const uint8_t *adv_data, size_t adv_data_len, const uint8_t *sr_data, size_t sr_data_len) {
DEBUG_EVENT_printf("mp_bluetooth_gap_advertise_start\n");
uint16_t adv_int_min = interval_us / 625;
Expand Down
18 changes: 18 additions & 0 deletions extmod/modbluetooth.c
Expand Up @@ -357,6 +357,11 @@ STATIC mp_obj_t bluetooth_ble_config(size_t n_args, const mp_obj_t *args, mp_map
m_del(uint8_t, old_irq_data_buf, old_irq_data_alloc);
break;
}
case MP_QSTR_mtu: {
mp_int_t value = mp_obj_get_int(e->value);
bluetooth_handle_errno(mp_bluetooth_gap_set_mtu(value));
break;
}
default:
mp_raise_ValueError(MP_ERROR_TEXT("unknown config param"));
}
Expand Down Expand Up @@ -891,6 +896,9 @@ STATIC mp_obj_t bluetooth_ble_invoke_irq(mp_obj_t none_in) {
} else if (event == MP_BLUETOOTH_IRQ_GATTS_INDICATE_DONE) {
// conn_handle, value_handle, status
ringbuf_extract(&o->ringbuf, data_tuple, 2, 1, NULL, 0, NULL, NULL);
} else if (event == MP_BLUETOOTH_IRQ_GATTS_MTU_UPDATE) {
// conn_handle, mtu_size
ringbuf_extract(&o->ringbuf, data_tuple, 2, 0, NULL, 0, NULL, NULL);
#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
} else if (event == MP_BLUETOOTH_IRQ_SCAN_RESULT) {
// addr_type, addr, adv_type, rssi, adv_data
Expand Down Expand Up @@ -1014,6 +1022,16 @@ void mp_bluetooth_gatts_on_indicate_complete(uint16_t conn_handle, uint16_t valu
schedule_ringbuf(atomic_state);
}

void mp_bluetooth_gatts_on_mtu_update(uint16_t conn_handle, uint16_t value) {
MICROPY_PY_BLUETOOTH_ENTER
mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth));
if (enqueue_irq(o, 2 + 2, MP_BLUETOOTH_IRQ_GATTS_MTU_UPDATE)) {
ringbuf_put16(&o->ringbuf, conn_handle);
ringbuf_put16(&o->ringbuf, value);
}
schedule_ringbuf(atomic_state);
}

#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
void mp_bluetooth_gap_on_scan_complete(void) {
MICROPY_PY_BLUETOOTH_ENTER
Expand Down
8 changes: 8 additions & 0 deletions extmod/modbluetooth.h
Expand Up @@ -109,6 +109,7 @@
#define MP_BLUETOOTH_IRQ_GATTC_NOTIFY (18)
#define MP_BLUETOOTH_IRQ_GATTC_INDICATE (19)
#define MP_BLUETOOTH_IRQ_GATTS_INDICATE_DONE (20)
#define MP_BLUETOOTH_IRQ_GATTS_MTU_UPDATE (21)

/*
These aren't included in the module for space reasons, but can be used
Expand All @@ -135,6 +136,7 @@ _IRQ_GATTC_WRITE_DONE = const(17)
_IRQ_GATTC_NOTIFY = const(18)
_IRQ_GATTC_INDICATE = const(19)
_IRQ_GATTS_INDICATE_DONE = const(20)
_IRQ_GATTS_MTU_UPDATE = const(21)
*/

// Common UUID type.
Expand Down Expand Up @@ -180,6 +182,9 @@ void mp_bluetooth_get_device_addr(uint8_t *addr);
size_t mp_bluetooth_gap_get_device_name(const uint8_t **buf);
int mp_bluetooth_gap_set_device_name(const uint8_t *buf, size_t len);

// Set the preferred / max MTU to be used on subsequent
int mp_bluetooth_gap_set_mtu(int len);

// Start advertisement. Will re-start advertisement when already enabled.
// Returns errno on failure.
int mp_bluetooth_gap_advertise_start(bool connectable, int32_t interval_us, const uint8_t *adv_data, size_t adv_data_len, const uint8_t *sr_data, size_t sr_data_len);
Expand Down Expand Up @@ -251,6 +256,9 @@ void mp_bluetooth_gatts_on_write(uint16_t conn_handle, uint16_t value_handle);
// Call this when an acknowledgment is received for an indication.
void mp_bluetooth_gatts_on_indicate_complete(uint16_t conn_handle, uint16_t value_handle, uint8_t status);

// Call this when MTU setting have changed.
void mp_bluetooth_gatts_on_mtu_update(uint16_t conn_handle, uint16_t value);

#if MICROPY_PY_BLUETOOTH_GATTS_ON_READ_CALLBACK
// Call this when a characteristic is read from. Return false to deny the read.
bool mp_bluetooth_gatts_on_read_request(uint16_t conn_handle, uint16_t value_handle);
Expand Down
20 changes: 18 additions & 2 deletions extmod/nimble/modbluetooth_nimble.c
Expand Up @@ -237,6 +237,7 @@ STATIC int gap_event_cb(struct ble_gap_event *event, void *arg) {
ble_gap_conn_find(event->connect.conn_handle, &desc);
reverse_addr_byte_order(addr, desc.peer_id_addr.val);
mp_bluetooth_gap_on_connected_disconnected(MP_BLUETOOTH_IRQ_CENTRAL_CONNECT, event->connect.conn_handle, desc.peer_id_addr.type, addr);
ble_gattc_exchange_mtu(event->connect.conn_handle, NULL, NULL);
} else {
// Connection failed.
mp_bluetooth_gap_on_connected_disconnected(MP_BLUETOOTH_IRQ_CENTRAL_DISCONNECT, event->connect.conn_handle, 0xff, addr);
Expand All @@ -249,14 +250,19 @@ STATIC int gap_event_cb(struct ble_gap_event *event, void *arg) {
mp_bluetooth_gap_on_connected_disconnected(MP_BLUETOOTH_IRQ_CENTRAL_DISCONNECT, event->disconnect.conn.conn_handle, event->disconnect.conn.peer_id_addr.type, addr);
break;

case BLE_GAP_EVENT_NOTIFY_TX: {
case BLE_GAP_EVENT_NOTIFY_TX:
DEBUG_EVENT_printf("gap_event_cb: notify_tx: %d %d\n", event->notify_tx.indication, event->notify_tx.status);
// This event corresponds to either a sent notify/indicate (status == 0), or an indication confirmation (status != 0).
if (event->notify_tx.indication && event->notify_tx.status != 0) {
// Map "done/ack" to 0, otherwise pass the status directly.
mp_bluetooth_gatts_on_indicate_complete(event->notify_tx.conn_handle, event->notify_tx.attr_handle, event->notify_tx.status == BLE_HS_EDONE ? 0 : event->notify_tx.status);
}
}
break;

case BLE_GAP_EVENT_MTU:
DEBUG_EVENT_printf("gap_event_cb: mtu update: cid=%d mtu=%d\n", event->mtu.channel_id, event->mtu.value);
mp_bluetooth_gatts_on_mtu_update(event->mtu.conn_handle, event->mtu.value);
break;
}

return 0;
Expand Down Expand Up @@ -363,6 +369,11 @@ int mp_bluetooth_gap_set_device_name(const uint8_t *buf, size_t len) {
return ble_hs_err_to_errno(ble_svc_gap_device_name_set(tmp_buf));
}

int mp_bluetooth_gap_set_mtu(int len) {
DEBUG_EVENT_printf("mp_bluetooth mtu:%d\n", len);
return ble_hs_err_to_errno(ble_att_set_preferred_mtu(len));
}

int mp_bluetooth_gap_advertise_start(bool connectable, int32_t interval_us, const uint8_t *adv_data, size_t adv_data_len, const uint8_t *sr_data, size_t sr_data_len) {
if (!mp_bluetooth_is_active()) {
return ERRNO_BLUETOOTH_NOT_ACTIVE;
Expand Down Expand Up @@ -738,6 +749,11 @@ STATIC int peripheral_gap_event_cb(struct ble_gap_event *event, void *arg) {
// TODO
break;

case BLE_GAP_EVENT_MTU:
DEBUG_EVENT_printf("periph_gap_event_cb: mtu update: cid=%d mtu=%d\n", event->mtu.channel_id, event->mtu.value);
mp_bluetooth_gatts_on_mtu_update(event->mtu.conn_handle, event->mtu.value);
break;

default:
break;
}
Expand Down

0 comments on commit c0bded6

Please sign in to comment.