5

我正在将无代码 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。以下是我的问题:

  1. 看起来 IOService 的默认子类适用于 USB - 这与 KEXT 中的 IOClass 相同。真的吗?

  2. DEXT 世界中的 IOUSBHostInterface 是否等同于 KEXT 世界中的 IOUSBInterface?

  3. IOUSBHostDevice 是否等同于 IOUSBDevice?

  4. 对于无代码 DEXT,我是否需要对 .cpp 或 .iig 做任何事情?我的大部分工作不是在 plist 和 entitlements 文件中完成吗?

  5. 我的 MyUsbDriver 目标的框架和库中是否需要 USBDriverKit.framework?

  6. 我在哪里可以找到如何完成此迁移的体面示例?

任何帮助将不胜感激。

更新:

使用答案中的示例和其他链接,我能够得到一些东西。我确实有一个“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,这是我试图去的方向。

更新第二个:

进步!

我最终不得不手动更改我的 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 运行时,应用程序只有一个闪光。我重新启动 - 仍然是相同的结果。但是,从终端运行 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>
4

1 回答 1

3

我一直在努力反对让同样的事情发挥作用。最后,我设法获得了一个有效的 DEXT,它为特定的供应商 ID/产品 ID 组合禁用了 Apple HID 驱动程序。我们已获得供应商 ID 的 DriverKit 权利。

  1. 看起来 IOService 的默认子类适用于 USB - 这与 KEXT 中的 IOClass 相同。真的吗?

这对我有用。我尝试完全删除.iigand.cpp文件,但与 KEXT 不同,似乎需要编译一些代码才能使签名正常工作。所以我最终得到了一个空的IOService.

  1. DEXT 世界中的 IOUSBHostInterface 是否等同于 KEXT 世界中的 IOUSBInterface?

我相信是这样。我用过IOUSBHostInterface我们IOUSBInterface的 KEXT。

  1. IOUSBHostDevice 是否等同于 IOUSBDevice?

我不知道,但我相信是的。

  1. 对于无代码 DEXT,我是否需要对 .cpp 或 .iig 做任何事情?我的大部分工作不是在 plist 和 entitlements 文件中完成吗?

我不需要更改.cpp.iig文件中的任何内容。您可能希望在释放文件之前删除文件os_log(OS_LOG_DEFAULT, "Hello World");中的行。.cpp但是在调试时,判断 DEXT 是否实际加载对我很有用。您可以log stream --source | grep 'HELLO' 在终端中运行以查找日志。

  1. 我的 MyUsbDriver 目标的框架和库中是否需要 USBDriverKit.framework?

我的 DEXT 链接到DriverKit.framework. 我不知道它是否需要。

  1. 我在哪里可以找到如何完成此迁移的体面示例?

也许这些可以帮助:

我为自己和未来的开发人员记下的一些笔记

在开发 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慷慨地使用终端中的命令来解决这个问题。

  • 您可以使用systemextensionsctl卸载 dext 或重置系统状态。但是,这实际上并没有改变驱动匹配,所以你需要重新启动。大方。我使用这个终端命令是因为我很懒:osascript -e 'tell app "System Events" to restart'

  • 您可以使用ioreg来检查设备是否与扩展程序匹配:ioreg -lirc IOUSBHostInterface.

  • 使扩展工作的关键是将 设置IOProviderClassIOUSBHostInterface而不是IOResources在 Info.plist 文件中。(作为参考,KEXT 使用IOUSBInterface的是 Apple 已弃用的类之一)

  • 每次对 DEXT 进行更改时,您可能都希望更新版本,Info.plist以确保您实际使用的是正确的版本。(systemextensionsctl将显示它已加载的版本)。

于 2020-08-04T13:52:55.960 回答