Contribute
Register

[Guide] USB power property injection for Sierra (and later)

Do you mean kUSBSleepPortCurrentLimit, kUSBSleepPowerSupply, kUSBWakePortCurrentLimit, kUSBWakePowerSupply

That is relevant to this guide.
Your ioreg clearly shows it is done.

need to add the SSDT is need "8086 _9xxx" corresponding port injection?

That is the topic of another guide (already linked).
 
I'm hoping someone can take a look at my setup and tell me what's wrong. I followed the guide very closely, but must be missing something. AppleBusPowerUSB is now showing up under my faked EC, but I still have no USBX. AppleBusPowerControllerUSB has all the right values for the power supply fields, but my iPad still doesn't get over 500mA. Any advice?
 
I'm hoping someone can take a look at my setup and tell me what's wrong. I followed the guide very closely, but must be missing something. AppleBusPowerUSB is now showing up under my faked EC, but I still have no USBX. AppleBusPowerControllerUSB has all the right values for the power supply fields, but my iPad still doesn't get over 500mA. Any advice?

USBX is there. Why do you think it is not?
Screen Shot 2017-09-08 at 10.18.13 AM.png
 
Ah you're right. I'm not sure why I didn't see that before. I'm still only getting 500mA to my iPhone/iPad even though everything appears to be correct though.
 
Ah you're right. I'm not sure why I didn't see that before. I'm still only getting 500mA to my iPhone/iPad even though everything appears to be correct though.

Maybe you have it connected to a hub port, and not a controller port.
 
Wow, you're amazing at figuring this stuff out. It was plugged into a hub (which has external power as well). When I plugged the iPad straight into the mobo it got the correct power. My Macbook is able to give it full power using the same hub, so I figured it would work. Is there a way to get full power out of a hub on a Hackintosh?
 
Wow, you're amazing at figuring this stuff out. It was plugged into a hub (which has external power as well). When I plugged the iPad straight into the mobo it got the correct power. My Macbook is able to give it full power using the same hub, so I figured it would work. Is there a way to get full power out of a hub on a Hackintosh?

Might be worthwhile comparing ioreg between the MacBook (with the hub plugged) and your hack.
Also you might look here: https://github.com/mkhon/USBHubPowerFix
 
Might be worthwhile comparing ioreg between the MacBook (with the hub plugged) and your hack.
Also you might look here: https://github.com/mkhon/USBHubPowerFix

The USBHubPowerFix kext did it, mostly. I modified the values of kUSBSleepPortCurrentLimit and kUSBWakePortCurrentLimit and got an additional 500mA extra operating current out of it. It's not the normal 1600mA extra, but it's enough to keep it juiced up while I'm using it. Thanks for all your help.
 
Signature: "ECDT" [Embedded Controller Boot Resources Table]
[03Ch 00604] UID: 00000000
[040h 0064] GPE Number: 0A
[041h 0065 19] Namepath: "\_SB.PCI0.LPCB.EC0"
As you said, my ECDT contains EC0 and cannot use rename EC0_ to EC? Is not found under PNP0C09 _STA, I in addition to inject a SSDT - EC. Outside the aml also need to add anything to cheat AppleBusPowerControllerUSB, let him can work?
Summary

It appears that Sierra has changed how USB power properties are set. In prior versions, we have injected AAPL,current-available, AAPL,current-extra, AAPL,current-extra-in-sleep, and AAPL,max-port-current-in-sleep directly on the XHC/EHCI ACPI objects. In Sierra, these appear to be replaced by new properties that are injected on the AppleBusPowerControllerUSB object in ioreg.

Let's take a look at the changes required...


Tracing the evidence

Some of these changes were noticed during development of USBInjectAll.kext... And I had remembered about some "kUSB*" properties that looked interesting in one of the USB kext Info.plist files. A simple grep search can reveal where we might look:

