diff --git a/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_rtl.c b/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_rtl.c index b9fbc1c12a29..c3fb98b46e6a 100644 --- a/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_rtl.c +++ b/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_rtl.c @@ -1,265 +1,266 @@ /* * ng_ubt_rtl.c */ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2019 Vladimir Kondratyev * Copyright (c) 2023 Future Crew LLC. * * 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. */ /* * Attempt to initialize FreeBSD bluetooth stack while Realtek 87XX/88XX USB * 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 rtlbtfw utility thus avoiding the lock up. */ #include #include #include #include #include #include #include #include "usbdevs.h" #include #include #define USB_DEBUG_VAR usb_debug #include #include #include #include #include #include #include #include static device_probe_t ubt_rtl_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 rtlbtfw utility. */ const STRUCT_USB_HOST_ID ubt_rtl_devs[] = { /* Generic Realtek Bluetooth class devices */ { USB_VENDOR(USB_VENDOR_REALTEK), USB_IFACE_CLASS(UDCLASS_WIRELESS), USB_IFACE_SUBCLASS(UDSUBCLASS_RF), USB_IFACE_PROTOCOL(UDPROTO_BLUETOOTH) }, /* Realtek 8821CE Bluetooth devices */ { USB_VPI(0x13d3, 0x3529, 0) }, /* Realtek 8822CE Bluetooth devices */ { USB_VPI(0x0bda, 0xb00c, 0) }, { USB_VPI(0x0bda, 0xc822, 0) }, /* Realtek 8822CU Bluetooth devices */ { USB_VPI(0x13d3, 0x3549, 0) }, /* Realtek 8852AE Bluetooth devices */ { USB_VPI(0x0bda, 0x2852, 0) }, { USB_VPI(0x0bda, 0xc852, 0) }, { USB_VPI(0x0bda, 0x385a, 0) }, { USB_VPI(0x0bda, 0x4852, 0) }, { USB_VPI(0x04c5, 0x165c, 0) }, { USB_VPI(0x04ca, 0x4006, 0) }, { USB_VPI(0x0cb8, 0xc549, 0) }, /* Realtek 8852CE Bluetooth devices */ { USB_VPI(0x04ca, 0x4007, 0) }, { USB_VPI(0x04c5, 0x1675, 0) }, { USB_VPI(0x0cb8, 0xc558, 0) }, { USB_VPI(0x13d3, 0x3587, 0) }, { USB_VPI(0x13d3, 0x3586, 0) }, { USB_VPI(0x13d3, 0x3592, 0) }, /* Realtek 8852BE Bluetooth devices */ { USB_VPI(0x0cb8, 0xc559, 0) }, { USB_VPI(0x0bda, 0x887b, 0) }, { USB_VPI(0x13d3, 0x3571, 0) }, /* Realtek 8723AE Bluetooth devices */ { USB_VPI(0x0930, 0x021d, 0) }, { USB_VPI(0x13d3, 0x3394, 0) }, /* Realtek 8723BE Bluetooth devices */ { USB_VPI(0x0489, 0xe085, 0) }, { USB_VPI(0x0489, 0xe08b, 0) }, { USB_VPI(0x04f2, 0xb49f, 0) }, { USB_VPI(0x13d3, 0x3410, 0) }, { USB_VPI(0x13d3, 0x3416, 0) }, { USB_VPI(0x13d3, 0x3459, 0) }, { USB_VPI(0x13d3, 0x3494, 0) }, /* Realtek 8723BU Bluetooth devices */ { USB_VPI(0x7392, 0xa611, 0) }, /* Realtek 8723DE Bluetooth devices */ { USB_VPI(0x0bda, 0xb009, 0) }, { USB_VPI(0x2ff8, 0xb011, 0) }, /* Realtek 8761BUV Bluetooth devices */ + { USB_VPI(0x2c4e, 0x0115, 0) }, { USB_VPI(0x2357, 0x0604, 0) }, { USB_VPI(0x0b05, 0x190e, 0) }, { USB_VPI(0x2550, 0x8761, 0) }, { USB_VPI(0x0bda, 0x8771, 0) }, { USB_VPI(0x6655, 0x8771, 0) }, { USB_VPI(0x7392, 0xc611, 0) }, { USB_VPI(0x2b89, 0x8761, 0) }, /* Realtek 8821AE Bluetooth devices */ { USB_VPI(0x0b05, 0x17dc, 0) }, { USB_VPI(0x13d3, 0x3414, 0) }, { USB_VPI(0x13d3, 0x3458, 0) }, { USB_VPI(0x13d3, 0x3461, 0) }, { USB_VPI(0x13d3, 0x3462, 0) }, /* Realtek 8822BE Bluetooth devices */ { USB_VPI(0x13d3, 0x3526, 0) }, { USB_VPI(0x0b05, 0x185c, 0) }, /* Realtek 8822CE Bluetooth devices */ { USB_VPI(0x04ca, 0x4005, 0) }, { USB_VPI(0x04c5, 0x161f, 0) }, { USB_VPI(0x0b05, 0x18ef, 0) }, { USB_VPI(0x13d3, 0x3548, 0) }, { USB_VPI(0x13d3, 0x3549, 0) }, { USB_VPI(0x13d3, 0x3553, 0) }, { USB_VPI(0x13d3, 0x3555, 0) }, { USB_VPI(0x2ff8, 0x3051, 0) }, { USB_VPI(0x1358, 0xc123, 0) }, { USB_VPI(0x0bda, 0xc123, 0) }, { USB_VPI(0x0cb5, 0xc547, 0) }, }; const size_t ubt_rtl_devs_sizeof = sizeof(ubt_rtl_devs); /* * List of lmp_subversion values that correspond to Realtek firmwares * incompatible with ng_ubt driver. Alternative firmware for these devices * has to be loaded with rtlbtfw utility. That will trigger lmp_subversion * change to different value. */ static const uint16_t ubt_rtl_lmp_subvers[] = { 0x8703, 0x1200, 0x8723, 0x8821, 0x8761, 0x8822, 0x8852, 0x8851, }; /* * Execute generic HCI command and return response in provided buffer. */ static usb_error_t ubt_rtl_do_hci_request(struct usb_device *udev, uint16_t opcode, void *resp, uint8_t resp_len) { #define UBT_RTL_HCICMD_TIMEOUT 2000 /* ms */ struct ubt_hci_event_command_compl *evt; struct ubt_hci_cmd cmd; usb_error_t error; memset(&cmd, 0, sizeof(cmd)); cmd.opcode = htole16(opcode); evt = malloc(offsetof(struct ubt_hci_event_command_compl, data) + resp_len, M_TEMP, M_ZERO | M_WAITOK); evt->header.event = NG_HCI_EVENT_COMMAND_COMPL; evt->header.length = resp_len + UBT_HCI_EVENT_COMPL_HEAD_SIZE; error = ubt_do_hci_request(udev, &cmd, evt, UBT_RTL_HCICMD_TIMEOUT); if (error != USB_ERR_NORMAL_COMPLETION) goto exit; if (evt->header.event == NG_HCI_EVENT_COMMAND_COMPL && evt->header.length == resp_len + UBT_HCI_EVENT_COMPL_HEAD_SIZE) memcpy(resp, evt->data, resp_len); else error = USB_ERR_INVAL; exit: free(evt, M_TEMP); return (error); } /* * Probe for a Realtek 87XX/88XX USB Bluetooth device. */ static int ubt_rtl_probe(device_t dev) { struct usb_attach_arg *uaa = device_get_ivars(dev); ng_hci_read_local_ver_rp ver; unsigned int i; 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_rtl_devs, sizeof(ubt_rtl_devs), uaa); if (error != 0) return (error); if (ubt_rtl_do_hci_request(uaa->device, NG_HCI_OPCODE(NG_HCI_OGF_INFO, NG_HCI_OCF_READ_LOCAL_VER), &ver, sizeof(ver)) != USB_ERR_NORMAL_COMPLETION) return (ENXIO); DPRINTFN(2, "hci_version 0x%02x\n", ver.hci_version); DPRINTFN(2, "hci_revision 0x%04x\n", le16toh(ver.hci_revision)); DPRINTFN(2, "lmp_version 0x%02x\n", ver.lmp_version); DPRINTFN(2, "lmp_subversion 0x%04x\n", le16toh(ver.lmp_subversion)); for (i = 0; i < nitems(ubt_rtl_lmp_subvers); i++) if (le16toh(ver.lmp_subversion) == ubt_rtl_lmp_subvers[i]) 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_rtl_methods[] = { DEVMETHOD(device_probe, ubt_rtl_probe), DEVMETHOD_END }; DEFINE_CLASS_1(ubt, ubt_rtl_driver, ubt_rtl_methods, sizeof(struct ubt_softc), ubt_driver); DRIVER_MODULE(ng_ubt_rtl, uhub, ubt_rtl_driver, 0, 0); MODULE_VERSION(ng_ubt_rtl, NG_BLUETOOTH_VERSION); MODULE_DEPEND(ng_ubt_rtl, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION); MODULE_DEPEND(ng_ubt_rtl, ng_hci, NG_BLUETOOTH_VERSION, NG_BLUETOOTH_VERSION, NG_BLUETOOTH_VERSION); MODULE_DEPEND(ng_ubt_rtl, usb, 1, 1, 1); diff --git a/usr.sbin/bluetooth/rtlbtfw/main.c b/usr.sbin/bluetooth/rtlbtfw/main.c index 029c04f98b26..e0445726c3a2 100644 --- a/usr.sbin/bluetooth/rtlbtfw/main.c +++ b/usr.sbin/bluetooth/rtlbtfw/main.c @@ -1,525 +1,526 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2013 Adrian Chadd * Copyright (c) 2019 Vladimir Kondratyev * Copyright (c) 2023 Future Crew LLC. * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "rtlbt_fw.h" #include "rtlbt_hw.h" #include "rtlbt_dbg.h" #define _DEFAULT_RTLBT_FIRMWARE_PATH "/usr/share/firmware/rtlbt" int rtlbt_do_debug = 0; int rtlbt_do_info = 0; struct rtlbt_devid { uint16_t product_id; uint16_t vendor_id; }; static struct rtlbt_devid rtlbt_list[] = { /* Realtek 8821CE Bluetooth devices */ { .vendor_id = 0x13d3, .product_id = 0x3529 }, /* Realtek 8822CE Bluetooth devices */ { .vendor_id = 0x0bda, .product_id = 0xb00c }, { .vendor_id = 0x0bda, .product_id = 0xc822 }, /* Realtek 8822CU Bluetooth devices */ { .vendor_id = 0x13d3, .product_id = 0x3549 }, /* Realtek 8852AE Bluetooth devices */ { .vendor_id = 0x0bda, .product_id = 0x2852 }, { .vendor_id = 0x0bda, .product_id = 0xc852 }, { .vendor_id = 0x0bda, .product_id = 0x385a }, { .vendor_id = 0x0bda, .product_id = 0x4852 }, { .vendor_id = 0x04c5, .product_id = 0x165c }, { .vendor_id = 0x04ca, .product_id = 0x4006 }, { .vendor_id = 0x0cb8, .product_id = 0xc549 }, #ifdef RTLBTFW_SUPPORTS_FW_V2 /* Realtek 8852CE Bluetooth devices */ { .vendor_id = 0x04ca, .product_id = 0x4007 }, { .vendor_id = 0x04c5, .product_id = 0x1675 }, { .vendor_id = 0x0cb8, .product_id = 0xc558 }, { .vendor_id = 0x13d3, .product_id = 0x3587 }, { .vendor_id = 0x13d3, .product_id = 0x3586 }, { .vendor_id = 0x13d3, .product_id = 0x3592 }, #endif /* Realtek 8852BE Bluetooth devices */ { .vendor_id = 0x0cb8, .product_id = 0xc559 }, { .vendor_id = 0x0bda, .product_id = 0x887b }, { .vendor_id = 0x13d3, .product_id = 0x3571 }, /* Realtek 8723AE Bluetooth devices */ { .vendor_id = 0x0930, .product_id = 0x021d }, { .vendor_id = 0x13d3, .product_id = 0x3394 }, /* Realtek 8723BE Bluetooth devices */ { .vendor_id = 0x0489, .product_id = 0xe085 }, { .vendor_id = 0x0489, .product_id = 0xe08b }, { .vendor_id = 0x04f2, .product_id = 0xb49f }, { .vendor_id = 0x13d3, .product_id = 0x3410 }, { .vendor_id = 0x13d3, .product_id = 0x3416 }, { .vendor_id = 0x13d3, .product_id = 0x3459 }, { .vendor_id = 0x13d3, .product_id = 0x3494 }, /* Realtek 8723BU Bluetooth devices */ { .vendor_id = 0x7392, .product_id = 0xa611 }, /* Realtek 8723DE Bluetooth devices */ { .vendor_id = 0x0bda, .product_id = 0xb009 }, { .vendor_id = 0x2ff8, .product_id = 0xb011 }, /* Realtek 8761BUV Bluetooth devices */ + { .vendor_id = 0x2c4e, .product_id = 0x0115 }, { .vendor_id = 0x2357, .product_id = 0x0604 }, { .vendor_id = 0x0b05, .product_id = 0x190e }, { .vendor_id = 0x2550, .product_id = 0x8761 }, { .vendor_id = 0x0bda, .product_id = 0x8771 }, { .vendor_id = 0x6655, .product_id = 0x8771 }, { .vendor_id = 0x7392, .product_id = 0xc611 }, { .vendor_id = 0x2b89, .product_id = 0x8761 }, /* Realtek 8821AE Bluetooth devices */ { .vendor_id = 0x0b05, .product_id = 0x17dc }, { .vendor_id = 0x13d3, .product_id = 0x3414 }, { .vendor_id = 0x13d3, .product_id = 0x3458 }, { .vendor_id = 0x13d3, .product_id = 0x3461 }, { .vendor_id = 0x13d3, .product_id = 0x3462 }, /* Realtek 8822BE Bluetooth devices */ { .vendor_id = 0x13d3, .product_id = 0x3526 }, { .vendor_id = 0x0b05, .product_id = 0x185c }, /* Realtek 8822CE Bluetooth devices */ { .vendor_id = 0x04ca, .product_id = 0x4005 }, { .vendor_id = 0x04c5, .product_id = 0x161f }, { .vendor_id = 0x0b05, .product_id = 0x18ef }, { .vendor_id = 0x13d3, .product_id = 0x3548 }, { .vendor_id = 0x13d3, .product_id = 0x3549 }, { .vendor_id = 0x13d3, .product_id = 0x3553 }, { .vendor_id = 0x13d3, .product_id = 0x3555 }, { .vendor_id = 0x2ff8, .product_id = 0x3051 }, { .vendor_id = 0x1358, .product_id = 0xc123 }, { .vendor_id = 0x0bda, .product_id = 0xc123 }, { .vendor_id = 0x0cb5, .product_id = 0xc547 }, }; static int rtlbt_is_realtek(struct libusb_device_descriptor *d) { int i; /* Search looking for whether it's a Realtek-based device */ for (i = 0; i < (int) nitems(rtlbt_list); i++) { if ((rtlbt_list[i].product_id == d->idProduct) && (rtlbt_list[i].vendor_id == d->idVendor)) { rtlbt_info("found USB Realtek"); return (1); } } /* Not found */ return (0); } static int rtlbt_is_bluetooth(struct libusb_device *dev) { struct libusb_config_descriptor *cfg; const struct libusb_interface *ifc; const struct libusb_interface_descriptor *d; int r; r = libusb_get_active_config_descriptor(dev, &cfg); if (r < 0) { rtlbt_err("Cannot retrieve config descriptor: %s", libusb_error_name(r)); return (0); } if (cfg->bNumInterfaces != 0) { /* Only 0-th HCI/ACL interface is supported by downloader */ ifc = &cfg->interface[0]; if (ifc->num_altsetting != 0) { /* BT HCI/ACL interface has no altsettings */ d = &ifc->altsetting[0]; /* Check if interface is a bluetooth */ if (d->bInterfaceClass == LIBUSB_CLASS_WIRELESS && d->bInterfaceSubClass == 0x01 && d->bInterfaceProtocol == 0x01) { rtlbt_info("found USB Realtek"); libusb_free_config_descriptor(cfg); return (1); } } } libusb_free_config_descriptor(cfg); /* Not found */ return (0); } static libusb_device * rtlbt_find_device(libusb_context *ctx, int bus_id, int dev_id) { libusb_device **list, *dev = NULL, *found = NULL; struct libusb_device_descriptor d; ssize_t cnt, i; int r; cnt = libusb_get_device_list(ctx, &list); if (cnt < 0) { rtlbt_err("libusb_get_device_list() failed: code %lld", (long long int) cnt); return (NULL); } /* * Scan through USB device list. */ for (i = 0; i < cnt; i++) { dev = list[i]; if (bus_id == libusb_get_bus_number(dev) && dev_id == libusb_get_device_address(dev)) { /* Get the device descriptor for this device entry */ r = libusb_get_device_descriptor(dev, &d); if (r != 0) { rtlbt_err("libusb_get_device_descriptor: %s", libusb_strerror(r)); break; } /* For non-Realtek match on the vendor/product id */ if (rtlbt_is_realtek(&d)) { /* * Take a reference so it's not freed later on. */ found = libusb_ref_device(dev); break; } /* For Realtek vendor match on the interface class */ if (d.idVendor == 0x0bda && rtlbt_is_bluetooth(dev)) { /* * Take a reference so it's not freed later on. */ found = libusb_ref_device(dev); break; } } } libusb_free_device_list(list, 1); return (found); } static void rtlbt_dump_version(ng_hci_read_local_ver_rp *ver) { rtlbt_info("hci_version 0x%02x", ver->hci_version); rtlbt_info("hci_revision 0x%04x", le16toh(ver->hci_revision)); rtlbt_info("lmp_version 0x%02x", ver->lmp_version); rtlbt_info("lmp_subversion 0x%04x", le16toh(ver->lmp_subversion)); } /* * Parse ugen name and extract device's bus and address */ static int parse_ugen_name(char const *ugen, uint8_t *bus, uint8_t *addr) { char *ep; if (strncmp(ugen, "ugen", 4) != 0) return (-1); *bus = (uint8_t) strtoul(ugen + 4, &ep, 10); if (*ep != '.') return (-1); *addr = (uint8_t) strtoul(ep + 1, &ep, 10); if (*ep != '\0') return (-1); return (0); } static void usage(void) { fprintf(stderr, "Usage: rtlbtfw (-D) -d ugenX.Y (-f firmware path) (-I)\n"); fprintf(stderr, " -D: enable debugging\n"); fprintf(stderr, " -d: device to operate upon\n"); fprintf(stderr, " -f: firmware path, if not default\n"); fprintf(stderr, " -I: enable informational output\n"); exit(127); } int main(int argc, char *argv[]) { libusb_context *ctx = NULL; libusb_device *dev = NULL; libusb_device_handle *hdl = NULL; ng_hci_read_local_ver_rp ver; int r; uint8_t bus_id = 0, dev_id = 0; int devid_set = 0; int n; char *firmware_dir = NULL; char *firmware_path = NULL; char *config_path = NULL; int retcode = 1; const struct rtlbt_id_table *ic; uint8_t rom_version; struct rtlbt_firmware fw, cfg; enum rtlbt_fw_type fw_type; uint16_t fw_lmp_subversion; /* Parse command line arguments */ while ((n = getopt(argc, argv, "Dd:f:hIm:p:v:")) != -1) { switch (n) { case 'd': /* ugen device name */ devid_set = 1; if (parse_ugen_name(optarg, &bus_id, &dev_id) < 0) usage(); break; case 'D': rtlbt_do_debug = 1; break; case 'f': /* firmware dir */ if (firmware_dir) free(firmware_dir); firmware_dir = strdup(optarg); break; case 'I': rtlbt_do_info = 1; break; case 'h': default: usage(); break; /* NOT REACHED */ } } /* Ensure the devid was given! */ if (devid_set == 0) { usage(); /* NOTREACHED */ } /* libusb setup */ r = libusb_init(&ctx); if (r != 0) { rtlbt_err("libusb_init failed: code %d", r); exit(127); } rtlbt_debug("opening dev %d.%d", (int) bus_id, (int) dev_id); /* Find a device based on the bus/dev id */ dev = rtlbt_find_device(ctx, bus_id, dev_id); if (dev == NULL) { rtlbt_err("device not found"); goto shutdown; } /* XXX enforce that bInterfaceNumber is 0 */ /* XXX enforce the device/product id if they're non-zero */ /* Grab device handle */ r = libusb_open(dev, &hdl); if (r != 0) { rtlbt_err("libusb_open() failed: code %d", r); goto shutdown; } /* Check if ng_ubt is attached */ r = libusb_kernel_driver_active(hdl, 0); if (r < 0) { rtlbt_err("libusb_kernel_driver_active() failed: code %d", r); goto shutdown; } if (r > 0) { rtlbt_info("Firmware has already been downloaded"); retcode = 0; goto shutdown; } /* Get local version */ r = rtlbt_read_local_ver(hdl, &ver); if (r < 0) { rtlbt_err("rtlbt_read_local_ver() failed code %d", r); goto shutdown; } rtlbt_dump_version(&ver); ic = rtlbt_get_ic(ver.lmp_subversion, ver.hci_revision, ver.hci_version); if (ic == NULL) { rtlbt_err("rtlbt_get_ic() failed: Unknown IC"); goto shutdown; } /* Default the firmware path */ if (firmware_dir == NULL) firmware_dir = strdup(_DEFAULT_RTLBT_FIRMWARE_PATH); firmware_path = rtlbt_get_fwname(ic->fw_name, firmware_dir, "_fw.bin"); if (firmware_path == NULL) goto shutdown; rtlbt_debug("firmware_path = %s", firmware_path); rtlbt_info("loading firmware %s", firmware_path); /* Read in the firmware */ if (rtlbt_fw_read(&fw, firmware_path) <= 0) { rtlbt_debug("rtlbt_fw_read() failed"); return (-1); } fw_type = rtlbt_get_fw_type(&fw, &fw_lmp_subversion); if (fw_type == RTLBT_FW_TYPE_UNKNOWN && (ic->flags & RTLBT_IC_FLAG_SIMPLE) == 0) { rtlbt_debug("Unknown firmware type"); goto shutdown; } if (fw_type != RTLBT_FW_TYPE_UNKNOWN) { /* Match hardware and firmware lmp_subversion */ if (fw_lmp_subversion != ver.lmp_subversion) { rtlbt_err("firmware is for %x but this is a %x", fw_lmp_subversion, ver.lmp_subversion); goto shutdown; } /* Query a ROM version */ r = rtlbt_read_rom_ver(hdl, &rom_version); if (r < 0) { rtlbt_err("rtlbt_read_rom_ver() failed code %d", r); goto shutdown; } rtlbt_debug("rom_version = %d", rom_version); /* Load in the firmware */ r = rtlbt_parse_fwfile_v1(&fw, rom_version); if (r < 0) { rtlbt_err("Parseing firmware file failed"); goto shutdown; } config_path = rtlbt_get_fwname(ic->fw_name, firmware_dir, "_config.bin"); if (config_path == NULL) goto shutdown; rtlbt_info("loading config %s", config_path); /* Read in the config file */ if (rtlbt_fw_read(&cfg, config_path) <= 0) { rtlbt_err("rtlbt_fw_read() failed"); if ((ic->flags & RTLBT_IC_FLAG_CONFIG) != 0) goto shutdown; } else { r = rtlbt_append_fwfile(&fw, &cfg); rtlbt_fw_free(&cfg); if (r < 0) { rtlbt_err("Appending config file failed"); goto shutdown; } } } r = rtlbt_load_fwfile(hdl, &fw); if (r < 0) { rtlbt_debug("Loading firmware file failed"); goto shutdown; } /* free it */ rtlbt_fw_free(&fw); rtlbt_info("Firmware download complete"); /* Execute Read Local Version one more time */ r = rtlbt_read_local_ver(hdl, &ver); if (r < 0) { rtlbt_err("rtlbt_read_local_ver() failed code %d", r); goto shutdown; } rtlbt_dump_version(&ver); retcode = 0; /* Ask kernel driver to probe and attach device again */ r = libusb_reset_device(hdl); if (r != 0) rtlbt_err("libusb_reset_device() failed: %s", libusb_strerror(r)); shutdown: /* Shutdown */ if (hdl != NULL) libusb_close(hdl); if (dev != NULL) libusb_unref_device(dev); if (ctx != NULL) libusb_exit(ctx); if (retcode == 0) rtlbt_info("Firmware download is successful!"); else rtlbt_err("Firmware download failed!"); return (retcode); } diff --git a/usr.sbin/bluetooth/rtlbtfw/rtlbtfw.conf b/usr.sbin/bluetooth/rtlbtfw/rtlbtfw.conf index d544913aaa12..d45ba0bd92c4 100644 --- a/usr.sbin/bluetooth/rtlbtfw/rtlbtfw.conf +++ b/usr.sbin/bluetooth/rtlbtfw/rtlbtfw.conf @@ -1,373 +1,381 @@ # # Download Realtek 87XX/88XX bluetooth adaptor firmware # # Generic Realtek vendor Bluetooth devices notify 100 { match "system" "USB"; match "subsystem" "INTERFACE"; match "type" "ATTACH"; match "vendor" "0x0bda"; # only interface 0 is supported by rtlbtfw match "interface" "0"; match "intclass" "0xe0"; match "intsubclass" "0x01"; match "intprotocol" "0x01"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; # Realtek 8821CE Bluetooth devices notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x13d3"; match "product" "0x3529"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; # Realtek 8822CE Bluetooth devices notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x0bda"; match "product" "(0xb00c|0xc822)"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; # Realtek 8822CU Bluetooth devices notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x13d3"; match "product" "0x3549"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; # Realtek 8852AE Bluetooth devices notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x0bda"; match "product" "(0x2852|0xc852|0x385a|0x4852)"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x04c5"; match "product" "0x165c"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x04ca"; match "product" "0x4006"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x0cb8"; match "product" "0xc549"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; # Realtek 8852CE Bluetooth devices notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x04ca"; match "product" "0x4007"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x04c5"; match "product" "0x1675"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x0cb8"; match "product" "0xc558"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x13d3"; match "product" "(0x3587|0x3586|0x3592)"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; # Realtek 8852BE Bluetooth devices notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x0cb8"; match "product" "0xc559"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x0bda"; match "product" "0x887b"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x13d3"; match "product" "0x3571"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; # Realtek 8723AE Bluetooth devices notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x0930"; match "product" "0x021d"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x13d3"; match "product" "0x3394"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; # Realtek 8723BE Bluetooth devices notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x0489"; match "product" "(0xe085|0xe08b)"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x04f2"; match "product" "0xb49f"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x13d3"; match "product" "(0x3410|0x3416|0x3459|0x3494)"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; # Realtek 8723BU Bluetooth devices notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x7392"; match "product" "0xa611"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; # Realtek 8723DE Bluetooth devices notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x0bda"; match "product" "0xb009"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x2ff8"; match "product" "0xb011"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; # Realtek 8761BUV Bluetooth devices +notify 100 { + match "system" "USB"; + match "subsystem" "DEVICE"; + match "type" "ATTACH"; + match "vendor" "0x2c4e"; + match "product" "0x0115"; + action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; +}; notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x2357"; match "product" "0x0604"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x0b05"; match "product" "0x190e"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x2550"; match "product" "0x8761"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x0bda"; match "product" "0x8771"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x6655"; match "product" "0x8771"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x7392"; match "product" "0xc611"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x2b89"; match "product" "0x8761"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; # Realtek 8821AE Bluetooth devices notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x0b05"; match "product" "0x17dc"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x13d3"; match "product" "(0x3414|0x3458|0x3461|0x3462)"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; # Realtek 8822BE Bluetooth devices notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x13d3"; match "product" "0x3526"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x0b05"; match "product" "0x185c"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; # Realtek 8822CE Bluetooth devices notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x04ca"; match "product" "0x4005"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x04c5"; match "product" "0x161f"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x0b05"; match "product" "0x18ef"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x13d3"; match "product" "(0x3548|0x3549|0x3553|0x3555)"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x2ff8"; match "product" "0x3051"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x1358"; match "product" "0xc123"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x0bda"; match "product" "0xc123"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; }; notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x0cb5"; match "product" "0xc547"; action "/usr/sbin/rtlbtfw -d $cdev -f /usr/local/share/rtlbt-firmware"; };