Page MenuHomeFreeBSD

Firmware loader for Intel Wireless 8260 based Bluetooth USB devices

Authored by wulf on Jul 25 2019, 9:19 PM.



It consist of 3 parts:

  1. Kernel: Forbid attachment of ng_ubt(4) to Intel Wireless 8260/8265 devices in bootloader mode.

    Add helper function for synchronous execution of HCI commands at probe stage and use this function to check firmware state of Intel Wireless 8260/8265 bluetooth devices found in many post 2016 year laptops.

    Attempt to initialize FreeBSD bluetooth stack while such a device is in bootloader mode locks the adapter hardly so it requires power on/off cycle to restore.

    This change blocks ng_ubt attachment unless operational firmware is loaded thus preventing the lock up.
  1. Userland: Firmware loader for Intel Wireless 8260 based Bluetooth USB devices (iwmbtfw)

    Currently supported models are: 8260, 8265, 9560, 9260 and 22161. Devd config file to do an autoloading is included.
  1. Firmware files (not included here)

    They can be installed with comms/iwmbt-firmware port attached to PR/237083 (


Test Plan

Execute hccontrol Inquiry and get a list of surrounding bt-devices

Diff Detail

rS FreeBSD src repository
Automatic diff as part of commit; lint not applicable.
Automatic diff as part of commit; unit tests not applicable.

Event Timeline

wulf created this revision.Jul 25 2019, 9:19 PM
hselasky accepted this revision.Jul 26 2019, 7:02 AM

Looks good!

This revision is now accepted and ready to land.Jul 26 2019, 7:02 AM
emax added a comment.Jul 30 2019, 12:05 AM

looks good, but i have some reservations about adding device specific code to ng_ubt(4)

596 ↗(On Diff #60150)

i'm wondering if this is a good idea to put hardware specific code in ng_ubt(4)? is it possible to take approach similar to ubtbcmfw(4) (or possibly ath3kfw(8)).

in case of ubtbcmfw(4) special driver it attaching to facilitate firmware download. later, after firmware is downloaded device will reset itself and present different identity to ng_ubt(4) allowing it to work.

in case of ath3kfw(8), ugen(4) is attached to the device without firmware, external tool loads firmware using dfu, and, again, device resets itself and present working identity to ng_ubt(4)

wulf added inline comments.Jul 30 2019, 11:02 AM
596 ↗(On Diff #60150)

Theoretically speaking it is possible but not easy. Briefly speaking:

Intel device uses higher level interface than ath3k to download the firmware.
It starts in bootloader mode where very limited subset of HCI commands is supported. Downloader executes these commands to query device state and capabilities and than to download firmware. Following device reset does not detach device from usb bus, does not change USB device descriptor and is mostly opaque from OS point of view. At first glance, libbluetooth or bluetooth socket can be used to do the work, but I faced with some obstacles when tried that way:

  1. Chicken and egg problem: We need to initialize bluetooth stack to download firmware to initialize bluetooth stack. It could be solved by placing downloader right before HCI reset command in /etc/rc.d/bluetooth script, but:
  2. Bootloader mode is very fragile. My bt-adapter locks hardly right after ubt0hci netgraph node attachment due to unconditional start of SCO transfer [1].
  3. It looks like our bt-stack does not support sending of HCI-formatted data through bulk USB endpoint. It is required by downloader and I got failures when had tried that.
  4. libusb can not be used to download the firmware at this stage as it detaches ng_ubt driver

That is why I decided to block attachment of uninitialized device like ath3k does, but unlike ath3k, intel's USB device descriptor does not reflect firmware state so device driver have to send HCI request to find it out.

[1] unconditional start of SCO transfer in ng_ubt is a bug. It prevents cpu core that servicing usb interrupts to enter C3 power state that causes eating of extra 0.3W on my laptop.

emax accepted this revision.Jul 30 2019, 7:48 PM
emax added inline comments.
596 ↗(On Diff #60150)

thank you. i think all your comments make a perfect case for having separate firmware loading driver similar to ubtbcmfw(4). i think you can have all the hardware specific logic contained, and, surely there is a vendor (intel) HCI command that will perform "warm reset" causing device to disconnect from the bus and reconnect. quick look at linux kernel shows separate driver for intel devices.

the other option would be to have a full driver for those devices cloned from ng_ubt(4). sure there is a code duplication, but since those devices are "weird" it is probably justifiable.

having said all that, i don't particularly care that much. i will leave it up you to make the decision. thank you for your work!

wulf updated this revision to Diff 60805.Aug 14 2019, 10:14 PM

Finally, I made separate small kernel module ng_ubt_intel which shares object file with ng_ubt.
It inherits device methods from ng_ubt while overriding it's probe() method.
That allows move vendor-specific code out of ng_ubt and avoid code duplication the same time.
Firmware is still downloaded with libusb as I don't see any benefits from moving one-shot driver to kernelspace.

This revision now requires review to proceed.Aug 14 2019, 10:14 PM
hselasky accepted this revision.Aug 15 2019, 8:36 PM

Looks very good!

This revision is now accepted and ready to land.Aug 15 2019, 8:36 PM