void InitUPSNotifications() { CFMutableDictionaryRef matchingDict; CFMutableDictionaryRef propertyDict; kern_return_t kr; // 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(kIOMasterPortDefault); CFRunLoopAddSource( CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(gNotifyPort), kCFRunLoopDefaultMode); // Create the IOKit notifications that we need // matchingDict = IOServiceMatching(kIOServiceClass); if (!matchingDict) return; propertyDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (!propertyDict) { CFRelease(matchingDict); return; } // We are only interested in devices that have kIOUPSDeviceKey property set CFDictionarySetValue(propertyDict, CFSTR(kIOUPSDeviceKey), kCFBooleanTrue); CFDictionarySetValue(matchingDict, CFSTR(kIOPropertyMatchKey), propertyDict); CFRelease(propertyDict); // Now set up a notification to be called when a device is first matched by I/O Kit. // Note that this will not catch any devices that were already plugged in so we take // care of those later. kr = IOServiceAddMatchingNotification(gNotifyPort, // notifyPort kIOFirstMatchNotification, // notificationType matchingDict, // matching UPSDeviceAdded, // callback NULL, // refCon &gAddedIter // notification ); if ( kr != kIOReturnSuccess ) return; UPSDeviceAdded( NULL, gAddedIter ); }
bool HIDDevice::setupDevicePluggedInNotification() { // Setup notification when devices are plugged in. RepluggedNotificationPort = IONotificationPortCreate(kIOMasterPortDefault); CFRunLoopSourceRef notificationRunLoopSource = IONotificationPortGetRunLoopSource(RepluggedNotificationPort); CFRunLoopAddSource(HIDManager->getRunLoop(), notificationRunLoopSource, kCFRunLoopDefaultMode); CFMutableDictionaryRef matchingDict = IOServiceMatching(kIOUSBDeviceClassName); // Have to specify vendorId and productId. Doesn't seem to accept additional // things like serial number. SInt32 vendorId = DevDesc.VendorId; CFNumberRef numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vendorId); CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), numberRef); CFRelease(numberRef); SInt32 deviceProductId = DevDesc.ProductId; numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &deviceProductId); CFDictionarySetValue(matchingDict, CFSTR(kUSBProductID), numberRef); CFRelease(numberRef); kern_return_t result = IOServiceAddMatchingNotification(RepluggedNotificationPort, kIOMatchedNotification, matchingDict, staticDeviceAddedCallback, this, &RepluggedNotification); if (result != KERN_SUCCESS) { CFRelease(RepluggedNotificationPort); RepluggedNotificationPort = 0; return false; } // Iterate through to arm. while (IOIteratorNext(RepluggedNotification)) { } return true; }
io_connect_t IORegisterForSystemPower ( void * refcon, IONotificationPortRef * thePortRef, IOServiceInterestCallback callback, io_object_t * root_notifier ) { io_connect_t fb = IO_OBJECT_NULL; IONotificationPortRef notify = NULL; kern_return_t kr; io_service_t obj = IO_OBJECT_NULL; *root_notifier = IO_OBJECT_NULL; notify = IONotificationPortCreate(MACH_PORT_NULL); obj = IORegistryEntryFromPath( IO_OBJECT_NULL, kIOPowerPlane ":/IOPowerConnection/IOPMrootDomain"); if( obj == IO_OBJECT_NULL) goto failure_exit; kr = IOServiceOpen( obj,mach_task_self(), 0, &fb); if ( (kr != kIOReturnSuccess) || (fb == IO_OBJECT_NULL) ) { goto failure_exit; } kr = IOServiceAddInterestNotification( notify,obj,kIOAppPowerStateInterest, callback,refcon,root_notifier); IOObjectRelease(obj); if ( kr == KERN_SUCCESS ) { // Successful exit case *thePortRef = notify; return fb; } failure_exit: if ( obj != IO_OBJECT_NULL) { IOObjectRelease(obj); } if ( notify != NULL) { IONotificationPortDestroy(notify); } if ( fb != IO_OBJECT_NULL) { IOServiceClose(fb); } if ( *root_notifier != IO_OBJECT_NULL) { IOObjectRelease(*root_notifier); } return IO_OBJECT_NULL; }
void IOKitEventPublisher::restart() { static std::vector<const std::string*> device_classes = { &kIOUSBDeviceClassName_, &kIOPCIDeviceClassName_, &kIOPlatformExpertDeviceClassName_, &kIOACPIPlatformDeviceClassName_, &kIOPlatformDeviceClassname_, }; if (run_loop_ == nullptr) { return; } // Remove any existing stream. stop(); { WriteLock lock(mutex_); port_ = IONotificationPortCreate(kIOMasterPortDefault); // Get a run loop source from the created IOKit notification port. auto run_loop_source = IONotificationPortGetRunLoopSource(port_); CFRunLoopAddSource(run_loop_, run_loop_source, kCFRunLoopDefaultMode); } publisher_started_ = false; for (const auto& class_name : device_classes) { // Service matching is USB for now, must find a way to get more! // Can provide a "IOPCIDevice" here too. auto matches = IOServiceMatching(class_name->c_str()); // Register attach/detaches (could use kIOPublishNotification). // Notification types are defined in IOKitKeys. IOReturn result = kIOReturnSuccess + 1; { WriteLock lock(mutex_); result = IOServiceAddMatchingNotification( port_, kIOFirstMatchNotification, matches, (IOServiceMatchingCallback)deviceAttach, this, &iterator_); } if (result == kIOReturnSuccess) { deviceAttach(this, iterator_); } } publisher_started_ = true; }
static void *media_poll_func(void *) { media_poll_loop = CFRunLoopGetCurrent(); mach_port_t masterPort; kern_return_t kernResult = IOMasterPort(bootstrap_port, &masterPort); if (kernResult != KERN_SUCCESS) { fprintf(stderr, "IOMasterPort() returned %d\n", kernResult); return NULL; } CFMutableDictionaryRef matchingDictionary = IOServiceMatching(kIOCDMediaClass); if (matchingDictionary == NULL) { fprintf(stderr, "IOServiceMatching() returned a NULL dictionary\n"); return NULL; } matchingDictionary = (CFMutableDictionaryRef)CFRetain(matchingDictionary); IONotificationPortRef notificationPort = IONotificationPortCreate(kIOMasterPortDefault); CFRunLoopAddSource(media_poll_loop, IONotificationPortGetRunLoopSource(notificationPort), kCFRunLoopDefaultMode); io_iterator_t mediaArrivedIterator; kernResult = IOServiceAddMatchingNotification(notificationPort, kIOMatchedNotification, matchingDictionary, (IOServiceMatchingCallback)media_arrived, (void *)MEDIA_CD, &mediaArrivedIterator); if (kernResult != KERN_SUCCESS) fprintf(stderr, "IOServiceAddMatchingNotification() returned %d\n", kernResult); media_arrived(MEDIA_CD, mediaArrivedIterator); io_iterator_t mediaRemovedIterator; kernResult = IOServiceAddMatchingNotification(notificationPort, kIOTerminatedNotification, matchingDictionary, (IOServiceMatchingCallback)media_removed, (void *)MEDIA_CD, &mediaRemovedIterator); if (kernResult != KERN_SUCCESS) fprintf(stderr, "IOServiceAddMatchingNotification() returned %d\n", kernResult); media_removed(MEDIA_CD, mediaRemovedIterator); CFRunLoopRun(); return NULL; }
static void HPEstablishPCCardNotification(void) { io_iterator_t deviceAddedIterator; io_iterator_t deviceRemovedIterator; CFMutableDictionaryRef matchingDictionary; IONotificationPortRef notificationPort; IOReturn kret; notificationPort = IONotificationPortCreate(kIOMasterPortDefault); CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notificationPort), kCFRunLoopDefaultMode); matchingDictionary = IOServiceMatching("IOPCCard16Device"); if (!matchingDictionary) { Log1(PCSC_LOG_ERROR, "IOServiceMatching() failed"); } matchingDictionary = (CFMutableDictionaryRef) CFRetain(matchingDictionary); kret = IOServiceAddMatchingNotification(notificationPort, kIOMatchedNotification, matchingDictionary, HPDeviceAppeared, NULL, &deviceAddedIterator); if (kret) { Log2(PCSC_LOG_ERROR, "IOServiceAddMatchingNotification()-1 failed with code %d", kret); } HPDeviceAppeared(NULL, deviceAddedIterator); kret = IOServiceAddMatchingNotification(notificationPort, kIOTerminatedNotification, matchingDictionary, HPDeviceDisappeared, NULL, &deviceRemovedIterator); if (kret) { Log2(PCSC_LOG_ERROR, "IOServiceAddMatchingNotification()-2 failed with code %d", kret); } HPDeviceDisappeared(NULL, deviceRemovedIterator); }
void InitDetection() { kern_return_t kr; // Set up the matching criteria for the devices we're interested in. The matching criteria needs to follow // the same rules as kernel drivers: mainly it needs to follow the USB Common Class Specification, pp. 6-7. // See also Technical Q&A QA1076 "Tips on USB driver matching on Mac OS X" // <http://developer.apple.com/qa/qa2001/qa1076.html>. // One exception is that you can use the matching dictionary "as is", i.e. without adding any matching // criteria to it and it will match every IOUSBDevice in the system. IOServiceAddMatchingNotification will // consume this dictionary reference, so there is no need to release it later on. // Interested in instances of class // IOUSBDevice and its subclasses matchingDict = IOServiceMatching(kIOUSBDeviceClassName); if (matchingDict == NULL) { fprintf(stderr, "IOServiceMatching returned NULL.\n"); } // 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(kIOMasterPortDefault); // Now set up a notification to be called when a device is first matched by I/O Kit. kr = IOServiceAddMatchingNotification( gNotifyPort, // notifyPort kIOFirstMatchNotification, // notificationType matchingDict, // matching DeviceAdded, // callback NULL, // refCon &gAddedIter // notification ); if (KERN_SUCCESS != kr) { printf("IOServiceAddMatchingNotification returned 0x%08x.\n", kr); } // Iterate once to get already-present devices and arm the notification DeviceAdded(NULL, gAddedIter); initialDeviceImport = false; }
static int InitUSB() { CFMutableDictionaryRef matchingDict; CFRunLoopSourceRef runLoopSource; //* To set up asynchronous notifications, create a notification port and //* add its run loop event source to the program's run loop notificationPort = IONotificationPortCreate(kIOMasterPortDefault); runLoopSource = IONotificationPortGetRunLoopSource(notificationPort); CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode); //* Create our matching dictionary to find the Android device's //* adb interface //* IOServiceAddMatchingNotification consumes the reference, so we do //* not need to release this matchingDict = IOServiceMatching(kIOUSBInterfaceClassName); if (!matchingDict) { DBG("ERR: Couldn't create USB matching dictionary.\n"); return -1; } //* We have to get notifications for all potential candidates and test them //* at connection time because the matching rules don't allow for a //* USB interface class of 0xff for class+subclass+protocol matches //* See https://developer.apple.com/library/mac/qa/qa1076/_index.html IOServiceAddMatchingNotification( notificationPort, kIOFirstMatchNotification, matchingDict, AndroidInterfaceAdded, NULL, ¬ificationIterator); //* Iterate over set of matching interfaces to access already-present //* devices and to arm the notification AndroidInterfaceAdded(NULL, notificationIterator); return 0; }
void find_device () { CFMutableDictionaryRef matchingDict; CFNumberRef refUsage; CFNumberRef refUsagePageKey; SInt32 usage = 1; /* mouse */ SInt32 usagePageKey = 2; /* mouse */ mach_port_t masterPort; kern_return_t kr; kr = IOMasterPort (bootstrap_port, &masterPort); if (kr || !masterPort) { return; } gNotifyPort = IONotificationPortCreate (masterPort); CFRunLoopAddSource (CFRunLoopGetCurrent (), IONotificationPortGetRunLoopSource (gNotifyPort), kCFRunLoopDefaultMode); matchingDict = IOServiceMatching ("IOHIDDevice"); if (!matchingDict) { return; } refUsage = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &usage); refUsagePageKey = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &usagePageKey); CFDictionarySetValue (matchingDict, CFSTR (kIOHIDPrimaryUsageKey), refUsagePageKey); CFDictionarySetValue (matchingDict, CFSTR (kIOHIDPrimaryUsagePageKey), refUsage); CFRelease (refUsage); CFRelease (refUsagePageKey); kr = IOServiceAddMatchingNotification (gNotifyPort, kIOFirstMatchNotification, matchingDict, init_device, NULL, &gAddedIter); if (kr != kIOReturnSuccess) { return; } init_device (NULL, gAddedIter); }
CFStringRef copy_wifi_mac_address() { CFStringRef wifimac = NULL; IONotificationPortRef notify_port = 0; io_iterator_t iterator = 0; wifimac = lookup_mac_address("sdio"); if (wifimac != NULL) return wifimac; wifimac = lookup_mac_address("wlan"); if (wifimac != NULL) return wifimac; notify_port = IONotificationPortCreate(kIOMasterPortDefault); CFRunLoopSourceRef runLoopSource = IONotificationPortGetRunLoopSource(notify_port); CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode); if (!IOServiceAddMatchingNotification( notify_port, kIOMatchedNotification, IOServiceMatching("IONetworkController"), (IOServiceMatchingCallback) search_wifi_mac_callback, &wifimac, &iterator )) { search_wifi_mac_callback((void**)&wifimac, iterator); while( wifimac == NULL) { if( CFRunLoopRunInMode(kCFRunLoopDefaultMode,0, TRUE) != kCFRunLoopRunHandledSource) { printf("giving up on wifi mac address\n"); break; } } } IONotificationPortDestroy(notify_port); return wifimac; }
InputHandler_MacOSX_HID::InputHandler_MacOSX_HID() : m_Sem( "Input thread started" ), m_ChangeLock( "Input handler change lock" ) { InputDevice id = DEVICE_KEYBOARD; // Set up the notify ports. m_NotifyPort = IONotificationPortCreate( kIOMasterPortDefault ); // Add devices. LOG->Trace( "Finding keyboards" ); AddDevices( kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard, id ); LOG->Trace( "Finding mice" ); AddDevices( kHIDPage_GenericDesktop, kHIDUsage_GD_Mouse, id ); LOG->Trace( "Finding joysticks" ); id = DEVICE_JOY1; AddDevices( kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick, id ); AddDevices( kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad, id ); LOG->Trace( "Finding pump" ); id = DEVICE_PUMP1; AddDevices( kHIDPage_VendorDefinedStart, 0x0001, id ); // Pump pads use the first vendor specific usage page. m_bChanged = false; if( PREFSMAN->m_bThreadedInput ) { m_InputThread.SetName( "Input thread" ); m_InputThread.Create( InputHandler_MacOSX_HID::Run, this ); // Wait for the run loop to start before returning. m_Sem.Wait(); } else { m_LoopRef = CFRunLoopRef( GetCFRunLoopFromEventLoop(GetMainEventLoop()) ); CFRetain( m_LoopRef ); StartDevices(); } }
static void initializeDisplayNotifications (void) { io_service_t displayWrangler; IONotificationPortRef notificationPort; io_object_t notifier; displayWrangler = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceNameMatching("IODisplayWrangler")); if (! displayWrangler) { message (LOG_ERR, "IOServiceGetMatchingService failed\n"); exit (1); } notificationPort = IONotificationPortCreate(kIOMasterPortDefault); if (! notificationPort) { message (LOG_ERR, "IONotificationPortCreate failed\n"); exit (1); } if (IOServiceAddInterestNotification(notificationPort, displayWrangler, kIOGeneralInterest, displayCallback, NULL, ¬ifier) != kIOReturnSuccess) { message (LOG_ERR, "IOServiceAddInterestNotification failed\n"); exit (1); } CFRunLoopAddSource (CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notificationPort), kCFRunLoopDefaultMode); IOObjectRelease (displayWrangler); }
io_connect_t ks_connect_to_service(const char *className) { kern_return_t kernResult; io_connect_t connect = IO_OBJECT_NULL; io_iterator_t iterator = IO_OBJECT_NULL; IONotificationPortRef notifyport = NULL; CFDictionaryRef classToMatch; if ((classToMatch = IOServiceMatching(className)) == NULL) { asl_log(NULL, NULL, ASL_LEVEL_ERR, "IOServiceMatching failed for '%s'", className); return connect; } /* consumed by IOServiceGetMatchingServices, we need it if that fails. */ CFRetain(classToMatch); kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, classToMatch, &iterator); if (kernResult == KERN_SUCCESS) { CFRelease(classToMatch); } else { asl_log(NULL, NULL, ASL_LEVEL_WARNING, "IOServiceGetMatchingServices() failed %d", kernResult); notifyport = IONotificationPortCreate(kIOMasterPortDefault); if (!notifyport) { asl_log(NULL, NULL, ASL_LEVEL_ERR, "IONotificationPortCreate() failed"); return connect; } kernResult = IOServiceAddMatchingNotification(notifyport, kIOFirstMatchNotification, classToMatch, ks_service_matching_callback, &connect, &iterator); if (kernResult) { asl_log(NULL, NULL, ASL_LEVEL_ERR, "IOServiceAddMatchingNotification() failed: %d", kernResult); return connect; } } /* Check whether it was already there before we registered for the notification. */ ks_service_matching_callback(&connect, iterator); if (notifyport) { /* We'll get set up to wait for it to appear */ if (connect == IO_OBJECT_NULL) { asl_log(NULL, NULL, ASL_LEVEL_ERR, "Waiting for %s to show up.", className); CFStringRef mode = CFSTR("WaitForCryptoService"); CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notifyport), mode); CFRunLoopRunInMode(mode, 30.0, true); if (connect == MACH_PORT_NULL) asl_log(NULL, NULL, ASL_LEVEL_ERR, "Cannot find %s", className); } IONotificationPortDestroy(notifyport); } IOObjectRelease(iterator); if (connect != IO_OBJECT_NULL) { secdebug("iokit", "obtained connection for '%s'", className); } return connect; }
int main(int argc, const char *argv[]) { time_t current_time = time(NULL); char* c_time_string = ctime(¤t_time); size_t l = strlen(c_time_string); if (l > 0) c_time_string[l-1] = 0; DEBUG_LOG("%s: VoodooPS2Daemon 1.7.12 starting...\n", c_time_string); // first check for trackpad driver g_ioservice = IOServiceGetMatchingService(0, IOServiceMatching("ApplePS2SynapticsTouchPad")); if (!g_ioservice) { // otherwise, talk to mouse driver g_ioservice = IOServiceGetMatchingService(0, IOServiceMatching("ApplePS2Mouse")); if (!g_ioservice) { DEBUG_LOG("No ApplePS2SynapticsTouchPad or ApplePS2Mouse found\n"); return -1; } } // Set up a signal handler so we can clean up when we're interrupted from the command line // or otherwise asked to terminate. if (SIG_ERR == signal(SIGINT, SignalHandler1)) DEBUG_LOG("Could not establish new SIGINT handler\n"); if (SIG_ERR == signal(SIGTERM, SignalHandler1)) DEBUG_LOG("Could not establish new SIGTERM handler\n"); // First create a master_port for my task mach_port_t masterPort; kern_return_t kr = IOMasterPort(MACH_PORT_NULL, &masterPort); if (kr || !masterPort) { DEBUG_LOG("ERR: Couldn't create a master IOKit Port(%08x)\n", kr); return -1; } // Create dictionary to match all USB devices CFMutableDictionaryRef matchingDict = IOServiceMatching(kIOUSBDeviceClassName); if (!matchingDict) { DEBUG_LOG("Can't create a USB matching dictionary\n"); mach_port_deallocate(mach_task_self(), masterPort); return -1; } // Create a notification port and add its run loop event source to our run loop // This is how async notifications get set up. g_NotifyPort = IONotificationPortCreate(masterPort); CFRunLoopSourceRef runLoopSource = IONotificationPortGetRunLoopSource(g_NotifyPort); CFRunLoopRef runLoop = CFRunLoopGetCurrent(); CFRunLoopAddSource(runLoop, runLoopSource, kCFRunLoopDefaultMode); // Now set up a notification to be called when a device is first matched by I/O Kit. // Note that this will not catch any devices that were already plugged in so we take // care of those later. kr = IOServiceAddMatchingNotification(g_NotifyPort, kIOFirstMatchNotification, matchingDict, DeviceAdded, NULL, &g_AddedIter); // Iterate once to get already-present devices and arm the notification DeviceAdded(NULL, g_AddedIter); // 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 DEBUG_LOG("Unexpectedly back from CFRunLoopRun()!\n"); return 0; }
// rawhid_open - open 1 or more devices // // Inputs: // max = maximum number of devices to open // vid = Vendor ID, or -1 if any // pid = Product ID, or -1 if any // usage_page = top level usage page, or -1 if any // usage = top level usage number, or -1 if any // Output: // actual number of devices opened // int rawhid_open(int max, int vid, int pid, int usage_page, int usage) { //*** kern_return_t result; mach_port_t masterPort; CFMutableDictionaryRef matchingDict; CFRunLoopSourceRef runLoopSource; //Create a master port for communication with the I/O Kit result = IOMasterPort(MACH_PORT_NULL, &masterPort); if (result || !masterPort) { return -1; } //To set up asynchronous notifications, create a notification port and //add its run loop event source to the programs run loop gNotifyPort = IONotificationPortCreate(masterPort); runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort); CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode); // *** /* IOServiceAddMatchingNotification( gNotifyPort, kIOFirstMatchNotification, matchingDict, attach_callback, NULL, &gAddedIter); */ // *** static IOHIDManagerRef hid_manager=NULL; CFMutableDictionaryRef dict; CFNumberRef num; IOReturn ret; hid_t *p; int count=0; //fprintf(stderr,"fprintf rawhid_open\n"); if (first_hid) free_all_hid(); //printf("rawhid_open, max=%d\n", max); //fflush (stdout); if (max < 1) return 0; // Start the HID Manager // http://developer.apple.com/technotes/tn2007/tn2187.html if (!hid_manager) { hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); if (hid_manager == NULL || CFGetTypeID(hid_manager) != IOHIDManagerGetTypeID()) { if (hid_manager) CFRelease(hid_manager); return 0; } } if (vid > 0 || pid > 0 || usage_page > 0 || usage > 0) { // Tell the HID Manager what type of devices we want dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (!dict) return 0; if (vid > 0) { num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &vid); CFDictionarySetValue(dict, CFSTR(kIOHIDVendorIDKey), num); CFRelease(num); } if (pid > 0) { num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &pid); CFDictionarySetValue(dict, CFSTR(kIOHIDProductIDKey), num); CFRelease(num); } if (usage_page > 0) { num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage_page); CFDictionarySetValue(dict, CFSTR(kIOHIDPrimaryUsagePageKey), num); CFRelease(num); } if (usage > 0) { num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage); CFDictionarySetValue(dict, CFSTR(kIOHIDPrimaryUsageKey), num); CFRelease(num); } IOHIDManagerSetDeviceMatching(hid_manager, dict); CFRelease(dict); } else { IOHIDManagerSetDeviceMatching(hid_manager, NULL); } // set up a callbacks for device attach & detach IOHIDManagerScheduleWithRunLoop(hid_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); IOHIDManagerRegisterDeviceMatchingCallback(hid_manager, attach_callback, NULL); IOHIDManagerRegisterDeviceRemovalCallback(hid_manager, detach_callback, NULL); ret = IOHIDManagerOpen(hid_manager, kIOHIDOptionsTypeNone); if (ret != kIOReturnSuccess) { IOHIDManagerUnscheduleFromRunLoop(hid_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); CFRelease(hid_manager); return 0; } printf("run loop\n"); // let it do the callback for all devices while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true) == kCFRunLoopRunHandledSource) ; // count up how many were added by the callback for (p = first_hid; p; p = p->next) count++; usbstatus=count; return count; }
//================================================================================================ // main //================================================================================================ int main(int argc, const char *argv[]) { CFMutableDictionaryRef matchingDict; CFRunLoopSourceRef runLoopSource; CFNumberRef numberRef; kern_return_t kr; long usbVendor = kMyVendorID; long usbProduct = kMyProductID; 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) { fprintf(stderr, "Could not establish new signal handler."); } fprintf(stderr, "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. The matching criteria needs to follow // the same rules as kernel drivers: mainly it needs to follow the USB Common Class Specification, pp. 6-7. // See also Technical Q&A QA1076 "Tips on USB driver matching on Mac OS X" // <http://developer.apple.com/qa/qa2001/qa1076.html>. // One exception is that you can use the matching dictionary "as is", i.e. without adding any matching // criteria to it and it will match every IOUSBDevice in the system. IOServiceAddMatchingNotification will // consume this dictionary reference, so there is no need to release it later on. matchingDict = IOServiceMatching(kIOUSBDeviceClassName); // Interested in instances of class // IOUSBDevice and its subclasses if (matchingDict == NULL) { fprintf(stderr, "IOServiceMatching returned NULL.\n"); return -1; } // We are interested in all USB devices (as opposed to USB interfaces). The Common Class Specification // tells us that we need to specify the idVendor, idProduct, and bcdDevice fields, or, if we're not interested // in particular bcdDevices, just the idVendor and idProduct. Note that if we were trying to match an // IOUSBInterface, we would need to set more values in the matching dictionary (e.g. idVendor, idProduct, // bInterfaceNumber and bConfigurationValue. // Create a CFNumber for the idVendor and set the value in the dictionary numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbVendor); CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), numberRef); CFRelease(numberRef); // Create a CFNumber for the idProduct and set the value in the dictionary numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbProduct); CFDictionarySetValue(matchingDict, CFSTR(kUSBProductID), numberRef); CFRelease(numberRef); numberRef = NULL; // 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(kIOMasterPortDefault); runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort); gRunLoop = CFRunLoopGetCurrent(); CFRunLoopAddSource(gRunLoop, runLoopSource, kCFRunLoopDefaultMode); // Now set up a notification to be called when a device is first matched by I/O Kit. kr = IOServiceAddMatchingNotification(gNotifyPort, // notifyPort kIOFirstMatchNotification, // notificationType matchingDict, // matching DeviceAdded, // callback NULL, // refCon &gAddedIter // notification ); // Iterate once to get already-present devices and arm the notification DeviceAdded(NULL, gAddedIter); // Start the run loop. Now we'll receive notifications. fprintf(stderr, "Starting run loop.\n\n"); CFRunLoopRun(); // We should never get here fprintf(stderr, "Unexpectedly back from CFRunLoopRun()!\n"); 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; 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; }
/* Function to scan the system for joysticks. * Joystick 0 should be the system default joystick. * This function should return the number of available joysticks, or -1 * on an unrecoverable fatal error. */ int SDL_SYS_JoystickInit(void) { IOReturn result = kIOReturnSuccess; mach_port_t masterPort = 0; io_iterator_t hidObjectIterator = 0; CFMutableDictionaryRef hidMatchDictionary = NULL; io_object_t ioHIDDeviceObject = 0; io_iterator_t portIterator = 0; if (gpDeviceList) { SDL_SetError("Joystick: Device list already inited."); return -1; } result = IOMasterPort(bootstrap_port, &masterPort); if (kIOReturnSuccess != result) { SDL_SetError("Joystick: IOMasterPort error with bootstrap_port."); return -1; } /* Set up a matching dictionary to search I/O Registry by class name for all HID class devices. */ hidMatchDictionary = IOServiceMatching(kIOHIDDeviceKey); if (hidMatchDictionary) { /* Add key for device type (joystick, in this case) to refine the matching dictionary. */ /* NOTE: we now perform this filtering later UInt32 usagePage = kHIDPage_GenericDesktop; UInt32 usage = kHIDUsage_GD_Joystick; CFNumberRef refUsage = NULL, refUsagePage = NULL; refUsage = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &usage); CFDictionarySetValue (hidMatchDictionary, CFSTR (kIOHIDPrimaryUsageKey), refUsage); refUsagePage = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &usagePage); CFDictionarySetValue (hidMatchDictionary, CFSTR (kIOHIDPrimaryUsagePageKey), refUsagePage); */ } else { SDL_SetError ("Joystick: Failed to get HID CFMutableDictionaryRef via IOServiceMatching."); return -1; } /*/ Now search I/O Registry for matching devices. */ result = IOServiceGetMatchingServices(masterPort, hidMatchDictionary, &hidObjectIterator); /* Check for errors */ if (kIOReturnSuccess != result) { SDL_SetError("Joystick: Couldn't create a HID object iterator."); return -1; } if (!hidObjectIterator) { /* there are no joysticks */ gpDeviceList = NULL; return 0; } /* IOServiceGetMatchingServices consumes a reference to the dictionary, so we don't need to release the dictionary ref. */ /* build flat linked list of devices from device iterator */ gpDeviceList = NULL; while ((ioHIDDeviceObject = IOIteratorNext(hidObjectIterator))) { AddDeviceHelper( ioHIDDeviceObject ); } result = IOObjectRelease(hidObjectIterator); /* release the iterator */ /* now connect notification for new devices */ notificationPort = IONotificationPortCreate(masterPort); hidMatchDictionary = IOServiceMatching(kIOHIDDeviceKey); CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notificationPort), kCFRunLoopDefaultMode); // Register for notifications when a serial port is added to the system result = IOServiceAddMatchingNotification(notificationPort, kIOFirstMatchNotification, hidMatchDictionary, JoystickDeviceWasAddedCallback, NULL, &portIterator); while (IOIteratorNext(portIterator)) {}; // Run out the iterator or notifications won't start (you can also use it to iterate the available devices). return SDL_SYS_NumJoysticks(); }
static IOReturn HIDCreateOpenDeviceInterface(io_object_t hidDevice, recDevice * pDevice) { IOReturn result = kIOReturnSuccess; HRESULT plugInResult = S_OK; SInt32 score = 0; IOCFPlugInInterface **ppPlugInInterface = NULL; if (NULL == pDevice->interface) { result = IOCreatePlugInInterfaceForService(hidDevice, kIOHIDDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &ppPlugInInterface, &score); if (kIOReturnSuccess == result) { /* Call a method of the intermediate plug-in to create the device interface */ plugInResult = (*ppPlugInInterface)->QueryInterface(ppPlugInInterface, CFUUIDGetUUIDBytes (kIOHIDDeviceInterfaceID), (void *) &(pDevice->interface)); if (S_OK != plugInResult) HIDReportErrorNum ("CouldnÕt query HID class device interface from plugInInterface", plugInResult); (*ppPlugInInterface)->Release(ppPlugInInterface); } else HIDReportErrorNum ("Failed to create **plugInInterface via IOCreatePlugInInterfaceForService.", result); } if (NULL != pDevice->interface) { result = (*(pDevice->interface))->open(pDevice->interface, 0); if (kIOReturnSuccess != result) HIDReportErrorNum ("Failed to open pDevice->interface via open.", result); else { pDevice->portIterator = 0; // It's okay if this fails, we have another detection method below (*(pDevice->interface))->setRemovalCallback(pDevice->interface, HIDRemovalCallback, pDevice, pDevice); /* now connect notification for new devices */ pDevice->notificationPort = IONotificationPortCreate(kIOMasterPortDefault); CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(pDevice->notificationPort), kCFRunLoopDefaultMode); // Register for notifications when a serial port is added to the system result = IOServiceAddInterestNotification(pDevice->notificationPort, hidDevice, kIOGeneralInterest, JoystickDeviceWasRemovedCallback, pDevice, &pDevice->portIterator); if (kIOReturnSuccess != result) { HIDReportErrorNum ("Failed to register for removal callback.", result); } } } return result; }
// // Add Notification observer from Device Driver. // bool createDeviceNotification(const char *className, const io_name_t interestName, IOServiceInterestCallback callback, io_object_t *notification) { kern_return_t kernReturn; bool bResult = false; IONotificationPortRef notificationObject = NULL; CFRunLoopSourceRef notificationRunLoopSource = NULL; io_connect_t dataPort; io_service_t serviceObject; io_iterator_t iterator = 0; CFDictionaryRef classToMatch = NULL; // Obtain the device service. classToMatch = IOServiceMatching(className); if(classToMatch == NULL) { syslog(LOG_ERR, "IOServiceMatching returned a NULL dictionary."); return false; } notificationObject = IONotificationPortCreate(kIOMasterPortDefault); notificationRunLoopSource = IONotificationPortGetRunLoopSource(notificationObject); CFRetain(notificationRunLoopSource); CFRunLoopAddSource( CFRunLoopGetCurrent(), notificationRunLoopSource, kCFRunLoopCommonModes ); // Obtain the I/O Kit communication handle. kernReturn = IOMasterPort(MACH_PORT_NULL, &dataPort); if(kernReturn != KERN_SUCCESS) { syslog(LOG_ERR, "can't obtain I/O Kit's master port. %d\n", kernReturn); goto out; } kernReturn = IOServiceGetMatchingServices(dataPort, classToMatch, &iterator); classToMatch = NULL; // It will release by IOServiceGetMatchingServices if(kernReturn != KERN_SUCCESS) { syslog(LOG_ERR, "IOServiceGetMatchingServices returned. %d\n", kernReturn); goto out; } serviceObject = IOIteratorNext(iterator); /* kernReturn = IOServiceAddInterestNotification( notificationObject, serviceObject, kIOGeneralInterest, callback, NULL, ¬ification ); */ kernReturn = IOServiceAddInterestNotification( notificationObject, serviceObject, interestName, callback, NULL, notification ); if(kernReturn != KERN_SUCCESS) { syslog(LOG_ERR, "IOServiceAddInterestNotification returned. %d\n", kernReturn); goto out; } bResult = true; out: if(iterator) IOObjectRelease(iterator); if(notificationRunLoopSource) CFRelease(notificationRunLoopSource); if(classToMatch) CFRelease(classToMatch); return bResult; }
void HPMPrivate::run() { mach_port_t masterPort = 0; IONotificationPortRef notifyPort = 0; io_iterator_t rawAddedIter = 0; io_iterator_t rawRemovedIter = 0; // Create an IOMasterPort for accessing IOKit kern_return_t kr = IOMasterPort(MACH_PORT_NULL, &masterPort); if (kr || !masterPort) { qWarning() << Q_FUNC_INFO << "Unable to create a master I/O Kit port" << (void*) kr; return; } // Create a new dictionary for matching device classes CFMutableDictionaryRef matchingDict = IOServiceMatching(kIOUSBDeviceClassName); if (!matchingDict) { qWarning() << Q_FUNC_INFO << "Unable to create a USB matching dictionary"; mach_port_deallocate(mach_task_self(), masterPort); return; } // Take an extra reference because IOServiceAddMatchingNotification consumes one matchingDict = (CFMutableDictionaryRef) CFRetain(matchingDict); // Store the thread's run loop context loop = CFRunLoopGetCurrent(); // New notification port notifyPort = IONotificationPortCreate(masterPort); CFRunLoopSourceRef runLoopSource = IONotificationPortGetRunLoopSource(notifyPort); CFRunLoopAddSource(loop, runLoopSource, kCFRunLoopDefaultMode); // Listen to device add notifications kr = IOServiceAddMatchingNotification(notifyPort, kIOFirstMatchNotification, matchingDict, onHPMPrivateRawDeviceAdded, (void*) this, &rawAddedIter); if (kr != kIOReturnSuccess) qFatal("Unable to add notification for device additions"); // Iterate over set of matching devices to access already-present devices // and to arm the notification. onHPMPrivateRawDeviceAdded(this, rawAddedIter); // Listen to device removal notifications kr = IOServiceAddMatchingNotification(notifyPort, kIOTerminatedNotification, matchingDict, onHPMPrivateRawDeviceRemoved, (void*) this, &rawRemovedIter); if (kr != kIOReturnSuccess) qFatal("Unable to add notification for device termination"); // Iterate over set of matching devices to release each one and to // arm the notification. onHPMPrivateRawDeviceRemoved(this, rawRemovedIter); // No longer needed mach_port_deallocate(mach_task_self(), masterPort); masterPort = 0; // Start the run loop inside this thread. The thread "stops" here. CFRunLoopRun(); // Destroy the notification port when the thread exits IONotificationPortDestroy(notifyPort); notifyPort = 0; }
//================================================================================================ // main //================================================================================================ // int main (int argc, const char *argv[]) { mach_port_t masterPort; CFMutableDictionaryRef matchingDict; CFRunLoopSourceRef runLoopSource; CFNumberRef numberRef; CFStringRef stringRef; kern_return_t kr; long usbVendor = kMyVendorID; sig_t oldHandler; // pick up command line arguments // if (argc > 1) usbVendor = atoi(argv[1]); // 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\n", usbVendor); // Set up the matching criteria for the devices we're interested in. The matching criteria needs to follow // the same rules as kernel drivers: mainly it needs to follow the USB Common Class Specification, pp. 6-7. // See also http://developer.apple.com/qa/qa2001/qa1076.html // One exception is that you can use the matching dictionary "as is", i.e. without adding any matching criteria // to it and it will match every IOUSBDevice in the system. IOServiceAddMatchingNotification will consume this // dictionary reference, so there is no need to release it later on. // 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; } // We are interested in all USB Devices (as opposed to USB interfaces). The Common Class Specification // tells us that we need to specify the idVendor, idProduct, and bcdDevice fields, or, if we're not interested // in particular bcdDevices, just the idVendor and idProduct. Note that if we were trying to match an IOUSBInterface, // we would need to set more values in the matching dictionary (e.g. idVendor, idProduct, bInterfaceNumber and // bConfigurationValue. // // Create a CFNumber for the idVendor and set the value in the dictionary // numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbVendor); CFDictionarySetValue( matchingDict, CFSTR(kUSBVendorID), numberRef); CFRelease(numberRef); numberRef = 0; // Create a CFString for the wildcard product ID and set the value in the dictionary // stringRef = CFSTR("*"); CFDictionarySetValue( matchingDict, CFSTR(kUSBProductID), stringRef); CFRelease(stringRef); stringRef = 0; // 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); gRunLoop = CFRunLoopGetCurrent(); CFRunLoopAddSource(gRunLoop, runLoopSource, kCFRunLoopDefaultMode); // Now set up a notification to be called when a device is first matched by I/O Kit. // Note that this will not catch any devices that were already plugged in so we take // care of those later. // kr = IOServiceAddMatchingNotification(gNotifyPort, // notifyPort kIOFirstMatchNotification, // notificationType matchingDict, // matching DeviceAdded, // callback NULL, // refCon &gAddedIter // notification ); // Iterate once to get already-present devices and arm the notification // DeviceAdded(NULL, gAddedIter); // Now done with the master_port mach_port_deallocate(mach_task_self(), masterPort); masterPort = 0; // Start the run loop. Now we'll receive notifications. // printf("Starting run loop.\n"); CFRunLoopRun(); // We should never get here // printf("Unexpectedly back from CFRunLoopRun()!\n"); return 0; }
/* Create matching dictionaries for the devices we want to get notifications for, and add them to the current run loop. Invoke the callbacks that will be responding to these notifications once to arm them, and discover any devices that are currently connected at the time notifications are setup. */ void QextSerialEnumerator::setUpNotificationOSX( ) { kern_return_t kernResult; mach_port_t masterPort; CFRunLoopSourceRef notificationRunLoopSource; CFMutableDictionaryRef classesToMatch; CFMutableDictionaryRef cdcClassesToMatch; io_iterator_t portIterator; kernResult = IOMasterPort(MACH_PORT_NULL, &masterPort); if (KERN_SUCCESS != kernResult) { qDebug() << "IOMasterPort returned:" << kernResult; return; } classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue); if (classesToMatch == NULL) qDebug("IOServiceMatching returned a NULL dictionary."); else CFDictionarySetValue(classesToMatch, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes)); if( !(cdcClassesToMatch = IOServiceNameMatching("AppleUSBCDC") ) ) { qWarning("couldn't create cdc matching dict"); return; } // Retain an additional reference since each call to IOServiceAddMatchingNotification consumes one. classesToMatch = (CFMutableDictionaryRef) CFRetain(classesToMatch); cdcClassesToMatch = (CFMutableDictionaryRef) CFRetain(cdcClassesToMatch); notificationPortRef = IONotificationPortCreate(masterPort); if(notificationPortRef == NULL) { qDebug("IONotificationPortCreate return a NULL IONotificationPortRef."); return; } notificationRunLoopSource = IONotificationPortGetRunLoopSource(notificationPortRef); if (notificationRunLoopSource == NULL) { qDebug("IONotificationPortGetRunLoopSource returned NULL CFRunLoopSourceRef."); return; } CFRunLoopAddSource(CFRunLoopGetCurrent(), notificationRunLoopSource, kCFRunLoopDefaultMode); kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOMatchedNotification, classesToMatch, deviceDiscoveredCallbackOSX, this, &portIterator); if (kernResult != KERN_SUCCESS) { qDebug() << "IOServiceAddMatchingNotification return:" << kernResult; return; } // arm the callback, and grab any devices that are already connected deviceDiscoveredCallbackOSX( this, portIterator ); kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOMatchedNotification, cdcClassesToMatch, deviceDiscoveredCallbackOSX, this, &portIterator); if (kernResult != KERN_SUCCESS) { qDebug() << "IOServiceAddMatchingNotification return:" << kernResult; return; } // arm the callback, and grab any devices that are already connected deviceDiscoveredCallbackOSX( this, portIterator ); kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOTerminatedNotification, classesToMatch, deviceTerminatedCallbackOSX, this, &portIterator); if (kernResult != KERN_SUCCESS) { qDebug() << "IOServiceAddMatchingNotification return:" << kernResult; return; } // arm the callback, and clear any devices that are terminated deviceTerminatedCallbackOSX( this, portIterator ); kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOTerminatedNotification, cdcClassesToMatch, deviceTerminatedCallbackOSX, this, &portIterator); if (kernResult != KERN_SUCCESS) { qDebug() << "IOServiceAddMatchingNotification return:" << kernResult; return; } // arm the callback, and clear any devices that are terminated deviceTerminatedCallbackOSX( this, portIterator ); }
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; }