Code:
SPEEDY-NUC:nuc.git rehabman$ grep -l kUSB.* -R /System/Library/Extensions/IOUSBHostFamily.kext
/System/Library/Extensions/IOUSBHostFamily.kext/Contents/Info.plist
/System/Library/Extensions/IOUSBHostFamily.kext/Contents/MacOS/IOUSBHostFamily
/System/Library/Extensions/IOUSBHostFamily.kext/Contents/PlugIns/AppleUSBEHCI.kext/Contents/MacOS/AppleUSBEHCI
/System/Library/Extensions/IOUSBHostFamily.kext/Contents/PlugIns/AppleUSBEHCIPCI.kext/Contents/Info.plist
/System/Library/Extensions/IOUSBHostFamily.kext/Contents/PlugIns/AppleUSBEHCIPCI.kext/Contents/MacOS/AppleUSBEHCIPCI
/System/Library/Extensions/IOUSBHostFamily.kext/Contents/PlugIns/AppleUSBHostCompositeDevice.kext/Contents/MacOS/AppleUSBHostCompositeDevice
/System/Library/Extensions/IOUSBHostFamily.kext/Contents/PlugIns/AppleUSBHostMergeProperties.kext/Contents/Info.plist
/System/Library/Extensions/IOUSBHostFamily.kext/Contents/PlugIns/AppleUSBHub.kext/Contents/Info.plist
/System/Library/Extensions/IOUSBHostFamily.kext/Contents/PlugIns/AppleUSBHub.kext/Contents/MacOS/AppleUSBHub
/System/Library/Extensions/IOUSBHostFamily.kext/Contents/PlugIns/AppleUSBOHCIPCI.kext/Contents/MacOS/AppleUSBOHCIPCI
/System/Library/Extensions/IOUSBHostFamily.kext/Contents/PlugIns/AppleUSBUHCI.kext/Contents/MacOS/AppleUSBUHCI
/System/Library/Extensions/IOUSBHostFamily.kext/Contents/PlugIns/AppleUSBUHCIPCI.kext/Contents/MacOS/AppleUSBUHCIPCI
/System/Library/Extensions/IOUSBHostFamily.kext/Contents/PlugIns/AppleUSBXHCI.kext/Contents/MacOS/AppleUSBXHCI
/System/Library/Extensions/IOUSBHostFamily.kext/Contents/PlugIns/AppleUSBXHCIPCI.kext/Contents/Info.plist
/System/Library/Extensions/IOUSBHostFamily.kext/Contents/PlugIns/AppleUSBXHCIPCI.kext/Contents/MacOS/AppleUSBXHCIPCI
/System/Library/Extensions/IOUSBHostFamily.kext/Contents/PlugIns/IOUSBHostHIDDevice.kext/Contents/MacOS/IOUSBHostHIDDevice

So... it looks like /System/Library/Extensions/IOUSBHostFamily.kext/Contents/Info.plist is a good place to start.

And look what we find:
View attachment 255374

As you can see there are various properties (kUSBSleepPortCurrentLimit, kUSBSleepPowerSupply, kUSBWakePortCurrentLimit, kUSBWakePowerSupply), which are being injected to provider AppleBusPOwerControllerUSB via an AppleUSBHostMergeProperties injector.

But I checked my own ioreg and AppleBusPowerControllerUSB was not loaded anywhere. So now the question is what causes it to load... Another simple grep search will tell us:

Code:
SPEEDY-NUC:nuc.git rehabman$ grep -l AppleBusPowerControllerUSB -R /System/Library/Extensions
/System/Library/Extensions/AppleBusPowerController.kext/Contents/Info.plist
/System/Library/Extensions/AppleBusPowerController.kext/Contents/MacOS/AppleBusPowerController
/System/Library/Extensions/IOUSBHostFamily.kext/Contents/Info.plist

And now, looking at AppleBusPowerController.kext's Info.plist:
View attachment 255375

We can see that it matches on an ACPI device named 'EC'. Some PCs use EC for the Embedded Controller, but most use EC0 or H_EC.
With that knowledge, we can simply rename H_EC->EC, or EC0->EC, and then AppleBusPowerControllerUSB will load, as will the related injections for each supported SMBIOS in IOUSBHostFamily.kext/Contents/Info.plist.

Now, if you look carefully at the IOUSBHostFamily Info.plist, you find that newer SMBIOS are missing. Such as MacBookPro9,1, iMac17,1, and MacBookPro13,x. These models must use a different method for USB power property injection.

Disassembly of AppleBusPowerController reveals that it is looking in IOACPIPlane for an object named 'USBX'. It then appears to extract the necessary data from device-properties. If we look at the ioreg for an iMac17,1, we find this:
View attachment 255376

And there are our power properties again...

