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

libusb_claim_interface() fails when compiled under macOS 10.14 and then running on a previous macOS release #519

Closed
morejanus opened this Issue Jan 9, 2019 · 11 comments

Comments

Projects
None yet
2 participants
@morejanus
Copy link

morejanus commented Jan 9, 2019

The following IOKit call inside darwin_claim_interface() fails and returns an error if built under 10.14 and run on a previous release.

/* Do the actual claim */
kresult = (*plugInInterface)->QueryInterface(plugInInterface,
CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID),
(LPVOID)&cInterface->interface);

Because it's passing in the IOKit define, kIOUSBInterfaceInterfaceID, it's using the newest ABI like this from IOUSBLib.h:
// The preferred interface ID is the newest version
#define kIOUSBInterfaceInterfaceID kIOUSBInterfaceInterfaceID942

and the newest Apple USB interface, "942" which is not available in previous macOS releases.

I think the code should be using it's own define instead, InterfaceInterfaceID, which will match the desired version of the IOUSBFamily as configured in darwin_usb.h using MAC_OS_X_VERSION_MIN_REQUIRED

@hjelmn

This comment has been minimized.

Copy link
Member

hjelmn commented Jan 15, 2019

Would take some work to match IOKit versions with macOS versions.

The recommended way of building for an older macOS release is to run configure like this:

./configure CFLAGS="-isysroot=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk" LDFLAGS="-isysroot=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk"

With whatever SDK you want to target. This is what Xcode does (or at least did) when you set the macOS SDK.

@hjelmn hjelmn added the macOS label Jan 15, 2019

@hjelmn

This comment has been minimized.

Copy link
Member

hjelmn commented Jan 15, 2019

The reason for the recommendation to use the isysroot (and why I never bothered to use the InterfaceInterfaceID macro-- even though we defined it) is that some of the other configure logic may necessary correctly detect other differences. I haven't really taken the time to see what works and what doesn't. I know isysroot does the right thing.

@morejanus

This comment has been minimized.

Copy link
Author

morejanus commented Jan 17, 2019

In 10.14, Apple changed the previously generically defined kIOUSBInterfaceInterfaceID to instead be defined as kIOUSBInterfaceInterfaceID942, (ie: the "942" version of the interface), which is specific to macOS 10.14 and macOS 10.14 only and is not available in previous macOS releases.

What was kIOUSBInterfaceInterfaceID in 10.13 and previous releases, is now defined as kIOUSBInterfaceInterfaceID100.

So Apple has changed out from underneath libusb, what the definition of kIOUSBInterfaceInterfaceID is and what it is meant to be.

So when you use a BASE SDK (aka isysroot) of 10.14, but your DEPLOYMENT SDK is any previous release, the runtime call to darwin_claim_interface()/QueryInterface() on eg: 10.13 will fail because libusb is now asking for the "942" version of the interface which doesn't exist in eg: 10.13.

@hjelmn

This comment has been minimized.

Copy link
Member

hjelmn commented Jan 17, 2019

@morejanus Yeah, I always assumed that if someone wanted to target an older release they would download and use the SDK for that release. With an older SDK the definition of kIOUSBInterfaceInterfaceID changes to match that release (i am 99% sure of this). It guarantees that the libusb build will work. It might also work if we just change kIOUSBInterfaceInterfaceID to InterfaceInterfaceID but without testing each case I don't know. If it works for you I am willing to make the change but will heavily caveat it in the README :).

@morejanus

This comment has been minimized.

Copy link
Author

morejanus commented Jan 17, 2019

"Yeah, I always assumed that if someone wanted to target an older release they would download and use the SDK for that release."

Wouldn't that be lovely! But no, not possible. With the current release of Xcode on 10.14, the only option available as a BASE SDK is 10.14. You can't build against any other/previous SDK (without installing an older version of Xcode). So unless you only want your App to work on 10.14, you set your DEPLOYMENT TARGET to be what turns into MAC_OS_X_VERSION_MIN_REQUIRED.

Changing it to InterfaceInterfaceID works for me, but I don't know if this is the right fix for the macOS libusb community.

Given that the old kIOUSBInterfaceInterfaceID is now defined as kIOUSBInterfaceInterfaceID100, I'm guessing that it never did change which was probably the bug. (I don't have access to enough older versions of the file to check). But the binary interface didn't change in every release, just releases where they revved the USB interface. If you look at the comments inside IOUSBLib.h, it's like every other macOS release or so.

@hjelmn

This comment has been minimized.

Copy link
Member

hjelmn commented Jan 17, 2019

It is possible. You download an old Xcode from developer.apple.com then copy the SDK out of it and into your current XCode install. I have done this many times and have SDKs for 10.14, 10.12, and 10.8 installed with XCode 10.1 specifically to build for older releases.

It used to be easier to install older SDKs, I give you that, but it is still possible and the recommended way to target an older release. That way any difference between releases is properly captured. Remember that if MAC_OS_X_VERSION_MIN_REQUIRED was sufficient then Apple would define kIOUSBInterfaceInterfaceID differently. Maybe they intended to and this is a bug in IOKit.

