Contribute
Register

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

I realized that I am in the laptop support (came through the front page). Any use of this for a desktop?

This guide applies to both desktops and laptops.
 
I inserted EC but am not sure if the rest of the injection worked. ssdt-uiac and new ioreg attached.


Screenshot%202017-05-28%2019.45.15.png
 

Attachments

  • SSDT-UIAC.aml
    1,004 bytes · Views: 156
  • usbpower.zip
    760.9 KB · Views: 96
Cool, and I understood correctly that I need EC and USBX injected both right? I couldn't find USBX after injecting it, which is why I am asking,

Yes. You need both. SSDT-EC.aml causes AppleBusPowerControllerUSB to load. And SSDT-USBX.aml provides the actual power properties in ACPI from which AppleBusPowerControllerUSB "imports" them.

You could, of course, combine SSDT-EC.aml and SSDT-USBX.aml content into a single SSDT if you wanted.

You will find USBX in IOACPIPlane:
Screen Shot 2017-05-28 at 5.28.44 PM.png
 
Thank you for the detailed guide, @RehabMan. I combined the codes for EC and USBX (as outlined in post #1) into a single SSDT-XXX.aml, put it in EFI/CLOVER/ACPI/patched and my iPad Air is now charging! My mobo is a Gigabyte Z270XP-SLI.

Screen Shot 2017-05-28 at 7.24.38 PM.png Screen Shot 2017-05-28 at 7.27.10 PM.png
IMG_0019.PNG
 
Yes. You need both. SSDT-EC.aml causes AppleBusPowerControllerUSB to load. And SSDT-USBX.aml provides the actual power properties in ACPI from which AppleBusPowerControllerUSB "imports" them.

You could, of course, combine SSDT-EC.aml and SSDT-USBX.aml content into a single SSDT if you wanted.

You will find USBX in IOACPIPlane:
View attachment 258018

Thanks! I already put USBX into my Port Injection, I suppose I can throw EC in there too and keep them to a minimum
 
Thanks! I already put USBX into my Port Injection, I suppose I can throw EC in there too and keep them to a minimum

Yes... all three EC, USBX, and UIAC can be combined, and probably logically should.
 
Buddy, It is difficult to understand this guide, can you simplify this for me?
or just tell me what is exactly I wanted to do to get the proper power supply.
I'm having trouble when I connect Pendrives and external HDD together. If any USB is connected my magic mouse becomes very slow and unresponsive also when two Pendrive is connected one will eject and reconnects automatically will this guide can fix these issues?
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.

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/
 
Back
Top