diff options
| author | Dan Halbert <halbert@halwitz.org> | 2020-08-20 20:29:57 -0400 |
|---|---|---|
| committer | Dan Halbert <halbert@halwitz.org> | 2020-08-20 20:29:57 -0400 |
| commit | 0e30dd8bccdbb4469e1bb54443f5d2fca66f7ff6 (patch) | |
| tree | 734b3c975287d2f922c1c6ca3bf7f3dc153d59d8 /devices/ble_hci | |
| parent | dfe50d08d573f2bf49a77e22de1843eb8db4b855 (diff) | |
| parent | 837abd6da072a55f3c46d62b013690a12e0ee262 (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.c | 33 | ||||
| -rw-r--r-- | devices/ble_hci/common-hal/_bleio/__init__.c | 37 | ||||
| -rw-r--r-- | devices/ble_hci/common-hal/_bleio/__init__.h | 6 | ||||
| -rw-r--r-- | devices/ble_hci/common-hal/_bleio/att.c | 61 | ||||
| -rw-r--r-- | devices/ble_hci/common-hal/_bleio/hci.c | 217 | ||||
| -rw-r--r-- | devices/ble_hci/common-hal/_bleio/hci.h | 6 | ||||
| -rw-r--r-- | devices/ble_hci/common-hal/_bleio/hci_debug.c | 2 |
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), ¶ms); } + +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, |