@hjelmn

This comment has been minimized.

Copy link
Member

hjelmn commented Jan 17, 2019

Looking at 10.13 SDK what changed was a deliberate change by Apple. This is the definition in 10.13:

// 73c97ae8-9ef3-11d4-b1d0-000a27052861
/*!
    @defined kIOUSBInterfaceInterfaceID
    @discussion This UUID constant is used to obtain a device interface corresponding 
    to an IOUSBInterface user client in the kernel. The type of this device interface 
    is IOUSBInterfaceInterface. This device interface is obtained after the device interface 
    for the service itself has been obtained.
    
    <b>Note:</b> The IOUSBInterfaceInterface is returned by all versions of the IOUSBFamily 
    currently shipping. However, there are some functions which are available only in 
    IOUSBFamily version 1.8.2 and above. Access to these functions, as well as to all of the functions 
    contained in IOUSBInterfaceInterface, can be obtained by using one of the other UUIDs listed in this header.
    
    Example:
    <pre>
    @textblock
    IOCFPluginInterface         **iodev;        // obtained earlier
    
    IOUSBInterfaceInterface     **intf;         // fetching this now
    IOReturn                    err;
    
    err = (*iodev)->QueryInterface(iodev,
                                CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID),
                                (LPVoid)&intf);
    @/textblock
    </pre>
*/
#define kIOUSBInterfaceInterfaceID CFUUIDGetConstantUUIDWithBytes(NULL, \
    0x73, 0xc9, 0x7a, 0xe8, 0x9e, 0xf3, 0x11, 0xD4,                     \
    0xb1, 0xd0, 0x00, 0x0a, 0x27, 0x05, 0x28, 0x61)

and this is the 10.14 SDK definition:

// The preferred interface ID is the newest version
#define kIOUSBInterfaceInterfaceID kIOUSBInterfaceInterfaceID942

So the SDK is most definitely the correct way to target an older release. Download XCode 9 then copy the 10.13 SDK out of it to get a version that will build the way you want. Though you should still probably go to an SDK as far back as you plan to support.

@hjelmn

This comment has been minimized.

Copy link
Member

hjelmn commented Jan 17, 2019

Wow, looked a little further up and saw this:

/*!
 @defined kIOUSBInterfaceInterfaceID942
 @discussion This UUID constant is used to obtain an interface interface corresponding to
 an IOUSBInterface user client in the kernel. The type of this device interface is
 kIOUSBInterfaceInterfaceID942. This device interface is obtained after the device interface
 for the service itself has been obtained.

 <b>Note:</b> The kIOUSBInterfaceInterfaceID942 is returned only by version 900.4.2 or above of
 the IOUSBFamily. This version of IOUSBFamily shipped with Mac OS X version 10.14.  If your software
 is running on a version of Mac OS X prior to 10.14 you will need to use the UUID kIOUSBInterfaceInterfaceID,
 kIOUSBInterfaceInterfaceID182, kIOUSBInterfaceInterfaceID183, kIOUSBInterfaceInterfaceID190, kIOUSBInterfaceInterfaceID192,
 kIOUSBInterfaceInterfaceID197, kIOUSBInterfaceInterfaceID220, kIOUSBInterfaceInterfaceID245, kIOUSBInterfaceInterfaceID300,
 kIOUSBInterfaceInterfaceID500, kIOUSBInterfaceInterfaceID550 , kIOUSBInterfaceInterfaceID650, kIOUSBInterfaceInterfaceID700, or kIOUSBInterfaceInterfaceID800 and you will not have access to some functions.

 Example:
 <pre>
 @textblock
 IOCFPluginInterface             **iodev;     // obtained earlier

 IOUSBInterfaceInterface942      **intf;     // fetching this now
 IOReturn                        err;

 err = (*iodev)->QueryInterface(iodev,
 CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID942),
 (LPVoid)&intf);
 @/textblock
 </pre>
 */

It specifically says to use kIOUSBInterfaceInterfaceID so something is not right with IOUSBLib.h.

@hjelmn

This comment has been minimized.

Copy link
Member

hjelmn commented Jan 17, 2019

Opened radar 47338464 to report this. Will see what they have to say.

@hjelmn

This comment has been minimized.

Copy link
Member

hjelmn commented Jan 17, 2019

Given this weirdness I will go ahead and update it to just use our own internal define for now. It won't guarantee everything works but it will at least resolve this particular issue in a way that doesn't require Apple to push an Xcode fix.

@hjelmn hjelmn closed this in efa1b28 Jan 17, 2019

@hjelmn

This comment has been minimized.

Copy link
Member

hjelmn commented Jan 17, 2019

Made that change. Will update the ticket once I hear back from Apple. If you see any other issues with building for older releases open another ticket. I would not be surprised if this is the only issue when using the 10.14 SDK.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.