Skip to content

Kinect v2 detected on Apple M4 / macOS, but start() fails with LIBUSB_ERROR_TIMEOUT and 0-byte bulk transfer #1211

Description

TITLE:
Kinect v2 detected on Apple M4 / macOS, but start() fails with LIBUSB_ERROR_TIMEOUT and 0-byte bulk transfer

BODY:

Hi,

I’m trying to get a Kinect v2 working on an Apple Silicon MacBook Pro with an Apple M4 chip.

After extensive testing, I’ve managed to compile and run libfreenect2/Protonect under x86_64/Rosetta. The Kinect is correctly detected and opened, but it consistently fails during Freenect2DeviceImpl::start() with a zero-length bulk transfer followed by LIBUSB_ERROR_TIMEOUT.

Hardware / setup

  • MacBook Pro with Apple M4
  • Kinect v2 / Xbox NUI Sensor
  • Kinect serial: 351859433947
  • Kinect external power supply connected
  • Tested multiple physical USB ports
  • USB connection confirmed as SuperSpeed 5 Gb/s

IOKit reports:

Xbox NUI Sensor
USB Vendor Name = Microsoft
USBSpeed = 4
UsbLinkSpeed = 5000000000
bcdUSB = 768
idVendor = 1118
idProduct = 708
USB Serial Number = 351859433947
UsbHostControllerProtocolRevision = 3.1

So the Kinect is negotiating at 5 Gb/s (USB 3 SuperSpeed), not USB 2.0.

What I have tried

1. openFrameworks + ofxMultiKinectV2

I initially tried using:

  • openFrameworks
  • ofxMultiKinectV2
  • ofxTurboJpeg
  • bundled libfreenect2 from ofxMultiKinectV2
  • bundled usb-1.0.0-superspeed.a

The old addon libraries contain x86_64 support:

libfreenect2.a:
Architectures: i386 x86_64

usb-1.0.0-superspeed.a:
Architectures: x86_64 i386

Getting this old project to compile on the M4 required fixing several compatibility issues:

  • Missing openFrameworks dependencies / XCFrameworks
  • Missing ofxTurboJpeg
  • Old compiler settings incompatible with Apple M4 when targeting x86_64
  • Two non-void functions in ofProtonect2.h returning no value
  • Old TurboJPEG dylib paths
  • Obsolete FMOD Ex and GLUT references/copy steps
  • Compatibility issues in the old Xcode project

Eventually the project successfully compiled:

** BUILD SUCCEEDED **

The application runs under Rosetta and detects the Kinect:

Device Count : 1
device serial: 351859433947

However, initialization fails with:

[Error] [protocol::CommandTransaction] bulk transfer failed: LIBUSB_ERROR_TIMEOUT Operation timed out

device serial: 351859433947
device firmware: <unknown>

The application therefore opens but does not receive Kinect data.

2. Modern libfreenect2 test

To rule out openFrameworks and ofxMultiKinectV2, I then cloned libfreenect2 separately and built Protonect.

I specifically wanted to test a modern version of libusb instead of the very old usb-1.0.0-superspeed.a bundled with ofxMultiKinectV2.

Homebrew libusb

Homebrew installed:

libusb 1.0.30
/opt/homebrew/opt/libusb

However, this library is ARM64.

When trying to build libfreenect2 as x86_64, the linker reported:

ld: warning: ignoring file '/opt/homebrew/opt/libusb/lib/libusb-1.0.dylib': found architecture 'arm64', required architecture 'x86_64'

This resulted in all the expected libusb symbols being unavailable.

Building libusb 1.0.30 manually for x86_64

I then cloned libusb v1.0.30 and built it manually for x86_64 using:

CFLAGS="-arch x86_64" \
CXXFLAGS="-arch x86_64" \
LDFLAGS="-arch x86_64" \
./configure \
  --prefix="$HOME/Downloads/libusb-x86" \
  --disable-shared \
  --enable-static

The resulting library is confirmed as:

Non-fat file: /Users/brendancassidy/Downloads/libusb-x86/lib/libusb-1.0.a is architecture: x86_64

Version:

libusb 1.0.30

