MacBook – kIOUSBEndpointCountExceeded error when plugging in USB device

macbook prousb

I keep a lot of USB devices plugged into my 15-inch Mid 2012 MacBook Pro for my job.

This MacBook Pro has 2 external USB ports. In one is for a laptop fan, and the other is a USB hub which has another USB hub and my Dell U2713HM monitor's hub.

Devices would seemingly not work at random or otherwise be… half detected? They'd appear in the USB device list but not work correctly, even though they have in the past. Passing them through to a Windows install on Parallels had just as half-results. Often the device was detected at the USB level but failed at the software level. Plugging them into a dedicated Windows laptop showed they worked fine.

I installed the IOUSBFamily logging drivers. USB Prober.app with detail set to 5 showed the following in the log when plugging in a device:

Sep  2 10:52:41.274  [5]    AppleUSBHub[0xffffff8026d7f800]::ProcessStatusChanged found (0x       2) in statusChangedBitmap
Sep  2 10:52:41.274  [3]    AppleUSBHub[0xffffff8026d7f800]::ChangeRaisedPowerState(+) now (1)
Sep  2 10:52:41.274  [5]    AppleUSBHubPort[0xffffff802703d200]::PortStatusChangedHandler: port 1 obtained runLock (_hasExternalConnector: 0)
Sep  2 10:52:41.274  [5]    AppleUSBHubPort[0xffffff802703d200]::PortStatusChangedHandler: calling GetPortStatus for port 1
Sep  2 10:52:41.274  [5]    AppleUSBHub[0xffffff8026d7f800]::powerChangeDone - spawning _checkForActivePortsThread
Sep  2 10:52:41.274  [4]    AppleUSBHub[0xffffff8026d7f800]::CheckForActivePorts - this hub does not allow low power, so abandoning
Sep  2 10:52:41.274  [5]    AppleUSBHubPort[0xffffff802703d200]::PortStatusChangedHandler - Hub 0x14221000 port 1 - Initial status(0x0101)/change(0x0001)
Sep  2 10:52:41.274  [5]    AppleUSBHubPort[0xffffff802703d200]::PortStatusChangedHandler - port 1 - change 6 clearing feature 0x10 (kUSBHubPortConnectionChangeFeature)
Sep  2 10:52:41.274  [5]    AppleUSBHub[0xffffff8026d7f800]::ClearPortFeature port/feature (10010) - clearing
Sep  2 10:52:41.274  [5]    AppleUSBHubPort[0xffffff802703d200]::PortStatusChangedHandler - port 1 - status(0x0101) - change(0x0000) - before call to (6) handler function
Sep  2 10:52:41.274  [5]    AppleUSBHubPort[0xffffff802703d200]::DefaultConnectionChangeHandler - handling port 1 changes (0x0101,0x0000)
Sep  2 10:52:41.274  [3]    AppleUSBHubPort[0xffffff802703d200]::DefaultConnectionChangeHandler port (1) - previous enumeration failed - sleeping 300 ms
Sep  2 10:52:41.575  [5]    AppleUSBHubPort[0xffffff802703d200]::DefaultConnectionChangeHandler - port 1 - no existing device found on port
Sep  2 10:52:41.575  [4]    AppleUSBHubPort[0xffffff802703d200]::DefaultConnectionChangeHandler port 1 status(0x0101)/change(0x0000) - no error from GetPortStatus
Sep  2 10:52:41.575  [5]    AppleUSBHubPort[0xffffff802703d200]::DefaultConnectionChangeHandler - port 1 - device detected, calling AddDevice
Sep  2 10:52:41.575  [3]    AppleUSBHub[0xffffff8026d7f800]::ChangeRaisedPowerState(+) now (2)
Sep  2 10:52:41.575  [5]    AppleUSBHubPort[0xffffff802703d200]::DefaultConnectionChangeHandler - port 1 done, ending (_portPMState: 3)
Sep  2 10:52:41.575  [5]    AppleUSBHubPort[0xffffff802703d200]::PortStatusChangedHandler - port 1 - err (0) on return from  call to (6) handler function
Sep  2 10:52:41.575  [5]    AppleUSBHubPort[0xffffff802703d200]::PortStatusChangedHandler - port 1 - err = 0 - done, releasing _runLock
Sep  2 10:52:41.575  [3]    AppleUSBHub[0xffffff8026d7f800]::ChangeRaisedPowerState(-) now (1)
Sep  2 10:52:41.575  [3]    AppleUSBHub[0xffffff8026d7f800]::DecrementOutstandingIO(1018), outstandingIO(0), _interruptReadPending(false) - rearming read
Sep  2 10:52:41.575  [5]    AppleUSBHub[0xffffff8026d7f800]::DecrementOutstandingIO(1018) - spawning _checkForActivePortsThread
Sep  2 10:52:41.575  [5]    ***** AppleUSBHubPort[0xffffff802703d200]::AddDevice - port 1 on hub at 0x14221000 - start (options: 0x00000000)
Sep  2 10:52:41.575  [4]    AppleUSBHub[0xffffff8026d7f800]::CheckForActivePorts - this hub does not allow low power, so abandoning
Sep  2 10:52:41.575  [5]    ***** AppleUSBHubPort[0xffffff802703d200]::AddDevice - port 1 on hub at 0x14221000 - bus 0xffffff81a6082000 - acquiring dev zero lock
Sep  2 10:52:41.575  [5]    AppleUSBXHCI[0xffffff81a6082000]::ProtectedDevZeroLock - about to obtain device zero lock
Sep  2 10:52:41.575  [5]    AppleUSBXHCI[0xffffff81a6082000]::ProtectedDevZeroLock - not already locked - obtaining
Sep  2 10:52:41.575  [5]    AppleUSBXHCI[0xffffff81a6082000]::ProtectedDevZeroLock - setting _devZeroLock to true
Sep  2 10:52:41.575  [5]    AppleUSBXHCI[0xffffff81a6082000]::AcquireDeviceZero  Acquired devZeroLock
Sep  2 10:52:41.575  [3]    AppleUSBHub[0xffffff8026d7f800]::ChangeRaisedPowerState(+) now (2)
Sep  2 10:52:41.576  [5]    ***** AppleUSBHubPort[0xffffff802703d200]::AddDevice - port 1 on hub at 0x14221000 - resetting port
Sep  2 10:52:41.576  [5]    AppleUSBHub[0xffffff8026d7f800]::SetPortFeature port/feature (0x10004) - setting
Sep  2 10:52:41.594  [5]    AppleUSBHub[0xffffff8026d7f800]::ProcessStatusChanged found (0x       2) in statusChangedBitmap
Sep  2 10:52:41.594  [3]    AppleUSBHub[0xffffff8026d7f800]::ChangeRaisedPowerState(+) now (3)
Sep  2 10:52:41.594  [5]    AppleUSBHubPort[0xffffff802703d200]::PortStatusChangedHandler: port 1 obtained runLock (_hasExternalConnector: 0)
Sep  2 10:52:41.594  [5]    AppleUSBHubPort[0xffffff802703d200]::PortStatusChangedHandler: delaying 100ms before first GetPortStatus after a reset of port 1
Sep  2 10:52:41.595  [5]    ***** AppleUSBHubPort[0xffffff802703d200]::AddDevice - port 1 on hub at 0x14221000 - (err = 0) done - (0x0503, 0x0010), returning
Sep  2 10:52:41.595  [3]    AppleUSBHub[0xffffff8026d7f800]::ChangeRaisedPowerState(-) now (2)
Sep  2 10:52:41.694  [5]    AppleUSBHubPort[0xffffff802703d200]::PortStatusChangedHandler: calling GetPortStatus for port 1
Sep  2 10:52:41.694  [5]    AppleUSBHubPort[0xffffff802703d200]::PortStatusChangedHandler - Hub 0x14221000 port 1 - Initial status(0x0503)/change(0x0010)
Sep  2 10:52:41.694  [5]    AppleUSBHubPort[0xffffff802703d200]::PortStatusChangedHandler - port 1 - change 2 clearing feature 0x14 (kUSBHubPortResetChangeFeature)
Sep  2 10:52:41.694  [5]    AppleUSBHub[0xffffff8026d7f800]::ClearPortFeature port/feature (10014) - clearing
Sep  2 10:52:41.695  [5]    AppleUSBHubPort[0xffffff802703d200]::PortStatusChangedHandler - port 1 - status(0x0503) - change(0x0000) - before call to (2) handler function
Sep  2 10:52:41.695  [5]    ***** AppleUSBHubPort[0xffffff802703d200]::AddDeviceResetChangeHandler - port 1 on hub at 0x14221000 - start - status(0x0503) change (0x0000)
Sep  2 10:52:41.695  [3]    **1** AppleUSBHubPort[0xffffff802703d200]::AddDeviceResetChangeHandler - port 1 on hub at 0x14221000 - new delay 300
Sep  2 10:52:41.695  [5]    **1** AppleUSBHubPort[0xffffff802703d200]::AddDeviceResetChangeHandler - port 1 on hub at 0x14221000 - delaying 300 ms
Sep  2 10:52:41.995  [5]    **2** AppleUSBHubPort[0xffffff802703d200]::AddDeviceResetChangeHandler - port 1 on hub at 0x14221000 - found high speed device
Sep  2 10:52:41.995  [5]    **2** AppleUSBHubPort[0xffffff802703d200]::AddDeviceResetChangeHandler - port 1 on hub at 0x14221000 - configuring dev zero
Sep  2 10:52:41.995  [5]    AppleUSBHubPort[0xffffff81a6082000]::DoConfigureDeviceZero - maxPacketSize: 64, speed: 2, hub: 10, port: 1
Sep  2 10:52:41.995  [3]    AppleUSBXHCI[0xffffff81a6082000]::UIM **** - ConfigureDeviceZero maxPacketSize:64, speed:2, hub:10, adj port:1
Sep  2 10:52:41.995  [5]    AppleUSBXHCI[0xffffff81a6082000]::ConfigureDeviceZero, new method called with speed : 2, hub:10, port:1
Sep  2 10:52:41.995  [5]    AppleUSBXHCI[0xffffff81a6082000]::UpdateTopology, high speed ancestor hub:0, port:0
Sep  2 10:52:41.995  [5]    AppleUSBXHCI[0xffffff81a6082000]::DoCreateEP, high speed ancestor hub:0, port:0, address: 0, speed: 2, maxStreams: 0, maxBurst: 0, mult: 0 EP: (0,0,64,0)
Sep  2 10:52:41.995  [1]    AppleUSBXHCI[0xffffff81a6082000]::TestConfiguredEpCount (kIOUSBEndpointCountExceeded) - sub 2 _configuredEndpointCount, was:(97)
Sep  2 10:52:41.995  [1]    AppleUSBXHCI[0xffffff81a6082000]::DoCreateEP - Received a kIOUSBEndpointCountExceeded, Address: 0, Speed: 2:  Endpoint: (0x0, 0x0, 0x40, 0x0)
Sep  2 10:52:41.995  [3]    AppleUSBXHCI[0xffffff81a6082000]::ConfigureDeviceZero (maxPacketSize: 64, Speed: 2) returned 0xe0004046 (Controller does not support more endpoints)
Sep  2 10:52:41.995  [3]    ASM107x[0xffffff802703dc00] DisplayUserNotification type 0x1000007
Sep  2 10:52:41.995  [3]    ASM107x[0xffffff802703dc00]::DisplayUserNotificationForDevice notificationType: 7, port 1
Sep  2 10:52:41.995  [5]    **3** AppleUSBHubPort[0xffffff802703d200]::AddDeviceResetChangeHandler - port 1 on hub at 0x14221000 - failed to create device zero, detach'ing device
Sep  2 10:52:41.995  [5]    AppleUSBHub[0xffffff8026d7f800]::ClearPortFeature port/feature (10001) - clearing
Sep  2 10:52:41.995  [3]    AppleUSBHub[0xffffff8026d7f800]::ChangeRaisedPowerState(-) now (1)
Sep  2 10:52:41.995  [3]    AppleUSBXHCI[0xffffff81a6082000]::UIMDeleteEndpoint - fn:0, ep:0, dir:3
Sep  2 10:52:41.995  [3]    AppleUSBXHCI[0xffffff81a6082000]::GetSlotID - functionNumber disabled: 0
Sep  2 10:52:41.995  [5]    AppleUSBXHCI[0xffffff81a6082000]::ProtectedDevZeroLock - about to release device zero lock
Sep  2 10:52:41.995  [5]    AppleUSBXHCI[0xffffff81a6082000]::ProtectedDevZeroLock - releasing lock
Sep  2 10:52:41.995  [5]    AppleUSBXHCI[0xffffff81a6082000]::ProtectedDevZeroLock - wakeup done
Sep  2 10:52:41.995  [5]    AppleUSBHubPort[0xffffff802703d200]::PortStatusChangedHandler - port 1 - err (0) on return from  call to (2) handler function
Sep  2 10:52:41.995  [5]    AppleUSBHubPort[0xffffff802703d200]::PortStatusChangedHandler - port 1 - err = 0 - done, releasing _runLock
Sep  2 10:52:41.995  [3]    AppleUSBHub[0xffffff8026d7f800]::ChangeRaisedPowerState(-) now (0)
Sep  2 10:52:41.995  [3]    AppleUSBHub[0xffffff8026d7f800]::DecrementOutstandingIO(1023), outstandingIO(0), _interruptReadPending(false) - rearming read
Sep  2 10:52:41.995  [5]    AppleUSBHub[0xffffff8026d7f800]::powerChangeDone - spawning _checkForActivePortsThread
Sep  2 10:52:41.995  [4]    AppleUSBHub[0xffffff8026d7f800]::CheckForActivePorts - this hub does not allow low power, so abandoning

