[英]Migrating a codeless KEXT to a codeless DEXT
我正在将无代码 KEXT 迁移到无代码 DEXT。 我观看了 WWDC 视频并阅读了 Apple Developer 网站上的大部分信息。 我遇到的困难不是找到做什么,而是如何开始。 带有示例项目的不错的教程会有所帮助。
在我的无代码 KEXT 中,对于 4 个单独的设备,我有 IOKitPersonalities 用于 IOUSBDevice 和 IOUSBInterface 用于每个设备。 KEXT 允许我将我的设备与我的“驱动程序”相匹配,这样 Apple HID 驱动程序就不会抓取它们。 我希望在无代码 DEXT 中做同样或类似的事情。
到目前为止,我已经在应用程序中创建了一个名为 MyUsbDriver 的 DriverKit 目标(用于 DriverKit.framework),并添加了一个 USBDriverKit.framework。 这在我的项目中添加了一个文件夹 MyUsbDriver,其中包含文件 MyUsbDriver.cpp、MyUsbDriver.iig、Info.plist 和 MyUsbDriver.entitlements。 以下是我的问题:
看起来 IOService 的默认子类对于 USB 来说是可以的——这与 KEXT 中的 IOClass 相同。 真的吗?
DEXT 世界中的 IOUSBHostInterface 是否等同于 KEXT 世界中的 IOUSBInterface?
IOUSBHostDevice 是否等同于 IOUSBDevice?
对于无代码 DEXT,我是否需要对 .cpp 或 .iig 做任何事情? 我的大部分工作不是在 plist 和 entitlements 文件中完成吗?
我的 MyUsbDriver 目标的框架和库中是否需要 USBDriverKit.framework?
我在哪里可以找到如何完成此迁移的体面示例?
任何帮助将不胜感激。
更新:
使用答案中的示例和其他链接,我能够得到一些东西。 我确实有一个“Doh”时刻:我最初的测试项目类型是命令行工具,我永远无法嵌入 DEXT。 我几乎只是手动编辑了 pbxproj 文件。 然而,在查看 Scott Knight 的原始示例 USBApp 时,我意识到他使用的项目类型是 App,事后看来,这是有道理的,但当时令人困惑。
这是到目前为止我在我们已弃用的设备之一上匹配的 info.plist:
<?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>
我不确定 IOResourceMatch - 值是 IOKit,这是我尝试 go 的方向。
更新第二个:
进步!
我最终不得不手动更改我的 pbxproj 文件中的签名规定。 禁用 SIP,在我的应用程序中设置系统扩展激活/停用并进行命令行签名。 我发现这个存储库对激活码的一个像样的 Objective-C 示例很有帮助 - https://github.com/google/santa.git 。 一切构建和代码签名似乎都很成功。 得到有趣的错误
SystemExtension "Home.MyUsbDrver" request did fail: Error Domain=OSSystemExtensionErrorDomain Code=8 "(null)"
更新 3:
我检查了我的 DEXT 和应用程序权利,看起来需要更新应用程序权利。 这就是我现在的应用程序:
<?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>
我错过了底部的两个。 清理我的项目,构建,再次签名。 当我尝试从 Xcode 运行时,仍然出现错误。 当我从 Finder 运行我的应用程序时,我得到了系统首选项对话框。 之后,Xcode 的结果仍然相同,现在从 Finder 运行时,只有应用程序的 flash。 我重新启动 - 仍然是相同的结果。 但是,从终端运行 systemextensionsctl -list 时,我得到:
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]
重新启动后,我得到这个:
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]
所以,看起来我的系统扩展已经到位,但我实际上不确定为什么,因为我刚刚重新启动并且没有运行我的应用程序。
更新 4:
我发现我的权利问题只是文件的格式。 我在 TextEdit 中对其进行了更改,现在我可以与我的设备进行通信了。 这是我最终得到的结果:
<?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>
我一直在努力反对让同样的事情发挥作用。 最后,我设法获得了一个有效的 DEXT,它为特定的供应商 ID/产品 ID 组合禁用了 Apple HID 驱动程序。 我们已获得供应商 ID 的 DriverKit 权利。
- 看起来 IOService 的默认子类对于 USB 来说是可以的——这与 KEXT 中的 IOClass 相同。 真的吗?
这对我有用。 我尝试完全删除.iig
和.cpp
文件,但与 KEXT 不同,似乎需要编译一些代码才能使签名正常工作。 所以我最终得到了一个空的IOService
子类。
- DEXT 世界中的 IOUSBHostInterface 是否等同于 KEXT 世界中的 IOUSBInterface?
我相信是这样。 我使用了IOUSBHostInterface
,我们的 KEXT 中有IOUSBInterface
。
- IOUSBHostDevice 是否等同于 IOUSBDevice?
我不知道,但我相信是的。
- 对于无代码 DEXT,我是否需要对 .cpp 或 .iig 做任何事情? 我的大部分工作不是在 plist 和 entitlements 文件中完成吗?
我不需要更改.cpp
和.iig
文件中的任何内容。 您可能想要删除os_log(OS_LOG_DEFAULT, "Hello World");
.cpp
文件中的行,然后再发布它。 但是在调试时,判断 DEXT 是否实际加载对我很有用。 您可以运行log stream --source | grep 'HELLO'
log stream --source | grep 'HELLO'
在终端中查找日志。
- 我的 MyUsbDriver 目标的框架和库中是否需要 USBDriverKit.framework?
我的 DEXT 链接到DriverKit.framework
。 我不知道它是否需要。
- 我在哪里可以找到如何完成此迁移的体面示例?
也许这些可以帮助:
在开发 DriverKit 扩展 (dext) 期间,请执行以下操作:
禁用系统完整性保护 (SIP): https://apple.stackexchange.com/a/208481/21491 。 (在恢复模式下重新启动,运行csrutil disable
)。 记得重新启用它!
通过运行systemextensionsctl developer on
启用系统扩展开发模式
确保您没有安装旧的无代码 KEXT。 (从/Library/Extensions
和/或/System/Library/Extensions
中删除它。确保之后重新启动)
您可能需要包含 DriverKit 权利的手动配置文件。 我认为我的问题是我在企业开发团队而不是公共开发团队中获得了 DriverKit 权利。
加载扩展的应用程序需要“系统扩展”权利,但不需要手动配置配置文件。
当心系统偏好设置中的一个愚蠢的错误。 每次加载时,您都需要同意加载 dext。 但是,如果“安全和隐私”窗格已打开,则不会显示表示同意的按钮。 您需要重新启动系统偏好设置才能显示它。 我一直在使用命令pkill -9 "System Preferences"; open /System/Library/PreferencePanes/Security.prefPane
从终端慷慨地pkill -9 "System Preferences"; open /System/Library/PreferencePanes/Security.prefPane
以解决此问题。
您可以使用systemextensionsctl
卸载 dext 或重置系统 state。 但是,这实际上并没有改变驱动匹配,所以你需要重新启动。 大方。 我使用这个终端命令是因为我很懒: osascript -e 'tell app "System Events" to restart'
。
您可以使用ioreg
检查设备是否与扩展名匹配: ioreg -lirc IOUSBHostInterface
。
使扩展工作的关键是将IOProviderClass
设置为IOUSBHostInterface
而不是 Info.plist 文件中的IOResources
。 (作为参考,KEXT 使用IOUSBInterface
这是 Apple 已弃用的类之一)
每次更改 DEXT 时,您可能希望在Info.plist
更改版本,以确保您实际使用的是正确的版本。 ( systemextensionsctl
将显示它已加载的版本)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.