summaryrefslogtreecommitdiff
path: root/devices/ble_hci
diff options
context:
space:
mode:
authorDan Halbert <halbert@halwitz.org>2020-08-20 20:29:57 -0400
committerDan Halbert <halbert@halwitz.org>2020-08-20 20:29:57 -0400
commit0e30dd8bccdbb4469e1bb54443f5d2fca66f7ff6 (patch)
tree734b3c975287d2f922c1c6ca3bf7f3dc153d59d8 /devices/ble_hci
parentdfe50d08d573f2bf49a77e22de1843eb8db4b855 (diff)
parent837abd6da072a55f3c46d62b013690a12e0ee262 (diff)
merge from upstream; working; includes debug_out code for debugging via Saleae for posterity
Diffstat (limited to 'devices/ble_hci')
-rw-r--r--devices/ble_hci/common-hal/_bleio/Adapter.c33
-rw-r--r--devices/ble_hci/common-hal/_bleio/__init__.c37
-rw-r--r--devices/ble_hci/common-hal/_bleio/__init__.h6
-rw-r--r--devices/ble_hci/common-hal/_bleio/att.c61
-rw-r--r--devices/ble_hci/common-hal/_bleio/hci.c217
-rw-r--r--devices/ble_hci/common-hal/_bleio/hci.h6
-rw-r--r--devices/ble_hci/common-hal/_bleio/hci_debug.c2
7 files changed, 214 insertions, 148 deletions
diff --git a/devices/ble_hci/common-hal/_bleio/Adapter.c b/devices/ble_hci/common-hal/_bleio/Adapter.c
index a86893dcd..27a251281 100644
--- a/devices/ble_hci/common-hal/_bleio/Adapter.c
+++ b/devices/ble_hci/common-hal/_bleio/Adapter.c
@@ -280,7 +280,7 @@ STATIC void bleio_adapter_hci_init(bleio_adapter_obj_t *self) {
const size_t len = sizeof(default_ble_name);
bt_addr_t addr;
- check_hci_error(hci_read_bd_addr(&addr));
+ hci_check_error(hci_read_bd_addr(&addr));
default_ble_name[len - 4] = nibble_to_hex_lower[addr.val[1] >> 4 & 0xf];
default_ble_name[len - 3] = nibble_to_hex_lower[addr.val[1] & 0xf];
@@ -373,7 +373,7 @@ void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enable
}
// Enabling or disabling: stop any current activity; reset to known state.
- check_hci_error(hci_reset());
+ hci_reset();
self->now_advertising = false;
self->extended_advertising = false;
self->circuitpython_advertising = false;
@@ -397,7 +397,7 @@ bleio_address_obj_t *common_hal_bleio_adapter_get_address(bleio_adapter_obj_t *s
check_enabled(self);
bt_addr_t addr;
- check_hci_error(hci_read_bd_addr(&addr));
+ hci_check_error(hci_read_bd_addr(&addr));
bleio_address_obj_t *address = m_new_obj(bleio_address_obj_t);
address->base.type = &bleio_address_type;
@@ -406,6 +406,14 @@ bleio_address_obj_t *common_hal_bleio_adapter_get_address(bleio_adapter_obj_t *s
return address;
}
+bool common_hal_bleio_adapter_set_address(bleio_adapter_obj_t *self, bleio_address_obj_t *address) {
+ mp_buffer_info_t bufinfo;
+ if (!mp_get_buffer(address->bytes, &bufinfo, MP_BUFFER_READ)) {
+ return false;
+ }
+ return hci_le_set_random_address(bufinfo.buf) == HCI_OK;
+}
+
mp_obj_str_t* common_hal_bleio_adapter_get_name(bleio_adapter_obj_t *self) {
return self->name;
}
@@ -673,7 +681,7 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
// Advertising interval.
uint32_t interval_units = SEC_TO_UNITS(interval, UNIT_0_625_MS);
- check_hci_error(
+ hci_check_error(
hci_le_set_extended_advertising_parameters(
0, // handle
props, // adv properties
@@ -697,7 +705,7 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
uint8_t handle[1] = { 0 };
uint16_t duration_10msec[1] = { timeout * 100 };
uint8_t max_ext_adv_evts[1] = { 0 };
- check_hci_error(
+ hci_check_error(
hci_le_set_extended_advertising_enable(
BT_HCI_LE_ADV_ENABLE,
1, // one advertising set.
@@ -725,7 +733,7 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
// Advertising interval.
uint16_t interval_units = SEC_TO_UNITS(interval, UNIT_0_625_MS);
- check_hci_error(
+ hci_check_error(
hci_le_set_advertising_parameters(
interval_units, // min interval
interval_units, // max interval
@@ -740,11 +748,11 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
// even though the actual data length may be shorter.
uint8_t full_data[MAX_ADVERTISEMENT_SIZE] = { 0 };
memcpy(full_data, advertising_data, MIN(sizeof(full_data), advertising_data_len));
- check_hci_error(hci_le_set_advertising_data(advertising_data_len, full_data));
+ hci_check_error(hci_le_set_advertising_data(advertising_data_len, full_data));
memset(full_data, 0, sizeof(full_data));
if (scan_response_data_len > 0) {
memcpy(full_data, scan_response_data, MIN(sizeof(full_data), scan_response_data_len));
- check_hci_error(hci_le_set_scan_response_data(scan_response_data_len, full_data));
+ hci_check_error(hci_le_set_scan_response_data(scan_response_data_len, full_data));
}
// No duration mechanism is provided for legacy advertising, so we need to do our own.
@@ -752,7 +760,7 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
self->advertising_start_ticks = supervisor_ticks_ms64();
// Start advertising.
- check_hci_error(hci_le_set_advertising_enable(BT_HCI_LE_ADV_ENABLE));
+ hci_check_error(hci_le_set_advertising_enable(BT_HCI_LE_ADV_ENABLE));
self->extended_advertising = false;
} // end legacy advertising setup
@@ -809,7 +817,7 @@ void common_hal_bleio_adapter_stop_advertising(bleio_adapter_obj_t *self) {
// OK if we're already stopped. There seems to be an ESP32 HCI bug:
// If advertising is already off, then LE_SET_ADV_ENABLE does not return a response.
if (result != HCI_RESPONSE_TIMEOUT) {
- check_hci_error(result);
+ hci_check_error(result);
}
//TODO startup CircuitPython advertising again.
@@ -942,5 +950,8 @@ void bleio_adapter_background(bleio_adapter_obj_t* adapter) {
common_hal_bleio_adapter_stop_advertising(adapter);
}
- hci_poll_for_incoming_pkt();
+ hci_result_t result = hci_poll_for_incoming_pkt();
+ if (result != HCI_OK) {
+ mp_printf(&mp_plat_print, "bad hci_poll_for_incoming_pkt() result in background: %d\n", result);
+ }
}
diff --git a/devices/ble_hci/common-hal/_bleio/__init__.c b/devices/ble_hci/common-hal/_bleio/__init__.c
index 9dd531e25..25aca39b5 100644
--- a/devices/ble_hci/common-hal/_bleio/__init__.c
+++ b/devices/ble_hci/common-hal/_bleio/__init__.c
@@ -43,43 +43,6 @@ bleio_uuid_obj_t cccd_uuid;
bool vm_used_ble;
-void check_hci_error(hci_result_t result) {
- switch (result) {
- case HCI_OK:
- return;
-
- case HCI_RESPONSE_TIMEOUT:
- mp_raise_bleio_BluetoothError(translate("Timeout waiting for HCI response"));
- return;
-
- case HCI_WRITE_TIMEOUT:
- mp_raise_bleio_BluetoothError(translate("Timeout waiting to write HCI request"));
- return;
-
- case HCI_READ_ERROR:
- mp_raise_bleio_BluetoothError(translate("Error reading from HCI adapter"));
- return;
-
- case HCI_WRITE_ERROR:
- mp_raise_bleio_BluetoothError(translate("Error writing to HCI adapter"));
- return;
-
- case HCI_ATT_ERROR:
- mp_raise_RuntimeError(translate("Error in ATT protocol code"));
- return;
-
- default:
- // Should be an HCI status error, > 0.
- if (result > 0) {
- mp_raise_bleio_BluetoothError(translate("HCI status error: %02x"), result);
- } else {
- mp_raise_bleio_BluetoothError(translate("Unknown hci_result_t: %d"), result);
- }
- return;
- }
-}
-
-
// void check_sec_status(uint8_t sec_status) {
// if (sec_status == BLE_GAP_SEC_STATUS_SUCCESS) {
// return;
diff --git a/devices/ble_hci/common-hal/_bleio/__init__.h b/devices/ble_hci/common-hal/_bleio/__init__.h
index 086d56a4b..cd9940bf0 100644
--- a/devices/ble_hci/common-hal/_bleio/__init__.h
+++ b/devices/ble_hci/common-hal/_bleio/__init__.h
@@ -53,12 +53,6 @@ typedef struct {
#define BLE_GATTS_FIX_ATTR_LEN_MAX (510) /**< Maximum length for fixed length Attribute Values. */
#define BLE_GATTS_VAR_ATTR_LEN_MAX (512) /**< Maximum length for variable length Attribute Values. */
-
-// These helpers raise the appropriate exceptions if the code doesn't equal success.
-void check_hci_error(hci_result_t result);
-void check_gatt_status(uint16_t gatt_status);
-void check_sec_status(uint8_t sec_status);
-
// Track if the user code modified the BLE state to know if we need to undo it on reload.
extern bool vm_used_ble;
diff --git a/devices/ble_hci/common-hal/_bleio/att.c b/devices/ble_hci/common-hal/_bleio/att.c
index aa2568012..591e508a6 100644
--- a/devices/ble_hci/common-hal/_bleio/att.c
+++ b/devices/ble_hci/common-hal/_bleio/att.c
@@ -149,7 +149,8 @@ STATIC int send_req_wait_for_rsp(uint16_t conn_handle, size_t request_length, ui
}
for (uint64_t start = supervisor_ticks_ms64(); supervisor_ticks_ms64() - start < timeout;) {
- hci_poll_for_incoming_pkt();
+ // RUN_BACKGROUND_TASKS includes hci_poll_for_incoming_pkt();
+ RUN_BACKGROUND_TASKS;
if (!att_handle_is_connected(conn_handle)) {
break;
@@ -188,8 +189,6 @@ void bleio_att_reset(void) {
memset(bleio_connections[i].addr.a.val, 0, sizeof_field(bt_addr_t, val));
bleio_connections[i].mtu = BT_ATT_DEFAULT_LE_MTU;
}
-
- //FIX memset(event_handlers, 0x00, sizeof(event_handlers));
}
bool att_connect_to_address(bt_addr_le_t *addr) {
@@ -202,7 +201,8 @@ bool att_connect_to_address(bt_addr_le_t *addr) {
bool is_connected = false;
for (uint64_t start = supervisor_ticks_ms64(); supervisor_ticks_ms64() - start < timeout;) {
- hci_poll_for_incoming_pkt();
+ // RUN_BACKGROUND_TASKS includes hci_poll_for_incoming_pkt();
+ RUN_BACKGROUND_TASKS;
is_connected = att_address_is_connected(addr);
@@ -421,36 +421,36 @@ bool att_discover_attributes(bt_addr_le_t *addr, const char* service_uuid_filter
//FIX BLERemoteDevice* device = NULL;
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
- // if (bleio_connections[i].conn_handle == conn_handle) {
- // //FIX if (bleio_connections[i].device == NULL) {
- // //FIX
- // //bleio_connections[i].device = new BLERemoteDevice();
- // //}
+ // if (bleio_connections[i].conn_handle == conn_handle) {
+ // //FIX if (bleio_connections[i].device == NULL) {
+ // //FIX
+ // //bleio_connections[i].device = new BLERemoteDevice();
+ // //}
- // //device = bleio_connections[i].device;
+ // //device = bleio_connections[i].device;
- // break;
- // }
- // }
+ // break;
+ // }
+ // }
- // //FIX if (device == NULL) {
- // // return false;
- // // }
+ // //FIX if (device == NULL) {
+ // // return false;
+ // // }
- // if (service_uuid_filter == NULL) {
- // // clear existing services
- // //FIX device->clear_services();
- // } else {
- // //FIX int service_count = device->service_count();
+ // if (service_uuid_filter == NULL) {
+ // // clear existing services
+ // //FIX device->clear_services();
+ // } else {
+ // //FIX int service_count = device->service_count();
- // for (size_t i = 0; i < service_count; i++) {
- // //FIX BLERemoteService* service = device->service(i);
+ // for (size_t i = 0; i < service_count; i++) {
+ // //FIX BLERemoteService* service = device->service(i);
- // if (strcasecmp(service->uuid(), service_uuid_filter) == 0) {
- // // found an existing service with same UUID
- // return true;
- // }
- // }
+ // if (strcasecmp(service->uuid(), service_uuid_filter) == 0) {
+ // // found an existing service with same UUID
+ // return true;
+ // }
+ // }
}
// discover services
@@ -584,8 +584,6 @@ bool att_address_is_connected(bt_addr_le_t *addr) {
}
bool att_handle_is_connected(uint16_t handle) {
- hci_poll_for_incoming_pkt();
-
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
if (bleio_connections[i].conn_handle == handle) {
return true;
@@ -685,7 +683,8 @@ bool att_indicate(uint16_t handle, const uint8_t* value, int length) {
sizeof(indicate_bytes), indicate_bytes);
while (!confirm) {
- hci_poll_for_incoming_pkt();
+ // RUN_BACKGROUND_TASKS includes hci_poll_for_incoming_pkt();
+ RUN_BACKGROUND_TASKS;
if (!att_address_is_connected(&bleio_connections[i].addr)) {
break;
diff --git a/devices/ble_hci/common-hal/_bleio/hci.c b/devices/ble_hci/common-hal/_bleio/hci.c
index e8fc324e1..b366aa4ac 100644
--- a/devices/ble_hci/common-hal/_bleio/hci.c
+++ b/devices/ble_hci/common-hal/_bleio/hci.c
@@ -17,6 +17,8 @@
#include "hci.h"
#include "py/obj.h"
+#include "py/mperrno.h"
+#include "py/runtime.h"
// Zephyr include files to define HCI communication values and structs.
#include "hci_include/hci.h"
@@ -25,11 +27,19 @@
#include <string.h>
+#include "py/mphal.h" //*****************************
#include "supervisor/shared/tick.h"
#include "shared-bindings/_bleio/__init__.h"
#include "common-hal/_bleio/Adapter.h"
#include "shared-bindings/microcontroller/__init__.h"
+// Set to 1 for extensive HCI packet logging.
+#define HCI_DEBUG 0
+
+//FIX **********8
+busio_uart_obj_t debug_out;
+bool debug_out_in_use;
+
// HCI H4 protocol packet types: first byte in the packet.
#define H4_CMD 0x01
@@ -95,7 +105,7 @@ 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 pending_pkt;
+STATIC volatile size_t pending_pkt;
// Results from parsing a command response packet.
STATIC bool cmd_response_received;
@@ -106,13 +116,12 @@ STATIC uint8_t* cmd_response_data;
STATIC volatile bool hci_poll_in_progress = false;
-#define DEBUG_HCI 1
//////////////////////////////////////////////////////////////////////
-#if DEBUG_HCI
+#if HCI_DEBUG
#include "hci_debug.c"
-#endif // DEBUG_HCI
+#endif // HCI_DEBUG
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;
@@ -156,6 +165,11 @@ STATIC void process_acl_data_pkt(uint8_t pkt_len, uint8_t pkt_data[]) {
// Process number of completed packets. Reduce number of pending packets by reported
// number of completed.
STATIC void process_num_comp_pkts(uint16_t handle, uint16_t num_pkts) {
+ const uint8_t ff = 0xff;
+ int err;
+ common_hal_busio_uart_write(&debug_out, (uint8_t *) &pending_pkt, 1, &err);
+ common_hal_busio_uart_write(&debug_out, (uint8_t *) &ff, 1, &err);
+ common_hal_busio_uart_write(&debug_out, (uint8_t *) &ff, 1, &err);
if (num_pkts && pending_pkt > num_pkts) {
pending_pkt -= num_pkts;
} else {
@@ -271,26 +285,44 @@ STATIC void process_evt_pkt(size_t pkt_len, uint8_t pkt_data[])
}
default:
-#if DEBUG_HCI
+#if HCI_DEBUG
mp_printf(&mp_plat_print, "process_evt_pkt: Unknown event: %02x\n");
#endif
break;
}
}
+//FIX
+busio_uart_obj_t debug_out;
+bool debug_out_in_use;
+
void bleio_hci_reset(void) {
rx_idx = 0;
pending_pkt = 0;
hci_poll_in_progress = false;
-
+ debug_out_in_use = false;
bleio_att_reset();
}
hci_result_t hci_poll_for_incoming_pkt(void) {
+ if (!debug_out_in_use) {
+ debug_out.base.type = &busio_uart_type;
+ common_hal_busio_uart_construct(&debug_out,
+ &pin_PB12 /*D7*/, NULL, // no RX
+ NULL, NULL,
+ NULL, false,
+ 115200, 8, BUSIO_UART_PARITY_NONE, 1, 0,
+ 512, NULL, false);
+ debug_out_in_use = true;
+ }
+
+ common_hal_mcu_disable_interrupts();
if (hci_poll_in_progress) {
+ common_hal_mcu_enable_interrupts();
return HCI_OK;
}
hci_poll_in_progress = true;
+ common_hal_mcu_enable_interrupts();
// Assert RTS low to say we're ready to read data.
common_hal_digitalio_digitalinout_set_value(common_hal_bleio_adapter_obj.rts_digitalinout, false);
@@ -298,28 +330,55 @@ hci_result_t hci_poll_for_incoming_pkt(void) {
int errcode = 0;
bool packet_is_complete = false;
- // Read bytes until we run out, or accumulate a complete packet.
+ // Read bytes until we run out. There may be more than one packet in the input buffer.
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_rx_characters_available(common_hal_bleio_adapter_obj.hci_uart) > 0) {
+
+ // Read just one character a a time, so we don't accidentally get part of a second
+ // packet.
+ size_t num_read =
+ common_hal_busio_uart_read(common_hal_bleio_adapter_obj.hci_uart, rx_buffer + rx_idx, 1, &errcode);
+ if (num_read == 0) {
+ return HCI_OK;
+ }
if (errcode) {
+ if (errcode == EAGAIN) {
+ continue;
+ }
hci_poll_in_progress = false;
+ mp_printf(&mp_plat_print, "HCI_READ_ERROR, errcode: %x\n", errcode);
return HCI_READ_ERROR;
}
rx_idx++;
+ if (rx_idx >= sizeof(rx_buffer)) {
+ // Incoming packet is too large. Should not happen.
+ return HCI_READ_ERROR;
+ }
switch (rx_buffer[0]) {
case H4_ACL:
- if (rx_idx > sizeof(h4_hci_acl_pkt_t) &&
- rx_idx >= sizeof(h4_hci_acl_pkt_t) + ((h4_hci_acl_pkt_t *) rx_buffer)->data_len) {
- packet_is_complete = true;
+ if (rx_idx > sizeof(h4_hci_acl_pkt_t)) {
+ const size_t total_len =
+ sizeof(h4_hci_acl_pkt_t) + ((h4_hci_acl_pkt_t *) rx_buffer)->data_len;
+ if (rx_idx == total_len) {
+ packet_is_complete = true;
+ }
+ if (rx_idx > total_len) {
+ mp_printf(&mp_plat_print, "acl: rx_idx > total_len\n");
+ }
}
break;
case H4_EVT:
- if (rx_idx > sizeof(h4_hci_evt_pkt_t) &&
- rx_idx >= sizeof(h4_hci_evt_pkt_t) + ((h4_hci_evt_pkt_t *) rx_buffer)->param_len) {
- packet_is_complete = true;
+ if (rx_idx > sizeof(h4_hci_evt_pkt_t)) {
+ const size_t total_len =
+ sizeof(h4_hci_evt_pkt_t) + ((h4_hci_evt_pkt_t *) rx_buffer)->param_len;
+ if (rx_idx == total_len) {
+ packet_is_complete = true;
+ }
+ if (rx_idx > total_len) {
+ mp_printf(&mp_plat_print, "evt: rx_idx > total_len\n");
+ }
}
break;
@@ -328,45 +387,54 @@ hci_result_t hci_poll_for_incoming_pkt(void) {
rx_idx = 0;
break;
}
- }
+ } // end while
- if (!packet_is_complete) {
- hci_poll_in_progress = false;
- return HCI_OK;
- }
+ if (packet_is_complete) {
+ // Stop incoming data while processing packet.
+ common_hal_digitalio_digitalinout_set_value(common_hal_bleio_adapter_obj.rts_digitalinout, true);
+ size_t pkt_len = rx_idx;
- // Stop incoming data while processing packet.
- common_hal_digitalio_digitalinout_set_value(common_hal_bleio_adapter_obj.rts_digitalinout, true);
- size_t pkt_len = rx_idx;
- // Reset for next packet.
- rx_idx = 0;
+ //FIX output packet for debugging
+ int err;
+ common_hal_busio_uart_write(&debug_out, (uint8_t *) &rx_idx, 1, &err);
+ common_hal_busio_uart_write(&debug_out, (uint8_t *) &rx_idx, 1, &err);
+ common_hal_busio_uart_write(&debug_out, (uint8_t *) &rx_idx, 1, &err);
- switch (rx_buffer[0]) {
- case H4_ACL:
-#if DEBUG_HCI
- dump_acl_pkt(false, pkt_len, rx_buffer);
-#endif
+ common_hal_busio_uart_write(&debug_out, rx_buffer, rx_idx, &err);
- process_acl_data_pkt(pkt_len, rx_buffer);
- break;
- case H4_EVT:
-#if DEBUG_HCI
- dump_evt_pkt(false, pkt_len, rx_buffer);
+ // Reset for next packet.
+ rx_idx = 0;
+ packet_is_complete = false;
+
+ switch (rx_buffer[0]) {
+ case H4_ACL:
+#if HCI_DEBUG
+ dump_acl_pkt(false, pkt_len, rx_buffer);
#endif
+ process_acl_data_pkt(pkt_len, rx_buffer);
+ break;
- process_evt_pkt(pkt_len, rx_buffer);
- break;
+ case H4_EVT:
+#if HCI_DEBUG
+ dump_evt_pkt(false, pkt_len, rx_buffer);
+#endif
+ process_evt_pkt(pkt_len, rx_buffer);
+ break;
- default:
-#if DEBUG_HCI
- mp_printf(&mp_plat_print, "Unknown HCI packet type: %d\n", rx_buffer[0]);
+ default:
+#if HCI_DEBUG
+ mp_printf(&mp_plat_print, "Unknown HCI packet type: %d\n", rx_buffer[0]);
#endif
- break;
- }
+ break;
+ }
- common_hal_digitalio_digitalinout_set_value(common_hal_bleio_adapter_obj.rts_digitalinout, true);
+ // Let incoming bytes flow again.
+ common_hal_digitalio_digitalinout_set_value(common_hal_bleio_adapter_obj.rts_digitalinout, false);
+ }
+ // All done with this batch. Hold off receiving bytes until we're ready again.
+ ///common_hal_digitalio_digitalinout_set_value(common_hal_bleio_adapter_obj.rts_digitalinout, true);
hci_poll_in_progress = false;
return HCI_OK;
}
@@ -404,7 +472,7 @@ STATIC hci_result_t send_command(uint16_t opcode, uint8_t params_len, void* para
memcpy(cmd_pkt->params, params, params_len);
-#if DEBUG_HCI
+#if HCI_DEBUG
dump_cmd_pkt(true, sizeof(tx_buffer), tx_buffer);
#endif
@@ -419,12 +487,8 @@ STATIC hci_result_t send_command(uint16_t opcode, uint8_t params_len, void* para
// command responses.
uint64_t start = supervisor_ticks_ms64();
while (supervisor_ticks_ms64() - start < RESPONSE_TIMEOUT_MSECS) {
- result = hci_poll_for_incoming_pkt();
- if (result != HCI_OK) {
- // I/O error.
- return result;
- }
-
+ // RUN_BACKGROUND_TASKS includes hci_poll_for_incoming_pkt();
+ RUN_BACKGROUND_TASKS;
if (cmd_response_received && cmd_response_opcode == opcode) {
// If this is definitely a response to the command that was sent,
// return the status value, which will will be
@@ -432,20 +496,17 @@ STATIC hci_result_t send_command(uint16_t opcode, uint8_t params_len, void* para
// or a BT_HCI_ERR_x value (> 0x00) if there was a problem.
return cmd_response_status;
}
- RUN_BACKGROUND_TASKS;
}
// No I/O error, but no response sent back in time.
return HCI_RESPONSE_TIMEOUT;
}
-hci_result_t hci_send_acl_pkt(uint16_t handle, uint8_t cid, uint8_t data_len, uint8_t *data) {
- int result;
+hci_result_t hci_send_acl_pkt(uint16_t handle, uint8_t cid, uint16_t data_len, uint8_t *data) {
+ // Wait for all backlogged packets to finish.
while (pending_pkt >= common_hal_bleio_adapter_obj.max_acl_num_buffers) {
- result = hci_poll_for_incoming_pkt();
- if (result != HCI_OK) {
- return result;
- }
+ // RUN_BACKGROUND_TASKS includes hci_poll_for_incoming_pkt();
+ RUN_BACKGROUND_TASKS;
}
// buf_len is size of entire packet including header.
@@ -457,13 +518,14 @@ hci_result_t hci_send_acl_pkt(uint16_t handle, uint8_t cid, uint8_t data_len, ui
acl_pkt->pkt_type = H4_ACL;
acl_pkt->handle = handle;
acl_pkt->pb = ACL_DATA_PB_FIRST_FLUSH;
- acl_pkt->data_len = (uint8_t)(sizeof(acl_data_t) + data_len);
+ acl_pkt->bc = 0;
+ acl_pkt->data_len = (uint16_t)(sizeof(acl_data_t) + data_len);
acl_data->acl_data_len = data_len;
acl_data->cid = cid;
memcpy(&acl_data->acl_data, data, data_len);
-#if DEBUG_HCI
+#if HCI_DEBUG
dump_acl_pkt(true, buf_len, tx_buffer);
#endif
@@ -474,7 +536,6 @@ hci_result_t hci_send_acl_pkt(uint16_t handle, uint8_t cid, uint8_t data_len, ui
if (errcode) {
return HCI_WRITE_ERROR;
}
-
return HCI_OK;
}
@@ -738,3 +799,39 @@ hci_result_t hci_disconnect(uint16_t handle) {
return send_command(BT_HCI_OP_DISCONNECT, sizeof(params), &params);
}
+
+void hci_check_error(hci_result_t result) {
+ switch (result) {
+ case HCI_OK:
+ return;
+
+ case HCI_RESPONSE_TIMEOUT:
+ mp_raise_bleio_BluetoothError(translate("Timeout waiting for HCI response"));
+ return;
+
+ case HCI_WRITE_TIMEOUT:
+ mp_raise_bleio_BluetoothError(translate("Timeout waiting to write HCI request"));
+ return;
+
+ case HCI_READ_ERROR:
+ mp_raise_bleio_BluetoothError(translate("Error reading from HCI adapter"));
+ return;
+
+ case HCI_WRITE_ERROR:
+ mp_raise_bleio_BluetoothError(translate("Error writing to HCI adapter"));
+ return;
+
+ case HCI_ATT_ERROR:
+ mp_raise_RuntimeError(translate("Error in ATT protocol code"));
+ return;
+
+ default:
+ // Should be an HCI status error, > 0.
+ if (result > 0) {
+ mp_raise_bleio_BluetoothError(translate("HCI status error: %02x"), result);
+ } else {
+ mp_raise_bleio_BluetoothError(translate("Unknown hci_result_t: %d"), result);
+ }
+ return;
+ }
+}
diff --git a/devices/ble_hci/common-hal/_bleio/hci.h b/devices/ble_hci/common-hal/_bleio/hci.h
index 58aa71d3b..3d082c49c 100644
--- a/devices/ble_hci/common-hal/_bleio/hci.h
+++ b/devices/ble_hci/common-hal/_bleio/hci.h
@@ -38,7 +38,9 @@ typedef int hci_result_t;
#define HCI_WRITE_ERROR (-4)
#define HCI_ATT_ERROR (-5)
-void bleio_hci_reset(void);
+extern void bleio_hci_reset(void);
+
+void hci_check_error(hci_result_t result);
hci_result_t hci_disconnect(uint16_t handle);
@@ -72,7 +74,7 @@ hci_result_t hci_read_rssi(uint16_t handle, int *rssi);
hci_result_t hci_reset(void);
-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, uint16_t data_len, uint8_t *data);
hci_result_t hci_set_event_mask(uint64_t event_mask);
#endif // MICROPY_INCLUDED_DEVICES_BLE_HCI_COMMON_HAL_BLEIO_HCI_H
diff --git a/devices/ble_hci/common-hal/_bleio/hci_debug.c b/devices/ble_hci/common-hal/_bleio/hci_debug.c
index 8231bc5cc..9cdd38981 100644
--- a/devices/ble_hci/common-hal/_bleio/hci_debug.c
+++ b/devices/ble_hci/common-hal/_bleio/hci_debug.c
@@ -288,7 +288,7 @@ STATIC void dump_acl_pkt(bool tx, uint8_t pkt_len, uint8_t pkt_data[]) {
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, "att: %s (%02x), ", att_opcode_name(acl->acl_data[0]), acl->acl_data[0]);
}
mp_printf(&mp_plat_print,