Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F156712882
D21071.id60976.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
D21071.id60976.diff
View Options
Index: head/sys/conf/files
===================================================================
--- head/sys/conf/files
+++ head/sys/conf/files
@@ -4147,6 +4147,7 @@
netgraph/bluetooth/drivers/bt3c/ng_bt3c_pccard.c optional netgraph_bluetooth_bt3c
netgraph/bluetooth/drivers/h4/ng_h4.c optional netgraph_bluetooth_h4
netgraph/bluetooth/drivers/ubt/ng_ubt.c optional netgraph_bluetooth_ubt usb
+netgraph/bluetooth/drivers/ubt/ng_ubt_intel.c optional netgraph_bluetooth_ubt usb
netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c optional netgraph_bluetooth_ubtbcmfw usb
netgraph/bluetooth/hci/ng_hci_cmds.c optional netgraph_bluetooth_hci
netgraph/bluetooth/hci/ng_hci_evnt.c optional netgraph_bluetooth_hci
Index: head/sys/modules/netgraph/bluetooth/ubt/Makefile
===================================================================
--- head/sys/modules/netgraph/bluetooth/ubt/Makefile
+++ head/sys/modules/netgraph/bluetooth/ubt/Makefile
@@ -7,7 +7,7 @@
-I${SRCTOP}/sys/netgraph/bluetooth/drivers/ubt
KMOD= ng_ubt
-SRCS= ng_ubt.c opt_bus.h opt_usb.h device_if.h bus_if.h \
- usb_if.h usbdevs.h
+SRCS= ng_ubt.c ng_ubt_intel.c opt_bus.h opt_usb.h device_if.h \
+ bus_if.h usb_if.h usbdevs.h
.include <bsd.kmod.mk>
Index: head/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c
===================================================================
--- head/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c
+++ head/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c
@@ -252,6 +252,7 @@
****************************************************************************/
/* USB methods */
+static usb_callback_t ubt_probe_intr_callback;
static usb_callback_t ubt_ctrl_write_callback;
static usb_callback_t ubt_intr_read_callback;
static usb_callback_t ubt_bulk_read_callback;
@@ -421,6 +422,13 @@
/* Atheros AR5BBU12 with sflash firmware */
{ USB_VPI(0x0489, 0xe03c, 0), USB_DEV_BCD_LTEQ(1) },
{ USB_VPI(0x0489, 0xe036, 0), USB_DEV_BCD_LTEQ(1) },
+
+ /* Intel Wireless 8260 and successors are handled in ng_ubt_intel.c */
+ { USB_VPI(USB_VENDOR_INTEL2, 0x0a2b, 0) },
+ { USB_VPI(USB_VENDOR_INTEL2, 0x0aaa, 0) },
+ { USB_VPI(USB_VENDOR_INTEL2, 0x0025, 0) },
+ { USB_VPI(USB_VENDOR_INTEL2, 0x0026, 0) },
+ { USB_VPI(USB_VENDOR_INTEL2, 0x0029, 0) },
};
/* List of supported bluetooth devices */
@@ -503,6 +511,79 @@
};
/*
+ * Does a synchronous (waits for completion event) execution of HCI command.
+ * Size of both command and response buffers are passed in length field of
+ * corresponding structures in "Parameter Total Length" format i.e.
+ * not including HCI packet headers.
+ *
+ * Must not be used after USB transfers have been configured in attach routine.
+ */
+
+usb_error_t
+ubt_do_hci_request(struct usb_device *udev, struct ubt_hci_cmd *cmd,
+ void *evt, usb_timeout_t timeout)
+{
+ static const struct usb_config ubt_probe_config = {
+ .type = UE_INTERRUPT,
+ .endpoint = UE_ADDR_ANY,
+ .direction = UE_DIR_IN,
+ .flags = { .pipe_bof = 1, .short_xfer_ok = 1 },
+ .bufsize = UBT_INTR_BUFFER_SIZE,
+ .callback = &ubt_probe_intr_callback,
+ };
+ struct usb_device_request req;
+ struct usb_xfer *xfer[1];
+ struct mtx mtx;
+ usb_error_t error = USB_ERR_NORMAL_COMPLETION;
+ uint8_t iface_index = 0;
+
+ /* Initialize a USB control request and then do it */
+ bzero(&req, sizeof(req));
+ req.bmRequestType = UBT_HCI_REQUEST;
+ req.wIndex[0] = iface_index;
+ USETW(req.wLength, UBT_HCI_CMD_SIZE(cmd));
+
+ error = usbd_do_request(udev, NULL, &req, cmd);
+ if (error != USB_ERR_NORMAL_COMPLETION) {
+ printf("ng_ubt: usbd_do_request error=%s\n",
+ usbd_errstr(error));
+ return (error);
+ }
+
+ if (evt == NULL)
+ return (USB_ERR_NORMAL_COMPLETION);
+
+ /* Initialize INTR endpoint xfer and wait for response */
+ mtx_init(&mtx, "ubt pb", NULL, MTX_DEF);
+
+ error = usbd_transfer_setup(udev, &iface_index, xfer,
+ &ubt_probe_config, 1, evt, &mtx);
+ if (error == USB_ERR_NORMAL_COMPLETION) {
+
+ mtx_lock(&mtx);
+ usbd_transfer_start(*xfer);
+
+ if (msleep_sbt(evt, &mtx, 0, "ubt pb", SBT_1MS * timeout,
+ 0, C_HARDCLOCK) == EWOULDBLOCK) {
+ printf("ng_ubt: HCI command 0x%04x timed out\n",
+ le16toh(cmd->opcode));
+ error = USB_ERR_TIMEOUT;
+ }
+
+ usbd_transfer_stop(*xfer);
+ mtx_unlock(&mtx);
+
+ usbd_transfer_unsetup(xfer, 1);
+ } else
+ printf("ng_ubt: usbd_transfer_setup error=%s\n",
+ usbd_errstr(error));
+
+ mtx_destroy(&mtx);
+
+ return (error);
+}
+
+/*
* Probe for a USB Bluetooth device.
* USB context.
*/
@@ -717,6 +798,49 @@
return (0);
} /* ubt_detach */
+/*
+ * Called when incoming interrupt transfer (HCI event) has completed, i.e.
+ * HCI event was received from the device during device probe stage.
+ * USB context.
+ */
+
+static void
+ubt_probe_intr_callback(struct usb_xfer *xfer, usb_error_t error)
+{
+ struct ubt_hci_event *evt = usbd_xfer_softc(xfer);
+ struct usb_page_cache *pc;
+ int actlen;
+
+ usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
+
+ switch (USB_GET_STATE(xfer)) {
+ case USB_ST_TRANSFERRED:
+ if (actlen > UBT_HCI_EVENT_SIZE(evt))
+ actlen = UBT_HCI_EVENT_SIZE(evt);
+ pc = usbd_xfer_get_frame(xfer, 0);
+ usbd_copy_out(pc, 0, evt, actlen);
+ /* OneShot mode */
+ wakeup(evt);
+ break;
+
+ case USB_ST_SETUP:
+submit_next:
+ /* Try clear stall first */
+ usbd_xfer_set_stall(xfer);
+ usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
+ usbd_transfer_submit(xfer);
+ break;
+
+ default:
+ if (error != USB_ERR_CANCELLED) {
+ printf("ng_ubt: interrupt transfer failed: %s\n",
+ usbd_errstr(error));
+ goto submit_next;
+ }
+ break;
+ }
+} /* ubt_probe_intr_callback */
+
/*
* Called when outgoing control request (HCI command) has completed, i.e.
* HCI command was sent to the device.
@@ -1852,7 +1976,7 @@
return (error);
} /* ubt_modevent */
-static devclass_t ubt_devclass;
+devclass_t ubt_devclass;
static device_method_t ubt_methods[] =
{
@@ -1862,7 +1986,7 @@
DEVMETHOD_END
};
-static driver_t ubt_driver =
+driver_t ubt_driver =
{
.name = "ubt",
.methods = ubt_methods,
Index: head/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_intel.c
===================================================================
--- head/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_intel.c
+++ head/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_intel.c
@@ -0,0 +1,161 @@
+/*
+ * ng_ubt_intel.c
+ */
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2019 Vladimir Kondratyev <wulf@FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Attempt to initialize FreeBSD bluetooth stack while Intel Wireless 8260/8265
+ * device is in bootloader mode locks the adapter hardly so it requires power
+ * on/off cycle to restore. This driver blocks ng_ubt attachment until
+ * operational firmware is loaded by iwmbtfw utility thus avoiding the lock up.
+ */
+
+#include <sys/types.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/module.h>
+#include <sys/systm.h>
+#include <sys/taskqueue.h>
+
+#include "usbdevs.h"
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+
+#include <netgraph/ng_message.h>
+#include <netgraph/netgraph.h>
+#include <netgraph/ng_parse.h>
+#include <netgraph/bluetooth/include/ng_bluetooth.h>
+#include <netgraph/bluetooth/include/ng_hci.h>
+#include <netgraph/bluetooth/include/ng_ubt.h>
+#include <netgraph/bluetooth/drivers/ubt/ng_ubt_var.h>
+
+static device_probe_t ubt_intel_probe;
+
+/*
+ * List of supported bluetooth devices. If you add a new device PID here ensure
+ * that it is blacklisted in ng_ubt.c and is supported by iwmbtfw utility.
+ */
+
+static const STRUCT_USB_HOST_ID ubt_intel_devs[] =
+{
+ /* Intel Wireless 8260/8265 and successors */
+ { USB_VPI(USB_VENDOR_INTEL2, 0x0a2b, 0) },
+ { USB_VPI(USB_VENDOR_INTEL2, 0x0aaa, 0) },
+ { USB_VPI(USB_VENDOR_INTEL2, 0x0025, 0) },
+ { USB_VPI(USB_VENDOR_INTEL2, 0x0026, 0) },
+ { USB_VPI(USB_VENDOR_INTEL2, 0x0029, 0) },
+};
+
+/*
+ * Find if the Intel Wireless 8260/8265 device is in bootloader mode or is
+ * running operational firmware with checking of 4-th byte "Intel version"
+ * HCI command response. The value 0x23 identifies the operational firmware.
+ */
+
+static bool
+ubt_intel_check_firmware_state(struct usb_device *udev)
+{
+#define UBT_INTEL_VER_LEN 13
+#define UBT_INTEL_HCICMD_TIMEOUT 2000 /* ms */
+ struct ubt_hci_event_command_compl *evt;
+ uint8_t buf[offsetof(struct ubt_hci_event, data) + UBT_INTEL_VER_LEN];
+ static struct ubt_hci_cmd cmd = {
+ .opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_VENDOR, 0x05)),
+ .length = 0,
+ };
+ usb_error_t error;
+
+ bzero(buf, sizeof(buf));
+ evt = (struct ubt_hci_event_command_compl *)buf;
+ evt->header.length = UBT_INTEL_VER_LEN;
+
+ error = ubt_do_hci_request(udev, &cmd, evt, UBT_INTEL_HCICMD_TIMEOUT);
+ if (error != USB_ERR_NORMAL_COMPLETION)
+ return false;
+
+ return (evt->header.event == NG_HCI_EVENT_COMMAND_COMPL &&
+ evt->header.length == UBT_INTEL_VER_LEN &&
+ evt->data[4] == 0x23);
+}
+
+/*
+ * Probe for a Intel Wireless Bluetooth device.
+ */
+
+static int
+ubt_intel_probe(device_t dev)
+{
+ struct usb_attach_arg *uaa = device_get_ivars(dev);
+ int error;
+
+ if (uaa->usb_mode != USB_MODE_HOST)
+ return (ENXIO);
+
+ if (uaa->info.bIfaceIndex != 0)
+ return (ENXIO);
+
+ error = usbd_lookup_id_by_uaa(ubt_intel_devs, sizeof(ubt_intel_devs),
+ uaa);
+ if (error != 0)
+ return (error);
+
+ if (!ubt_intel_check_firmware_state(uaa->device))
+ return (ENXIO);
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+/*
+ * Module interface. Attach and detach methods, netgraph node type
+ * registration and PNP string are inherited from ng_ubt.c driver.
+ */
+
+static device_method_t ubt_intel_methods[] =
+{
+ DEVMETHOD(device_probe, ubt_intel_probe),
+ DEVMETHOD_END
+};
+
+static kobj_class_t ubt_baseclasses[] = { &ubt_driver, NULL };
+static driver_t ubt_intel_driver =
+{
+ .name = "ubt",
+ .methods = ubt_intel_methods,
+ .size = sizeof(struct ubt_softc),
+ .baseclasses = ubt_baseclasses,
+};
+
+DRIVER_MODULE(ng_ubt_intel, uhub, ubt_intel_driver, ubt_devclass, 0, 0);
+MODULE_VERSION(ng_ubt_intel, NG_BLUETOOTH_VERSION);
+MODULE_DEPEND(ng_ubt_intel, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION);
+MODULE_DEPEND(ng_ubt_intel, ng_hci, NG_BLUETOOTH_VERSION, NG_BLUETOOTH_VERSION, NG_BLUETOOTH_VERSION);
+MODULE_DEPEND(ng_ubt_intel, usb, 1, 1, 1);
Index: head/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_var.h
===================================================================
--- head/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_var.h
+++ head/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_var.h
@@ -74,6 +74,35 @@
UBT_N_TRANSFER, /* total number of transfers */
};
+/* USB control request (HCI command) structure */
+struct ubt_hci_cmd {
+ uint16_t opcode;
+ uint8_t length;
+ uint8_t data[];
+} __attribute__ ((packed));
+#define UBT_HCI_CMD_SIZE(cmd) \
+ ((cmd)->length + offsetof(struct ubt_hci_cmd, data))
+
+/* USB interrupt transfer HCI event header structure */
+struct ubt_hci_evhdr {
+ uint8_t event;
+ uint8_t length;
+} __attribute__ ((packed));
+/* USB interrupt transfer (generic HCI event) structure */
+struct ubt_hci_event {
+ struct ubt_hci_evhdr header;
+ uint8_t data[];
+} __attribute__ ((packed));
+/* USB interrupt transfer (HCI command completion event) structure */
+struct ubt_hci_event_command_compl {
+ struct ubt_hci_evhdr header;
+ uint8_t numpkt;
+ uint16_t opcode;
+ uint8_t data[];
+} __attribute__ ((packed));
+#define UBT_HCI_EVENT_SIZE(evt) \
+ ((evt)->header.length + offsetof(struct ubt_hci_event, data))
+
/* USB device softc structure */
struct ubt_softc {
device_t sc_dev; /* for debug printf */
@@ -128,6 +157,12 @@
};
typedef struct ubt_softc ubt_softc_t;
typedef struct ubt_softc * ubt_softc_p;
+
+usb_error_t ubt_do_hci_request(struct usb_device *, struct ubt_hci_cmd *,
+ void *, usb_timeout_t);
+
+extern devclass_t ubt_devclass;
+extern driver_t ubt_driver;
#endif /* ndef _NG_UBT_VAR_H_ */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, May 16, 8:32 PM (4 h, 44 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33151031
Default Alt Text
D21071.id60976.diff (12 KB)
Attached To
Mode
D21071: Firmware loader for Intel Wireless 8260 based Bluetooth USB devices
Attached
Detach File
Event Timeline
Log In to Comment