diff --git a/CHANGELOG.md b/CHANGELOG.md index bacd7c265..ca4f0e2bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - port/stm32-f4discovery-cc256x: add support for built-in MEMS microphone - libusb: add support for nRF52840-PCA10056 running Zephyr hci_usb example - port for Nucelo L073RZ with EM9304 DVK: stm32-l073rz-nucleo-em9304 +- hci_transport_h4: add workaround for flow control bug in CYW2070x, enable with ENABLE_CYPRESS_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND ## Changes February 2019 diff --git a/doc/manual/docs/how_to.md b/doc/manual/docs/how_to.md index e9a7ca545..4a2462163 100644 --- a/doc/manual/docs/how_to.md +++ b/doc/manual/docs/how_to.md @@ -90,6 +90,7 @@ ENABLE_ATT_DELAYED_RESPONSE | Enable support for delayed ATT operations, se ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE | Enable L2CAP Enhanced Retransmission Mode. Mandatory for AVRCP Browsing ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL | Enable HCI Controller to Host Flow Control, see below ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND | Enable workaround for bug in CC256x Flow Control during baud rate change, see chipset docs. +ENABLE_CYPRESS_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND | Enable workaround for bug in CYW2070x Flow Control during baud rate change, similar to CC256x. ENABLE_TLV_FLASH_EXPLICIT_DELETE_FIELD | Enable use of explicit delete field in TLV Flash implemenation - required when flash value cannot be overwritten with zero diff --git a/src/hci_transport_h4.c b/src/hci_transport_h4.c index cb64d3027..a7a34a224 100644 --- a/src/hci_transport_h4.c +++ b/src/hci_transport_h4.c @@ -147,9 +147,22 @@ static int read_pos; static uint8_t hci_packet_with_pre_buffer[HCI_INCOMING_PRE_BUFFER_SIZE + HCI_INCOMING_PACKET_BUFFER_SIZE + 1]; // packet type + max(acl header + acl payload, event header + event data) static uint8_t * hci_packet = &hci_packet_with_pre_buffer[HCI_INCOMING_PRE_BUFFER_SIZE]; +// Baudrate change bugs in TI CC256x and CYW20704 #ifdef ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND -static const uint8_t local_version_event_prefix[] = { 0x04, 0x0e, 0x0c, 0x01, 0x01, 0x10}; +#define ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND static const uint8_t baud_rate_command_prefix[] = { 0x01, 0x36, 0xff, 0x04}; +#endif + +#ifdef ENABLE_CYPRESS_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND +#ifdef ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND +#error "Please enable either ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND or ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND" +#endif +#define ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND +static const uint8_t baud_rate_command_prefix[] = { 0x01, 0x18, 0xfc, 0x06}; +#endif + +#ifdef ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND +static const uint8_t local_version_event_prefix[] = { 0x04, 0x0e, 0x0c, 0x01, 0x01, 0x10}; static enum { BAUDRATE_CHANGE_WORKAROUND_IDLE, BAUDRATE_CHANGE_WORKAROUND_CHIPSET_DETECTED, @@ -243,9 +256,10 @@ static void hci_transport_h4_block_read(void){ break; case H4_W4_PAYLOAD: -#ifdef ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND +#ifdef ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND if (baudrate_change_workaround_state == BAUDRATE_CHANGE_WORKAROUND_IDLE && memcmp(hci_packet, local_version_event_prefix, sizeof(local_version_event_prefix)) == 0){ +#ifdef ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND if (little_endian_read_16(hci_packet, 11) == BLUETOOTH_COMPANY_ID_TEXAS_INSTRUMENTS_INC){ // detect TI CC256x controller based on manufacturer log_info("Detected CC256x controller"); @@ -255,6 +269,18 @@ static void hci_transport_h4_block_read(void){ log_info("Bluetooth controller not by TI"); baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_DONE; } +#endif +#ifdef ENABLE_CYPRESS_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND + if (little_endian_read_16(hci_packet, 11) == BLUETOOTH_COMPANY_ID_CYPRESS_SEMICONDUCTOR){ + // detect Cypress controller based on manufacturer + log_info("Detected Cypress controller"); + baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_CHIPSET_DETECTED; + } else { + // work around not needed + log_info("Bluetooth controller not by Cypress"); + baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_DONE; + } +#endif } #endif packet_handler(hci_packet[0], &hci_packet[1], read_pos-1); @@ -264,7 +290,7 @@ static void hci_transport_h4_block_read(void){ break; } -#ifdef ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND +#ifdef ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND if (baudrate_change_workaround_state == BAUDRATE_CHANGE_WORKAROUND_BAUDRATE_COMMAND_SENT){ baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_IDLE; // avoid flowcontrol problem by reading expected hci command complete event of 7 bytes in a single block read @@ -316,7 +342,7 @@ static int hci_transport_h4_send_packet(uint8_t packet_type, uint8_t * packet, i packet--; *packet = packet_type; -#ifdef ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND +#ifdef ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND if ((baudrate_change_workaround_state == BAUDRATE_CHANGE_WORKAROUND_CHIPSET_DETECTED) && (memcmp(packet, baud_rate_command_prefix, sizeof(baud_rate_command_prefix)) == 0)) { log_info("Baud rate command detected, expect command complete event next");