summaryrefslogtreecommitdiffstatshomepage
path: root/extmod/btstack
diff options
context:
space:
mode:
authorJim Mussared <jim.mussared@gmail.com>2020-05-11 21:46:56 +1000
committerDamien George <damien.p.george@gmail.com>2020-06-05 14:07:52 +1000
commit6a3c89d584db4f14c7e2432b7c5ad87951e6c2d5 (patch)
tree866cf6ef026c65d3fae6f4bc54a2dd707892399c /extmod/btstack
parente6881f08292d03f089185718c131f543d095089b (diff)
downloadmicropython-6a3c89d584db4f14c7e2432b7c5ad87951e6c2d5.tar.gz
micropython-6a3c89d584db4f14c7e2432b7c5ad87951e6c2d5.zip
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.
Diffstat (limited to 'extmod/btstack')
-rw-r--r--extmod/btstack/modbluetooth_btstack.c89
1 files changed, 62 insertions, 27 deletions
diff --git a/extmod/btstack/modbluetooth_btstack.c b/extmod/btstack/modbluetooth_btstack.c
index 772fe4bed1..625ccf4c4a 100644
--- a/extmod/btstack/modbluetooth_btstack.c
+++ b/extmod/btstack/modbluetooth_btstack.c
@@ -56,10 +56,17 @@ volatile int mp_bluetooth_btstack_state = MP_BLUETOOTH_BTSTACK_STATE_OFF;
STATIC btstack_packet_callback_registration_t hci_event_callback_registration;
STATIC int btstack_error_to_errno(int err) {
+ DEBUG_EVENT_printf(" --> btstack error: %d\n", err);
if (err == ERROR_CODE_SUCCESS) {
return 0;
- } else if (err == BTSTACK_ACL_BUFFERS_FULL) {
+ } else if (err == BTSTACK_ACL_BUFFERS_FULL || err == BTSTACK_MEMORY_ALLOC_FAILED) {
return MP_ENOMEM;
+ } else if (err == GATT_CLIENT_IN_WRONG_STATE) {
+ return MP_EALREADY;
+ } else if (err == GATT_CLIENT_BUSY) {
+ return MP_EBUSY;
+ } else if (err == GATT_CLIENT_NOT_CONNECTED) {
+ return MP_ENOTCONN;
} else {
return MP_EINVAL;
}
@@ -78,10 +85,8 @@ STATIC mp_obj_bluetooth_uuid_t create_mp_uuid(uint16_t uuid16, const uint8_t *uu
return result;
}
-STATIC void btstack_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
- (void)channel;
- (void)size;
- DEBUG_EVENT_printf("btstack_packet_handler(packet_type=%u, channel=%u, packet=%p, size=%u)\n", packet_type, channel, packet, size);
+STATIC void btstack_packet_handler(uint8_t packet_type, uint8_t *packet, uint8_t irq) {
+ DEBUG_EVENT_printf("btstack_packet_handler(packet_type=%u, packet=%p)\n", packet_type, packet);
if (packet_type != HCI_EVENT_PACKET) {
return;
}
@@ -157,6 +162,18 @@ STATIC void btstack_packet_handler(uint8_t packet_type, uint16_t channel, uint8_
#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
} else if (event_type == GATT_EVENT_QUERY_COMPLETE) {
DEBUG_EVENT_printf(" --> gatt query complete\n");
+ uint16_t conn_handle = gatt_event_query_complete_get_handle(packet);
+ uint16_t status = gatt_event_query_complete_get_att_status(packet);
+ if (irq == MP_BLUETOOTH_IRQ_GATTC_READ_DONE || irq == MP_BLUETOOTH_IRQ_GATTC_WRITE_DONE) {
+ // TODO there is no value_handle available to pass here
+ mp_bluetooth_gattc_on_read_write_status(irq, conn_handle, 0, status);
+ } else if (irq == MP_BLUETOOTH_IRQ_GATTC_SERVICE_DONE ||
+ irq == MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_DONE ||
+ irq == MP_BLUETOOTH_IRQ_GATTC_DESCRIPTOR_DONE) {
+ mp_bluetooth_gattc_on_discover_complete(irq, conn_handle, status);
+ } else {
+ // Note that query complete is fired for other operations like query value too.
+ }
} else if (event_type == GATT_EVENT_SERVICE_QUERY_RESULT) {
DEBUG_EVENT_printf(" --> gatt service query result\n");
uint16_t conn_handle = gatt_event_service_query_result_get_handle(packet);
@@ -208,31 +225,50 @@ STATIC void btstack_packet_handler(uint8_t packet_type, uint16_t channel, uint8_
len = mp_bluetooth_gattc_on_data_available_start(MP_BLUETOOTH_IRQ_GATTC_INDICATE, conn_handle, value_handle, len, &atomic_state);
mp_bluetooth_gattc_on_data_available_chunk(data, len);
mp_bluetooth_gattc_on_data_available_end(atomic_state);
- #endif
+ #endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
} else {
DEBUG_EVENT_printf(" --> hci event type: unknown (0x%02x)\n", event_type);
}
}
+// Because the packet handler callbacks don't support an argument, we use a specific
+// handler when we need to provide additional state to the handler (in the "irq" parameter).
+// This is the generic handler for when you don't need extra state.
+STATIC void btstack_packet_handler_generic(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
+ (void)channel;
+ (void)size;
+ btstack_packet_handler(packet_type, packet, 0);
+}
+
#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
-STATIC void btstack_packet_handler_write_with_response(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
+// For when the handler is being used for service discovery.
+STATIC void btstack_packet_handler_discover_services(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
(void)channel;
(void)size;
- DEBUG_EVENT_printf("btstack_packet_handler_write_with_response(packet_type=%u, channel=%u, packet=%p, size=%u)\n", packet_type, channel, packet, size);
- if (packet_type != HCI_EVENT_PACKET) {
- return;
- }
+ btstack_packet_handler(packet_type, packet, MP_BLUETOOTH_IRQ_GATTC_SERVICE_DONE);
+}
- uint8_t event_type = hci_event_packet_get_type(packet);
- if (event_type == GATT_EVENT_QUERY_COMPLETE) {
- DEBUG_EVENT_printf(" --> gatt query complete\n");
- uint16_t conn_handle = gatt_event_query_complete_get_handle(packet);
- uint8_t status = gatt_event_query_complete_get_att_status(packet);
- // TODO there is no value_handle to pass here
- mp_bluetooth_gattc_on_write_status(conn_handle, 0, status);
- }
+// For when the handler is being used for characteristic discovery.
+STATIC void btstack_packet_handler_discover_characteristics(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
+ (void)channel;
+ (void)size;
+ btstack_packet_handler(packet_type, packet, MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_DONE);
}
-#endif
+
+// For when the handler is being used for descriptor discovery.
+STATIC void btstack_packet_handler_discover_descriptors(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
+ (void)channel;
+ (void)size;
+ btstack_packet_handler(packet_type, packet, MP_BLUETOOTH_IRQ_GATTC_DESCRIPTOR_DONE);
+}
+
+// For when the handler is being used for write-with-response.
+STATIC void btstack_packet_handler_write_with_response(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
+ (void)channel;
+ (void)size;
+ btstack_packet_handler(packet_type, packet, MP_BLUETOOTH_IRQ_GATTC_WRITE_DONE);
+}
+#endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
STATIC btstack_timer_source_t btstack_init_deinit_timeout;
@@ -285,7 +321,7 @@ int mp_bluetooth_init(void) {
#endif
// Register for HCI events.
- hci_event_callback_registration.callback = &btstack_packet_handler;
+ hci_event_callback_registration.callback = &btstack_packet_handler_generic;
hci_add_event_handler(&hci_event_callback_registration);
// Set a timeout for HCI initialisation.
@@ -314,7 +350,7 @@ int mp_bluetooth_init(void) {
#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
// Enable GATT_EVENT_NOTIFICATION/GATT_EVENT_INDICATION for all connections and handles.
- gatt_client_listen_for_characteristic_value_updates(&MP_STATE_PORT(bluetooth_btstack_root_pointers)->notification, &btstack_packet_handler, GATT_CLIENT_ANY_CONNECTION, NULL);
+ gatt_client_listen_for_characteristic_value_updates(&MP_STATE_PORT(bluetooth_btstack_root_pointers)->notification, &btstack_packet_handler_generic, GATT_CLIENT_ANY_CONNECTION, NULL);
#endif
return 0;
@@ -643,12 +679,11 @@ int mp_bluetooth_gap_peripheral_connect(uint8_t addr_type, const uint8_t *addr,
int mp_bluetooth_gattc_discover_primary_services(uint16_t conn_handle) {
DEBUG_EVENT_printf("mp_bluetooth_gattc_discover_primary_services\n");
- return btstack_error_to_errno(gatt_client_discover_primary_services(&btstack_packet_handler, conn_handle));
+ return btstack_error_to_errno(gatt_client_discover_primary_services(&btstack_packet_handler_discover_services, conn_handle));
}
int mp_bluetooth_gattc_discover_characteristics(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle) {
DEBUG_EVENT_printf("mp_bluetooth_gattc_discover_characteristics\n");
-
gatt_client_service_t service = {
// Only start/end handles needed for gatt_client_discover_characteristics_for_service.
.start_group_handle = start_handle,
@@ -656,7 +691,7 @@ int mp_bluetooth_gattc_discover_characteristics(uint16_t conn_handle, uint16_t s
.uuid16 = 0,
.uuid128 = {0},
};
- return btstack_error_to_errno(gatt_client_discover_characteristics_for_service(&btstack_packet_handler, conn_handle, &service));
+ return btstack_error_to_errno(gatt_client_discover_characteristics_for_service(&btstack_packet_handler_discover_characteristics, conn_handle, &service));
}
int mp_bluetooth_gattc_discover_descriptors(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle) {
@@ -670,12 +705,12 @@ int mp_bluetooth_gattc_discover_descriptors(uint16_t conn_handle, uint16_t start
.uuid16 = 0,
.uuid128 = {0},
};
- return btstack_error_to_errno(gatt_client_discover_characteristic_descriptors(&btstack_packet_handler, conn_handle, &characteristic));
+ return btstack_error_to_errno(gatt_client_discover_characteristic_descriptors(&btstack_packet_handler_discover_descriptors, conn_handle, &characteristic));
}
int mp_bluetooth_gattc_read(uint16_t conn_handle, uint16_t value_handle) {
DEBUG_EVENT_printf("mp_bluetooth_gattc_read\n");
- return btstack_error_to_errno(gatt_client_read_value_of_characteristic_using_value_handle(&btstack_packet_handler, conn_handle, value_handle));
+ return btstack_error_to_errno(gatt_client_read_value_of_characteristic_using_value_handle(&btstack_packet_handler_generic, conn_handle, value_handle));
}
int mp_bluetooth_gattc_write(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t *value_len, unsigned int mode) {