Wake on Bluetooth 4 on Legacy Hackintosh: A Practical Guide

Learn how to fix wake-on-Bluetooth on legacy Hackintosh builds: USB wake support, DSDT _PRW patches, kext tweaks, and testing steps for macOS 10.12–10.14.

Waking a Hackintosh from sleep using a Bluetooth 4.0 keyboard or mouse is a feature that many users assume will work out of the box, but on legacy builds it often fails silently. The root cause is almost never the Bluetooth module itself; it is the way macOS handles the USB host controller and the power management tree during sleep. If you have a Broadcom BCM20702-based USB dongle or an Apple-branded module connected via an internal USB header, and you press a key after sleep and nothing happens, this guide walks through the actual steps to diagnose and fix the wake path.

Understanding the Wake Chain

When you press a key on a Bluetooth keyboard, the following events must occur for the system to wake:

  1. The Bluetooth controller receives the HID event and signals the host controller (USB or PCIe).
  2. The host controller asserts a wake signal on the appropriate ACPI GPE (General Purpose Event).
  3. The ACPI firmware wakes the CPU and the kernel resumes the system.
  4. The Bluetooth stack reinitializes and delivers the HID report to the login window.

On a genuine Mac, the firmware and ACPI tables are tuned for this chain. On a Hackintosh, a single misconfigured USB port or a missing _PRW method in the DSDT can break the entire sequence. The most common failure point is the USB port's ability to generate a wake event, not the Bluetooth module.

Check the Bluetooth Module and Connection

Before diving into ACPI, verify that your Bluetooth hardware is actually capable of wake. The vast majority of legacy Hackintosh builds use one of two configurations:

  • A USB dongle based on the Broadcom BCM20702 chipset (e.g., the IOGEAR GBU521 or similar).
  • An Apple BCM94360CD or BCM94331PCIEBT card connected via a PCIe adapter, with Bluetooth routed through an internal USB 2.0 header.

Both are capable of wake-on-Bluetooth, but only if the USB port they are attached to is properly configured in the ACPI tables. If your dongle is plugged into a USB 3.0 port on a legacy motherboard with an older XHCI controller, you may need to force the port to USB 2.0 mode or remap it. Use IORegistryExplorer to confirm that the device appears under a UHCI/EHCI controller, not XHCI, if you are running macOS 10.13 or earlier. For detailed IORegistry debugging, refer to our earlier guide on NVIDIA Graphics 12: Legacy Kepler and Maxwell Cards on macOS 10.12–10.14 — the same principles of device tree inspection apply.

Verify USB Wake Support in the DSDT

For a USB device to wake the system, its parent USB controller must have a _PRW method that defines the wake GPE. On many legacy motherboards, this method is missing or incorrectly scoped. You can check this by disassembling your DSDT and looking for the controller's device node. For example, on an Intel Z77 board, the EHCI controller is usually named EHC1 or EHC2. The _PRW method should look like:

Method (_PRW, 0, NotSerialized)
{
    Return (GPRW (0x6D, 0x04))
}

If the method is absent, you must add it via a SSDT patch or a DSDT edit. The GPE number is board-specific; you can find it by testing with a USB 2.0 flash drive and observing which GPE fires in the kernel log. A safer approach is to use a SSDT that injects _PRW into the existing device node without modifying the DSDT directly. This is a standard practice in Clover and OpenCore configurations.

Power Management and the Bluetooth Device's Wake Capability

Even with a correct _PRW, the Bluetooth device itself must be marked as wake-capable. In macOS, this is controlled by the device-properties or by the IOHIDFamily kext. For Broadcom modules, you often need to inject a board-id property to enable the wake feature. A common trick is to add the following to your bootloader's device properties for the Bluetooth USB device:

<key>device-properties</key>
<dict>
    <key>USBWake</key>
    <true/>
</dict>

However, this is not a documented Apple property, and its effect varies by macOS version. In practice, the most reliable method is to ensure the Bluetooth controller is not put into a deep sleep state. You can do this by setting the IdleSleep power property via ACPI or by using a small kext like BT4LEContinuityFixup (though that kext is more about continuity). For legacy versions (10.9–10.13), patching the IOBluetoothFamily kext is sometimes necessary to prevent the controller from disconnecting during sleep.

Testing the Wake Path

After making any changes, you need to test the wake path methodically. Here is a step-by-step procedure:

  1. Ensure your Bluetooth device is paired and connected.
  2. Put the system to sleep using pmset sleepnow in Terminal.
  3. Wait for the power LED to blink or the system to enter S3.
  4. Press a key on the Bluetooth keyboard or click the mouse.
  5. Immediately check the system log for wake events: log show --last 2m | grep -i wake.
  6. If no wake event appears, the GPE is not firing. Re-check your _PRW method.
  7. If a wake event appears but the system does not fully resume, the issue is likely in the Bluetooth stack reinitialization. Try waking with a USB keyboard to confirm the system can wake at all.

