You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

IOServiceMatching无法稳定匹配dext服务的技术求助

问题描述

我们开发的iPad端App启动时执行以下代码查找dext服务(驱动已在iOS设置中提前启用):

io_service_t mService = IO_OBJECT_NULL;
kern_return_t ret = kIOReturnSuccess;
io_iterator_t iterator = IO_OBJECT_NULL;

// 临时检查所有服务,后续会用其他Key优化
CFMutableDictionaryRef matchingDict = IOServiceMatching("IOUserService");

if (__builtin_available(iOS 15.0, *)) {
    ret = IOServiceGetMatchingServices(kIOMainPortDefault, matchingDict, &iterator);
} else {
    // 早期版本兼容逻辑
}
if (ret != kIOReturnSuccess)
{
    printf("Unable to find service");
}

while ((mService = IOIteratorNext(iterator)) != IO_OBJECT_NULL)
{
    // 只有先启动App再连接设备时,才能找到"MyDriver"
    ret = IOServiceOpen(mService, mach_task_self_, 0, &mConnection);
    ..........
}

使用IOServiceMatching("IOUSBDevice")结合idVendor+idProduct匹配设备时,无论设备先连还是后连都正常,但匹配驱动时存在以下问题:

  • 先连接USB设备再启动App:MyDriver的Start()未被调用,IOServiceMatching("IOUserService")无法找到MyDriver;
  • 先启动App再连接设备:MyDriver正常启动,可正常匹配并调用IOServiceOpen;
  • 驱动运行时,在iOS设置中禁用再启用驱动(不插拔设备):MyDriver的Start()不触发,也无法再次匹配。

驱动Info.plist中IOProviderClass本应设为IOUSBHostDevice(设备为非HID USB设备),当前驱动配置文件如下:

驱动Info.plist

<plist version="1.0">
<dict>
    <key>IOKitPersonalities</key>
    <dict>
        <key>MyDriver</key>
        <dict>
            <key>CFBundleIdentifier</key>
            <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
            <key>CFBundleIdentifierKernel</key>
            <string>com.apple.kpi.iokit</string>
            <key>CFBundleName</key>
            <string>$(PRODUCT_NAME)</string>
            <key>IOClass</key>
            <string>IOUserService</string>
            <key>IOMatchCategory</key>
            <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
            <key>IOProviderClass</key>
            <string>IOUserResources</string>
            <key>IOResourceMatch</key>
            <string>IOKit</string>
            <key>IOUserClass</key>
            <string>MyDriver</string>
            <key>IOUserServerName</key>
            <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
            <key>MyDriverUserClientProperties</key>
            <dict>
                <key>IOClass</key>
                <string>IOUserUserClient</string>
                <key>IOUserClass</key>
                <string>MyDriverClient</string>
            </dict>
            <key>bConfigurationValue</key>
            <integer>1</integer>
            <key>bInterfaceNumber</key>
            <integer>0</integer>
            <key>idProduct</key>
            <integer>1234</integer>
            <key>idVendor</key>
            <integer>5678</integer>
        </dict>
    </dict>
</dict>
</plist>

驱动entitlements文件

<?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/>
    </array>
    <key>com.apple.security.app-sandbox</key>
    <true/>
</dict>
</plist>
解决方案

针对问题1和3,核心是修正驱动匹配逻辑,让驱动能正确关联已连接的USB设备,同时让App能监听驱动服务的动态变化:

1. 修正驱动Info.plist的匹配配置

当前Info.plist中IOProviderClass设为IOUserResources是错误的,需改为IOUSBHostDevice,同时调整匹配规则:

  • 将IOProviderClass的值从IOUserResources改为IOUSBHostDevice
  • 删除IOResourceMatch键值对(该配置针对资源服务,不适用于USB设备)
  • 确保idVendor、idProduct、bConfigurationValue、bInterfaceNumber等USB匹配参数与目标设备一致

修改后的MyDriver Personality核心片段:

<key>IOProviderClass</key>
<string>IOUSBHostDevice</string>
<key>IOMatchCategory</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>IOUserClass</key>
<string>MyDriver</string>
<key>IOUserServerName</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>bConfigurationValue</key>
<integer>1</integer>
<key>bInterfaceNumber</key>
<integer>0</integer>
<key>idProduct</key>
<integer>1234</integer>
<key>idVendor</key>
<integer>5678</integer>

2. 优化App端的服务查找逻辑

不要直接匹配所有IOUserService,改用驱动的IOMatchCategory进行精准匹配:

CFMutableDictionaryRef matchingDict = IOServiceMatching("IOUserService");
CFDictionarySetValue(matchingDict, CFSTR("IOMatchCategory"), CFSTR("$(PRODUCT_BUNDLE_IDENTIFIER)"));

if (__builtin_available(iOS 15.0, *)) {
    kern_return_t ret = IOServiceGetMatchingServices(kIOMainPortDefault, matchingDict, &iterator);
    if (ret != kIOReturnSuccess) {
        printf("Unable to find service");
    }
    
    while ((mService = IOIteratorNext(iterator)) != IO_OBJECT_NULL) {
        ret = IOServiceOpen(mService, mach_task_self_, 0, &mConnection);
        // 处理连接逻辑
        IOObjectRelease(mService);
    }
    IOObjectRelease(iterator);
} else {
    // 早期版本兼容逻辑
}

3. 监听驱动服务的动态变化

针对驱动禁用再启用的场景,使用IOServiceAddMatchingNotification注册监听,实时捕获驱动服务的出现事件:

void driverAppearedCallback(void *refcon, io_iterator_t iterator) {
    io_service_t service;
    while ((service = IOIteratorNext(iterator)) != IO_OBJECT_NULL) {
        // 处理新出现的驱动服务
        kern_return_t ret = IOServiceOpen(service, mach_task_self_, 0, &mConnection);
        // 后续业务逻辑
        IOObjectRelease(service);
    }
}

// App启动时注册监听
CFMutableDictionaryRef matchDict = IOServiceMatching("IOUserService");
CFDictionarySetValue(matchDict, CFSTR("IOMatchCategory"), CFSTR("$(PRODUCT_BUNDLE_IDENTIFIER)"));

io_iterator_t iterator;
kern_return_t ret = IOServiceAddMatchingNotification(
    kIOMainPortDefault,
    kIOFirstMatchNotification,
    matchDict,
    driverAppearedCallback,
    NULL, // 可传递App上下文
    &iterator
);

// 触发初始查找
driverAppearedCallback(NULL, iterator);

上述配置完成后,无论设备先连接还是后连接,驱动都能正确匹配启动;驱动重新启用时,App也能通过监听事件捕获到驱动服务并建立连接。

内容的提问来源于stack exchange,提问作者K880

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 21:54:55