git: aa0b938434a8 - main - iwmbtfw(8): Ignore unexpected HCI events
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 06 Nov 2024 23:31:55 UTC
The branch main has been updated by wulf: URL: https://cgit.FreeBSD.org/src/commit/?id=aa0b938434a8af8eebf8f2634914f2d9fe8a5dc4 commit aa0b938434a8af8eebf8f2634914f2d9fe8a5dc4 Author: Vladimir Kondratyev <wulf@FreeBSD.org> AuthorDate: 2024-11-06 23:27:48 +0000 Commit: Vladimir Kondratyev <wulf@FreeBSD.org> CommitDate: 2024-11-06 23:27:48 +0000 iwmbtfw(8): Ignore unexpected HCI events If Intel firmware is already in operational mode at boot that takes place at warm boot, BT adaptor can generate extra HCI events which interferes with firmware mode detection logic. Ignore them. Sponsored by: Future Crew LLC MFC after: 1 month Differential Revision: https://reviews.freebsd.org/D46737 --- usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.c | 58 +++++++++++++++++++++++++++-------- usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.h | 6 ++++ 2 files changed, 52 insertions(+), 12 deletions(-) diff --git a/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.c b/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.c index 05a851f9d85b..1efd24ecf9f6 100644 --- a/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.c +++ b/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.c @@ -37,10 +37,13 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <time.h> #include <unistd.h> #include <libusb.h> +#include <netgraph/bluetooth/include/ng_hci.h> + #include "iwmbt_fw.h" #include "iwmbt_hw.h" #include "iwmbt_dbg.h" @@ -95,6 +98,7 @@ static int iwmbt_hci_command(struct libusb_device_handle *hdl, struct iwmbt_hci_cmd *cmd, void *event, int size, int *transferred, int timeout) { + struct timespec to, now, remains; int ret; ret = libusb_control_transfer(hdl, @@ -112,18 +116,47 @@ iwmbt_hci_command(struct libusb_device_handle *hdl, struct iwmbt_hci_cmd *cmd, return (ret); } - ret = libusb_interrupt_transfer(hdl, - IWMBT_INTERRUPT_ENDPOINT_ADDR, - event, - size, - transferred, - timeout); + clock_gettime(CLOCK_MONOTONIC, &now); + to = IWMBT_MSEC2TS(timeout); + timespecadd(&to, &now, &to); - if (ret < 0) - iwmbt_err("libusb_interrupt_transfer() failed: err=%s", - libusb_strerror(ret)); + do { + timespecsub(&to, &now, &remains); + ret = libusb_interrupt_transfer(hdl, + IWMBT_INTERRUPT_ENDPOINT_ADDR, + event, + size, + transferred, + IWMBT_TS2MSEC(remains) + 1); - return (ret); + if (ret < 0) { + iwmbt_err("libusb_interrupt_transfer() failed: err=%s", + libusb_strerror(ret)); + return (ret); + } + + switch (((struct iwmbt_hci_event *)event)->header.event) { + case NG_HCI_EVENT_COMMAND_COMPL: + if (*transferred < + (int)offsetof(struct iwmbt_hci_event_cmd_compl, data)) + break; + if (cmd->opcode != + ((struct iwmbt_hci_event_cmd_compl *)event)->opcode) + break; + /* FALLTHROUGH */ + case 0xFF: + return (0); + default: + break; + } + iwmbt_debug("Stray HCI event: %x", + ((struct iwmbt_hci_event *)event)->header.event); + } while (timespeccmp(&to, &now, >)); + + iwmbt_err("libusb_interrupt_transfer() failed: err=%s", + libusb_strerror(LIBUSB_ERROR_TIMEOUT)); + + return (LIBUSB_ERROR_TIMEOUT); } int @@ -691,6 +724,7 @@ iwmbt_load_ddc(struct libusb_device_handle *hdl, int size, sent = 0; int ret, transferred; uint8_t buf[IWMBT_HCI_MAX_CMD_SIZE]; + uint8_t evt[IWMBT_HCI_MAX_CMD_SIZE]; struct iwmbt_hci_cmd *cmd = (struct iwmbt_hci_cmd *)buf; size = ddc->len; @@ -713,8 +747,8 @@ iwmbt_load_ddc(struct libusb_device_handle *hdl, ret = iwmbt_hci_command(hdl, cmd, - buf, - sizeof(buf), + evt, + sizeof(evt), &transferred, IWMBT_HCI_CMD_TIMEOUT); diff --git a/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.h b/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.h index 9467c3807a2a..89ee344fe587 100644 --- a/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.h +++ b/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.h @@ -72,6 +72,12 @@ struct iwmbt_hci_event_cmd_compl { #define IWMBT_HCI_MAX_CMD_SIZE 256 #define IWMBT_HCI_MAX_EVENT_SIZE 16 +#define IWMBT_MSEC2TS(msec) \ + (struct timespec) { \ + .tv_sec = (msec) / 1000, \ + .tv_nsec = ((msec) % 1000) * 1000000 \ + }; +#define IWMBT_TS2MSEC(ts) ((ts).tv_sec * 1000 + (ts).tv_nsec / 1000000) #define IWMBT_HCI_CMD_TIMEOUT 2000 /* ms */ #define IWMBT_LOADCMPL_TIMEOUT 5000 /* ms */