Realtek RTL8761B / RTL8761BU Bluetooth firmware loader for macOS (OpenCore Hackintosh).
Makes the TP-Link UB500 (and other RTL8761BU USB dongles) work as a real
Bluetooth controller on macOS 12–26 by uploading the Realtek firmware at boot —
the same approach Linux's btrtl driver uses, reimplemented as an IOKit kext.
The RTL8761BU ships with no firmware. Linux uploads rtl8761bu_fw.bin via HCI
vendor commands before the generic Bluetooth stack takes over; macOS has no
driver that does this, which is why the usual advice is to replace the adapter
with a Broadcom one. This kext performs the firmware upload, then hands the
controller to macOS's own bluetoothd (patched by BlueToolFixup).
Confirmed on macOS 26 (Tahoe), OpenCore 1.0.7, Intel: phone and audio (A2DP/HFP/AVRCP) connected, battery reporting, and HID.
| Feature | State |
|---|---|
| Firmware upload at boot | Works, automatic on every boot |
| Controller adopted by macOS | Works (THIRD_PARTY_DONGLE, real BD_ADDR) |
| Pairing and connecting | Works |
| Audio (A2DP / HFP / AVRCP) and battery | Works |
| HID (mice, keyboards) | Works |
| Discovering brand-new devices | Limited. macOS runs only a short inquiry on this chip, so put a device in pairing mode and select it promptly. Already-paired devices reconnect fine. |
| Apple Continuity (Handoff, AirDrop, Universal Clipboard) | Not supported. Requires genuine Apple Bluetooth/Wi-Fi hardware. |
- Prebuilt kext: latest
.kexton the Releases page. - Build from source: run
make(see Build; the firmware is fetched automatically).
This kext targets the TP-Link UB500 (Realtek RTL8761BU). If you would prefer Bluetooth with no kext at all, a CSR8510 dongle works natively on macOS. See Hardware for options and compatibility.
This kext supports the Realtek RTL8761BU only (USB 0x2357 / 0x0604). Other
chips need a different driver or none at all; other RTL8761BU dongles can work by
adding their VID/PID to Info.plist.
| Adapter | Chip | macOS support | Link |
|---|---|---|---|
| TP-Link UB500 | RTL8761BU | this kext | Amazon |
| CSR8510 A10 dongle | CSR8510 | native, no kext | Amazon |
| Broadcom BCM20702 dongle | BCM20702 | BrcmPatchRAM3 | Amazon |
Amazon occasionally ships a revised UB500 under the same listing. Confirm it
reports PID 0x0604 (RTL8761BU) with system_profiler SPUSBDataType before
relying on it.
Different or newer chips, or Wi-Fi + Bluetooth combos: UB500 Plus (B0DKFXGR21), UB600 (B0GVPZ4P6B), UB400 (B07V1SZCY6), Archer T2UB (B0BJ7XJ27X), Archer TX10UB (B0F9CNQN42).
Accessory: a short USB 2.0 extension cable helps if a rear USB-2 port is awkward to reach.
Some links above are Amazon affiliate links; a purchase may earn the maintainer a small commission at no additional cost to you. Verify chipset compatibility before buying.
- macOS 12 (Monterey) – 26 (Tahoe), Intel
x86_64 - OpenCore with kext injection
- Lilu + BlueToolFixup (BlueToolFixup is what lets
bluetoothdaccept a non-Apple controller — required) SecureBootModel = Disabledin your OpenCore config (this kext is ad-hoc signed), which is standard for kext-injection hackintoshes- Xcode Command Line Tools (or full Xcode) to build
git clone https://github.com/<you>/RTLBluetoothFirmware.git
cd RTLBluetoothFirmware
makemake automatically downloads the Realtek firmware (rtl8761bu_fw.bin +
rtl8761bu_config.bin) from kernel.org's linux-firmware, embeds it into the
kext, compiles, and ad-hoc signs. The firmware blobs are not redistributed in
this repo (Realtek's license) — they're fetched at build time.
Result: RTLBluetoothFirmware.kext.
- Mount your OpenCore EFI:
sudo diskutil mount diskXsY # your EFI partition - Copy the kext:
cp -R RTLBluetoothFirmware.kext /Volumes/EFI/EFI/OC/Kexts/
- Add it to
config.plist → Kernel → Add(ProperTree OC Snapshot, or by hand):BundlePath=RTLBluetoothFirmware.kextExecutablePath=Contents/MacOS/RTLBluetoothFirmwarePlistPath=Contents/Info.plistMinKernel=21.0.0,Enabled=true,Arch=x86_64- Load order: after
LiluandBlueToolFixup.
- First-time only — clear the stale Bluetooth blacklist. If you previously
ran the firmware-less dongle, macOS set
bluetoothExternalDongleFailed. Add these toconfig.plist → NVRAM → Deleteunder GUID7C436110-AB2A-4BBB-A880-FE41995C9F82:bluetoothExternalDongleFailed,bluetoothInternalControllerInfo,bluetoothHostControllerSwitchBehavior. - Reboot with the dongle plugged in (a USB-2 port is ideal).
The scripts/ helpers automate install + verification — read them before running;
they touch your EFI.
log show --last boot --predicate 'eventMessage CONTAINS "RTLBluetoothFirmware"'
system_profiler SPBluetoothDataType | grep -iE "Firmware|Chipset|Address|State"Good = the log shows download complete, and Firmware Version is NOT the ROM
identity 0x8761 / 0x000B (it becomes the patch version, e.g. 0xDFC6D922).
- Matches the UB500
IOUSBHostDeviceearly in boot (ownIOMatchCategory, beforebluetoothd). - Sets configuration, opens the HCI interface + interrupt-IN pipe.
HCI Read Local Version→ detects ROM mode; on a warm reboot, sends the Realtek vendor reset (0xFC66) to drop back to ROM.- Parses the
Realtechepatch container, picks the patch for this ROM version, appends the config blob (mirrorsrtlbt_parse_firmwareinbtrtl.c). - Uploads it in 252-byte fragments via
0xFC20, thenHCI Reset. - Closes all USB handles and releases the device —
bluetoothd(via BlueToolFixup) then drives it as a standard USB HCI controller.
- Discovering new devices is finicky (see table). Paired devices reconnect fine.
- Sleep/wake: if USB power is cut, the volatile firmware is lost — replug or reboot re-patches it.
- Continuity features need real Apple hardware; not fixable here.
- Linux kernel
drivers/bluetooth/btrtl.c&btusb.c— the protocol reference (GPL-2.0). linux-firmwarertl_bt/— the firmware blobs.- OpenIntelWireless/IntelBluetoothFirmware — the "upload-then-handoff" IOKit pattern.
- acidanthera — Lilu & BlueToolFixup.
GPL-2.0-or-later. The firmware-upload protocol is derived from the GPL-2.0
Linux btrtl driver; this kext is an independent IOKit implementation of it.
See LICENSE.
Experimental, community-built, provided as-is. Kernel extensions can crash or
prevent boot. The kext only matches the UB500's VID/PID, so if anything misbehaves
at boot, unplug the dongle and it's inert. Use at your own risk.