Here is my code and it will detect the devices when I run the application at first, but it will not detect the new one after it is running.
//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);
}
What's more, if I unplug one of USB drive, how should I detect that ? Should I add one more
IOServiceAddMatchingNotification(notificationObject,kIOFirstMatchNotification, matchingDict,isDetached,(__bridge void*)self,&iter );
after isAttached function? Actually I added but it gives me bad access error. Could you guys tell me how to handle these problems? Thanks!!
The problem lies with the IOObjectRelease() call in your handler function. You need to hold on to the iterator that you get from the IOServiceAddMatchingNotification for as long as you want to receive these notifications. If you remove the release call, the code works.
As for your second question: the call gives a bad access error, because matchingDict gets released by IOServiceAddMatchingNotification. If you do a CFRetain(matchingDict) before that call, you can add a second Notification using the same matching dictionary. (BTW: you should pass kIOTerminatedNotification instead of kIOFirstMatchNotification if you are interested in device removal notifications.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With