Myu*_*rik 2 macos ipados driverkit
我们正在 macOS 上试验 DriverKit,而在 iPadOS 上 DriverKit 仍处于测试阶段。我们想要构建一个 iPad 驱动程序,允许我们的 iPad 应用程序与 USB 设备进行通信。
\n我们做了什么:
\nUSBDriverKit::IOUSBHostInterface。当我们将设备插入 USB 端口时,macOS 会自动匹配/启动该驱动程序。接下来我们利用USBDriverKit::IOUSBHostPipe从我们的设备发送/接收数据。我们现在在日志中打印来自设备的数据。IOUserClientmacOS 应用程序并允许使用 API 打开通信通道的驱动程序IOServiceOpen。驱动程序有回调将数据传递到 macOS 客户端应用程序。目前,我们希望组合 2 个驱动程序,并使用回调将从 USB 设备接收到的数据传递到我们的客户端应用程序。不幸的是,我们陷入了困境,因为现在我们有 2 个驱动程序实例:
\nvirtual kern_return_t NewUserClient(uint32_t type, IOUserClient** userClient)当我们从客户端应用程序连接并调用方法时创建第二个实例。因此,我们不能使用第二个实例进行 USB 设备通信,因为它有错误的提供程序(IOUserClient),kern_return_t Start(IOService * provider)但我们需要IOUSBHostInterface启动:
\xc2\xa0 \xc2\xa0 ivars->interface = OSDynamicCast(IOUSBHostInterface, provider);\n\xc2\xa0 \xc2\xa0 if(ivars->interface == NULL) {\n\xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 ret = kIOReturnNoDevice;\n\xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 goto Exit;\n\xc2\xa0 \xc2\xa0 }\nRun Code Online (Sandbox Code Playgroud)\n我们做错了吗?也许IOUSBHostInterface我们应该从 UserClient 驱动程序手动进行匹配或使用其他方法,而不是自动匹配?
正如我们所知,我们必须在NewUserClient方法中创建一个新的服务实例,并且无法返回操作系统运行的驱动程序:
kern_return_t IMPL(MyDriver, NewUserClient)\n{\n\xc2\xa0 \xc2\xa0 kern_return_t ret = kIOReturnSuccess;\n\xc2\xa0 \xc2\xa0 IOService* client = nullptr;\n\xc2\xa0 \xc2\xa0 ret = Create(this, "UserClientProperties", &client);\n\n\xc2\xa0 \xc2\xa0 if (ret != kIOReturnSuccess)\n\xc2\xa0 \xc2\xa0 {\n\xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 goto Exit;\n\xc2\xa0 \xc2\xa0 }\n\n\xc2\xa0 \xc2\xa0 *userClient = OSDynamicCast(IOUserClient, client);\n\n\xc2\xa0 \xc2\xa0 if (*userClient == NULL)\n\xc2\xa0 \xc2\xa0 {\n\xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 client->release();\n\xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 ret = kIOReturnError;\n\xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 goto Exit;\n\xc2\xa0 \xc2\xa0 }\nExit:\n\xc2\xa0 \xc2\xa0 return ret;\n}\nRun Code Online (Sandbox Code Playgroud)\n顺便说一句,也许有更简单的方法将数据从 USB 设备转发到 iPadOS 应用程序?
\n我不了解 USBDriverKit 和 iPadOS,但也许我在 macOS 上使用 PCIDriverKit 的有限经验可以作为有用的类比。
我已经为自定义 PCI 设备实现了 DEXT,以及与驱动程序通信以对设备执行操作的用户空间应用程序。
DEXT 由两个类组成(两对.iig和.cpp文件):
class MyDriver: public IOServiceclass MyDriverClient: public IOUserClient具有以下内容Info.plist:
<dict>
<key>IOKitPersonalities</key>
<dict>
<key>MyDriver</key>
<dict>
<key>CFBundleIdentifierKernel</key <string>com.apple.kpi.iokit</string>
<key>IOClass</key> <string>IOUserService</string>
<key>IOPCIMatch</key> <string>0xcafebabe</string>
<key>IOPCITunnelCompatible</key> <true/>
<key>IOProviderClass</key> <string>IOPCIDevice</string>
<key>IOUserClass</key> <string>MyDriver</string>
<key>IOUserServerName</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>MyDriverClientProperties</key>
<dict>
<key>IOClass</key>
<string>IOUserUserClient</string>
<key>IOUserClass</key>
<string>MyDriverClient</string>
</dict>
</dict>
</dict>
</dict>
Run Code Online (Sandbox Code Playgroud)
当系统根据IOPCIMatch属性值发现具有匹配供应商/设备 ID 的 PCI 设备时,它:
IOUserService类(根据IOClass属性的要求)以促进与驻留在用户空间中的 DEXT 的通信IOPCIDevice根据属性IOProviderClass)。MyDriver根据IOUserClass属性),为其提供指向上面创建的指针provider。作为其Start实现的一部分,MyDriver调用RegisterService()使其自身出现在 I/O 注册表中(例如ioreg -l)。
当用户空间应用程序(具有适当的权利)稍后找到注册的MyDriver服务(例如使用IOServiceGetMatchingService())并打开它(IOServiceOpen())时,最终会在 DEXT 端调用MyDriver::NewUserClient()(docs),如下所示:
kern_return_t IMPL(MyDriver, NewUserClient)
{
kern_return_t ret = kIOReturnSuccess;
IOService* client = nullptr;
ret = Create(this, "MyDriverClientProperties", &client);
// ... Error handling
*userClient = OSDynamicCast(IOUserClient, client);
// ... Error handling
// If you need to remember/keep track of the client, you could stash it in the `ivars`, already casted to its true type:
ivars->client = OSDynamicCast(MyDriverClient, client);
// ...
}
Run Code Online (Sandbox Code Playgroud)
到底要做什么由提供的属性字典(在 中任意命名的键Create下)决定。在这种情况下,在内核(属性)中创建一个(双-不是拼写错误)对象,并在用户空间(属性)中创建一个对象。MyDriverClientPropertiesInfo.plistIOUserUserClient UserIOClassMyDriverClientIOUserClass
您在问题中的描述似乎表明不然,但至少在我的情况下,客户端对象被MyDriver作为实例提供provider,并且我能够获得对它的引用:
kern_return_t IMPL(MyDriverClient, Start)
{
kern_return_t ret;
ret = Start(provider, SUPERDISPATCH);
// ... Error handling
ivars->driver = OSDynamicCast(MyDriver, provider);
// ... Error handling
// ...
}
Run Code Online (Sandbox Code Playgroud)
稍后,当调用例如MyDriverClient::ExternalMethod(docsivars->driver )时,我可以用来调用该类的功能MyDriver并与底层设备交互。
| 归档时间: |
|
| 查看次数: |
1068 次 |
| 最近记录: |