Looking at DSDT.aml for the iMac17,1, we find the source for USBX:
Code:
    Scope (_SB)
    {
...
        Device (USBX)
        {
            Name (_ADR, Zero)  // _ADR: Address
            Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
            {
                Store (Package (0x08)
                    {
                        "kUSBSleepPowerSupply",
                        0x13EC,
                        "kUSBSleepPortCurrentLimit",
                        0x0834,
                        "kUSBWakePowerSupply",
                        0x13EC,
                        "kUSBWakePortCurrentLimit",
                        0x0834
                    }, Local0)
                DTGP (Arg0, Arg1, Arg2, Arg3, RefOf (Local0))
                Return (Local0)
            }
        }

So, no surprise there... standard _DSM injection of the four USB power properties.

Summary:
- if the PC has an EC, name it 'EC' and AppleBusPowerControllerUSB will load.
- if the SMBIOS matches one of the "legacy SMBIOS" in IOUSBHostFamily.kext/Contents/Info.plist, power properties for that Mac model will be injected (they may or may not be appropriate for your hardware)
- if the SMBIOS is not present in IOUSBHostFamily.kext/Contents/Info.plist, power properties are determined by the USBX device in ACPI via normal _DSM property injection


Insuring AppleBusPowerControllerUSB loads

If you have an Embedded Controller (most laptops, some desktops), you can simply make sure the ACPI device is named EC. This is easily accomplished with a ACPI hotpatch in config.plist. I have added both the common renames into all the laptop guide plists.

Here is what they look like:
View attachment 255377

Note: If you are using static patched SSDTs (that is, patched OEM SSDTs in ACPI/patched), you must make sure the EC rename is accomplished in each of those files manually. Clover config.plist/ACPI/DSDT/Patches applies only to DSDT.aml in ACPI/patched, and OEM DSDT and SSDTs loaded from BIOS... not to SSDTs in ACPI/patched.

Note: If your computer has an ECDT in ACPI, you should not rename anything along the EC path, including the EC itself. Use a "Fake EC" instead as described below. You can check if you have ECDT by extracting ACPI with Clover (F4) and checking for ECDT.aml in EFI/Clover/ACPI/origin.

If you don't have an embedded controller, you can add a "fake" one with the following SSDT-EC.dsl (compile to AML):
Code:
// Inject Fake EC device
DefinitionBlock("", "SSDT", 2, "hack", "EC", 0)
{
    Device(_SB.EC)
    {
        Name(_HID, "EC000000")
    }
}
//EOF

Note: You may find you have an EC in your DSDT: Device with "Name (_HID, EisaId ("PNP0C09"))", even if it is not active.

For example, this is on my NUC6i7KYK:
Code:
    Scope (_SB.PCI0.LPCB)
    {
        Device (H_EC)
        {
            Name (_HID, EisaId ("PNP0C09"))  // _HID: Hardware ID
            Name (_UID, One)  // _UID: Unique ID
            Method (_STA, 0, NotSerialized)  // _STA: Status
            {
                Store (0x03, ^^^IGPU.CLID)
                Return (Zero)
            }
...

As you can see, it is returning zero from _STA. Which according to the ACPI spec is "not present". It means this H_EC device is effectively ignored. You will notice that it doesn't show in ioreg, IOService plane.

DO NOT be tempted to activate the EC device by changing the return value of _STA. The reason it is returning zero here is because the computer DOES NOT HAVE an EC. In this case, you should add a "fake" EC as mentioned above.


An SSDT to inject the USBX device

For SMBIOS that are not already covered in IOUSBHostFamily.kext/Contents/Info.plist, you will need to inject the USBX device in order to provide the power properties for AppleBusPowerControllerUSB.

Here is an example SSDT-USBX.dsl:
Code:
// USB power properties via USBX device
DefinitionBlock("", "SSDT", 2, "hack", "USBX", 0)
{
    Device(_SB.USBX)
    {
        Name(_ADR, 0)
        Method (_DSM, 4)
        {
            If (!Arg2) { Return (Buffer() { 0x03 } ) }
            Return (Package()
            {
                // these values from iMac17,1
                "kUSBSleepPortCurrentLimit", 2100,
                "kUSBSleepPowerSupply", 5100,
                "kUSBWakePortCurrentLimit", 2100,
                "kUSBWakePowerSupply", 5100,
            })
        }
    }
}
//EOF

You might think that you could also override the values provided by IOUSBHostFamily.kext/Contents/Info.plist in the case a supported SMBIOS is being used. But unfortunately, that is not the case... the values in IOUSBHostFamily.kext/Contents/Info.plist override those that are provided by USBX.

Also, if you already have an SSDT-UIAC.aml (as you should), it probably makes sense to simply add the _SB.USBX device to that SSDT instead of creating a new one.


Overriding the IOUSBHostFamily.kext/Contents/Info.plist

Although you could patch this kext Info.plist to provide different properties for any supported SMBIOS, it is desirable to do so without patching since patching would need to be redone after any update that provided a new copy of the file.

I have added support in USBInjectAll.kext to inject these properties. And, at least in my testing, the properties injected by USBInjectAll.kext are succesful in overriding those from IOUSBHostFamily.kext.

To specify power property overrides via USBInjectAll.kext, you must provide an "AppleBusPowerControllerUSB" in your UIAC.RMCF.

For example:
Code:
DefinitionBlock ("", "SSDT", 2, "hack", "usb", 0)
{
//
// Override for USBInjectAll.kext
//
    Device(UIAC)
    {
        Name(_HID, "UIA00000")
        Name(RMCF, Package()
        {
            // USB Power Properties for Sierra (using USBInjectAll injection)
            "AppleBusPowerControllerUSB", Package()
            {
                // these values happen to be iMac14,2 values...
                "kUSBSleepPortCurrentLimit", 2100,
                "kUSBSleepPowerSupply", 4700,
                "kUSBWakePortCurrentLimit", 2100,
                "kUSBWakePowerSupply", 4700,
            },
            // XHC overrides (8086:9cb1, NUC5)
            "8086_9cb1", Package()
            {
// other UIAC.RMCF content follows (for custom port injection)
...
}
//EOF

This feature is newly added in v0.6.0 of USBInjectAll.kext, so don't expect it to work in older versions.


Problem Reporting

Read FAQ, "Problem Reporting"
https://www.tonymacx86.com/threads/faq-read-first-laptop-frequent-questions.164990/
 
Signature: "ECDT" [Embedded Controller Boot Resources Table]
[03Ch 00604] UID: 00000000
[040h 0064] GPE Number: 0A
[041h 0065 19] Namepath: "\_SB.PCI0.LPCB.EC0"
As you said, my ECDT contains EC0 and cannot use rename EC0_ to EC?

Correct.
Use SSDT-EC.aml.
 
Back
Top