I am migrating a codeless KEXT to a codeless DEXT. I have watched the WWDC video and read much of the information on the Apple Developer site. The difficulty I am having is finding not what to do but how to get started. A nice tutorial with an example project would help.
In my codeless KEXT, for 4 separate devices I have IOKitPersonalities for IOUSBDevice and IOUSBInterface for each device. The KEXT allowed me to match my devices to my "driver" so the Apple HID driver wouldn't grab them. I wish to do the same or something similar in the codeless DEXT.
So far, I have created a DriverKit target (for a DriverKit.framework) called MyUsbDriver in an app and added a USBDriverKit.framework. That added a folder MyUsbDriver to my project with files MyUsbDriver.cpp, MyUsbDriver.iig, Info.plist and MyUsbDriver.entitlements. Here are my questions:
It looks like the default subclass of IOService is OK for USB - that is the same as the IOClass from the KEXT. Is that true?
Is IOUSBHostInterface in DEXT-world equivalent to IOUSBInterface in KEXT-world?
Is IOUSBHostDevice equivalent to IOUSBDevice?
Do I need to do anything to the .cpp or .iig for codeless DEXT? Isn't most of my work to be done in the plist and entitlements files?
Do I need the USBDriverKit.framework in my Frameworks and Libraries of MyUsbDriver target?
Where can I find a decent example of how to complete this migration?
Any help would be greatly appreciated.
Update:
Using the example and other links in the answer I was able to get something together. I did have a "Doh" moment: My initial test project type was Command Line Tool and I could never get the DEXT to embed. I almost just hand-edited the pbxproj file. However, in looking at the original example USBApp from Scott Knight, I realized the project type he was using was App, In hindsight, that makes sense but at the time was confounding.
Here is the info.plist I have so far to match on one of our deprecated devices:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>IOKitPersonalities</key>
<dict>
<key>MyUsbDrver</key>
<dict>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleIdentifierKernel</key>
<string>com.apple.kpi.iokit</string>
<key>IOClass</key>
<string>IOUserService</string>
<key>IOMatchCategory</key>
<string>com.apple.null.driver</string>
<key>IOProviderClass</key>
<string>IOUsbHostInterface</string>
<key>IOResourceMatch</key>
<string>IOKit</string>
<key>IOUserClass</key>
<string>MyUsbDrver</string>
<key>IOUserServerName</key>
<string>Home.MyUsbDrver</string>
<key>bConfigurationValue</key>
<integer>1</integer>
<key>bInterfaceNumber</key>
<integer>0</integer>
<key>idProduct</key>
<integer>2</integer>
<key>idVendor</key>
<integer>5843</integer>
</dict>
</dict>
<key>OSBundleUsageDescription</key>
<string>Codless DEXT to match on IOKit.</string>
</dict>
</plist>
I am not sure about IOResourceMatch - the value is IOKit, which is the direction I am trying to go.
Update the Second:
Progress!
I ended up having to manually change the signing provisions in my pbxproj file. Disabled SIP, set up System Extension activation/deactivation in my app and did command-line signing. I found this repository to be helpful with a decent Objective-C example for the activation code - https://github.com/google/santa.git. Everything builds and code signing seemed to be successful. Getting the fun error
SystemExtension "Home.MyUsbDrver" request did fail: Error Domain=OSSystemExtensionErrorDomain Code=8 "(null)"
Update 3:
I checked my DEXT and app entitlements, and it looked like the app entitlements needed to be updated. This is what I have now for app:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
<key>com.apple.developer.system-extension.install</key>
<true/>
<key>com.apple.developer.system-extension.uninstall</key>
<true/>
</dict>
</plist>
I was missing the bottom two. Cleaned my project, built, signed again. When I tried running from Xcode, still got the error. When I ran my app from Finder, I got the system preferences dialog. After that, still the same result from Xcode, and now nothing but a flash of the app when run from Finder. I rebooted - still the same results. However, from terminal when I run systemextensionsctl -list, I get:
3 extension(s)
--- com.apple.system_extension.driver_extension
enabled active teamID bundleID (version) name [state]
<REDACTED> Home.MyUsbDrver (1.0/1) Home.MyUsbDrver [terminated waiting to uninstall on reboot]
* * <REDACTED> Home.MyUsbDrver (1.0/1) Home.MyUsbDrver [activated enabled]
<REDACTED> Home.MyUsbDrver (1.0/1) Home.MyUsbDrver [activated waiting to upgrade]
After a reboot I get this:
1 extension(s)
--- com.apple.system_extension.driver_extension
enabled active teamID bundleID (version) name [state]
* * <REDACTED> Home.MyUsbDrver (1.0/1) Home.MyUsbDrver [activated enabled]
So, it looks like my system extension is in place, but I am actually not sure why since I just did a fresh reboot and have not run my app.
Update 4:
I figured out the problem with my entitlements was just the format of the file. I changed it in TextEdit and I can now communicate with my device. Here is what I ended up with:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.driverkit</key>
<true/>
<key>com.apple.developer.driverkit.transport.usb</key>
<array>
<dict>
<key>idVendor</key>
<integer>VID0</integer>
<key>idProductArray</key>
<array>
<integer>PID0</integer>
<integer>PID1</integer>
<integer>PID2</integer>
<integer>PID3</integer>
<integer>PID4</integer>
</array>
</dict>
</array>
<key>com.apple.security.app-sandbox</key>
<true/>
</dict>
</plist>