2013-06-25 2 views
2

Вот мой код, и он обнаружит устройства при первом запуске приложения, но он не обнаружит новый после его запуска.Цель c/c: Обнаружение USB-накопителя через IOKit только на Mac

//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 функция? Фактически я добавил, но это дает мне плохую ошибку доступа. Не могли бы вы, ребята, сказать мне, как справляться с этими проблемами? Благодаря!!

ответ

3

Проблема заключается в вызове IOObjectRelease() в функции вашего обработчика. Вам нужно удержать итератор, который вы получаете от IOServiceAddMatchingNotification, пока вы хотите получать эти уведомления. Если вы удалите звонок, код работает.

Что касается вашего второго вопроса: вызов дает плохую ошибку доступа, потому что matchingDict освобождается IOServiceAddMatchingNotification. Если вы делаете CFRetain(matchingDict) перед этим вызовом, вы можете добавить второе уведомление с использованием того же совпадающего словаря. (BTW: вы должны передать kIOTerminatedNotification вместо kIOFirstMatchNotification, если вас интересуют уведомления об удалении устройства.

+0

BTW: вам также нужно добавить два разных источника для работы. – valvoline