目标c / c:仅在Mac上通过IOKit检测USB驱动器

时间:2013-06-25 18:49:46

标签: objective-c macos cocoa notifications iokit

这是我的代码,它会在我首先运行应用程序时检测设备,但在运行后它不会检测到新设备。

//Just for testing
 - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
   [self detectUSB];
}

void detectUSB()
{
  //dictionary
  CFMutableDictionaryRef matchingDict = matchingDict = IOServiceMatching(kIOUSBDeviceClassName);

  //create notification
  IONotificationPortRef notificationObject; //notification object to listen
  mach_port_t masterPort = 0; //received from IOMasterPort
  notificationObject = IONotificationPortCreate(masterPort);

  //create run loop
  CFRunLoopSourceRef notificationRunLoopSource;

  //use notification obejct received from notificationPortCreate
  notificationRunLoopSource = IONotificationPortGetRunLoopSource(notificationObject);

  CFRunLoopAddSource(CFRunLoopGetCurrent(), notificationRunLoopSource, kCFRunLoopDefaultMode);

  IOServiceAddMatchingNotification(notificationObject,kIOFirstMatchNotification, matchingDict,isAttached,(__bridge void*)self,&iter );

  isAttached(NULL, iter);
}

void isAttached(void *refcon, io_iterator_t iterator) {

    io_service_t usbDevice;
    while((usbDevice = IOIteratorNext(iterator))) {
         io_name_t name; 
         IORegistryEntryGetName(usbDevice, name);
         printf("\tName:\t\t%s\n", (char *)name);

         CFNumberRef idProduct = (CFNumberRef)IORegistryEntrySearchCFProperty(usbDevice, kIOServicePlane, CFSTR("idProduct"), kCFAllocatorDefault, 0);
         uint16_t PID;
         CFNumberGetValue(idProduct, kCFNumberSInt16Type, (void *)&PID);
         printf("\tidProduct:\t0x%x\n", PID);

         IOObjectRelease(usbDevice);
         CFRelease(idProduct);
      }
   IOObjectRelease(iterator);
 }

更重要的是,如果我拔掉一个USB驱动器,我该如何检测?我应该再添加一个

  IOServiceAddMatchingNotification(notificationObject,kIOFirstMatchNotification, matchingDict,isDetached,(__bridge void*)self,&iter );

在isAttached函数之后?实际上我添加但它给了我错误的访问错误。你能告诉我如何处理这些问题吗?谢谢!

1 个答案:

答案 0 :(得分:3)

问题在于处理程序函数中的IOObjectRelease()调用。只要您想接收这些通知,就需要保留从IOServiceAddMatchingNotification获得的迭代器。如果您删除了发布调用,则代码可以正常运行。

关于你的第二个问题:调用会产生错误的访问错误,因为matchingDict会释放IOServiceAddMatchingNotification。如果您在该呼叫之前执行CFRetain(matchingDict),则可以使用相同的匹配字典添加第二个通知。 (顺便说一句:如果您对设备删除通知感兴趣,则应该通过kIOTerminatedNotification而不是kIOFirstMatchNotification