The error is on these lines:

Sep  2 10:52:41.995  [1]    AppleUSBXHCI[0xffffff81a6082000]::TestConfiguredEpCount (kIOUSBEndpointCountExceeded) - sub 2 _configuredEndpointCount, was:(97)
Sep  2 10:52:41.995  [1]    AppleUSBXHCI[0xffffff81a6082000]::DoCreateEP - Received a kIOUSBEndpointCountExceeded, Address: 0, Speed: 2:  Endpoint: (0x0, 0x0, 0x40, 0x0)

Source for IOUSBControllerV2.cpp, which throws that error. Sadly, that file is rather aged, as Apple no longer releases that source. The source is for 10.8.4 and I'm on 10.9.4.

The error is defined in USB.h as #define kIOUSBEndpointCountExceeded // 0xe0004046 The endpoint was not created because the controller cannot support more endpoints but sadly that's just as little detail.

The name of the error suggests that it's an exceeded device limit (dur), so I unplugged a lot of devices and after plugging in just one it was detected and working fine.

My questions are:

  • Where is the limitation?
  • Is this documented?
  • Is there a workaround?

Best Answer

Patching the kernel to work around the issue

I do not recommend you do this. You're editing the binary of a very important file. If it gets messed up, well, ya. But this is the only solution.

