stm32/rfcore: Update to support WS=1.9.0.0.4.

This WS update to 1.9.0.0.4 broke the workaround used in rfcore for
OCF_CB_SET_EVENT_MASK2, so fix it to support WS 1.8 and 1.9.
bound-method-equality
Jim Mussared 2020-10-09 16:51:47 +11:00 committed by Damien George
parent 222ec1a4a8
commit fa12bfc227
1 changed files with 32 additions and 13 deletions

View File

@ -66,6 +66,7 @@
#define HCI_KIND_VENDOR_EVENT (0x12) #define HCI_KIND_VENDOR_EVENT (0x12)
#define HCI_EVENT_COMMAND_COMPLETE (0x0E) // <num packets><opcode 16><status><data...> #define HCI_EVENT_COMMAND_COMPLETE (0x0E) // <num packets><opcode 16><status><data...>
#define HCI_EVENT_COMMAND_STATUS (0x0F) // <status><num_packets><opcode 16>
// There can be quite long delays during firmware update. // There can be quite long delays during firmware update.
#define SYS_ACK_TIMEOUT_MS (1000) #define SYS_ACK_TIMEOUT_MS (1000)
@ -275,9 +276,19 @@ void ipcc_init(uint32_t irq_pri) {
/******************************************************************************/ /******************************************************************************/
// Transport layer HCI interface // Transport layer HCI interface
// The WS firmware doesn't support OCF_CB_SET_EVENT_MASK2, and fails with:
// v1.8.0.0.4 (and below): HCI_EVENT_COMMAND_COMPLETE with a non-zero status
// v1.9.0.0.4 (and above): HCI_EVENT_COMMAND_STATUS with a non-zero status
// In either case we detect the failure response and inject this response
// instead (which is HCI_EVENT_COMMAND_COMPLETE for OCF_CB_SET_EVENT_MASK2
// with status=0).
STATIC const uint8_t set_event_event_mask2_fix_payload[] = { 0x04, 0x0e, 0x04, 0x01, 0x63, 0x0c, 0x00 };
STATIC size_t tl_parse_hci_msg(const uint8_t *buf, parse_hci_info_t *parse) { STATIC size_t tl_parse_hci_msg(const uint8_t *buf, parse_hci_info_t *parse) {
const char *info; const char *info;
bool applied_set_event_event_mask2_fix = false; #if HCI_TRACE
int applied_set_event_event_mask2_fix = 0;
#endif
size_t len; size_t len;
switch (buf[0]) { switch (buf[0]) {
case HCI_KIND_BT_ACL: { case HCI_KIND_BT_ACL: {
@ -300,10 +311,12 @@ STATIC size_t tl_parse_hci_msg(const uint8_t *buf, parse_hci_info_t *parse) {
uint8_t status = buf[6]; uint8_t status = buf[6];
if (opcode == HCI_OPCODE(OGF_CTLR_BASEBAND, OCF_CB_SET_EVENT_MASK2) && status != 0) { if (opcode == HCI_OPCODE(OGF_CTLR_BASEBAND, OCF_CB_SET_EVENT_MASK2) && status != 0) {
// The WB doesn't support this command (despite being in CS 4.1), so pretend like // For WS firmware v1.8.0.0.4 and below. Reply with the "everything OK" payload.
// it succeeded by replacing the final byte (status) with a zero. parse->cb_fun(parse->cb_env, set_event_event_mask2_fix_payload, sizeof(set_event_event_mask2_fix_payload));
applied_set_event_event_mask2_fix = true; #if HCI_TRACE
len -= 1; applied_set_event_event_mask2_fix = 18;
#endif
break; // Don't send the original payload.
} }
if (opcode == HCI_OPCODE(OGF_CTLR_BASEBAND, OCF_CB_RESET) && status == 0) { if (opcode == HCI_OPCODE(OGF_CTLR_BASEBAND, OCF_CB_RESET) && status == 0) {
@ -313,15 +326,21 @@ STATIC size_t tl_parse_hci_msg(const uint8_t *buf, parse_hci_info_t *parse) {
} }
} }
parse->cb_fun(parse->cb_env, buf, len); if (buf[1] == HCI_EVENT_COMMAND_STATUS && len == 7) {
uint16_t opcode = (buf[6] << 8) | buf[5];
uint8_t status = buf[3];
if (applied_set_event_event_mask2_fix) { if (opcode == HCI_OPCODE(OGF_CTLR_BASEBAND, OCF_CB_SET_EVENT_MASK2) && status != 0) {
// Inject the zero status. // For WS firmware v1.9.0.0.4 and higher. Reply with the "everything OK" payload.
uint8_t data = 0; parse->cb_fun(parse->cb_env, set_event_event_mask2_fix_payload, sizeof(set_event_event_mask2_fix_payload));
parse->cb_fun(parse->cb_env, &data, 1); #if HCI_TRACE
// Restore the length for the HCI tracing below. applied_set_event_event_mask2_fix = 19;
len += 1; #endif
break; // Don't send the original payload.
}
} }
parse->cb_fun(parse->cb_env, buf, len);
} }
break; break;
} }
@ -356,7 +375,7 @@ STATIC size_t tl_parse_hci_msg(const uint8_t *buf, parse_hci_info_t *parse) {
printf(" (reset)"); printf(" (reset)");
} }
if (applied_set_event_event_mask2_fix) { if (applied_set_event_event_mask2_fix) {
printf(" (mask2 fix)"); printf(" (mask2 fix %d)", applied_set_event_event_mask2_fix);
} }
printf("\n"); printf("\n");