Btfirmware-nonfree

From SlackWiki
Jump to navigation Jump to search

I recently was presented with a Thinkpad T430s containing a Broadcom BCM20702 bluetooth chip, and bluetooth wouldn't work at all on it.

$ lsusb Bus 003 Device 009: ID 0a5c:21e6 Broadcom Corp. BCM20702 Bluetooth 4.0 [ThinkPad]

On boot, I saw this in /var/log/syslog:
Nov 24 13:37:35 liberty kernel: bluetooth hci0: Direct firmware load for brcm/BCM20702A1-0a5c-21e6.hcd failed with error -2
Sure enough, /lib/firmware/brcm/BCM20702A1-0a5c-21e6.hcd did not exist.

After a bit of research, I determined that nobody had already written clear instructions on just how to obtain the needed firmware. There were a few results with links to different firmware that someone had already obtained from some mysterious source, and vague references about "get it from your Windows system" and such, but well, I don't have a Windows system.

I went to the Lenovo support site, downloaded the bluetooth driver file (currently located at https://download.lenovo.com/ibmdl/pub/pc/pccbbs/mobiles/g4wb12ww.exe but of course, this link will not always be valid), and poked around a bit in its contents. To do that, you'll first need to get innoextract (see http://constexpr.org/innoextract/ or search SlackBuilds.org for it).
root@liberty:~/fw# ls
g4wb12ww.exe
root@liberty:~/fw# innoextract g4wb12ww.exe
...lots of output, all extracted to an "app/" directory...

Now to see if we can find the important bits in here... I notice that the firmware expected to be loaded has "0a5c-21e6" in the name, and the usb ID of the bluetooth hardware is "0a5c:21e6" so let's poke around and see if we can find anything with that name:

find app/ -name "*0a5c*" -o -name "*0A5C*"

Hmm, no output. Okay.


root@liberty:~/fw#grep -Eir 0a5c.*21e6 .
Binary file ./app/Win64/BTW.msi matches
./app/Win64/bcbtums-win7x64-brcm.inf:%BRCM20702Thinkpad.DeviceDesc%=RAMUSB21E6, USB\VID_0A5C&PID_21E6  ; 20702 non-UHE Lenovo Japan
Binary file ./app/Win32/BTW.msi matches
./app/Win32/bcbtums-win7x86-brcm.inf:%BRCM20702Thinkpad.DeviceDesc%=RAMUSB21E6, USB\VID_0A5C&PID_21E6  ; 20702 non-UHE Lenovo Japan


Well, I don't want to poke around in binary files too much, but I know that .inf are plaintext files, so let's look in there. That "DeviceDesc" looks important, so we'll search for that in the .inf file once we get it opened. I use vi, but hopefully you know your editor well enough to do the equivalent, and you'll find something like this:

...
%BRCM20702Thinkpad.DeviceDesc%=RAMUSB21E6, USB\VID_0A5C&PID_21E6  ; 20702 non-UHE Lenovo Japan
...

RAMUSB21E6;;;;;;;;;;;;;;;;;


[RAMUSB21E6.CopyList]
bcbtums.sys
BCM20702A1_001.002.014.0449.0462.hex

[RAMUSB21E6.NTX86]
Include=bth.inf
Needs=BthUsb.NT
FeatureScore=F0
CopyFiles=RAMUSB21E6.CopyList

[RAMUSB21E6.NTX86.hw]
AddReg=RAMUSB21E6.NTX86.hw.reg

[RAMUSB21E6.NTX86.hw.reg]
HKR,,LowerFilters, 0x00010000, "bcbtums"
HKR,,%RAMPatchFileName%,0x00000, "BCM20702A1_001.002.014.0449.0462.hex"
HKR,,%RemoteWakeEnabled%,0x00010001,1
HKR,,%DeviceRemoteWakeSupported%,0x00010001,1

[RAMUSB21E6.NTX86.Services]
needs=BthUsb.NT.Services
AddService=bcbtums,,BCBTUMS_Service_Inst, BTWSECFL_EventLog_Inst

...

I happen to know from my research that the firmware files are .hex file, so this line is awesome to see:
HKR,,%RAMPatchFileName%,0x00000, "BCM20702A1_001.002.014.0449.0462.hex"

Copy that file out of the directory structure into a place that's easier to work with:
root@liberty:~/fw# cp app/Win64/BCM20702A1_001.002.014.0449.0462.hex .
root@liberty:~/fw# ls
BCM20702A1_001.002.014.0449.0462.hex app/ g4wb12ww.exe

Now we need to put this in a form that the linux kernel expects, so that's where hex2hcd comes in:
root@liberty:~/fw# git clone git://github.com/jessesung/hex2hcd.git
Cloning into 'hex2hcd'...
remote: Counting objects: 8, done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 8 (delta 1), reused 8 (delta 1), pack-reused 0
Receiving objects: 100% (8/8), 8.71 KiB | 0 bytes/s, done.
Resolving deltas: 100% (1/1), done.
Checking connectivity... done.
root@liberty:~/fw# cd hex2hcd/
root@liberty:~/fw/hex2hcd# make
gcc -O2 -march=native hex2hcd.c -o hex2hcd

Now we use hex2hcd: root@liberty:~/fw/hex2hcd# ./hex2hcd ../BCM20702A1_001.002.014.0449.0462.hex ../BCM20702A1-0a5c-21e6.hcd
... lots of text and binary data ...

Finally, let's back up a directory, make sure what think is there is actually there, and copy it into place:

root@liberty:~/fw/hex2hcd# cd ..
root@liberty:~/fw# ls
BCM20702A1-0a5c-21e6.hcd BCM20702A1_001.002.014.0449.0462.hex app/ g4wb12ww.exe hex2hcd/
root@liberty:~/fw# cp BCM20702A1-0a5c-21e6.hcd /lib/firmware/brcm/

The first person who finds this useful is expected to clean up the formatting and such. :-) Enjoy! -RW