简体   繁体   中英

OSX: Workaround for getting BSD name of an IOUSBDevice

We have been using the solution described at OSX: How to get a volume name (or bsd name) from a IOUSBDeviceInterface or location id to map a USB device from IOKit to its corresponding BSD device location. The code for this is:

CFTypeRef name = IORegistryEntrySearchCFProperty(usbDevice,
                                                 kIOServicePlane,
                                                 CFSTR(kIOBSDNameKey),
                                                 kCFAllocatorDefault,
                                                 kIORegistryIterateRecursively);

This solution no longer works on El Capitan due to a regression that was introduced in the beta versions. According to the thread at https://forums.developer.apple.com/thread/7974 , Apple has confirmed the bug but hasn't released a fix yet, so I need a workaround. So far the only one I'm aware of involves parsing the entire I/O registry from the root and looking for my specific device.

Does anyone know of a simpler workaround?

Recently ran into this problem as well. The problem didn't start at filtering the bsdName for me, it was actually related to getting results from the USB query in the first place. Turns out in El Capitan IOUSBDevice is sort of deprecated in favor of IOUSBHostDevice. Here's what I did to get what I needed:

// -- Begin Relevant Changes Part! ---
// Get current version
auto current_supported_version = __MAC_OS_X_VERSION_MAX_ALLOWED;
// El Capitan is 101100 (in AvailabilityInternal.h)
auto el_capitan = 101100;

// IOUSBDevice has become IOUSBHostDevice in El Capitan...
auto service_matcher = current_supported_version < el_capitan ? "IOUSBDevice" : "IOUSBHostDevice";

// Create matching dict to search
CFMutableDictionaryRef matchingDict = IOServiceMatching(service_matcher);
// -- End Relevant Changes Part! ---


// The rest of this is just example implementation code.
if (matchingDict == NULL)
{
   // IOServiceMatching Failed
}

// Fill it with other stuff if necessary (vendor id, etc...)

// Do actual search
io_iterator_t iter;
kern_return_t kr;
kr = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &iter);
if (kr != KERN_SUCCESS)
{
    // IOServiceGetMatchingServices Failed
}

io_service_t service;
while ((service = IOIteratorNext(iter)))
{
    // Ought to work now, regardless of version of OSX being ran.
    CFStringRef bsdName = (CFStringRef) IORegistryEntrySearchCFProperty(
        service,
        kIOServicePlane,
        CFSTR(kIOBSDNameKey),
        kCFAllocatorDefault,
        kIORegistryIterateRecursively
        );
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM