wip: partial discovery responses; compiles; not tested

This commit is contained in:
Dan Halbert 2020-08-03 21:02:57 -04:00
parent 0a60aee3e4
commit a995a5c58f
7 changed files with 496 additions and 147 deletions

View File

@ -43,6 +43,8 @@
#include "shared-bindings/_bleio/__init__.h" #include "shared-bindings/_bleio/__init__.h"
#include "shared-bindings/_bleio/Adapter.h" #include "shared-bindings/_bleio/Adapter.h"
#include "shared-bindings/_bleio/Address.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/nvm/ByteArray.h"
#include "shared-bindings/_bleio/Connection.h" #include "shared-bindings/_bleio/Connection.h"
#include "shared-bindings/_bleio/ScanEntry.h" #include "shared-bindings/_bleio/ScanEntry.h"
@ -70,6 +72,12 @@
bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT]; 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) { // 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; // 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; 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. // Stop any current activity; reset to known state.
check_hci_error(hci_reset()); check_hci_error(hci_reset());
self->now_advertising = false; 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) { bleio_address_obj_t *common_hal_bleio_adapter_get_address(bleio_adapter_obj_t *self) {
check_enabled(self);
bt_addr_t addr; bt_addr_t addr;
check_hci_error(hci_read_bd_addr(&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) { 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 (self->scan_results != NULL) {
if (!shared_module_bleio_scanresults_get_done(self->scan_results)) { if (!shared_module_bleio_scanresults_get_done(self->scan_results)) {
mp_raise_bleio_BluetoothError(translate("Scan already in progess. Stop with stop_scan.")); 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) { 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)); 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); shared_module_bleio_scanresults_set_done(self->scan_results, true);
self->scan_results = NULL; 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) { 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; // ble_gap_addr_t addr;
// addr.addr_type = address->type; // 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) { 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->now_advertising) {
if (self->circuitpython_advertising) { if (self->circuitpython_advertising) {
common_hal_bleio_adapter_stop_advertising(self); 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) { 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. // interval value has already been validated.
check_data_fit(advertising_data_bufinfo->len, connectable); 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) { void common_hal_bleio_adapter_stop_advertising(bleio_adapter_obj_t *self) {
check_enabled(self);
self->now_advertising = false; self->now_advertising = false;
self->extended_advertising = false; self->extended_advertising = false;
self->circuitpython_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) { bool common_hal_bleio_adapter_get_advertising(bleio_adapter_obj_t *self) {
check_enabled(self);
return self->now_advertising; return self->now_advertising;
} }
bool common_hal_bleio_adapter_get_connected(bleio_adapter_obj_t *self) { 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++) { for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
bleio_connection_internal_t *connection = &bleio_connections[i]; bleio_connection_internal_t *connection = &bleio_connections[i];
if (connection->conn_handle != BLE_CONN_HANDLE_INVALID) { 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) { mp_obj_t common_hal_bleio_adapter_get_connections(bleio_adapter_obj_t *self) {
check_enabled(self);
if (self->connection_objs != NULL) { if (self->connection_objs != NULL) {
return self->connection_objs; 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) { void common_hal_bleio_adapter_erase_bonding(bleio_adapter_obj_t *self) {
check_enabled(self);
//FIX bonding_erase_storage(); //FIX bonding_erase_storage();
} }
uint16_t bleio_adapter_add_attribute(bleio_adapter_obj_t *adapter, mp_obj_t *attribute) { 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. // The handle is the index of this attribute in the attributes list.
uint16_t handle = (uint16_t) adapter->attributes->len; uint16_t handle = (uint16_t) adapter->attributes->len;
mp_obj_list_append(adapter->attributes, attribute); 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; return handle;
} }
mp_obj_t* bleio_adapter_get_attribute(bleio_adapter_obj_t *adapter, uint16_t 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) { if (handle == 0 || handle >= adapter->attributes->len) {
return mp_const_none; 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) { uint16_t bleio_adapter_max_attribute_handle(bleio_adapter_obj_t *adapter) {
check_enabled(adapter);
return adapter->attributes->len - 1; 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) { 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); common_hal_bleio_adapter_stop_scan(adapter);
if (adapter->now_advertising) { if (adapter->now_advertising) {
common_hal_bleio_adapter_stop_advertising(adapter); 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) { void bleio_adapter_background(bleio_adapter_obj_t* adapter) {
if (!common_hal_bleio_adapter_get_enabled(adapter)) {
return;
}
if (adapter->advertising_timeout_msecs > 0 && if (adapter->advertising_timeout_msecs > 0 &&
supervisor_ticks_ms64() - adapter->advertising_start_ticks > adapter->advertising_timeout_msecs) { supervisor_ticks_ms64() - adapter->advertising_start_ticks > adapter->advertising_timeout_msecs) {
adapter->advertising_timeout_msecs = 0; adapter->advertising_timeout_msecs = 0;

View File

@ -30,7 +30,7 @@
#include "shared-bindings/_bleio/Service.h" #include "shared-bindings/_bleio/Service.h"
// Return the type of the attribute. // 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)) { if (MP_OBJ_IS_TYPE(attribute, &bleio_characteristic_type)) {
return BLE_TYPE_CHARACTERISTIC; return BLE_TYPE_CHARACTERISTIC;
} }

View File

@ -36,7 +36,7 @@ typedef enum {
BLE_TYPE_SECONDARY_SERVICE = 0x2801, BLE_TYPE_SECONDARY_SERVICE = 0x2801,
BLE_TYPE_CHARACTERISTIC = 0x2803, BLE_TYPE_CHARACTERISTIC = 0x2803,
BLE_TYPE_DESCRIPTOR = 0x2900 BLE_TYPE_DESCRIPTOR = 0x2900
} ble_attribute_type; } ble_attribute_type_uuid;
// typedef struct // typedef struct
// { // {
@ -45,6 +45,6 @@ typedef enum {
// } ble_gap_conn_sec_mode_t; // } 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 #endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_ATTRIBUTE_H

View File

@ -33,6 +33,7 @@
#include "common-hal/_bleio/Attribute.h" #include "common-hal/_bleio/Attribute.h"
#include "shared-bindings/_bleio/__init__.h" #include "shared-bindings/_bleio/__init__.h"
#include "shared-bindings/_bleio/Characteristic.h" #include "shared-bindings/_bleio/Characteristic.h"
#include "shared-bindings/_bleio/UUID.h"
#include "supervisor/shared/tick.h" #include "supervisor/shared/tick.h"
STATIC uint16_t max_mtu = BT_ATT_DEFAULT_LE_MTU; // 23 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[]) { 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; struct bt_att_error_rsp *rsp = (struct bt_att_error_rsp *) data;
if (dlen != sizeof(struct bt_att_error_rsp)) { if (dlen != sizeof(struct bt_att_error_rsp)) {
// Incorrect size; ignore. // Incorrect size; ignore.
return; 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[]) { 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; 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); send_error(conn_handle, BT_ATT_OP_MTU_REQ, BLE_GATT_HANDLE_INVALID, BT_ATT_ERR_INVALID_PDU);
return; return;
} }
@ -720,7 +723,7 @@ STATIC void process_mtu_req(uint16_t conn_handle, uint8_t dlen, uint8_t data[])
struct __packed { struct __packed {
struct bt_att_hdr h; struct bt_att_hdr h;
struct bt_att_exchange_mtu_req r; struct bt_att_exchange_mtu_rsp r;
} rsp = { { } rsp = { {
.code = BT_ATT_OP_MTU_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[]) { 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)) { if (dlen != sizeof(struct bt_att_exchange_mtu_rsp)) {
return; 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++) { for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
if (bleio_connections[i].conn_handle == conn_handle) { if (bleio_connections[i].conn_handle == conn_handle) {
bleio_connections[i].mtu = rsp->mtu; 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[]) { 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; 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) || if (dlen != sizeof(struct bt_att_read_group_req) + sizeof(type_uuid) ||
(uuid != BLE_TYPE_PRIMARY_SERVICE && (type_uuid != BLE_TYPE_PRIMARY_SERVICE &&
uuid != BLE_TYPE_SECONDARY_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); send_error(conn_handle, BT_ATT_OP_READ_GROUP_REQ, req->start_handle, BT_ATT_ERR_UNSUPPORTED_GROUP_TYPE);
return; return;
} }
uint8_t response[mtu]; typedef struct __packed {
uint16_t response_length; struct bt_att_hdr h;
struct bt_att_read_group_rsp r;
} rsp_t;
response[0] = BT_ATT_OP_READ_GROUP_RSP; uint8_t rsp_bytes[mtu];
response[1] = 0x00; rsp_t *rsp = (rsp_t *) &rsp_bytes;
response_length = 2; rsp->h.code = BT_ATT_OP_READ_GROUP_RSP;
rsp->r.len = 0;
// FIX // Keeps track of total length of the response.
// for (uint16_t i = (readByGroupReq->start_handle - 1); i < GATT.attributeCount() && i <= (readByGroupReq->end_handle - 1); i++) { size_t rsp_length = sizeof(rsp_t);
//FIX
// BLELocalAttribute* attribute = GATT.attribute(i);
// if (readByGroupReq->uuid != attribute->type()) { bool no_data = true;
// // not the type
// continue;
// }
// int uuidLen = attribute->uuidLength(); // All the data chunks must have uuid's that are the same size.
// size_t infoSize = (uuidLen == 2) ? 6 : 20; // 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;
// if (response[1] == 0) { mp_obj_t *attribute_obj = bleio_adapter_get_attribute(&common_hal_bleio_adapter_obj, handle);
// response[1] = infoSize; 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);
// if (response[1] != infoSize) { // Is this a 16-bit or a 128-bit uuid? It must match in size with any previous attribute
// // different size // in this transmission.
// break; 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;
}
// BLELocalService* service = (BLELocalService*)attribute; // Size of bt_att_group_data chunk with uuid.
const uint16_t data_length = sizeof(struct bt_att_group_data) + sizeof_service_uuid;
// // add the start handle if (rsp_length + data_length > mtu) {
// uint16_t start_handle = service->start_handle(); // No room for another bt_att_group_data chunk.
// memcpy(&response[response_length], &start_handle, sizeof(start_handle)); break;
// response_length += sizeof(start_handle); }
// // add the end handle // Pass the length of ONE bt_att_group_data chunk. There may be multiple ones in this transmission.
// uint16_t end_handle = service->end_handle(); rsp->r.len = data_length;
// memcpy(&response[response_length], &end_handle, sizeof(end_handle));
// response_length += sizeof(end_handle);
// // add the UUID uint8_t group_data_bytes[data_length];
// memcpy(&response[response_length], service->uuidData(), uuidLen); struct bt_att_group_data *group_data = (struct bt_att_group_data *) group_data_bytes;
// response_length += uuidLen;
// if ((response_length + infoSize) > mtu) { group_data->start_handle = service->start_handle;
// break; group_data->end_handle = service->end_handle;
// } common_hal_bleio_uuid_pack_into(service->uuid, group_data->value);
// }
if (response_length == 2) { rsp_length += data_length;
}
if (no_data) {
send_error(conn_handle, BT_ATT_OP_READ_GROUP_REQ, req->start_handle, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND); send_error(conn_handle, BT_ATT_OP_READ_GROUP_REQ, req->start_handle, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND);
} else { } 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; handle = req->handle;
response_opcode = BT_ATT_OP_READ_RSP; 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)) { 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); send_error(conn_handle, BT_ATT_OP_READ_BLOB_REQ, BLE_GATT_HANDLE_INVALID, BT_ATT_ERR_INVALID_PDU);
return; return;
@ -996,8 +1012,11 @@ STATIC void process_read_or_read_blob_req(uint16_t conn_handle, uint16_t mtu, ui
handle = req->handle; handle = req->handle;
offset = req->offset; offset = req->offset;
response_opcode = BT_ATT_OP_READ_BLOB_RSP; response_opcode = BT_ATT_OP_READ_BLOB_RSP;
} else {
return;
} }
//FIX //FIX
(void) offset; (void) offset;
(void) handle; (void) handle;

View File

@ -95,7 +95,6 @@ STATIC uint8_t acl_data_buffer[ACL_DATA_BUFFER_SIZE];
STATIC size_t acl_data_len; STATIC size_t acl_data_len;
STATIC size_t num_command_packets_allowed; STATIC size_t num_command_packets_allowed;
STATIC size_t max_pkt;
STATIC size_t pending_pkt; STATIC size_t pending_pkt;
// Results from parsing a command response packet. // 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 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_HCI
if (debug) { #include "hci_debug.c"
h4_hci_cmd_pkt_t *pkt = (h4_hci_cmd_pkt_t *) pkt_data; #endif // DEBUG_HCI
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");
}
}
STATIC void process_acl_data_pkt(uint8_t pkt_len, uint8_t pkt_data[]) { 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; 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; 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. // We don't have the full packet yet.
return; return;
} }
@ -330,9 +265,9 @@ STATIC void process_evt_pkt(size_t pkt_len, uint8_t pkt_data[])
} }
default: default:
if (debug) { #if DEBUG_HCI
mp_printf(&mp_plat_print, "process_evt_pkt: Unknown event: %02x\n"); mp_printf(&mp_plat_print, "process_evt_pkt: Unknown event: %02x\n");
} #endif
break; break;
} }
} }
@ -374,7 +309,8 @@ hci_result_t hci_poll_for_incoming_pkt(void) {
bool packet_is_complete = false; bool packet_is_complete = false;
// Read bytes until we run out, or accumulate a complete packet. // 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); common_hal_busio_uart_read(common_hal_bleio_adapter_obj.hci_uart, rx_buffer + rx_idx, 1, &errcode);
if (errcode) { if (errcode) {
hci_poll_in_progress = false; hci_poll_in_progress = false;
@ -417,25 +353,25 @@ hci_result_t hci_poll_for_incoming_pkt(void) {
switch (rx_buffer[0]) { switch (rx_buffer[0]) {
case H4_ACL: case H4_ACL:
if (debug) { #if DEBUG_HCI
dump_acl_pkt(false, pkt_len, rx_buffer); dump_acl_pkt(false, pkt_len, rx_buffer);
} #endif
process_acl_data_pkt(pkt_len, rx_buffer); process_acl_data_pkt(pkt_len, rx_buffer);
break; break;
case H4_EVT: case H4_EVT:
if (debug) { #if DEBUG_HCI
dump_evt_pkt(false, pkt_len, rx_buffer); dump_evt_pkt(false, pkt_len, rx_buffer);
} #endif
process_evt_pkt(pkt_len, rx_buffer); process_evt_pkt(pkt_len, rx_buffer);
break; break;
default: default:
if (debug) { #if DEBUG_HCI
mp_printf(&mp_plat_print, "Unknown HCI packet type: %d\n", rx_buffer[0]); mp_printf(&mp_plat_print, "Unknown HCI packet type: %d\n", rx_buffer[0]);
} #endif
break; 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); memcpy(cmd_pkt->params, params, params_len);
if (debug) { #if DEBUG_HCI
dump_cmd_pkt(true, sizeof(tx_buffer), tx_buffer); dump_cmd_pkt(true, sizeof(tx_buffer), tx_buffer);
} #endif
int result = write_pkt(tx_buffer, cmd_pkt_len); int result = write_pkt(tx_buffer, cmd_pkt_len);
if (result != HCI_OK) { 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) { hci_result_t hci_send_acl_pkt(uint16_t handle, uint8_t cid, uint8_t data_len, uint8_t *data) {
int result; 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(); result = hci_poll_for_incoming_pkt();
if (result != HCI_OK) { if (result != HCI_OK) {
return result; 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. // 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]; uint8_t tx_buffer[buf_len];
h4_hci_acl_pkt_t *acl_pkt = (h4_hci_acl_pkt_t *) tx_buffer; 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_data_t *acl_data = (acl_data_t *) acl_pkt->data;
acl_pkt->pkt_type = H4_ACL; acl_pkt->pkt_type = H4_ACL;
acl_pkt->handle = handle; acl_pkt->handle = handle;
acl_pkt->data_len = (uint8_t)(cid_len + data_len); acl_pkt->pb = ACL_DATA_PB_FIRST_FLUSH;
acl_data->acl_data_len = (uint8_t) data_len; acl_pkt->data_len = (uint8_t)(sizeof(acl_data_t) + data_len);
acl_data->acl_data_len = data_len;
acl_data->cid = cid; 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); dump_acl_pkt(true, buf_len, tx_buffer);
} #endif
pending_pkt++; pending_pkt++;

View File

@ -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");
}

View File

@ -112,7 +112,7 @@ CFLAGS += $(OPTIMIZATION_FLAGS) -DNDEBUG
$(echo PERIPHERALS_CHIP_FAMILY=$(PERIPHERALS_CHIP_FAMILY)) $(echo PERIPHERALS_CHIP_FAMILY=$(PERIPHERALS_CHIP_FAMILY))
#Debugging/Optimization #Debugging/Optimization
ifeq ($(DEBUG), 1) ifeq ($(DEBUG), 1)
CFLAGS += -ggdb CFLAGS += -ggdb -Og
# You may want to disable -flto if it interferes with debugging. # You may want to disable -flto if it interferes with debugging.
CFLAGS += -flto -flto-partition=none CFLAGS += -flto -flto-partition=none
# You may want to enable these flags to make setting breakpoints easier. # You may want to enable these flags to make setting breakpoints easier.