halfwaythru
halfwaythru

Reputation: 187

Notifications from Mac OS on usb device addition/removal

I am writing a method to receive notification from the OS when a USB device is plugged/unplugged. I used the advice on this question

How to know when a HID USB/Bluetooth device is connected in Cocoa?.

And this is what I have:

io_iterator_t portIterator;

CFMutableDictionaryRef matchingDict = IOServiceMatching(kIOUSBDeviceClassName);    // Interested in instances of class
long vendorID  = usbVendorId;
long productID = usbProductID;

// Create a CFNumber for the idVendor and set the value in the dictionary
CFNumberRef numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vendorID);
CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), numberRef);
CFRelease(numberRef);

// Create a CFNumber for the idProduct and set the value in the dictionary
numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &productID);
CFDictionarySetValue(matchingDict, CFSTR(kUSBProductID),  numberRef);
CFRelease(numberRef);
numberRef = NULL; 

mach_port_t             masterPort;
IOMasterPort(MACH_PORT_NULL, &masterPort);

// Set up notification port and add it to the current run loop for addition notifications.
IONotificationPortRef notificationPort = IONotificationPortCreate(masterPort);
CFRunLoopAddSource(CFRunLoopGetCurrent(), 
                   IONotificationPortGetRunLoopSource(notificationPort), 
                   kCFRunLoopDefaultMode);


// Register for notifications when a serial port is added to the system.
// Retain dictionary first because all IOServiceMatching calls consume dictionary.
CFRetain(matchingDict);
kern_return_t result = IOServiceAddMatchingNotification(notificationPort,
                                                        kIOMatchedNotification,
                                                        matchingDict,
                                                        usbDeviceAdded,
                                                        nil,           
                                                        &portIterator);
// Run out the iterator or notifications won't start.
while (IOIteratorNext(portIterator)) {}; 


// Also Set up notification port and add it to the current run loop removal notifications.
IONotificationPortRef terminationNotificationPort = IONotificationPortCreate(kIOMasterPortDefault);
CFRunLoopAddSource(CFRunLoopGetCurrent(),
                   IONotificationPortGetRunLoopSource(terminationNotificationPort),
                   kCFRunLoopDefaultMode); 

// Register for notifications when a serial port is added to the system.
// Retain dictionary first because all IOServiceMatching calls consume dictionary.
CFRetain(matchingDict);
kern_return_t result1 = IOServiceAddMatchingNotification(terminationNotificationPort,
                                          kIOTerminatedNotification,
                                          matchingDict,
                                          usbDeviceRemoved,
                                          this,         
                                          &portIterator);

// Run out the iterator or notifications won't start.
while (IOIteratorNext(portIterator)) {}; 
CFRetain(matchingDict);

I am having the same problem that the original poster had. I am getting the notifications, but only once for removing/adding. It doesnt matter if I try adding/removing a different device, I am only getting one notification. After that, I just dont get notified.

Can someone please help me figure out why this might be happening. Thanks!

Upvotes: 5

Views: 4133

Answers (1)

halfwaythru
halfwaythru

Reputation: 187

IOKit device adding/removal notifications - only fire once?

This is where I found my answer, though it wasnt easy to spot.

As it turns out, the methods that receive the notifications upon addition/removal of a device need to run the port iterator necessarily.

So, in the callback methods, a statement like this is required.

while (IOIteratorNext(portIterator)) {};

or do something else with it, just run the iterator. I am diappointed that this isn't specified anywhere.

Upvotes: 2

Related Questions