Friday, January 13, 2017

How to fix bluetooth after sleep on a hackintosh

How to fix bluetooth after sleep on a hackintosh


In my experience, bluetooth typically just works out of the box on OSX.  But my most recent hack, a Lenovo Thinkpad W700DS (which would be the coolest thing since sliced bread if it didnt weigh 20 pounds), had a problem where the bluetooth would die after putting the computer to sleep and then the only way I could "switch" it back on would be to reboot into Linux and reenable the card.  Obviously, this is less than optimal so I decided to figure out what it would take to fix it.

Like most things hackintosh, a simple device and vendor ID injection into the proper kext would suffice, but as the bluetooth is not a PCI device there were extra hoops to jump through.  My bluetooth card is a Lenovo ThinkPad Bluetooth with EDR II, (Broadcom 2145 chipset).

the PCI ID is 0x21450A5C where the part in red is the hexadecimal device ID and the blue being the vendor ID.

But upon investigating the system .kexts, (in my case /System/Library/Extensions/IOBluetoothFamily.kext/Contents/Plugins/BroadcomBluetoothTransportHostControllerUSBTransport.kext) I discovered that (like most USB devices) they dont use hexadecimal IDs, but rather decimal IDs.

So going back to my programming classes I took back in college, I knew Id have to convert from hexadecimal to decimal format.  If you cant figure it out or dont know how to do it on a calculator, you could always use an online converter like this http://www.binaryhexconverter.com/hex-to-decimal-converter

0x21458517
0x0A5C2652

With my decimal values now in hand, I crack open the broadcom kext

sudo nano /System/Library/Extensions/IOBluetoothFamily.kext/Contents/PlugIns/BroadcomBluetoothHostControllerUSBTransport.kext/Contents/Info.plist

and add a section like this at the bottom of the array

                <key>BroadcomUSBBluetoothHCIController - Lenovo</key>
                <dict>
                        <key>CFBundleIdentifier</key>
                        <string>com.apple.iokit.BroadcomBluetoothHostControllerUSBTransport</string>
                        <key>IOClass</key>
                        <string>BroadcomBluetoothHostControllerUSBTransport</string>
                        <key>IOProviderClass</key>
                        <string>IOUSBDevice</string>
                        <key>idProduct</key>
                        <integer>8517</integer>
                        <key>idVendor</key>
                        <integer>2652</integer>

                </dict>


as you can see from examining the rest of the Info.plist, the idVendor value is the same for all the entries... 

after that I cleared the kernel cache 

sudo rm -rfv /System/Library/Caches/com.apple.kextcache/Startup/*

and rebooted with "-v -c -f UseKernelCaches=No".  For some reason, it took two reboots for the change to take (I could be wrong, but I think Clover bootloader also caches your KernelCache), but after that, I could sleep my laptop and wake it back up without losing bluetooth.


Oh, and if you are on Yosemite, you definitely need to be booting with kext-dev-mode=1.  Modifying the kext will make it unloadable without kext-dev-mode=1 even if you re codesign it.


Available link for download