Search code examples
c++macosusbhid

Can't send HID feature reports of more than 64 bytes on Mac


I have a device which exposes MaxFeatureReportSize = 263. The protocol for communicating with the device requires me to send feature reports with length of exactly 263 bytes. This works fine on Windows, but I ran into a strange problem on Mac - IOHIDDeviceSetReport on OS X 10.11 and 10.12 returns cryptic error 0xe0005000 which I couldn't deduce from IOKit headers, and code for corresponding driver (IOUSBHostHIDDevice) is closedsource.

Further investigation showed that

  1. The error doesn't appear when sending requests of 64 bytes or less. Unfortunately, this doesn't really help because the protocol is set in stone and I cannot change it - I have to send 263 bytes.
  2. On OS X 10.10 which uses old IOUSBHIDDriver instead of 0xe0005000 I get 0xe000404f error. This is kIOUSBPipeStalled, but I still get it every time I try to send more than 64 bytes.

This is as far as I got. I'm now considering downloading OS X 10.8 and debugging IOUSBFamily to see why it can't handle more than 64 byte reports. It's a shame that Apple chose to remove IOUSBFamily sources from OS X 10.9 and above.


Solution

  • The hardware protocol analyzer finally uncovered what was wrong with Mac packets. All Mac packets were 263 bytes long (exactly what I set them to be), while some Windows packets were truncated to 64 bytes (by the system!). As soon as I added a hack to truncate these packets on Mac it worked flawlessly.

    I don't know why Windows decided to truncate them - maybe because of a specific report ID (something in a descriptor?), or maybe because the actual packet length never exceeded 20 bytes and everything else was padding. But this weird behavior was actually the one that device was expecting.