If the system wakes with a USB keyboard but not with Bluetooth, the problem is almost certainly the USB port's wake capability, not the Bluetooth module. Use pmset -g assertions to see if any power assertions are blocking sleep, and ensure that Bluetooth is not listed as a sleep prevention factor.

Legacy Considerations for macOS 10.12–10.14

On High Sierra and Mojave, Apple changed the way Bluetooth wake is handled. The IOBluetoothFamily kext now expects the controller to support the HostWake feature, which is only present in newer Broadcom chips. Older BCM20702 modules may not advertise this capability, and macOS will disable wake-on-Bluetooth even if the hardware supports it. In such cases, you can try forcing the wake by patching the kext's Info.plist to enable the BluetoothWakeSupport key. This is a known workaround, but it is not guaranteed to work on every build. Always back up your kext before modifying it.

If you are using a NVIDIA GPU with these macOS versions, remember that wake issues can also be related to GPU power management. Our guide on NVIDIA Hackintosh Builds: Pascal, Maxwell, and Kepler on High Sierra and Mojave covers the necessary web driver settings to avoid wake-from-sleep black screens, which can be confused with Bluetooth wake failures.

Using a SSDT to Inject Wake Support

For advanced users, the most robust solution is to create a SSDT that explicitly defines the wake path for your Bluetooth controller. Here is a minimal example for a USB Bluetooth device on port 3 of EHCI:

DefinitionBlock ("SSDT-BTWAKE.aml", "SSDT", 2, "HACK", "BTWAKE", 0x00000001)
{
    External (_SB_.PCI0.EHC1, DeviceObj)
    Scope (_SB_.PCI0.EHC1)
    {
        Method (_PRW, 0, NotSerialized)
        {
            Return (GPRW (0x6D, 0x04))
        }
    }
}

Compile this with iASL and load it via your bootloader. The GPE number (0x6D) must match your motherboard's ACPI table; you can find it by looking at the _PRW of a working USB port, such as the one used by a USB keyboard. This method is clean and reversible, and it does not alter the DSDT.

Real-World Example: Z77X-UD5H with BCM94360CD

On a Gigabyte Z77X-UD5H with a BCM94360CD card, the Bluetooth module is connected to the internal USB 2.0 header, which is routed to the EHC2 controller. The default DSDT does not include a _PRW for EHC2, so wake-on-Bluetooth does not work out of the box. After adding the SSDT above with the correct GPE (0x6D), wake worked reliably on macOS 10.13.6. However, on Mojave, the system would wake but the Bluetooth mouse required a few seconds to reconnect. This was resolved by adding the board-id property Mac-031B6874CF7F642A (from a MacBook Pro 11,2) to the Bluetooth device in the bootloader's device properties.

Risks and Data Safety

Modifying ACPI tables and kexts carries inherent risks. A malformed SSDT can prevent your system from booting, and a patched kext can cause a kernel panic. Always keep a backup of your current EFI partition and your kexts before making any changes. Test each change individually, and have a recovery method ready, such as a USB boot drive with a known-good configuration. If you are not comfortable with DSDT editing, start with the simpler device-properties injection, as it is less likely to cause a boot failure.

Diagnosing with IORegistryExplorer

To confirm that your Bluetooth device is correctly recognized as wake-capable, open IORegistryExplorer and navigate to the Bluetooth USB device. Look for the USB Wake Capability property in the IOUSBDevice object. If it is missing or set to No, the system will not allow the device to wake the computer. In that case, you may need to patch the IOUSBHostFamily kext to enable the WakeOnConnect feature. This is a more invasive fix and should be done only after exhausting the ACPI route.

For a comprehensive approach to diagnosing legacy Hackintosh issues, including how to read IORegistry data effectively, our guide on Intel HD Graphics Hackintosh Guide: Fixing Black Screen, Framebuffer Injection for Sandy Bridge to Haswell demonstrates similar diagnostic patterns for GPU issues that can also apply to USB device property inspection.

Final Practical Steps

To get wake-on-Bluetooth working on your legacy Hackintosh, follow this checklist:

  • Confirm the Bluetooth module is connected to a USB 2.0 port, not a USB 3.0 port that may be disabled during sleep.
  • Disassemble your DSDT and verify that the USB controller has a _PRW method. If not, create a SSDT to inject it.
  • Test with a USB keyboard to ensure the system can wake from S3 at all.
  • Use IORegistryExplorer to verify the wake capability property on the Bluetooth device.
  • If necessary, patch the Bluetooth kext or inject a board-id property to enable wake support.
  • Always back up your EFI partition and kexts before each modification, and test after every change.

Wake-on-Bluetooth is a convenience feature that depends on a fragile chain of ACPI, USB, and Bluetooth stack interactions. On legacy hardware, it often requires manual intervention, but with systematic testing and the right ACPI patches, you can achieve reliable wake behavior even on older macOS versions.