首先新建一个线程,这个线程负责监控设备的插入拔出
线程入口函数:
1 int DeviceThreadEntryForMac(ClassProcMan *pProcMan) 2 { 3 if(pProcMan == NULL) { 4 fprintf(stderr, "DeviceThreadEntryForMac called NULL pointer\n"); 5 return __LINE__; 6 } 7 mach_port_t masterPort; 8 CFMutableDictionaryRef matchingDict; 9 kern_return_t kr; 10 SInt32 usbVendor = kOurVendorID; 11 SInt32 usbProduct = kOurProductID; 12 CFRunLoopSourceRef runLoopSource; 13 14 printf("DeviceThreadEntryForMac called\n"); 15 16 sig_t oldHandler = signal(SIGTERM, CleanUp); 17 if(oldHandler == SIG_ERR) 18 printf("Create new signal handler failed\n"); 19 20 kr = IOMasterPort(MACH_PORT_NULL, &masterPort); 21 if (kr != kIOReturnSuccess || !masterPort) { 22 fprintf(stderr, "Couldn't create a master I/O Kit port (%08x)\n", kr); 23 return __LINE__; 24 } 25 26 matchingDict = IOServiceMatching(kIOUSBDeviceClassName); 27 if (!matchingDict) { 28 fprintf(stderr, "Couldn't cerate a USB matching dictionary\n"); 29 mach_port_deallocate(mach_task_self(), masterPort); 30 return __LINE__; 31 } 32 33 CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorName), 34 CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbVendor)); 35 CFDictionarySetValue(matchingDict, CFSTR(kUSBProductName), 36 CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbProduct)); 37 38 gNotifyPort = IONotificationPortCreate(masterPort); 39 runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort); 40 CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, 41 kCFRunLoopDefaultMode); 42 43 matchingDict = (CFMutableDictionaryRef) CFRetain(matchingDict); 44 45 kr = IOServiceAddMatchingNotification(gNotifyPort, 46 kIOFirstMatchNotification, matchingDict, 47 DeviceAttach, (void *)pProcMan, &gAttachIter); 48 DeviceAttach((void *)pProcMan, gAttachIter); 49 50 kr = IOServiceAddMatchingNotification(gNotifyPort, 51 kIOTerminatedNotification, matchingDict, 52 DeviceDetach, (void *)pProcMan, &gDetachIter); 53 DeviceDetach((void *)pProcMan, gDetachIter); 54 55 mach_port_deallocate(mach_task_self(), masterPort); 56 masterPort = 0; 57 58 CFRunLoopRun(); 59 60 return 0; 61 }
设备进入或者拔出,由类ClassProcMan的实例来处理。
1 void DeviceAttach(void *refcon, io_iterator_t iterator) 2 { 3 kern_return_t kr; 4 io_service_t usbDevice; 5 IOCFPlugInInterface **plugInInterface = NULL; 6 IOUSBDeviceInterface **dev = NULL; 7 HRESULT result; 8 SInt32 score; 9 UInt16 vendor; 10 UInt16 product; 11 ClassProcMan *pProcMan = (ClassProcMan *)refcon; 12 13 while ((usbDevice = IOIteratorNext(iterator))) { 14 15 kr = IOCreatePlugInInterfaceForService(usbDevice, kIOUSBDeviceUserClientTypeID, 16 kIOCFPlugInInterfaceID, &plugInInterface, &score); 17 kr = IOObjectRelease(usbDevice); 18 if (kr != kIOReturnSuccess || !plugInInterface) { 19 20 fprintf(stderr, "Unable to create a plug-in (%08x)\n", kr); 21 continue; 22 } 23 24 result = (*plugInInterface)->QueryInterface(plugInInterface, 25 CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID *)&dev); 26 (*plugInInterface)->Release(plugInInterface); 27 if (result || !dev) { 28 fprintf(stderr, "Unable to create a device interface (%08x)\n", (int)result); 29 continue; 30 } 31 32 kr = (*dev)->GetDeviceVendor(dev, &vendor); 33 kr = (*dev)->GetDeviceProduct(dev, &product); 34 if(vendor == kOurVendorID && product == kOurProductID) { //找到了我们指定的设备 35 char szRet[32] = {0}; 36 UInt32 locationID; 37 (*dev)->GetLocationID(dev, (UInt32 *)&locationID); 38 sprintf(szRet, "%08x", locationID); 39 pProcMan->GetDeviceMessage().DevicePlugIn(szRet, TRUE); //处理设备插入 40 } 41 } 42 } 43 44 void DeviceDetach(void *refcon, io_iterator_t iterator) 45 { 46 kern_return_t kr; 47 io_service_t object; 48 ClassProcMan *pProc = (ClassProcMan *)refcon; 49 50 while ((object = IOIteratorNext(iterator))) { 51 52 kr = IOObjectRelease(object); 53 if (kr != kIOReturnSuccess) { 54 55 fprintf(stderr, "Couldn't release raw device object: %08x\n", kr); 56 continue; 57 } 58 } 59 // pProcMan->m_DeviceMessage.DevicePlugOut(szRet, TRUE); 60 } 61 62 static void CleanUp(int sigraised) 63 { 64 printf("\nClean up\n"); 65 66 // Clean up here 67 IONotificationPortDestroy(gNotifyPort); 68 if(gAttachIter) { 69 IOObjectRelease(gAttachIter); 70 gAttachIter = 0; 71 } 72 if(gDetachIter) { 73 IOObjectRelease(gDetachIter); 74 gDetachIter = 0; 75 } 76 }