hidapi
hidapi copied to clipboard
Open a specific interface on OS X
I know interfaces aren't supported on OS X. The work-around to check the usage to be sure you have the correct one is fine... except then what? I can either hid_open or hid_open_path. Both end up using the path to the device - which could be either interface in my case.
If I call hid_open_path twice with the same path, will I get each one? Or can it open whatever it finds first more than once? I wrote some test code to check this case and it seems it just opens whatever it wants.
I really need to get a handle to each interface on this device in OS X. Ideas?
Bit more info:
I wrote some test code to try and open the path more than twice. The third time fails, so this is good. It appears that I'm opening each interface.
When I enumerate devices, I see one interface on usage 0 and one on 5. I wrote some code to take these handles and query IOKit for what it thinks the usages are. I either get two zeros or two fives. This doesn't make any sense to me.
Okay. Much test code later I've learned that my prior test of opening the same path multiple times to get the different interfaces was bad. It does open the same one every time. So sometimes you get what you want as the first one opened, sometimes not.
I ended up modifying make_path() to include the usage so I could later hid_open_path() the exact one I wanted...
res = snprintf(buf, len, "%s_%04hx_%04hx_%x_%02d",
transport, vid, pid, location,
get_int_property(device, CFSTR(kIOHIDPrimaryUsageKey)));
A "device" as reported by hid_enumerate() is really a USB interface. The path points to an interface. This is the same on all platforms.
I get the same path for both interfaces on the Razer Hydra on OS X. There was no way for me to open a particular one without the above modification. Am I missing something?
hmm, so there are two "devices" (interfaces) with the same "path." We need something in the constructed path to differentiate them. Usage is not good enough because they could both have the same usage. Is there any other property (maybe one with the interface number in it) which would be better?
Using the 'usage' was a hack for this particular case. I don't really know a proper solution. Perhaps another open method that can take a device handle from hid_enumerate? Then we don't care if the path is the same.
I'm using hidapi because I don't know enough to do it myself. :-P You're the expert! :-D
Perhaps another open method that can take a device handle from hid_enumerate?
It seems like I used to use the handle (pointer) as part of the constructed path. Have a look at the git log to see why I may have taken that out. I can't remember what the story was there. If there's no good reason not to, maybe we should do that.
Then we don't care if the path is the same.
If we used the handle as part of the path, then the paths won't be the same.
If it's consistent, that'd be great. OS X seems to just return devices in whatever order it feels like at that particular moment. Would you have to open it before you free'd the list returned by hid_enumerate()?
All true. Maybe the enumerate -> store path -> free enumeration -> open use case was the problem. Check the git log on mac/hid.c
That's how I was using it, too. :-)
I made a branch/pull request long ago to use real IOKit paths instead of constructing paths.
The resulting paths look like: IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/EHC1@1D,7/ AppleUSBEHCI/PLAYSTATION(R)3 Controller@fd12000/IOUSBInterface@0/IOUSBHIDDriver
I haven't tested multiple interfaces but maybe it would have IOUSBInterface@1
, etc.
https://github.com/signal11/hidapi/pull/40
Hi Brendan,
I'm sorry. I forgot all about this. Are there any glaring drawbacks to your method? I'm sure you probably don't have 10.4, but do you know whether it should work on 10.4? You mention testing on 10.5. It may be ok to not work on 10.4. It's pretty old at this point. Maybe it already doesn't work on 10.4. I don't remember.
I'm happy to get this in.
- Rebase with the latest HIDAPI.
- Move patch #2 to first (weak link against 10.5)
- Combine the other two patches.
The idea is that each commit needs to compile and operate properly.
Thanks bud,
Alan.
This sounds fantastic. Thanks gang!
Hey Alan,
I rebased on the latest master and ended up squashing it all into one commit. The "-mmacosx-version-min=10.5" part isn't a big patch and it's only needed for IOHIDDeviceGetService()
.
I can split it out if you want though.
HIDAPI doesn't work on 10.4 anyway, the HID Manager didn't exist until 10.5 :stuck_out_tongue:
My app has been shipping for at least a year/year and a half with this patch, so I think the basic functionality (enumeration, etc) should be solid. The only drawback I can see is that it is a significant change, and there always could be new bugs / HID Manager fragility exposed.
Also I found a very easy way to get the USB bInterfaceNumber for a HID device, just want to test and see what happens with a non-USB HID device connected. I'll make a separate pull request for that.
Brendan
This patch is a godsend when working with HID devices that have multiple interfaces on OS X. Thank you kindly, @mrpippy.
Is this patch available for download from the git hub?
@hallidayts It's available from @mrpippy's fork: https://github.com/mrpippy/hidapi/tree/iokit_path
Works great for me! I'm using it from node-hid, which I forked from another fork to make it work with Node 0.11.x and to use mrpippy's fork of hidapi. Enough forks, I need a spoon.
Here is your spoon: https://www.youtube.com/watch?v=dYBjVTMUQY0
Also, this patch is great, please merge it.
Haha, thank you very much. Can't believe I hadn't heard of the technique before.
Can the fix merged for https://github.com/signal11/hidapi/pull/288 be considered as fixing this issue as well? The paths for a multifunction device are now different (and, if I am not mistaken, based on @mrpippy's code.)
@mrpippy
"Also I found a very easy way to get the USB bInterfaceNumber for a HID device, just want to test and see what happens with a non-USB HID device connected. I'll make a separate pull request for that."
Hello! I wanted to ask, if the solution for getting the bInterfaceNumber is somewhere existing? I cannot find it. I really only need this interface number and I dont care if it is not correctly handled for non-HID devices. I would be grateful if you could explain me your solution you found back then. Incredible that Apple restricts such a basic information.
Thank you!
@zzyppo Try this code in hid_enumerate()
:
/* Interface Number */
cur_dev->interface_number = get_int_property(dev, CFSTR(kUSBInterfaceNumber));
@mrpippy and @zzyppo I also had to add the following to the includes section( line 27 for me)
#include <IOKit/usb/USBSpec.h>
I've taken the two patches posted (thanks @mrpippy and @jschloer!) and turned it into a PR.
It is not clear if the interface number returned from IOKit is valid for non-HID devices. Because of this, I have opted to simply store the interface number if and only if the USB device is an HID device.
See #380
If anybody would like to use my branch, it is at dylanmckay:mac-hid-interface-support.