I then configured libfreenect2 to use this x86_64 libusb instead of the ARM64 Homebrew installation.

Because the static libusb build requires macOS frameworks, the initial link failed with missing symbols including:

_IOCreatePlugInInterfaceForService
_IOIteratorNext
_IOKitWaitQuiet
_IONotificationPortCreate
_IOObjectRelease
_IORegistryEntryCreateCFProperty
_IOServiceAddMatchingNotification
_IOServiceAuthorize
_SecTaskCopyValueForEntitlement
_SecTaskCreateFromSelf

I resolved this by linking:

-framework IOKit
-framework CoreFoundation
-framework Security
-lobjc

After that, modern libfreenect2 and Protonect successfully compiled:

[ 92%] Built target freenect2
[100%] Linking CXX executable ../bin/Protonect
[100%] Built target Protonect

3. Protonect test with modern libfreenect2 + libusb 1.0.30 x86_64

I run Protonect through Rosetta using:

arch -x86_64 ./bin/Protonect

The Kinect is correctly enumerated:

[Info] [Freenect2Impl] enumerating devices...
[Info] [Freenect2Impl] 1 usb devices connected
[Info] [Freenect2Impl] found valid Kinect v2 @1:1 with serial 351859433947
[Info] [Freenect2Impl] found 1 devices

OpenCL also initializes successfully:

[Info] [OpenCLDepthPacketProcessorImpl] devices:
[Info] [OpenCLDepthPacketProcessorImpl] 0: Apple M4 (CPU)[Intel]
[Info] [OpenCLDepthPacketProcessorImpl] 1: Apple M4 (GPU)[Apple]
[Info] [OpenCLDepthPacketProcessorImpl] selected device: Apple M4 (GPU)[Apple]
[Info] [OpenCLDepthPacketProcessorImpl] building OpenCL program...
[Info] [OpenCLDepthPacketProcessorImpl] OpenCL program built successfully

The Kinect opens successfully:

[Info] [Freenect2DeviceImpl] opening...
[Info] [Freenect2DeviceImpl] transfer pool sizes rgb: 20*16384 ir: 4*128*33792
[Info] [Freenect2DeviceImpl] opened

However, it fails immediately during start():

[Info] [Freenect2DeviceImpl] starting...

[Error] [protocol::CommandTransaction] bulk transfer too short! expected at least: 1302572 got : 0

[Info] [Freenect2DeviceImpl] closing...

[Error] [protocol::CommandTransaction] bulk transfer failed: LIBUSB_ERROR_TIMEOUT Operation timed out
[Error] [protocol::CommandTransaction] bulk transfer failed: LIBUSB_ERROR_TIMEOUT Operation timed out
[Error] [protocol::CommandTransaction] bulk transfer failed: LIBUSB_ERROR_TIMEOUT Operation timed out

[Info] [Freenect2DeviceImpl] releasing usb interfaces...
[Info] [Freenect2DeviceImpl] deallocating usb transfer pools...
[Info] [Freenect2DeviceImpl] closing usb device...
[Info] [Freenect2DeviceImpl] closed

4. CPU pipeline test

To rule out OpenCL / Apple GPU compatibility, I also ran:

arch -x86_64 ./bin/Protonect cpu

The Kinect is again detected and opened successfully:

[Info] [Freenect2Impl] 1 usb devices connected
[Info] [Freenect2Impl] found valid Kinect v2 @1:2 with serial 351859433947
[Info] [Freenect2Impl] found 1 devices

[Info] [Freenect2DeviceImpl] opening...
[Info] [Freenect2DeviceImpl] transfer pool sizes rgb: 20*16384 ir: 4*128*33792
[Info] [Freenect2DeviceImpl] opened
[Info] [Freenect2DeviceImpl] starting...

But the exact same error occurs:

[Error] [protocol::CommandTransaction] bulk transfer too short! expected at least: 1302572 got : 0

[Info] [Freenect2DeviceImpl] closing...

[Error] [protocol::CommandTransaction] bulk transfer failed: LIBUSB_ERROR_TIMEOUT Operation timed out
[Error] [protocol::CommandTransaction] bulk transfer failed: LIBUSB_ERROR_TIMEOUT Operation timed out
[Error] [protocol::CommandTransaction] bulk transfer failed: LIBUSB_ERROR_TIMEOUT Operation timed out

