Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open a specific interface on OS X #193

Open
sduensin opened this issue Oct 16, 2014 · 24 comments
Open

Open a specific interface on OS X #193

sduensin opened this issue Oct 16, 2014 · 24 comments

Comments

@sduensin
Copy link

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?

@sduensin
Copy link
Author

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.

@sduensin
Copy link
Author

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)));

@signal11
Copy link
Owner

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.

@sduensin
Copy link
Author

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?

@signal11
Copy link
Owner

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?

@sduensin
Copy link
Author

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

@signal11
Copy link
Owner

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.

@sduensin
Copy link
Author

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()?

@signal11
Copy link
Owner

All true. Maybe the
enumerate -> store path -> free enumeration -> open
use case was the problem. Check the git log on mac/hid.c

@sduensin
Copy link
Author

That's how I was using it, too. :-)

@mrpippy
Copy link
Contributor

mrpippy commented Oct 31, 2014

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.

#40

@signal11
Copy link
Owner

signal11 commented Nov 3, 2014

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.

  1. Rebase with the latest HIDAPI.
  2. Move patch Mac #2 to first (weak link against 10.5)
  3. Combine the other two patches.

The idea is that each commit needs to compile and operate properly.

Thanks bud,

Alan.

@sduensin
Copy link
Author

sduensin commented Nov 3, 2014

This sounds fantastic. Thanks gang!

@mrpippy
Copy link
Contributor

mrpippy commented Nov 6, 2014

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 😛

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

@travisgoodspeed
Copy link

This patch is a godsend when working with HID devices that have multiple interfaces on OS X. Thank you kindly, @mrpippy.

@hallidayts
Copy link

Is this patch available for download from the git hub?

@joakim
Copy link

joakim commented Feb 14, 2015

@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.

@pepijndevos
Copy link

Here is your spoon: https://www.youtube.com/watch?v=dYBjVTMUQY0

Also, this patch is great, please merge it.

@joakim
Copy link

joakim commented Feb 21, 2015

Haha, thank you very much. Can't believe I hadn't heard of the technique before.

@amadsen
Copy link

amadsen commented Nov 12, 2016

Can the fix merged for #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.)

@zzyppo
Copy link

zzyppo commented Nov 29, 2017

@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!

@mrpippy
Copy link
Contributor

mrpippy commented Dec 1, 2017

@zzyppo Try this code in hid_enumerate():

/* Interface Number */
cur_dev->interface_number = get_int_property(dev, CFSTR(kUSBInterfaceNumber));

@jschloer
Copy link

@mrpippy and @zzyppo I also had to add the following to the includes section( line 27 for me)

#include <IOKit/usb/USBSpec.h>

@dylanmckay
Copy link

dylanmckay commented Feb 15, 2018

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.

erikolofsson pushed a commit to Malterlib/hidapi that referenced this issue Nov 25, 2020
…#193)

It improves backward compatibility with versions of hidapi, where
usage/usage_pairs didn't emit seaprate hid_devices_info.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests