USBInterfaceOpen 总是报 kIOReturnExclusiveAccess 错误
USBInterfaceOpen always report kIOReturnExclusiveAccess error
最近很头疼这个问题,我已经在这个问题上折腾了一个星期了,还是不行。希望你能帮我把这块石头踢开,非常感谢。
我的问题:
我们公司为iPhone生产USB存储设备,实际上这个存储设备中有一个SDCard。现在,我们想开发一个 Mac 应用程序来更新此存储设备的固件。但是每次我将存储设备连接到 Mac 时,Mac 都会自动安装它,并且在调用 USBInterfaceOpen[= 时我总是失败并显示 kIOReturnExclusiveAccess 27=].
我也尝试写了一个codeless kext来提高probe score,但是还是不行。不知道是我走错了路,还是写了codeless kext有什么错误,比如IOClass写错了,bundle ID写错了。
我的无代码 kext 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>BuildMachineOSBuild</key>
<string>14E46</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleIdentifier</key>
<string>com.mophie.MyDriverTest3</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>MyDriverTest3</string>
<key>CFBundlePackageType</key>
<string>KEXT</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0.3</string>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key>
<string>6E35b</string>
<key>DTPlatformVersion</key>
<string>GM</string>
<key>DTSDKBuild</key>
<string>14D125</string>
<key>DTSDKName</key>
<string>macosx10.10</string>
<key>DTXcode</key>
<string>0640</string>
<key>DTXcodeBuild</key>
<string>6E35b</string>
<key>IOKitPersonalities</key>
<dict>
<key>MyDriverTest3</key>
<dict>
<key>CFBundleIdentifier</key>
<string>com.apple.iokit.IOUSBFamily</string>
<key>IOClass</key>
<string>IOService</string>
<key>IOProviderClass</key>
<string>IOUSBDevice</string>
<key>bcdDevice</key>
<string>256</string>
<key>idProduct</key>
<integer>4369</integer>
<key>idVendor</key>
<integer>6631</integer>
</dict>
</dict>
<key>OSBundleRequired</key>
<string>Root</string>
</dict>
</plist>
以下是我的存储设备的 ioreg 结果:
space pack@1a122000 <class IOUSBDevice, id 0x100001773, registered, matched, active, busy 0 (300 ms), retain 9>
+-o IOUSBCompositeDriver <class IOUSBCompositeDriver, id 0x100001775, !registered, !matched, active, busy 0, retain 4>
+-o IOUSBInterface@0 <class IOUSBInterface, id 0x100001776, registered, matched, active, busy 0 (293 ms), retain 8>
+-o IOUSBMassStorageClass <class IOUSBMassStorageClass, id 0x100001777, registered, matched, active, busy 0 (201 ms), retain 9>
+-o IOSCSIPeripheralDeviceNub <class IOSCSIPeripheralDeviceNub, id 0x100001779, registered, matched, active, busy 0 (99 ms), retain 7>
+-o IOSCSIPeripheralDeviceType00 <class IOSCSIPeripheralDeviceType00, id 0x10000177a, !registered, !matched, active, busy 0 (13 ms), retain 9>
+-o IOBlockStorageServices <class IOBlockStorageServices, id 0x10000177d, registered, matched, active, busy 0 (13 ms), retain 6>
+-o IOBlockStorageDriver <class IOBlockStorageDriver, id 0x10000177e, registered, matched, active, busy 0 (12 ms), retain 47>
+-o mophie SpacePack Media <class IOMedia, id 0x100001784, registered, matched, active, busy 0 (12 ms), retain 11>
+-o IOMediaBSDClient <class IOMediaBSDClient, id 0x100001785, registered, matched, active, busy 0 (0 ms), retain 6>
+-o IOFDiskPartitionScheme <class IOFDiskPartitionScheme, id 0x100001788, !registered, !matched, active, busy 0 (1 ms), retain 6>
+-o Untitled 1@1 <class IOMedia, id 0x10000178a, registered, matched, active, busy 0 (1 ms), retain 10>
+-o IOMediaBSDClient <class IOMediaBSDClient, id 0x10000178b, registered, matched, active, busy 0 (0 ms), retain 7>
希望你能帮我解决这个问题,非常感谢,非常感谢你的帮助!
听起来您正在尝试使用 IOUSBInterfaceInterface 提供的低级 USB 命令连接到 USB 大容量存储接口并发送一些自定义命令来更新固件。由于该接口由 Apple 大容量存储驱动程序声明,因此您可能不允许这样做。
相反,您可以尝试在您的设备上制作第二个 USB 接口,这是供应商定义的接口。您将能够连接到该接口并将任意控制传输发送到您的设备。如果您的设备尚未成为复合设备,那么它就是复合设备。
或者,您可以尝试使用某种破解方法通过大容量存储接口发送信号。例如,每当将具有特殊名称的文件写入设备时,这可能是设备进入引导加载程序模式以进行固件更新的信号。
几点:
- 无代码 kext 方法通常适用于这种情况。
- 通常,您的无代码 kext 会匹配(通过 IOProviderClass)
IOUSBInterface
,而不是 IOUSBDevice
。 (例如,参见 the FTDI example)
IOService
的包标识符是 com.apple.kpi.iokit
,而不是 com.apple.iokit.IOUSBFamily
,尽管我怀疑这不应该成为问题。
- 您的无代码 kext 是否已正确签名和安装? (我遇到过 /Library/Extensions/ 中的 kext 在启动时不起作用的情况,至少在 OSX 10.9.x 上,不像 /System/Library/Extensions,尽管它应该对于任何热插拔设备都可以正常工作。)确保 kext/personality 缓存是最新的,换句话说,每当您更新 kext 时,
touch
Extensions 目录。
kextutil -n
说了什么?
- 您是否尝试过设置
IOKitDebug
个性 属性 以查看您的 kext 是否有机会匹配设备?
- 根据固件更新命令的实施方式,您可以在设备节点上使用
ioctl
s。您可以通过 ioctl 将原始 SCSI 请求发送到 SCSI 设备。我不确定这是否适用于 USB 大容量存储 class,但它肯定适用于 USB 连接的 SCSI (UAS) 或任何其他 "true" SCSI 设备。显然,这只有在您的固件更新命令通过 SCSI 公开时才有用。
如果在所有这些之后,您仍然卡住了,请提供更多与上述建议相关的信息!
最近很头疼这个问题,我已经在这个问题上折腾了一个星期了,还是不行。希望你能帮我把这块石头踢开,非常感谢。
我的问题: 我们公司为iPhone生产USB存储设备,实际上这个存储设备中有一个SDCard。现在,我们想开发一个 Mac 应用程序来更新此存储设备的固件。但是每次我将存储设备连接到 Mac 时,Mac 都会自动安装它,并且在调用 USBInterfaceOpen[= 时我总是失败并显示 kIOReturnExclusiveAccess 27=].
我也尝试写了一个codeless kext来提高probe score,但是还是不行。不知道是我走错了路,还是写了codeless kext有什么错误,比如IOClass写错了,bundle ID写错了。
我的无代码 kext 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>BuildMachineOSBuild</key>
<string>14E46</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleIdentifier</key>
<string>com.mophie.MyDriverTest3</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>MyDriverTest3</string>
<key>CFBundlePackageType</key>
<string>KEXT</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0.3</string>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key>
<string>6E35b</string>
<key>DTPlatformVersion</key>
<string>GM</string>
<key>DTSDKBuild</key>
<string>14D125</string>
<key>DTSDKName</key>
<string>macosx10.10</string>
<key>DTXcode</key>
<string>0640</string>
<key>DTXcodeBuild</key>
<string>6E35b</string>
<key>IOKitPersonalities</key>
<dict>
<key>MyDriverTest3</key>
<dict>
<key>CFBundleIdentifier</key>
<string>com.apple.iokit.IOUSBFamily</string>
<key>IOClass</key>
<string>IOService</string>
<key>IOProviderClass</key>
<string>IOUSBDevice</string>
<key>bcdDevice</key>
<string>256</string>
<key>idProduct</key>
<integer>4369</integer>
<key>idVendor</key>
<integer>6631</integer>
</dict>
</dict>
<key>OSBundleRequired</key>
<string>Root</string>
</dict>
</plist>
以下是我的存储设备的 ioreg 结果:
space pack@1a122000 <class IOUSBDevice, id 0x100001773, registered, matched, active, busy 0 (300 ms), retain 9>
+-o IOUSBCompositeDriver <class IOUSBCompositeDriver, id 0x100001775, !registered, !matched, active, busy 0, retain 4>
+-o IOUSBInterface@0 <class IOUSBInterface, id 0x100001776, registered, matched, active, busy 0 (293 ms), retain 8>
+-o IOUSBMassStorageClass <class IOUSBMassStorageClass, id 0x100001777, registered, matched, active, busy 0 (201 ms), retain 9>
+-o IOSCSIPeripheralDeviceNub <class IOSCSIPeripheralDeviceNub, id 0x100001779, registered, matched, active, busy 0 (99 ms), retain 7>
+-o IOSCSIPeripheralDeviceType00 <class IOSCSIPeripheralDeviceType00, id 0x10000177a, !registered, !matched, active, busy 0 (13 ms), retain 9>
+-o IOBlockStorageServices <class IOBlockStorageServices, id 0x10000177d, registered, matched, active, busy 0 (13 ms), retain 6>
+-o IOBlockStorageDriver <class IOBlockStorageDriver, id 0x10000177e, registered, matched, active, busy 0 (12 ms), retain 47>
+-o mophie SpacePack Media <class IOMedia, id 0x100001784, registered, matched, active, busy 0 (12 ms), retain 11>
+-o IOMediaBSDClient <class IOMediaBSDClient, id 0x100001785, registered, matched, active, busy 0 (0 ms), retain 6>
+-o IOFDiskPartitionScheme <class IOFDiskPartitionScheme, id 0x100001788, !registered, !matched, active, busy 0 (1 ms), retain 6>
+-o Untitled 1@1 <class IOMedia, id 0x10000178a, registered, matched, active, busy 0 (1 ms), retain 10>
+-o IOMediaBSDClient <class IOMediaBSDClient, id 0x10000178b, registered, matched, active, busy 0 (0 ms), retain 7>
希望你能帮我解决这个问题,非常感谢,非常感谢你的帮助!
听起来您正在尝试使用 IOUSBInterfaceInterface 提供的低级 USB 命令连接到 USB 大容量存储接口并发送一些自定义命令来更新固件。由于该接口由 Apple 大容量存储驱动程序声明,因此您可能不允许这样做。
相反,您可以尝试在您的设备上制作第二个 USB 接口,这是供应商定义的接口。您将能够连接到该接口并将任意控制传输发送到您的设备。如果您的设备尚未成为复合设备,那么它就是复合设备。
或者,您可以尝试使用某种破解方法通过大容量存储接口发送信号。例如,每当将具有特殊名称的文件写入设备时,这可能是设备进入引导加载程序模式以进行固件更新的信号。
几点:
- 无代码 kext 方法通常适用于这种情况。
- 通常,您的无代码 kext 会匹配(通过 IOProviderClass)
IOUSBInterface
,而不是IOUSBDevice
。 (例如,参见 the FTDI example) IOService
的包标识符是com.apple.kpi.iokit
,而不是com.apple.iokit.IOUSBFamily
,尽管我怀疑这不应该成为问题。- 您的无代码 kext 是否已正确签名和安装? (我遇到过 /Library/Extensions/ 中的 kext 在启动时不起作用的情况,至少在 OSX 10.9.x 上,不像 /System/Library/Extensions,尽管它应该对于任何热插拔设备都可以正常工作。)确保 kext/personality 缓存是最新的,换句话说,每当您更新 kext 时,
touch
Extensions 目录。 kextutil -n
说了什么?- 您是否尝试过设置
IOKitDebug
个性 属性 以查看您的 kext 是否有机会匹配设备? - 根据固件更新命令的实施方式,您可以在设备节点上使用
ioctl
s。您可以通过 ioctl 将原始 SCSI 请求发送到 SCSI 设备。我不确定这是否适用于 USB 大容量存储 class,但它肯定适用于 USB 连接的 SCSI (UAS) 或任何其他 "true" SCSI 设备。显然,这只有在您的固件更新命令通过 SCSI 公开时才有用。
如果在所有这些之后,您仍然卡住了,请提供更多与上述建议相关的信息!