This is likely 10.9.4 specific.

Location 0x00016942 of /System/Library/Extensions/IOUSBFamily.kext/Contents/PlugIns/AppleUSBXHCI.kext/Contents/MacOS/AppleUSBXHCI should contain 66 B9 60 00. That translates to mov cx, 60h

I edited it to 66 B9 *80* 00 and all of my devices come online now. I assume going even higher, or removing the "errata" check altogether, is also safe. If you run into trouble you can just unplug devices and reboot.


Research

It appears to be breaking inside of the function AppleUSBXHCI::TestConfiguredEpCount in AppleUSBXHCIUIM.cpp.

Which is using a max value, which is set from:

// default max number of endpoints we allow to be configured
_maxControllerEndpoints = kMaxXHCIControllerEndpoints;

// this will switch the mux for panther point
EnableXHCIPorts();

if( (_errataBits & kXHCIErrataPPT) != 0)
{   
    // Panther Point - limit endpoints to 64 <rdar://problem/10385765>
    // does this need a separate errata bit?
    _maxControllerEndpoints = 64;
}

The flags are being set by this code

static ErrataListEntry  errataList[] = {

    {0x1033, 0x0194, 0, 0xffff, kXHCIErrata_NEC},   // NEC XHCI, check firmware
    {0x1b73, 0x1000, 0, 0xffff, kXHCIErrata_NoMSI}, // Fresco Logic XHCI
    {0x8086, 0x1e31, 0, 0xffff, kXHCIErrataPPT | kXHCIErrataPPTMux | kXHCIErrata_EnableAutoCompliance | kErrataSWAssistXHCIIdle | kXHCIErrata_ParkRing},    // Intel Panther Point
    {0x1b21, 0, 0, 0xffff,  kXHCIErrata_ASMedia},   // ASMedia XHCI
    {0x1b73, 0, 0, 0xffff, kXHCIErrata_FrescoLogic},// Fresco Logic
    {0x1b73, 0x1100, 0, 16, kXHCIErrata_FL1100_Ax}, // Fresco Logic FL1100-Ax
    {0x1b6f, 0x7052, 1, 0xffff, kXHCIErrata_Etron7052}
};

0x1e31 is the Device ID of my MacBook Pro's built in USB controller!

The logging shows my max limit is set to 96 (it hits 97 and sets the err value causing it to revert). This source is old as Apple has closed the source to IOUSBFamily a while ago, so there's no real way to tell where the 96 is coming from, but the conclusion appears to be my hub is black listed by the OSX kernel for reasons unknown.

Apple increased the limit by 50% in 10.8, where it was 64, to 96 in 10.9. This shows that the number is arbitrary. The hardware did not change but there was a 50% increase allowed in the software, that's a significant change. But why not 128? Why not 95, or 96? The units of power of two are likely also meaningless here.


Why 96 end points is a very low limit

Each one of my USB hubs has 3 USB controllers inside of it. Each one supports "Full/Low Speed" and "SuperSpeed." Each one of those has an endpoint for input, and one for output. 3 hubs * 3 controllers each * 2 protocols each controller * 2 for IO = 36 end points... just on hubs!

The bluetooth built into the laptop uses 8, the HD FaceTime Camera uses 6, a Nexus 4 uses 6.

96 is a very low amount of end points.