int main (int argc, const char *argv[]) { mach_port_t masterPort; CFMutableDictionaryRef matchingDict; CFRunLoopSourceRef runLoopSource; kern_return_t kr; SInt32 usbVendor = kOurVendorID; SInt32 usbProduct = kOurProductID; sig_t oldHandler; // pick up command line arguments if (argc > 1) usbVendor = atoi(argv[1]); if (argc > 2) usbProduct = atoi(argv[2]); // Set up a signal handler so we can clean up when we're interrupted from the command line // Otherwise we stay in our run loop forever. oldHandler = signal(SIGINT, SignalHandler); if (oldHandler == SIG_ERR) printf("Could not establish new signal handler"); // first create a master_port for my task kr = IOMasterPort(MACH_PORT_NULL, &masterPort); if (kr || !masterPort) { printf("ERR: Couldn't create a master IOKit Port(%08x)\n", kr); return -1; } printf("Looking for devices matching vendor ID=%ld and product ID=%ld\n", usbVendor, usbProduct); // Set up the matching criteria for the devices we're interested in matchingDict = IOServiceMatching(kIOUSBDeviceClassName); // Interested in instances of class IOUSBDevice and its subclasses if (!matchingDict) { printf("Can't create a USB matching dictionary\n"); mach_port_deallocate(mach_task_self(), masterPort); return -1; } // Add our vendor and product IDs to the matching criteria CFDictionarySetValue( matchingDict, CFSTR(kUSBVendorID), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbVendor)); CFDictionarySetValue( matchingDict, CFSTR(kUSBProductID), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbProduct)); // Create a notification port and add its run loop event source to our run loop // This is how async notifications get set up. gNotifyPort = IONotificationPortCreate(masterPort); runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort); CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode); // Retain additional references because we use this same dictionary with four calls to // IOServiceAddMatchingNotification, each of which consumes one reference. matchingDict = (CFMutableDictionaryRef) CFRetain( matchingDict ); matchingDict = (CFMutableDictionaryRef) CFRetain( matchingDict ); matchingDict = (CFMutableDictionaryRef) CFRetain( matchingDict ); // Now set up two notifications, one to be called when a raw device is first matched by I/O Kit, and the other to be // called when the device is terminated. kr = IOServiceAddMatchingNotification( gNotifyPort, kIOFirstMatchNotification, matchingDict, RawDeviceAdded, NULL, &gRawAddedIter ); RawDeviceAdded(NULL, gRawAddedIter); // Iterate once to get already-present devices and // arm the notification kr = IOServiceAddMatchingNotification( gNotifyPort, kIOTerminatedNotification, matchingDict, RawDeviceRemoved, NULL, &gRawRemovedIter ); RawDeviceRemoved(NULL, gRawRemovedIter); // Iterate once to arm the notification // Change the USB product ID in our matching dictionary to the one the device will have once the // bulktest firmware has been downloaded. usbProduct = kOurProductIDBulkTest; CFDictionarySetValue( matchingDict, CFSTR(kUSBProductID), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbProduct)); // Now set up two more notifications, one to be called when a bulk test device is first matched by I/O Kit, and the other to be // called when the device is terminated. kr = IOServiceAddMatchingNotification( gNotifyPort, kIOFirstMatchNotification, matchingDict, BulkTestDeviceAdded, NULL, &gBulkTestAddedIter ); BulkTestDeviceAdded(NULL, gBulkTestAddedIter); // Iterate once to get already-present devices and // arm the notification kr = IOServiceAddMatchingNotification( gNotifyPort, kIOTerminatedNotification, matchingDict, BulkTestDeviceRemoved, NULL, &gBulkTestRemovedIter ); BulkTestDeviceRemoved(NULL, gBulkTestRemovedIter); // Iterate once to arm the notification // Now done with the master_port mach_port_deallocate(mach_task_self(), masterPort); masterPort = 0; // Start the run loop. Now we'll receive notifications. CFRunLoopRun(); // We should never get here return 0; }
int main (int argc, const char *argv[]) { mach_port_t masterPort; CFMutableDictionaryRef matchingDict; CFRunLoopSourceRef runLoopSource; kern_return_t kr; SInt32 usbVendor = kOurVendorID; SInt32 usbProduct = kOurProductID; kr = IOMasterPort(MACH_PORT_NULL, &masterPort); if (kr || !masterPort) { printf("ERR: Couldn't create a master I/O Kit port(%08x)\n", kr); return -1; } // Setup matching dictionary for class IOUSBDevice and its subclasses matchingDict = IOServiceMatching(kIOUSBDeviceClassName); if (!matchingDict) { printf("couldn't craete a usb matching dictionary :(\n"); mach_port_deallocate(mach_task_self(), masterPort); return -1; } // add vendor and product Ids to dict CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorName), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbVendor)); CFDictionarySetValue(matchingDict, CFSTR(kUSBProductName), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbProduct)); gNotifyPort = IONotificationPortCreate(masterPort); runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort); CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode); //Now set up two notifications: one to be called when a raw device //is first matched by the I/O Kit and another to be called when the //device is terminated //Notification of first match: kr = IOServiceAddMatchingNotification(gNotifyPort, kIOFirstMatchNotification, matchingDict, RawDeviceAdded, NULL, &gRawAddedIter); //Iterate over set of matching devices to access already-present devices //and to arm the notification RawDeviceAdded(NULL, gRawAddedIter); /* //Notification of termination: kr = IOServiceAddMatchingNotification(gNotifyPort, kIOTerminatedNotification, matchingDict, RawDeviceRemoved, NULL, &gRawRemovedIter); //Iterate over set of matching devices to release each one and to //arm the notification RawDeviceRemoved(NULL, gRawRemovedIter); */ mach_port_deallocate(mach_task_self(), masterPort); masterPort = 0; CFRunLoopRun(); return 0; }