FlyingMan
FlyingMan

Reputation: 53

USBInterfaceOpen always report kIOReturnExclusiveAccess error

Recently I encountered this problem headachely, I've already spend one week on this issue, but still failed. Hopefully, you can help me to kick this stone away, many thanks.

My Problem: Our compony produce USB storage device for iPhone, actually there is a SDCard in this storage device. Now, we want to develop an Mac app to update firmware for this storage device. But every time I connect the storage device to Mac, Mac mounts it automatically, and I always fails with kIOReturnExclusiveAccess when invoke USBInterfaceOpen.

I also try to write a codeless kext to increase the probe score, but it still doesn't work. I don't know wether I go a wrong way, or some mistakes for writing the codeless kext, eg, write some wrong IOClass, wrong bundle ID.

My codeless kext info.plist is:

<?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>    

Below is the result from ioreg for my storage device:

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>

Hopefully you can help me on this problem, many many many thanks, I preciate your help very much!

Upvotes: 5

Views: 1659

Answers (2)

pmdj
pmdj

Reputation: 23438

A few points:

  • The codeless kext approach should normally work for this kind of situation.
  • Typically, your codeless kext would match (via IOProviderClass) an IOUSBInterface, not an IOUSBDevice. (e.g. see the FTDI example)
  • The bundle identifier for IOService is com.apple.kpi.iokit, not com.apple.iokit.IOUSBFamily, although I suspect that shouldn't be an issue.
  • Is your codeless kext signed and installed correctly? (I have had instances where a kext in /Library/Extensions/ would not work at boot time, at least on OSX 10.9.x, unlike /System/Library/Extensions, although it should work OK for any hot-plugged devices.) Make sure the kext/personality cache is up to date, in other words, touch the Extensions directory whenever you update the kext.
  • What does kextutil -n say?
  • Have you tried setting the IOKitDebug personality property to see if your kext is even getting a chance to match the device?
  • Depending on how your firmware update commands are implemented, you may be able to use ioctls on the device node. You can send raw SCSI requests to SCSI devices via ioctl. I'm not sure this will work for the USB mass storage class, but it definitely will for USB attached SCSI (UAS) or any other "true" SCSI device. Obviously this only helps if the your firmware update commands are exposed via SCSI.

If after all of that, you're still stuck, please provide some more information related to the above suggestions!

Upvotes: 1

David Grayson
David Grayson

Reputation: 87426

It sounds like you are trying to use the low-level USB commands provided by IOUSBInterfaceInterface to connect to a USB mass storage interface and send some custom commands for updating the firmware. Since that interface is claimed by the Apple mass-storage drivers, you probably aren't allowed to do that.

Instead, you might try making a second USB interface on your device which is a vendor-defined interface. You would be able to connect to that interface and send arbitrary control transfers to your device. Your device would then be a composite device if it is not already.

Alternatively, you might try some sort of hack to send signals over the mass storage interface. For example, whenever a file with a special name is written to the device, that could be a signal to the device to go into bootloader mode for a firmware update.

Upvotes: 1

Related Questions