summaryrefslogtreecommitdiff
path: root/devices
diff options
context:
space:
mode:
authorDan Halbert <halbert@halwitz.org>2020-08-03 21:02:57 -0400
committerDan Halbert <halbert@halwitz.org>2020-08-03 21:02:57 -0400
commita995a5c58fa4c231fcfb8c5e0eb6a3847faabbcc (patch)
tree1c9341a36b0654212b6effb472293d73abd0c1a7 /devices
parent0a60aee3e4270d1da42d67f933578d60d56b8b52 (diff)
wip: partial discovery responses; compiles; not tested
Diffstat (limited to 'devices')
-rw-r--r--devices/ble_hci/common-hal/_bleio/Adapter.c60
-rw-r--r--devices/ble_hci/common-hal/_bleio/Attribute.c2
-rw-r--r--devices/ble_hci/common-hal/_bleio/Attribute.h4
-rw-r--r--devices/ble_hci/common-hal/_bleio/att.c127
-rw-r--r--devices/ble_hci/common-hal/_bleio/hci.c123
-rw-r--r--devices/ble_hci/common-hal/_bleio/hci_debug.c335
6 files changed, 500 insertions, 151 deletions
diff --git a/devices/ble_hci/common-hal/_bleio/Adapter.c b/devices/ble_hci/common-hal/_bleio/Adapter.c
index 3acae9beb..c8147fbc1 100644
--- a/devices/ble_hci/common-hal/_bleio/Adapter.c
+++ b/devices/ble_hci/common-hal/_bleio/Adapter.c
@@ -43,6 +43,8 @@
#include "shared-bindings/_bleio/__init__.h"
#include "shared-bindings/_bleio/Adapter.h"
#include "shared-bindings/_bleio/Address.h"
+#include "shared-bindings/_bleio/Characteristic.h"
+#include "shared-bindings/_bleio/Service.h"
#include "shared-bindings/nvm/ByteArray.h"
#include "shared-bindings/_bleio/Connection.h"
#include "shared-bindings/_bleio/ScanEntry.h"
@@ -70,6 +72,12 @@
bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT];
+STATIC void check_enabled(bleio_adapter_obj_t *adapter) {
+ if (!common_hal_bleio_adapter_get_enabled(adapter)) {
+ mp_raise_bleio_BluetoothError(translate("Adapter not enabled"));
+ }
+}
+
// STATIC bool adapter_on_ble_evt(ble_evt_t *ble_evt, void *self_in) {
// bleio_adapter_obj_t *self = (bleio_adapter_obj_t*)self_in;
@@ -232,6 +240,14 @@ void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enable
self->enabled = enabled;
+ // We must poll for input from the HCI adapter.
+ // TODO Can we instead trigger an interrupt on UART input traffic?
+ if (enabled) {
+ supervisor_enable_tick();
+ } else {
+ supervisor_disable_tick();
+ }
+
// Stop any current activity; reset to known state.
check_hci_error(hci_reset());
self->now_advertising = false;
@@ -253,6 +269,8 @@ bool common_hal_bleio_adapter_get_enabled(bleio_adapter_obj_t *self) {
}
bleio_address_obj_t *common_hal_bleio_adapter_get_address(bleio_adapter_obj_t *self) {
+ check_enabled(self);
+
bt_addr_t addr;
check_hci_error(hci_read_bd_addr(&addr));
@@ -306,6 +324,8 @@ void common_hal_bleio_adapter_set_name(bleio_adapter_obj_t *self, const char* na
// }
mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t* prefixes, size_t prefix_length, bool extended, mp_int_t buffer_size, mp_float_t timeout, mp_float_t interval, mp_float_t window, mp_int_t minimum_rssi, bool active) {
+ check_enabled(self);
+
if (self->scan_results != NULL) {
if (!shared_module_bleio_scanresults_get_done(self->scan_results)) {
mp_raise_bleio_BluetoothError(translate("Scan already in progess. Stop with stop_scan."));
@@ -350,6 +370,8 @@ mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t*
}
void common_hal_bleio_adapter_stop_scan(bleio_adapter_obj_t *self) {
+ check_enabled(self);
+
check_hci_error(hci_le_set_scan_enable(BT_HCI_LE_SCAN_DISABLE, BT_HCI_LE_SCAN_FILTER_DUP_DISABLE));
shared_module_bleio_scanresults_set_done(self->scan_results, true);
self->scan_results = NULL;
@@ -385,6 +407,8 @@ void common_hal_bleio_adapter_stop_scan(bleio_adapter_obj_t *self) {
mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout) {
+ check_enabled(self);
+
// ble_gap_addr_t addr;
// addr.addr_type = address->type;
@@ -482,6 +506,8 @@ STATIC void check_data_fit(size_t data_len, bool connectable) {
// }
uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, bool anonymous, uint32_t timeout, float interval, uint8_t *advertising_data, uint16_t advertising_data_len, uint8_t *scan_response_data, uint16_t scan_response_data_len) {
+ check_enabled(self);
+
if (self->now_advertising) {
if (self->circuitpython_advertising) {
common_hal_bleio_adapter_stop_advertising(self);
@@ -603,6 +629,8 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
}
void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, bool anonymous, uint32_t timeout, mp_float_t interval, mp_buffer_info_t *advertising_data_bufinfo, mp_buffer_info_t *scan_response_data_bufinfo) {
+ check_enabled(self);
+
// interval value has already been validated.
check_data_fit(advertising_data_bufinfo->len, connectable);
@@ -638,6 +666,8 @@ void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool
}
void common_hal_bleio_adapter_stop_advertising(bleio_adapter_obj_t *self) {
+ check_enabled(self);
+
self->now_advertising = false;
self->extended_advertising = false;
self->circuitpython_advertising = false;
@@ -651,10 +681,14 @@ void common_hal_bleio_adapter_stop_advertising(bleio_adapter_obj_t *self) {
}
bool common_hal_bleio_adapter_get_advertising(bleio_adapter_obj_t *self) {
+ check_enabled(self);
+
return self->now_advertising;
}
bool common_hal_bleio_adapter_get_connected(bleio_adapter_obj_t *self) {
+ check_enabled(self);
+
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
bleio_connection_internal_t *connection = &bleio_connections[i];
if (connection->conn_handle != BLE_CONN_HANDLE_INVALID) {
@@ -665,6 +699,8 @@ bool common_hal_bleio_adapter_get_connected(bleio_adapter_obj_t *self) {
}
mp_obj_t common_hal_bleio_adapter_get_connections(bleio_adapter_obj_t *self) {
+ check_enabled(self);
+
if (self->connection_objs != NULL) {
return self->connection_objs;
}
@@ -685,17 +721,31 @@ mp_obj_t common_hal_bleio_adapter_get_connections(bleio_adapter_obj_t *self) {
}
void common_hal_bleio_adapter_erase_bonding(bleio_adapter_obj_t *self) {
+ check_enabled(self);
+
//FIX bonding_erase_storage();
}
uint16_t bleio_adapter_add_attribute(bleio_adapter_obj_t *adapter, mp_obj_t *attribute) {
+ check_enabled(adapter);
+
// The handle is the index of this attribute in the attributes list.
uint16_t handle = (uint16_t) adapter->attributes->len;
mp_obj_list_append(adapter->attributes, attribute);
+
+ if (MP_OBJ_IS_TYPE(attribute, &bleio_service_type)) {
+ adapter->last_added_service_handle = handle;
+ }
+ if (MP_OBJ_IS_TYPE(attribute, &bleio_characteristic_type)) {
+ adapter->last_added_characteristic_handle = handle;
+ }
+
return handle;
}
mp_obj_t* bleio_adapter_get_attribute(bleio_adapter_obj_t *adapter, uint16_t handle) {
+ check_enabled(adapter);
+
if (handle == 0 || handle >= adapter->attributes->len) {
return mp_const_none;
}
@@ -703,6 +753,8 @@ mp_obj_t* bleio_adapter_get_attribute(bleio_adapter_obj_t *adapter, uint16_t han
}
uint16_t bleio_adapter_max_attribute_handle(bleio_adapter_obj_t *adapter) {
+ check_enabled(adapter);
+
return adapter->attributes->len - 1;
}
@@ -713,6 +765,10 @@ void bleio_adapter_gc_collect(bleio_adapter_obj_t* adapter) {
}
void bleio_adapter_reset(bleio_adapter_obj_t* adapter) {
+ if (!common_hal_bleio_adapter_get_enabled(adapter)) {
+ return;
+ }
+
common_hal_bleio_adapter_stop_scan(adapter);
if (adapter->now_advertising) {
common_hal_bleio_adapter_stop_advertising(adapter);
@@ -731,6 +787,10 @@ void bleio_adapter_reset(bleio_adapter_obj_t* adapter) {
}
void bleio_adapter_background(bleio_adapter_obj_t* adapter) {
+ if (!common_hal_bleio_adapter_get_enabled(adapter)) {
+ return;
+ }
+
if (adapter->advertising_timeout_msecs > 0 &&
supervisor_ticks_ms64() - adapter->advertising_start_ticks > adapter->advertising_timeout_msecs) {
adapter->advertising_timeout_msecs = 0;
diff --git a/devices/ble_hci/common-hal/_bleio/Attribute.c b/devices/ble_hci/common-hal/_bleio/Attribute.c
index 0c56c08a8..d32ed1167 100644
--- a/devices/ble_hci/common-hal/_bleio/Attribute.c
+++ b/devices/ble_hci/common-hal/_bleio/Attribute.c
@@ -30,7 +30,7 @@
#include "shared-bindings/_bleio/Service.h"
// Return the type of the attribute.
-ble_attribute_type bleio_attribute_type_uuid(mp_obj_t *attribute) {
+ble_attribute_type_uuid bleio_attribute_type_uuid(mp_obj_t *attribute) {
if (MP_OBJ_IS_TYPE(attribute, &bleio_characteristic_type)) {
return BLE_TYPE_CHARACTERISTIC;
}
diff --git a/devices/ble_hci/common-hal/_bleio/Attribute.h b/devices/ble_hci/common-hal/_bleio/Attribute.h
index 4301614fc..47327437b 100644
--- a/devices/ble_hci/common-hal/_bleio/Attribute.h
+++ b/devices/ble_hci/common-hal/_bleio/Attribute.h
@@ -36,7 +36,7 @@ typedef enum {
BLE_TYPE_SECONDARY_SERVICE = 0x2801,
BLE_TYPE_CHARACTERISTIC = 0x2803,
BLE_TYPE_DESCRIPTOR = 0x2900
-} ble_attribute_type;
+} ble_attribute_type_uuid;
// typedef struct
// {
@@ -45,6 +45,6 @@ typedef enum {
// } ble_gap_conn_sec_mode_t;
-// extern void bleio_attribute_gatts_set_security_mode(ble_gap_conn_sec_mode_t *perm, bleio_attribute_security_mode_t security_mode);
+ble_attribute_type_uuid bleio_attribute_type_uuid(mp_obj_t *attribute);
#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_ATTRIBUTE_H
diff --git a/devices/ble_hci/common-hal/_bleio/att.c b/devices/ble_hci/common-hal/_bleio/att.c
index 2982861f7..08324c37e 100644
--- a/devices/ble_hci/common-hal/_bleio/att.c
+++ b/devices/ble_hci/common-hal/_bleio/att.c
@@ -33,6 +33,7 @@
#include "common-hal/_bleio/Attribute.h"
#include "shared-bindings/_bleio/__init__.h"
#include "shared-bindings/_bleio/Characteristic.h"
+#include "shared-bindings/_bleio/UUID.h"
#include "supervisor/shared/tick.h"
STATIC uint16_t max_mtu = BT_ATT_DEFAULT_LE_MTU; // 23
@@ -685,6 +686,7 @@ bool att_indicate(uint16_t handle, const uint8_t* value, int length) {
STATIC void process_error(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) {
struct bt_att_error_rsp *rsp = (struct bt_att_error_rsp *) data;
+
if (dlen != sizeof(struct bt_att_error_rsp)) {
// Incorrect size; ignore.
return;
@@ -700,7 +702,8 @@ STATIC void process_error(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) {
STATIC void process_mtu_req(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) {
struct bt_att_exchange_mtu_req *req = (struct bt_att_exchange_mtu_req *) data;
- if (dlen != sizeof(req)) {
+
+ if (dlen != sizeof(struct bt_att_exchange_mtu_req)) {
send_error(conn_handle, BT_ATT_OP_MTU_REQ, BLE_GATT_HANDLE_INVALID, BT_ATT_ERR_INVALID_PDU);
return;
}
@@ -720,7 +723,7 @@ STATIC void process_mtu_req(uint16_t conn_handle, uint8_t dlen, uint8_t data[])
struct __packed {
struct bt_att_hdr h;
- struct bt_att_exchange_mtu_req r;
+ struct bt_att_exchange_mtu_rsp r;
} rsp = { {
.code = BT_ATT_OP_MTU_RSP,
}, {
@@ -732,12 +735,12 @@ STATIC void process_mtu_req(uint16_t conn_handle, uint8_t dlen, uint8_t data[])
}
STATIC void process_mtu_rsp(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) {
+ struct bt_att_exchange_mtu_rsp *rsp = (struct bt_att_exchange_mtu_rsp *) data;
+
if (dlen != sizeof(struct bt_att_exchange_mtu_rsp)) {
return;
}
- struct bt_att_exchange_mtu_rsp *rsp = (struct bt_att_exchange_mtu_rsp *) data;
-
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
if (bleio_connections[i].conn_handle == conn_handle) {
bleio_connections[i].mtu = rsp->mtu;
@@ -879,69 +882,82 @@ STATIC void process_find_by_type_req(uint16_t conn_handle, uint16_t mtu, uint8_t
void process_read_by_group_req(uint16_t conn_handle, uint16_t mtu, uint8_t dlen, uint8_t data[]) {
struct bt_att_read_group_req *req = (struct bt_att_read_group_req *) data;
- uint16_t uuid = req->uuid[0] | (req->uuid[1] << 8);
+ uint16_t type_uuid = req->uuid[0] | (req->uuid[1] << 8);
- if (dlen != sizeof(struct bt_att_find_type_req) ||
- (uuid != BLE_TYPE_PRIMARY_SERVICE &&
- uuid != BLE_TYPE_SECONDARY_SERVICE)) {
+ if (dlen != sizeof(struct bt_att_read_group_req) + sizeof(type_uuid) ||
+ (type_uuid != BLE_TYPE_PRIMARY_SERVICE &&
+ type_uuid != BLE_TYPE_SECONDARY_SERVICE)) {
send_error(conn_handle, BT_ATT_OP_READ_GROUP_REQ, req->start_handle, BT_ATT_ERR_UNSUPPORTED_GROUP_TYPE);
return;
}
- uint8_t response[mtu];
- uint16_t response_length;
-
- response[0] = BT_ATT_OP_READ_GROUP_RSP;
- response[1] = 0x00;
- response_length = 2;
-
- // FIX
- // for (uint16_t i = (readByGroupReq->start_handle - 1); i < GATT.attributeCount() && i <= (readByGroupReq->end_handle - 1); i++) {
- //FIX
- // BLELocalAttribute* attribute = GATT.attribute(i);
-
- // if (readByGroupReq->uuid != attribute->type()) {
- // // not the type
- // continue;
- // }
-
- // int uuidLen = attribute->uuidLength();
- // size_t infoSize = (uuidLen == 2) ? 6 : 20;
-
- // if (response[1] == 0) {
- // response[1] = infoSize;
- // }
+ typedef struct __packed {
+ struct bt_att_hdr h;
+ struct bt_att_read_group_rsp r;
+ } rsp_t;
+
+ uint8_t rsp_bytes[mtu];
+ rsp_t *rsp = (rsp_t *) &rsp_bytes;
+ rsp->h.code = BT_ATT_OP_READ_GROUP_RSP;
+ rsp->r.len = 0;
+
+ // Keeps track of total length of the response.
+ size_t rsp_length = sizeof(rsp_t);
+
+ bool no_data = true;
+
+ // All the data chunks must have uuid's that are the same size.
+ // Keep track fo the first one to make sure.
+ size_t sizeof_first_service_uuid = 0;
+ const uint16_t max_attribute_handle = bleio_adapter_max_attribute_handle(&common_hal_bleio_adapter_obj);
+ for (uint16_t handle = req->start_handle;
+ handle <= max_attribute_handle && handle <= req->end_handle;
+ handle++) {
+ no_data = false;
+
+ mp_obj_t *attribute_obj = bleio_adapter_get_attribute(&common_hal_bleio_adapter_obj, handle);
+ if (type_uuid != bleio_attribute_type_uuid(attribute_obj)) {
+ // Not a primary or secondary service.
+ continue;
+ }
+ // Now we know it's a service.
+ bleio_service_obj_t *service = MP_OBJ_TO_PTR(attribute_obj);
+
+ // Is this a 16-bit or a 128-bit uuid? It must match in size with any previous attribute
+ // in this transmission.
+ const uint8_t sizeof_service_uuid = common_hal_bleio_uuid_get_size(service->uuid) / 8;
+ if (sizeof_first_service_uuid == 0) {
+ sizeof_first_service_uuid = sizeof_service_uuid;
+ } else if (sizeof_first_service_uuid != sizeof_service_uuid) {
+ // Mismatched sizes. Transmit just what we have so far in this batch.
+ break;
+ }
- // if (response[1] != infoSize) {
- // // different size
- // break;
- // }
+ // Size of bt_att_group_data chunk with uuid.
+ const uint16_t data_length = sizeof(struct bt_att_group_data) + sizeof_service_uuid;
- // BLELocalService* service = (BLELocalService*)attribute;
+ if (rsp_length + data_length > mtu) {
+ // No room for another bt_att_group_data chunk.
+ break;
+ }
- // // add the start handle
- // uint16_t start_handle = service->start_handle();
- // memcpy(&response[response_length], &start_handle, sizeof(start_handle));
- // response_length += sizeof(start_handle);
+ // Pass the length of ONE bt_att_group_data chunk. There may be multiple ones in this transmission.
+ rsp->r.len = data_length;
- // // add the end handle
- // uint16_t end_handle = service->end_handle();
- // memcpy(&response[response_length], &end_handle, sizeof(end_handle));
- // response_length += sizeof(end_handle);
+ uint8_t group_data_bytes[data_length];
+ struct bt_att_group_data *group_data = (struct bt_att_group_data *) group_data_bytes;
- // // add the UUID
- // memcpy(&response[response_length], service->uuidData(), uuidLen);
- // response_length += uuidLen;
+ group_data->start_handle = service->start_handle;
+ group_data->end_handle = service->end_handle;
+ common_hal_bleio_uuid_pack_into(service->uuid, group_data->value);
- // if ((response_length + infoSize) > mtu) {
- // break;
- // }
- // }
+ rsp_length += data_length;
+ }
- if (response_length == 2) {
+ if (no_data) {
send_error(conn_handle, BT_ATT_OP_READ_GROUP_REQ, req->start_handle, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND);
} else {
- hci_send_acl_pkt(conn_handle, BT_L2CAP_CID_ATT, response_length, response);
+ hci_send_acl_pkt(conn_handle, BT_L2CAP_CID_ATT, rsp_length, rsp_bytes);
}
}
@@ -986,7 +1002,7 @@ STATIC void process_read_or_read_blob_req(uint16_t conn_handle, uint16_t mtu, ui
handle = req->handle;
response_opcode = BT_ATT_OP_READ_RSP;
- } else {
+ } else if (opcode == BT_ATT_OP_READ_BLOB_REQ) {
if (dlen != sizeof(struct bt_att_read_blob_req)) {
send_error(conn_handle, BT_ATT_OP_READ_BLOB_REQ, BLE_GATT_HANDLE_INVALID, BT_ATT_ERR_INVALID_PDU);
return;
@@ -996,8 +1012,11 @@ STATIC void process_read_or_read_blob_req(uint16_t conn_handle, uint16_t mtu, ui
handle = req->handle;
offset = req->offset;
response_opcode = BT_ATT_OP_READ_BLOB_RSP;
+ } else {
+ return;
}
+
//FIX
(void) offset;
(void) handle;
diff --git a/devices/ble_hci/common-hal/_bleio/hci.c b/devices/ble_hci/common-hal/_bleio/hci.c
index 9c8d7f692..7b4adaa79 100644
--- a/devices/ble_hci/common-hal/_bleio/hci.c
+++ b/devices/ble_hci/common-hal/_bleio/hci.c
@@ -95,7 +95,6 @@ STATIC uint8_t acl_data_buffer[ACL_DATA_BUFFER_SIZE];
STATIC size_t acl_data_len;
STATIC size_t num_command_packets_allowed;
-STATIC size_t max_pkt;
STATIC size_t pending_pkt;
// Results from parsing a command response packet.
@@ -107,77 +106,13 @@ STATIC uint8_t* cmd_response_data;
STATIC volatile bool hci_poll_in_progress = false;
-STATIC bool debug = true;
+#define DEBUG_HCI 1
//////////////////////////////////////////////////////////////////////
-STATIC void dump_cmd_pkt(bool tx, uint8_t pkt_len, uint8_t pkt_data[]) {
- if (debug) {
- h4_hci_cmd_pkt_t *pkt = (h4_hci_cmd_pkt_t *) pkt_data;
- mp_printf(&mp_plat_print,
- "%s HCI COMMAND (%x) opcode: %04x, len: %d, data: ",
- tx ? "TX->" : "RX<-",
- pkt->pkt_type, pkt->opcode, pkt->param_len);
- for (size_t i = 0; i < pkt->param_len; i++) {
- mp_printf(&mp_plat_print, "%02x ", pkt->params[i]);
- }
- if (pkt_len != sizeof(h4_hci_cmd_pkt_t) + pkt->param_len) {
- mp_printf(&mp_plat_print, " LENGTH MISMATCH");
- }
- mp_printf(&mp_plat_print, "\n");
- }
-}
-
-STATIC void dump_acl_pkt(bool tx, uint8_t pkt_len, uint8_t pkt_data[]) {
- if (debug) {
- // mp_printf(&mp_plat_print, "\\ PKT_DATA: ");
- // for (size_t i = 0; i < pkt_len; i++) {
- // mp_printf(&mp_plat_print, "%02x ", pkt_data[i]);
- // }
- // mp_printf(&mp_plat_print, "\n");
- h4_hci_acl_pkt_t *pkt = (h4_hci_acl_pkt_t *) pkt_data;
- mp_printf(&mp_plat_print,
- "%s HCI ACLDATA (%x) handle: %04x, pb: %d, bc: %d, data_len: %d, ",
- tx ? "TX->" : "RX<-", pkt->pkt_type, pkt->handle, pkt->pb, pkt->bc, pkt->data_len);
-
- if (pkt->pb != ACL_DATA_PB_MIDDLE) {
- // This is the start of a fragmented acl_data packet or is a full packet.
- acl_data_t *acl = (acl_data_t *) pkt->data;
- mp_printf(&mp_plat_print,
- "acl data_len: %d, cid: %04x, data: ",
- acl->acl_data_len, acl->cid);
- for (size_t i = 0; i < acl->acl_data_len; i++) {
- mp_printf(&mp_plat_print, "%02x ", acl->acl_data[i]);
- }
- } else {
- for (size_t i = 0; i < pkt->data_len; i++) {
- mp_printf(&mp_plat_print, "more data: %02x ", pkt->data[i]);
- }
- }
-
- if (pkt_len != sizeof(h4_hci_acl_pkt_t) + pkt->data_len) {
- mp_printf(&mp_plat_print, " LENGTH MISMATCH");
- }
- mp_printf(&mp_plat_print, "\n");
- }
-}
-
-STATIC void dump_evt_pkt(bool tx, uint8_t pkt_len, uint8_t pkt_data[]) {
- if (debug) {
- h4_hci_evt_pkt_t *pkt = (h4_hci_evt_pkt_t *) pkt_data;
- mp_printf(&mp_plat_print,
- "%s HCI EVENT (%x) evt: %02x, param_len: %d, data: ",
- tx ? "TX->" : "RX<-",
- pkt->pkt_type, pkt->evt, pkt->param_len);
- for (size_t i = 0; i < pkt->param_len; i++) {
- mp_printf(&mp_plat_print, "%02x ", pkt->params[i]);
- }
- if (pkt_len != sizeof(h4_hci_evt_pkt_t) + pkt->param_len) {
- mp_printf(&mp_plat_print, " LENGTH MISMATCH");
- }
- mp_printf(&mp_plat_print, "\n");
- }
-}
+#if DEBUG_HCI
+#include "hci_debug.c"
+#endif // DEBUG_HCI
STATIC void process_acl_data_pkt(uint8_t pkt_len, uint8_t pkt_data[]) {
h4_hci_acl_pkt_t *pkt = (h4_hci_acl_pkt_t*) pkt_data;
@@ -194,7 +129,7 @@ STATIC void process_acl_data_pkt(uint8_t pkt_len, uint8_t pkt_data[]) {
}
acl_data_t *acl = (acl_data_t *) &acl_data_buffer;
- if (acl_data_len != acl->acl_data_len) {
+ if (acl_data_len != sizeof(acl) + acl->acl_data_len) {
// We don't have the full packet yet.
return;
}
@@ -330,9 +265,9 @@ STATIC void process_evt_pkt(size_t pkt_len, uint8_t pkt_data[])
}
default:
- if (debug) {
- mp_printf(&mp_plat_print, "process_evt_pkt: Unknown event: %02x\n");
- }
+#if DEBUG_HCI
+ mp_printf(&mp_plat_print, "process_evt_pkt: Unknown event: %02x\n");
+#endif
break;
}
}
@@ -374,7 +309,8 @@ hci_result_t hci_poll_for_incoming_pkt(void) {
bool packet_is_complete = false;
// Read bytes until we run out, or accumulate a complete packet.
- while (common_hal_busio_uart_rx_characters_available(common_hal_bleio_adapter_obj.hci_uart)) {
+ while (!packet_is_complete &&
+ common_hal_busio_uart_rx_characters_available(common_hal_bleio_adapter_obj.hci_uart)) {
common_hal_busio_uart_read(common_hal_bleio_adapter_obj.hci_uart, rx_buffer + rx_idx, 1, &errcode);
if (errcode) {
hci_poll_in_progress = false;
@@ -417,25 +353,25 @@ hci_result_t hci_poll_for_incoming_pkt(void) {
switch (rx_buffer[0]) {
case H4_ACL:
- if (debug) {
- dump_acl_pkt(false, pkt_len, rx_buffer);
- }
+#if DEBUG_HCI
+ dump_acl_pkt(false, pkt_len, rx_buffer);
+#endif
process_acl_data_pkt(pkt_len, rx_buffer);
break;
case H4_EVT:
- if (debug) {
- dump_evt_pkt(false, pkt_len, rx_buffer);
- }
+#if DEBUG_HCI
+ dump_evt_pkt(false, pkt_len, rx_buffer);
+#endif
process_evt_pkt(pkt_len, rx_buffer);
break;
default:
- if (debug) {
- mp_printf(&mp_plat_print, "Unknown HCI packet type: %d\n", rx_buffer[0]);
- }
+#if DEBUG_HCI
+ mp_printf(&mp_plat_print, "Unknown HCI packet type: %d\n", rx_buffer[0]);
+#endif
break;
}
@@ -478,9 +414,9 @@ STATIC hci_result_t send_command(uint16_t opcode, uint8_t params_len, void* para
memcpy(cmd_pkt->params, params, params_len);
- if (debug) {
+#if DEBUG_HCI
dump_cmd_pkt(true, sizeof(tx_buffer), tx_buffer);
- }
+#endif
int result = write_pkt(tx_buffer, cmd_pkt_len);
if (result != HCI_OK) {
@@ -519,32 +455,31 @@ STATIC hci_result_t send_command(uint16_t opcode, uint8_t params_len, void* para
hci_result_t hci_send_acl_pkt(uint16_t handle, uint8_t cid, uint8_t data_len, uint8_t *data) {
int result;
- while (pending_pkt >= max_pkt) {
+ while (pending_pkt >= common_hal_bleio_adapter_obj.max_acl_num_buffers) {
result = hci_poll_for_incoming_pkt();
if (result != HCI_OK) {
return result;
}
}
- // data_len does not include cid
- const size_t cid_len = sizeof_field(acl_data_t, cid);
// buf_len is size of entire packet including header.
- const size_t buf_len = sizeof(h4_hci_acl_pkt_t) + cid_len + data_len;
+ const size_t buf_len = sizeof(h4_hci_acl_pkt_t) + sizeof(acl_data_t) + data_len;
uint8_t tx_buffer[buf_len];
h4_hci_acl_pkt_t *acl_pkt = (h4_hci_acl_pkt_t *) tx_buffer;
acl_data_t *acl_data = (acl_data_t *) acl_pkt->data;
acl_pkt->pkt_type = H4_ACL;
acl_pkt->handle = handle;
- acl_pkt->data_len = (uint8_t)(cid_len + data_len);
- acl_data->acl_data_len = (uint8_t) data_len;
+ acl_pkt->pb = ACL_DATA_PB_FIRST_FLUSH;
+ acl_pkt->data_len = (uint8_t)(sizeof(acl_data_t) + data_len);
+ acl_data->acl_data_len = data_len;
acl_data->cid = cid;
- memcpy(&tx_buffer[sizeof(h4_hci_acl_pkt_t)], data, data_len);
+ memcpy(&acl_data->acl_data, data, data_len);
- if (debug) {
+#if DEBUG_HCI
dump_acl_pkt(true, buf_len, tx_buffer);
- }
+#endif
pending_pkt++;
diff --git a/devices/ble_hci/common-hal/_bleio/hci_debug.c b/devices/ble_hci/common-hal/_bleio/hci_debug.c
new file mode 100644
index 000000000..8231bc5cc
--- /dev/null
+++ b/devices/ble_hci/common-hal/_bleio/hci_debug.c
@@ -0,0 +1,335 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+// This file is #include'd in hci.c when HCI_DEBUG is non-zero.
+
+STATIC const char* att_opcode_name(uint16_t opcode) {
+ switch (opcode) {
+ case BT_ATT_OP_ERROR_RSP: return "ERROR_RSP";
+ case BT_ATT_OP_MTU_REQ: return "MTU_REQ";
+ case BT_ATT_OP_MTU_RSP: return "MTU_RSP";
+ case BT_ATT_OP_FIND_INFO_REQ: return "FIND_INFO_REQ";
+ case BT_ATT_OP_FIND_INFO_RSP: return "FIND_INFO_RSP";
+ case BT_ATT_OP_FIND_TYPE_REQ: return "FIND_TYPE_REQ";
+ case BT_ATT_OP_FIND_TYPE_RSP: return "FIND_TYPE_RSP";
+ case BT_ATT_OP_READ_TYPE_REQ: return "READ_TYPE_REQ";
+ case BT_ATT_OP_READ_TYPE_RSP: return "READ_TYPE_RSP";
+ case BT_ATT_OP_READ_REQ: return "READ_REQ";
+ case BT_ATT_OP_READ_RSP: return "READ_RSP";
+ case BT_ATT_OP_READ_BLOB_REQ: return "READ_BLOB_REQ";
+ case BT_ATT_OP_READ_BLOB_RSP: return "READ_BLOB_RSP";
+ case BT_ATT_OP_READ_MULT_REQ: return "READ_MULT_REQ";
+ case BT_ATT_OP_READ_MULT_RSP: return "READ_MULT_RSP";
+ case BT_ATT_OP_READ_GROUP_REQ: return "READ_GROUP_REQ";
+ case BT_ATT_OP_READ_GROUP_RSP: return "READ_GROUP_RSP";
+ case BT_ATT_OP_WRITE_REQ: return "WRITE_REQ";
+ case BT_ATT_OP_WRITE_RSP: return "WRITE_RSP";
+ case BT_ATT_OP_PREPARE_WRITE_REQ: return "PREPARE_WRITE_REQ";
+ case BT_ATT_OP_PREPARE_WRITE_RSP: return "PREPARE_WRITE_RSP";
+ case BT_ATT_OP_EXEC_WRITE_REQ: return "EXEC_WRITE_REQ";
+ case BT_ATT_OP_EXEC_WRITE_RSP: return "EXEC_WRITE_RSP";
+ case BT_ATT_OP_NOTIFY: return "NOTIFY";
+ case BT_ATT_OP_INDICATE: return "INDICATE";
+ case BT_ATT_OP_CONFIRM: return "CONFIRM";
+ case BT_ATT_OP_READ_MULT_VL_REQ: return "READ_MULT_VL_REQ";
+ case BT_ATT_OP_READ_MULT_VL_RSP: return "READ_MULT_VL_RSP";
+ case BT_ATT_OP_NOTIFY_MULT: return "NOTIFY_MULT";
+ case BT_ATT_OP_WRITE_CMD: return "WRITE_CMD";
+ case BT_ATT_OP_SIGNED_WRITE_CMD: return "SIGNED_WRITE_CMD";
+ default: return "";
+ }
+}
+
+STATIC const char* hci_evt_name(uint8_t evt) {
+ switch (evt) {
+ case BT_HCI_EVT_UNKNOWN: return "UNKNOWN";
+ case BT_HCI_EVT_VENDOR: return "VENDOR";
+ case BT_HCI_EVT_INQUIRY_COMPLETE: return "INQUIRY_COMPLETE";
+ case BT_HCI_EVT_CONN_COMPLETE: return "CONN_COMPLETE";
+ case BT_HCI_EVT_CONN_REQUEST: return "CONN_REQUEST";
+ case BT_HCI_EVT_DISCONN_COMPLETE: return "DISCONN_COMPLETE";
+ case BT_HCI_EVT_AUTH_COMPLETE: return "AUTH_COMPLETE";
+ case BT_HCI_EVT_REMOTE_NAME_REQ_COMPLETE: return "REMOTE_NAME_REQ_COMPLETE";
+ case BT_HCI_EVT_ENCRYPT_CHANGE: return "ENCRYPT_CHANGE";
+ case BT_HCI_EVT_REMOTE_FEATURES: return "REMOTE_FEATURES";
+ case BT_HCI_EVT_REMOTE_VERSION_INFO: return "REMOTE_VERSION_INFO";
+ case BT_HCI_EVT_CMD_COMPLETE: return "CMD_COMPLETE";
+ case BT_HCI_EVT_CMD_STATUS: return "CMD_STATUS";
+ case BT_HCI_EVT_ROLE_CHANGE: return "ROLE_CHANGE";
+ case BT_HCI_EVT_NUM_COMPLETED_PACKETS: return "NUM_COMPLETED_PACKETS";
+ case BT_HCI_EVT_PIN_CODE_REQ: return "PIN_CODE_REQ";
+ case BT_HCI_EVT_LINK_KEY_REQ: return "LINK_KEY_REQ";
+ case BT_HCI_EVT_LINK_KEY_NOTIFY: return "LINK_KEY_NOTIFY";
+ case BT_HCI_EVT_DATA_BUF_OVERFLOW: return "DATA_BUF_OVERFLOW";
+ case BT_HCI_EVT_INQUIRY_RESULT_WITH_RSSI: return "INQUIRY_RESULT_WITH_RSSI";
+ case BT_HCI_EVT_REMOTE_EXT_FEATURES: return "REMOTE_EXT_FEATURES";
+ case BT_HCI_EVT_SYNC_CONN_COMPLETE: return "SYNC_CONN_COMPLETE";
+ case BT_HCI_EVT_EXTENDED_INQUIRY_RESULT: return "EXTENDED_INQUIRY_RESULT";
+ case BT_HCI_EVT_ENCRYPT_KEY_REFRESH_COMPLETE: return "ENCRYPT_KEY_REFRESH_COMPLETE";
+ case BT_HCI_EVT_IO_CAPA_REQ: return "IO_CAPA_REQ";
+ case BT_HCI_EVT_IO_CAPA_RESP: return "IO_CAPA_RESP";
+ case BT_HCI_EVT_USER_CONFIRM_REQ: return "USER_CONFIRM_REQ";
+ case BT_HCI_EVT_USER_PASSKEY_REQ: return "USER_PASSKEY_REQ";
+ case BT_HCI_EVT_SSP_COMPLETE: return "SSP_COMPLETE";
+ case BT_HCI_EVT_USER_PASSKEY_NOTIFY: return "USER_PASSKEY_NOTIFY";
+ case BT_HCI_EVT_LE_META_EVENT: return "LE_META_EVENT";
+ case BT_HCI_EVT_AUTH_PAYLOAD_TIMEOUT_EXP: return "AUTH_PAYLOAD_TIMEOUT_EXP";
+ default: return "";
+ }
+}
+
+STATIC const char* hci_evt_le_name(uint8_t evt_le) {
+ switch (evt_le) {
+ case BT_HCI_EVT_LE_CONN_COMPLETE: return "LE_CONN_COMPLETE";
+ case BT_HCI_EVT_LE_ADVERTISING_REPORT: return "LE_ADVERTISING_REPORT";
+ case BT_HCI_EVT_LE_CONN_UPDATE_COMPLETE: return "LE_CONN_UPDATE_COMPLETE";
+ case BT_HCI_EVT_LE_LTK_REQUEST: return "LE_LTK_REQUEST";
+ case BT_HCI_EVT_LE_CONN_PARAM_REQ: return "LE_CONN_PARAM_REQ";
+ case BT_HCI_EVT_LE_DATA_LEN_CHANGE: return "LE_DATA_LEN_CHANGE";
+ case BT_HCI_EVT_LE_P256_PUBLIC_KEY_COMPLETE: return "LE_P256_PUBLIC_KEY_COMPLETE";
+ case BT_HCI_EVT_LE_GENERATE_DHKEY_COMPLETE: return "LE_GENERATE_DHKEY_COMPLETE";
+ case BT_HCI_EVT_LE_ENH_CONN_COMPLETE: return "LE_ENH_CONN_COMPLETE";
+ case BT_HCI_EVT_LE_DIRECT_ADV_REPORT: return "LE_DIRECT_ADV_REPORT";
+ case BT_HCI_EVT_LE_PHY_UPDATE_COMPLETE: return "LE_PHY_UPDATE_COMPLETE";
+ case BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT: return "LE_EXT_ADVERTISING_REPORT";
+ case BT_HCI_EVT_LE_PER_ADV_SYNC_ESTABLISHED: return "LE_PER_ADV_SYNC_ESTABLISHED";
+ case BT_HCI_EVT_LE_PER_ADVERTISING_REPORT: return "LE_PER_ADVERTISING_REPORT";
+ case BT_HCI_EVT_LE_PER_ADV_SYNC_LOST: return "LE_PER_ADV_SYNC_LOST";
+ case BT_HCI_EVT_LE_SCAN_TIMEOUT: return "LE_SCAN_TIMEOUT";
+ case BT_HCI_EVT_LE_ADV_SET_TERMINATED: return "LE_ADV_SET_TERMINATED";
+ case BT_HCI_EVT_LE_SCAN_REQ_RECEIVED: return "LE_SCAN_REQ_RECEIVED";
+ case BT_HCI_EVT_LE_CHAN_SEL_ALGO: return "LE_CHAN_SEL_ALGO";
+ default: return "";
+ }
+}
+
+STATIC const char* hci_opcode_name(uint16_t opcode) {
+ switch (opcode) {
+ case BT_OP_NOP: return "NOP";
+ case BT_HCI_OP_INQUIRY: return "INQUIRY";
+ case BT_HCI_OP_INQUIRY_CANCEL: return "INQUIRY_CANCEL";
+ case BT_HCI_OP_CONNECT: return "CONNECT";
+ case BT_HCI_OP_DISCONNECT: return "DISCONNECT";
+ case BT_HCI_OP_CONNECT_CANCEL: return "CONNECT_CANCEL";
+ case BT_HCI_OP_ACCEPT_CONN_REQ: return "ACCEPT_CONN_REQ";
+ case BT_HCI_OP_SETUP_SYNC_CONN: return "SETUP_SYNC_CONN";
+ case BT_HCI_OP_ACCEPT_SYNC_CONN_REQ: return "ACCEPT_SYNC_CONN_REQ";
+ case BT_HCI_OP_REJECT_CONN_REQ: return "REJECT_CONN_REQ";
+ case BT_HCI_OP_LINK_KEY_REPLY: return "LINK_KEY_REPLY";
+ case BT_HCI_OP_LINK_KEY_NEG_REPLY: return "LINK_KEY_NEG_REPLY";
+ case BT_HCI_OP_PIN_CODE_REPLY: return "PIN_CODE_REPLY";
+ case BT_HCI_OP_PIN_CODE_NEG_REPLY: return "PIN_CODE_NEG_REPLY";
+ case BT_HCI_OP_AUTH_REQUESTED: return "AUTH_REQUESTED";
+ case BT_HCI_OP_SET_CONN_ENCRYPT: return "SET_CONN_ENCRYPT";
+ case BT_HCI_OP_REMOTE_NAME_REQUEST: return "REMOTE_NAME_REQUEST";
+ case BT_HCI_OP_REMOTE_NAME_CANCEL: return "REMOTE_NAME_CANCEL";
+ case BT_HCI_OP_READ_REMOTE_FEATURES: return "READ_REMOTE_FEATURES";
+ case BT_HCI_OP_READ_REMOTE_EXT_FEATURES: return "READ_REMOTE_EXT_FEATURES";
+ case BT_HCI_OP_READ_REMOTE_VERSION_INFO: return "READ_REMOTE_VERSION_INFO";
+ case BT_HCI_OP_IO_CAPABILITY_REPLY: return "IO_CAPABILITY_REPLY";
+ case BT_HCI_OP_USER_CONFIRM_REPLY: return "USER_CONFIRM_REPLY";
+ case BT_HCI_OP_USER_CONFIRM_NEG_REPLY: return "USER_CONFIRM_NEG_REPLY";
+ case BT_HCI_OP_USER_PASSKEY_REPLY: return "USER_PASSKEY_REPLY";
+ case BT_HCI_OP_USER_PASSKEY_NEG_REPLY: return "USER_PASSKEY_NEG_REPLY";
+ case BT_HCI_OP_IO_CAPABILITY_NEG_REPLY: return "IO_CAPABILITY_NEG_REPLY";
+ case BT_HCI_OP_SET_EVENT_MASK: return "SET_EVENT_MASK";
+ case BT_HCI_OP_RESET: return "RESET";
+ case BT_HCI_OP_WRITE_LOCAL_NAME: return "WRITE_LOCAL_NAME";
+ case BT_HCI_OP_WRITE_PAGE_TIMEOUT: return "WRITE_PAGE_TIMEOUT";
+ case BT_HCI_OP_WRITE_SCAN_ENABLE: return "WRITE_SCAN_ENABLE";
+ case BT_HCI_OP_READ_TX_POWER_LEVEL: return "READ_TX_POWER_LEVEL";
+ case BT_HCI_OP_SET_CTL_TO_HOST_FLOW: return "SET_CTL_TO_HOST_FLOW";
+ case BT_HCI_OP_HOST_BUFFER_SIZE: return "HOST_BUFFER_SIZE";
+ case BT_HCI_OP_HOST_NUM_COMPLETED_PACKETS: return "HOST_NUM_COMPLETED_PACKETS";
+ case BT_HCI_OP_WRITE_INQUIRY_MODE: return "WRITE_INQUIRY_MODE";
+ case BT_HCI_OP_WRITE_SSP_MODE: return "WRITE_SSP_MODE";
+ case BT_HCI_OP_SET_EVENT_MASK_PAGE_2: return "SET_EVENT_MASK_PAGE_2";
+ case BT_HCI_OP_LE_WRITE_LE_HOST_SUPP: return "LE_WRITE_LE_HOST_SUPP";
+ case BT_HCI_OP_WRITE_SC_HOST_SUPP: return "WRITE_SC_HOST_SUPP";
+ case BT_HCI_OP_READ_AUTH_PAYLOAD_TIMEOUT: return "READ_AUTH_PAYLOAD_TIMEOUT";
+ case BT_HCI_OP_WRITE_AUTH_PAYLOAD_TIMEOUT: return "WRITE_AUTH_PAYLOAD_TIMEOUT";
+ case BT_HCI_OP_READ_LOCAL_VERSION_INFO: return "READ_LOCAL_VERSION_INFO";
+ case BT_HCI_OP_READ_SUPPORTED_COMMANDS: return "READ_SUPPORTED_COMMANDS";
+ case BT_HCI_OP_READ_LOCAL_EXT_FEATURES: return "READ_LOCAL_EXT_FEATURES";
+ case BT_HCI_OP_READ_LOCAL_FEATURES: return "READ_LOCAL_FEATURES";
+ case BT_HCI_OP_READ_BUFFER_SIZE: return "READ_BUFFER_SIZE";
+ case BT_HCI_OP_READ_BD_ADDR: return "READ_BD_ADDR";
+ case BT_HCI_OP_READ_RSSI: return "READ_RSSI";
+ case BT_HCI_OP_READ_ENCRYPTION_KEY_SIZE: return "READ_ENCRYPTION_KEY_SIZE";
+ case BT_HCI_OP_LE_SET_EVENT_MASK: return "LE_SET_EVENT_MASK";
+ case BT_HCI_OP_LE_READ_BUFFER_SIZE: return "LE_READ_BUFFER_SIZE";
+ case BT_HCI_OP_LE_READ_LOCAL_FEATURES: return "LE_READ_LOCAL_FEATURES";
+ case BT_HCI_OP_LE_SET_RANDOM_ADDRESS: return "LE_SET_RANDOM_ADDRESS";
+ case BT_HCI_OP_LE_SET_ADV_PARAM: return "LE_SET_ADV_PARAM";
+ case BT_HCI_OP_LE_READ_ADV_CHAN_TX_POWER: return "LE_READ_ADV_CHAN_TX_POWER";
+ case BT_HCI_OP_LE_SET_ADV_DATA: return "LE_SET_ADV_DATA";
+ case BT_HCI_OP_LE_SET_SCAN_RSP_DATA: return "LE_SET_SCAN_RSP_DATA";
+ case BT_HCI_OP_LE_SET_ADV_ENABLE: return "LE_SET_ADV_ENABLE";
+ case BT_HCI_OP_LE_SET_SCAN_PARAM: return "LE_SET_SCAN_PARAM";
+ case BT_HCI_OP_LE_SET_SCAN_ENABLE: return "LE_SET_SCAN_ENABLE";
+ case BT_HCI_OP_LE_CREATE_CONN: return "LE_CREATE_CONN";
+ case BT_HCI_OP_LE_CREATE_CONN_CANCEL: return "LE_CREATE_CONN_CANCEL";
+ case BT_HCI_OP_LE_READ_WL_SIZE: return "LE_READ_WL_SIZE";
+ case BT_HCI_OP_LE_CLEAR_WL: return "LE_CLEAR_WL";
+ case BT_HCI_OP_LE_ADD_DEV_TO_WL: return "LE_ADD_DEV_TO_WL";
+ case BT_HCI_OP_LE_REM_DEV_FROM_WL: return "LE_REM_DEV_FROM_WL";
+ case BT_HCI_OP_LE_CONN_UPDATE: return "LE_CONN_UPDATE";
+ case BT_HCI_OP_LE_SET_HOST_CHAN_CLASSIF: return "LE_SET_HOST_CHAN_CLASSIF";
+ case BT_HCI_OP_LE_READ_CHAN_MAP: return "LE_READ_CHAN_MAP";
+ case BT_HCI_OP_LE_READ_REMOTE_FEATURES: return "LE_READ_REMOTE_FEATURES";
+ case BT_HCI_OP_LE_ENCRYPT: return "LE_ENCRYPT";
+ case BT_HCI_OP_LE_RAND: return "LE_RAND";
+ case BT_HCI_OP_LE_START_ENCRYPTION: return "LE_START_ENCRYPTION";
+ case BT_HCI_OP_LE_LTK_REQ_REPLY: return "LE_LTK_REQ_REPLY";
+ case BT_HCI_OP_LE_LTK_REQ_NEG_REPLY: return "LE_LTK_REQ_NEG_REPLY";
+ case BT_HCI_OP_LE_READ_SUPP_STATES: return "LE_READ_SUPP_STATES";
+ case BT_HCI_OP_LE_RX_TEST: return "LE_RX_TEST";
+ case BT_HCI_OP_LE_TX_TEST: return "LE_TX_TEST";
+ case BT_HCI_OP_LE_TEST_END: return "LE_TEST_END";
+ case BT_HCI_OP_LE_CONN_PARAM_REQ_REPLY: return "LE_CONN_PARAM_REQ_REPLY";
+ case BT_HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY: return "LE_CONN_PARAM_REQ_NEG_REPLY";
+ case BT_HCI_OP_LE_SET_DATA_LEN: return "LE_SET_DATA_LEN";
+ case BT_HCI_OP_LE_READ_DEFAULT_DATA_LEN: return "LE_READ_DEFAULT_DATA_LEN";
+ case BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN: return "LE_WRITE_DEFAULT_DATA_LEN";
+ case BT_HCI_OP_LE_P256_PUBLIC_KEY: return "LE_P256_PUBLIC_KEY";
+ case BT_HCI_OP_LE_GENERATE_DHKEY: return "LE_GENERATE_DHKEY";
+ case BT_HCI_OP_LE_ADD_DEV_TO_RL: return "LE_ADD_DEV_TO_RL";
+ case BT_HCI_OP_LE_REM_DEV_FROM_RL: return "LE_REM_DEV_FROM_RL";
+ case BT_HCI_OP_LE_CLEAR_RL: return "LE_CLEAR_RL";
+ case BT_HCI_OP_LE_READ_RL_SIZE: return "LE_READ_RL_SIZE";
+ case BT_HCI_OP_LE_READ_PEER_RPA: return "LE_READ_PEER_RPA";
+ case BT_HCI_OP_LE_READ_LOCAL_RPA: return "LE_READ_LOCAL_RPA";
+ case BT_HCI_OP_LE_SET_ADDR_RES_ENABLE: return "LE_SET_ADDR_RES_ENABLE";
+ case BT_HCI_OP_LE_SET_RPA_TIMEOUT: return "LE_SET_RPA_TIMEOUT";
+ case BT_HCI_OP_LE_READ_MAX_DATA_LEN: return "LE_READ_MAX_DATA_LEN";
+ case BT_HCI_OP_LE_READ_PHY: return "LE_READ_PHY";
+ case BT_HCI_OP_LE_SET_DEFAULT_PHY: return "LE_SET_DEFAULT_PHY";
+ case BT_HCI_OP_LE_SET_PHY: return "LE_SET_PHY";
+ case BT_HCI_OP_LE_ENH_RX_TEST: return "LE_ENH_RX_TEST";
+ case BT_HCI_OP_LE_ENH_TX_TEST: return "LE_ENH_TX_TEST";
+ case BT_HCI_OP_LE_SET_ADV_SET_RANDOM_ADDR: return "LE_SET_ADV_SET_RANDOM_ADDR";
+ case BT_HCI_OP_LE_SET_EXT_ADV_PARAM: return "LE_SET_EXT_ADV_PARAM";
+ case BT_HCI_OP_LE_SET_EXT_ADV_DATA: return "LE_SET_EXT_ADV_DATA";
+ case BT_HCI_OP_LE_SET_EXT_SCAN_RSP_DATA: return "LE_SET_EXT_SCAN_RSP_DATA";
+ case BT_HCI_OP_LE_SET_EXT_ADV_ENABLE: return "LE_SET_EXT_ADV_ENABLE";
+ case BT_HCI_OP_LE_READ_MAX_ADV_DATA_LEN: return "LE_READ_MAX_ADV_DATA_LEN";
+ case BT_HCI_OP_LE_READ_NUM_ADV_SETS: return "LE_READ_NUM_ADV_SETS";
+ case BT_HCI_OP_LE_REMOVE_ADV_SET: return "LE_REMOVE_ADV_SET";
+ case BT_HCI_OP_CLEAR_ADV_SETS: return "CLEAR_ADV_SETS";
+ case BT_HCI_OP_LE_SET_PER_ADV_PARAM: return "LE_SET_PER_ADV_PARAM";
+ case BT_HCI_OP_LE_SET_PER_ADV_DATA: return "LE_SET_PER_ADV_DATA";
+ case BT_HCI_OP_LE_SET_PER_ADV_ENABLE: return "LE_SET_PER_ADV_ENABLE";
+ case BT_HCI_OP_LE_SET_EXT_SCAN_PARAM: return "LE_SET_EXT_SCAN_PARAM";
+ case BT_HCI_OP_LE_SET_EXT_SCAN_ENABLE: return "LE_SET_EXT_SCAN_ENABLE";
+ case BT_HCI_OP_LE_EXT_CREATE_CONN: return "LE_EXT_CREATE_CONN";
+ case BT_HCI_OP_LE_PER_ADV_CREATE_SYNC: return "LE_PER_ADV_CREATE_SYNC";
+ case BT_HCI_OP_LE_PER_ADV_CREATE_SYNC_CANCEL: return "LE_PER_ADV_CREATE_SYNC_CANCEL";
+ case BT_HCI_OP_LE_PER_ADV_TERMINATE_SYNC: return "LE_PER_ADV_TERMINATE_SYNC";
+ case BT_HCI_OP_LE_ADD_DEV_TO_PER_ADV_LIST: return "LE_ADD_DEV_TO_PER_ADV_LIST";
+ case BT_HCI_OP_LE_REM_DEV_FROM_PER_ADV_LIST: return "LE_REM_DEV_FROM_PER_ADV_LIST";
+ case BT_HCI_OP_LE_CLEAR_PER_ADV_LIST: return "LE_CLEAR_PER_ADV_LIST";
+ case BT_HCI_OP_LE_READ_PER_ADV_LIST_SIZE: return "LE_READ_PER_ADV_LIST_SIZE";
+ case BT_HCI_OP_LE_READ_TX_POWER: return "LE_READ_TX_POWER";
+ case BT_HCI_OP_LE_READ_RF_PATH_COMP: return "LE_READ_RF_PATH_COMP";
+ case BT_HCI_OP_LE_WRITE_RF_PATH_COMP: return "LE_WRITE_RF_PATH_COMP";
+ case BT_HCI_OP_LE_SET_PRIVACY_MODE: return "LE_SET_PRIVACY_MODE";
+ default: return "";
+ }
+}
+
+
+STATIC void dump_cmd_pkt(bool tx, uint8_t pkt_len, uint8_t pkt_data[]) {
+ h4_hci_cmd_pkt_t *pkt = (h4_hci_cmd_pkt_t *) pkt_data;
+ mp_printf(&mp_plat_print,
+ "%s HCI COMMAND (%x) op: %s (%04x), len: %d, data: ",
+ tx ? "TX->" : "RX<-",
+ pkt->pkt_type,
+ hci_opcode_name(pkt->opcode), pkt->opcode, pkt->param_len);
+ for (size_t i = 0; i < pkt->param_len; i++) {
+ mp_printf(&mp_plat_print, "%02x ", pkt->params[i]);
+ }
+ if (pkt_len != sizeof(h4_hci_cmd_pkt_t) + pkt->param_len) {
+ mp_printf(&mp_plat_print, " LENGTH MISMATCH, pkt_len: %d", pkt_len);
+ }
+ mp_printf(&mp_plat_print, "\n");
+}
+
+STATIC void dump_acl_pkt(bool tx, uint8_t pkt_len, uint8_t pkt_data[]) {
+ h4_hci_acl_pkt_t *pkt = (h4_hci_acl_pkt_t *) pkt_data;
+ acl_data_t *acl = (acl_data_t *) pkt->data;
+
+ mp_printf(&mp_plat_print,
+ "%s HCI ACLDATA (%x) ",
+ tx ? "TX->" : "RX<-", pkt->pkt_type);
+
+ if (pkt->pb != ACL_DATA_PB_MIDDLE && acl->cid == BT_L2CAP_CID_ATT) {
+ // This is the start of a fragmented acl_data packet or is a full packet,
+ // and is an ATT protocol packet.
+ mp_printf(&mp_plat_print, "att: %s, ", att_opcode_name(acl->acl_data[0]));
+ }
+
+ mp_printf(&mp_plat_print,
+ "handle: %04x, pb: %d, bc: %d, data_len: %d, ",
+ pkt->handle, pkt->pb, pkt->bc, pkt->data_len);
+
+ if (pkt->pb != ACL_DATA_PB_MIDDLE) {
+ // This is the start of a fragmented acl_data packet or is a full packet.
+ mp_printf(&mp_plat_print,
+ "acl data_len: %d, cid: %04x, data: ",
+ acl->acl_data_len, acl->cid);
+ for (size_t i = 0; i < acl->acl_data_len; i++) {
+ mp_printf(&mp_plat_print, "%02x ", acl->acl_data[i]);
+ }
+ } else {
+ for (size_t i = 0; i < pkt->data_len; i++) {
+ mp_printf(&mp_plat_print, "more data: %02x ", pkt->data[i]);
+ }
+ }
+
+ if (pkt_len != sizeof(h4_hci_acl_pkt_t) + pkt->data_len) {
+ mp_printf(&mp_plat_print, " LENGTH MISMATCH, pkt_len: %d", pkt_len);
+ }
+ mp_printf(&mp_plat_print, "\n");
+}
+
+STATIC void dump_evt_pkt(bool tx, uint8_t pkt_len, uint8_t pkt_data[]) {
+ h4_hci_evt_pkt_t *pkt = (h4_hci_evt_pkt_t *) pkt_data;
+ mp_printf(&mp_plat_print,
+ "%s HCI EVENT (%x) evt: %s (%02x), param_len: %d, data: ",
+ tx ? "TX->" : "RX<-",
+ pkt->pkt_type,
+ pkt->evt == BT_HCI_EVT_LE_META_EVENT
+ ? hci_evt_le_name(pkt->params[0])
+ : hci_evt_name(pkt->evt),
+ pkt->evt, pkt->param_len);
+ for (size_t i = 0; i < pkt->param_len; i++) {
+ mp_printf(&mp_plat_print, "%02x ", pkt->params[i]);
+ }
+ if (pkt_len != sizeof(h4_hci_evt_pkt_t) + pkt->param_len) {
+ mp_printf(&mp_plat_print, " LENGTH MISMATCH, pkt_len: %d", pkt_len);
+ }
+ mp_printf(&mp_plat_print, "\n");
+}