Therefore, the problem does not appear to be related to OpenCL or GPU processing.

5. libusb debug output

I also enabled detailed libusb logging.

Immediately before the libfreenect2 error I get:

libusbx: debug [darwin_async_io_callback] an async io operation has completed
libusbx: debug [handle_events] poll() returned 1
libusbx: debug [darwin_handle_callback] handling bulk completion with kernel status -536854447
libusbx: warning [darwin_transfer_status] transfer error: timed out
libusbx: debug [sync_transfer_cb] actual_length=0

[Error] [protocol::CommandTransaction] bulk transfer failed: LIBUSB_ERROR_TIMEOUT Operation timed out

So the USB operation reaches the Darwin callback, but completes with a timeout and actual_length=0.

6. USB connection / different ports

I tested multiple physical USB ports on the Mac.

Depending on the port/reconnection, libfreenect2 reports locations such as:

found valid Kinect v2 @3:1
found valid Kinect v2 @1:1

and:

found valid Kinect v2 @1:2

The failure is identical in every case.

IOKit correctly detects the device as:

Xbox NUI Sensor
USB Vendor Name = Microsoft

and reports:

USBSpeed = 4
UsbLinkSpeed = 5000000000

The relevant IOKit information is:

"USBSpeed" = 4
"UsbLinkSpeed" = 5000000000
"idProduct" = 708
"bcdUSB" = 768
"kUSBSerialNumberString" = "351859433947"
"USB Product Name" = "Xbox NUI Sensor"
"USB Vendor Name" = "Microsoft"
"idVendor" = 1118
"USB Serial Number" = "351859433947"

The host controller reports:

UsbHostControllerProtocolRevision = "3.1"

So the Kinect is definitely negotiating at USB 3 SuperSpeed / 5 Gb/s rather than falling back to USB 2.0.

Current state

At this point I believe I have ruled out:

  • ofxMultiKinectV2 itself
  • the old bundled libusb
  • OpenCL / GPU processing
  • accidental USB 2.0 negotiation
  • one specific physical USB port
  • inability to enumerate the Kinect
  • inability to open the Kinect

The device can successfully:

  1. Be enumerated
  2. Be identified as a Kinect v2
  3. Return its serial number
  4. Be opened by libfreenect2
  5. Allocate its USB transfer pools

The failure consistently occurs during:

Freenect2DeviceImpl::start()

The critical error is:

[Error] [protocol::CommandTransaction] bulk transfer too short! expected at least: 1302572 got : 0

followed by:

[Error] [protocol::CommandTransaction] bulk transfer failed: LIBUSB_ERROR_TIMEOUT Operation timed out

This happens both with the old ofxMultiKinectV2 setup and with a separate modern libfreenect2 build using libusb 1.0.30 compiled specifically for x86_64.

Questions

Has anyone successfully used a Kinect v2 with libfreenect2 on an Apple M4 Mac with a recent version of macOS?

More specifically:

  1. Is this a known issue with libusb's Darwin backend / IOUSBHost on Apple Silicon or recent versions of macOS?

  2. Could running x86_64 libusb/libfreenect2 through Rosetta cause this kind of USB bulk transfer failure even though device enumeration, serial access and opening all work correctly?

  3. Does the expected at least: 1302572 got: 0 transaction correspond to a specific Kinect initialization command that could help identify exactly where communication is failing?

  4. Is there a known patch or workaround for modern Apple Silicon USB controllers / IOUSBHost?

  5. Would building libfreenect2 and its dependencies natively for ARM64 potentially behave differently at the USB layer?

  6. Is there additional libfreenect2/libusb debugging I can enable to see the exact endpoint, command and transaction that is timing out?

  7. Is there anything else worth testing before concluding that this is an incompatibility between the Kinect v2 USB protocol and the current Apple Silicon/macOS USB stack?

I’m happy to test patches, instrument CommandTransaction, rebuild libusb/libfreenect2, or provide the complete libusb debug logs.

Any help would be greatly appreciated.

Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions