SCM usb_device(SCM name) { io_iterator_t iterator = 0; CFDictionaryRef matchDict = IOServiceMatching(kIOUSBDeviceClassName); IOServiceGetMatchingServices(kIOMasterPortDefault, matchDict, &iterator); io_service_t device; int cnt = 0; int found_device = false; while(device = IOIteratorNext(iterator)) { io_name_t dev_name; if(IORegistryEntryGetName(device, dev_name) == KERN_SUCCESS) if(!strncmp(dev_name,scm_to_locale_string(name),strlen(scm_to_locale_string(name)))) found_device = true; IOObjectRelease(device); ++cnt; } IOObjectRelease(iterator); return scm_from_int(found_device); }
void dumpIter( io_iterator_t iter, mach_port_t recvPort ) { kern_return_t kr; io_object_t obj; io_name_t name; io_string_t path; mach_port_t iter3; while( (obj = IOIteratorNext( iter))) { assert( KERN_SUCCESS == ( kr = IORegistryEntryGetName( obj, name ) )); printf("name:%s(%d)\n", name, obj); kr = IORegistryEntryGetPath( obj, kIOServicePlane, path ); if( KERN_SUCCESS == kr) { // if the object is detached, getPath will fail printf("path:%s\n", path); // as will IOServiceAddInterestNotification if( KERN_SUCCESS != ( kr = IOServiceAddInterestNotificationMsg( obj, kIOGeneralInterest, recvPort, (unsigned int) obj, &iter3) )) printf("IOServiceAddInterestNotification(%lx)\n", kr); // can compare two kernel objects with IOObjectIsEqualTo() if we keep the object, // otherwise, release IOObjectRelease( obj ); } } }
void IOKitEventPublisher::newEvent(const io_service_t& device, IOKitEventContext::Action action) { auto ec = createEventContext(); ec->action = action; { // The IORegistry name is not needed. io_name_t class_name = {0}; if (IOObjectGetClass(device, class_name) != kIOReturnSuccess) { return; } ec->type = std::string(class_name); } // Get the device details CFMutableDictionaryRef details; IORegistryEntryCreateCFProperties( device, &details, kCFAllocatorDefault, kNilOptions); if (ec->type == kIOUSBDeviceClassName_) { ec->path = getIOKitProperty(details, "USB Address") + ":"; ec->path += getIOKitProperty(details, "PortNum"); ec->model = getIOKitProperty(details, "USB Product Name"); ec->model_id = getIOKitProperty(details, "idProduct"); ec->vendor = getIOKitProperty(details, "USB Vendor Name"); ec->vendor_id = getIOKitProperty(details, "idVendor"); idToHex(ec->vendor_id); idToHex(ec->model_id); ec->serial = getIOKitProperty(details, "USB Serial Number"); if (ec->serial.size() == 0) { ec->serial = getIOKitProperty(details, "iSerialNumber"); } ec->version = ""; ec->driver = getIOKitProperty(details, "IOUserClientClass"); } else if (ec->type == kIOPCIDeviceClassName_) { auto compatible = getIOKitProperty(details, "compatible"); auto properties = IOKitPCIProperties(compatible); ec->model_id = properties.model_id; ec->vendor_id = properties.vendor_id; ec->driver = properties.driver; if (ec->driver.empty()) { ec->driver = getIOKitProperty(details, "IOName"); } ec->path = getIOKitProperty(details, "pcidebug"); ec->version = getIOKitProperty(details, "revision-id"); ec->model = getIOKitProperty(details, "model"); } else { // Get the name as the model. io_name_t name = {0}; IORegistryEntryGetName(device, name); if (name[0] != 0) { ec->model = std::string(name); } } CFRelease(details); fire(ec); }
bool find_service(const char *target_name, io_connect_t *ptarget_port) { io_iterator_t iter; kern_return_t r = IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching("IOService"), &iter); if (r != KERN_SUCCESS) { fprintf(stderr, " [!] IOServiceGetMatchingServices() failed\n"); return -1; } io_object_t service; while ((service = IOIteratorNext(iter)) != IO_OBJECT_NULL) { /* Get service name */ io_name_t name; r = IORegistryEntryGetName(service, name); if (r != KERN_SUCCESS) { fprintf(stderr, " [!] IORegistryEntryGetName() failed\n"); IOObjectRelease(service); continue; } io_string_t path; r = IORegistryEntryGetPath(service, "IOService", path); /* Try to open service */ io_connect_t port = (io_connect_t) 0; r = IOServiceOpen(service, mach_task_self(), 0, &port); IOObjectRelease(service); if (r != kIOReturnSuccess) { continue; } if (strstr(name, target_name)) { printf(" [+] Found service %s\n", name); *ptarget_port = port; return true; } IOServiceClose(port); } return false; }
void search_wifi_mac_callback(void** context, io_iterator_t iterator) { unsigned char macaddrBytes[6]; io_iterator_t iterator2=0; io_object_t obj2=0; io_name_t name; CFDataRef t1=0; io_object_t next; while ((next = IOIteratorNext(iterator)) != 0) { if (!IORegistryEntryCreateIterator(next, "IOService", 3, &iterator2)) { while((obj2 = IOIteratorNext(iterator2)) != 0) { if (!IORegistryEntryGetName(obj2,name)) { if (!strcmp(name, "sdio") || !strcmp(name, "wlan")) { if((t1 = IORegistryEntryCreateCFProperty(obj2, CFSTR("local-mac-address"), kCFAllocatorDefault, 0)) != 0) { CFDataGetBytes(t1, CFRangeMake(0,6), macaddrBytes); *context = (void*) CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%02x:%02x:%02x:%02x:%02x:%02x"), macaddrBytes[0], macaddrBytes[1], macaddrBytes[2], macaddrBytes[3], macaddrBytes[4], macaddrBytes[5]); CFRelease(t1); } } } } IOObjectRelease(iterator2); } IOObjectRelease(next); if (*context != NULL) break; } }
static void DeviceAdded(void *refCon, io_iterator_t iter1) { int oldMouseCount = g_MouseCount; io_service_t service; while ((service = IOIteratorNext(iter1))) { io_iterator_t iter2; kern_return_t kr = IORegistryEntryCreateIterator(service, kIOServicePlane, kIORegistryIterateRecursively, &iter2); if (KERN_SUCCESS != kr) { DEBUG_LOG("IORegistryEntryCreateIterator returned 0x%08x\n", kr); continue; } io_service_t temp; while ((temp = IOIteratorNext(iter2))) { io_name_t name; kr = IORegistryEntryGetName(temp, name); if (KERN_SUCCESS != kr) continue; if (0 == strcmp("IOHIDPointing", name) || 0 == strcmp("IOHIDPointingDevice", name)) { NotificationData* pData = (NotificationData*)malloc(sizeof(*pData)); if (pData == NULL) continue; kr = IOServiceAddInterestNotification(g_NotifyPort, temp, kIOGeneralInterest, DeviceNotification, pData, &pData->notification); if (KERN_SUCCESS != kr) { DEBUG_LOG("IOServiceAddInterestNotification returned 0x%08x\n", kr); continue; } ++g_MouseCount; DEBUG_LOG("mouse count is now: %d\n", g_MouseCount); } IOObjectRelease(temp); } IOObjectRelease(iter2); IOObjectRelease(service); } if (oldMouseCount != g_MouseCount) SendMouseCount(g_MouseCount); }
TorcUSBDevice TorcUSBPrivOSX::GetDevice(io_service_t Device) { TorcUSBDevice usbdevice; if (Device) { io_name_t buffer; IOReturn ok = IORegistryEntryGetName(Device, buffer); QString name = kIOReturnSuccess == ok ? QString(buffer) : "Unknown"; IOCFPlugInInterface **plugin; qint32 score; ok = IOCreatePlugInInterfaceForService(Device, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugin, &score); if (kIOReturnSuccess == ok) { IOUSBDeviceInterface **interface; ok = (*plugin)->QueryInterface(plugin, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (void**)&interface); if (kIOReturnSuccess == ok) { quint16 vendor; quint16 product; quint32 location; quint8 classtype; IOReturn vendorok = (*interface)->GetDeviceVendor(interface, &vendor); IOReturn productok = (*interface)->GetDeviceProduct(interface, &product); IOReturn locationok = (*interface)->GetLocationID(interface, &location); IOReturn classtypeok = (*interface)->GetDeviceClass(interface, &classtype); if ((classtypeok == kIOReturnSuccess) && !TorcUSBDevice::IgnoreClass(ToTorcClass(classtype))) { TorcUSBDevice::Classes torcclass = ToTorcClass(classtype); io_service_t usbinterface; io_iterator_t iterator; IOUSBFindInterfaceRequest request; request.bInterfaceClass = kIOUSBFindInterfaceDontCare; request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare; request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare; request.bAlternateSetting = kIOUSBFindInterfaceDontCare; ok = (*interface)->CreateInterfaceIterator(interface, &request, &iterator); while ((ok == kIOReturnSuccess) && (usbinterface = IOIteratorNext(iterator))) { IOCFPlugInInterface **interfaceplugin; if (kIOReturnSuccess == IOCreatePlugInInterfaceForService(usbinterface, kIOUSBInterfaceUserClientTypeID, kIOCFPlugInInterfaceID, &interfaceplugin, &score)) { IOUSBInterfaceInterface** interfaceinterface; if (kIOReturnSuccess == (*interfaceplugin)->QueryInterface(interfaceplugin, CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (void**)&interfaceinterface)) { QString path = locationok == kIOReturnSuccess ? QString::number(location) : "Error"; quint8 interfaceclass; IOReturn result = (*interfaceinterface)->GetInterfaceClass(interfaceinterface, &interfaceclass); if (result == kIOReturnSuccess) { io_registry_entry_t parent; kern_return_t kernresult; kernresult = IORegistryEntryGetParentEntry(usbinterface, kIOServicePlane, &parent); if (kernresult == KERN_SUCCESS) { CFStringRef pathstring = (CFStringRef)IORegistryEntrySearchCFProperty(parent, kIOServicePlane, CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, kIORegistryIterateRecursively); if (pathstring) path = CFStringReftoQString(pathstring); IOObjectRelease(parent); } } usbdevice = TorcUSBDevice(path, vendorok == kIOReturnSuccess ? vendor : 0, productok == kIOReturnSuccess ? product : 0, torcclass); usbdevice.m_product = name; } IODestroyPlugInInterface(interfaceplugin); } IOObjectRelease(usbinterface); } } } IODestroyPlugInInterface(plugin); } } return usbdevice; }
void traverse(unsigned int options, io_name_t plane, io_iterator_t services, io_registry_entry_t serviceUpNext, int depth, UInt64 stackOfBits) { io_registry_entry_t service; ///ok Boolean doProps; // We loop for every service in the list of services provided. while ( (service = serviceUpNext) ) { io_iterator_t children; Boolean hasChildren; io_name_t name; kern_return_t status; io_registry_entry_t child; int busy; // Obtain the next service entry, if any. serviceUpNext = IOIteratorNext(services); // Obtain the current service entry's children, if any. status = IORegistryEntryGetChildIterator(service, plane, &children); assert(status == KERN_SUCCESS); child = IOIteratorNext(children); ///ok hasChildren = child ? true : false; // Save has-more-siblings state into stackOfBits for this depth. if (serviceUpNext) stackOfBits |= (1 << depth); else stackOfBits &= ~(1 << depth); // Save has-children state into stackOfBits for this depth. if (hasChildren) stackOfBits |= (2 << depth); else stackOfBits &= ~(2 << depth); indent(true, depth, stackOfBits); // Print out the name of the service. status = IORegistryEntryGetName(service, name); assert(status == KERN_SUCCESS); printf("%s", name); if (strcmp("Root", name)) doProps = (options & kDoPropsOption) != 0; else doProps = (options & kDoRootOption) != 0; // Print out the class of the service. status = IOObjectGetClass(service, name); assert(status == KERN_SUCCESS); printf(" <class %s", name); status = IOServiceGetBusyState(service, &busy); if(status == KERN_SUCCESS) printf(", busy %d", busy); // Print out the retain count of the service. printf(", retain count %d>\n", IOObjectGetRetainCount(service)); // Print out the properties of the service. if (doProps) properties(service, depth, stackOfBits); // Recurse down. traverse(options, plane, children, child, depth + 1, stackOfBits); // Release resources. IOObjectRelease(children); children = 0; IOObjectRelease(service); service = 0; } }
void notifyTest( char * arg ) { kern_return_t kr; io_iterator_t iter1, iter2, iter3; mach_port_t port; io_service_t obj; io_name_t name; const char * type; IOServiceInterestContent * content; vm_size_t size; unsigned long int notifyType; unsigned long int ref; struct { mach_msg_header_t msgHdr; OSNotificationHeader notifyHeader; IOServiceInterestContent content; mach_msg_trailer_t trailer; } msg; assert( KERN_SUCCESS == ( kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port) )); type = kIOMatchedNotification;// or kIOPublishNotification; assert( KERN_SUCCESS == ( kr = IOServiceAddNotification( masterPort, type, IOServiceMatching( arg ), // IOBSDNameMatching( masterPort, 0, arg ), port, (unsigned int) type, &iter2 ) )); printf("IOServiceAddNotification: %s: ", type ); // dumping the iterator gives us the current list // and arms the notification for changes dumpIter( iter2, port ); printf("\n"); type = kIOTerminatedNotification; assert( KERN_SUCCESS == ( kr = IOServiceAddNotification( masterPort, type, IOServiceMatching( arg ), port, (unsigned int) type, &iter1 ) )); printf("IOServiceAddNotification: %s: ", type ); dumpIter( iter1, port ); printf("\n"); type = kIOBusyInterest; obj = IORegistryEntryFromPath( masterPort, kIOServicePlane ":/"); assert( obj ); assert( KERN_SUCCESS == ( kr = IOServiceAddInterestNotificationMsg( obj, type, port, (unsigned int) obj, &iter3) )); printf("ports: iter1=%d, iter2=%d, rcv=%d\n", iter1, iter2, port); do { printf("waiting...\n"); assert( KERN_SUCCESS == ( kr = mach_msg(&msg.msgHdr, MACH_RCV_MSG, 0, sizeof(msg), port, 0, MACH_PORT_NULL) )); assert( KERN_SUCCESS == ( kr = OSGetNotificationFromMessage( &msg.msgHdr, 0, ¬ifyType, &ref, (void **) &content, &size ) )); // we passed a string for the refcon printf("got notification, type=%d, local=%d, remote=%d\n", notifyType, msg.msgHdr.msgh_local_port, msg.msgHdr.msgh_remote_port ); if( notifyType == kIOServiceMessageNotificationType) { obj = ref; if( KERN_SUCCESS == ( kr = IORegistryEntryGetName( obj, name ) )) printf(name); else printf("???"); printf(": messageType %08lx, arg %08lx\n", content->messageType, content->messageArgument[0]); } else { printf("%s: ", ref ); // remote port is the notification (an iterator_t) that fired dumpIter( msg.msgHdr.msgh_remote_port, port ); } } while( TRUE ); IOObjectRelease( iter1 ); IOObjectRelease( iter2 ); IOObjectRelease( iter3 ); }
static void dumpDevice(io_connect_t connect, uint32_t segment, uint32_t bus, uint32_t device, uint32_t fn, uint32_t * maxBus, uint32_t * maxFn) { io_registry_entry_t service; kern_return_t status; io_name_t name; uint64_t entryID; uint32_t off; uint32_t vendProd; uint32_t vend; uint32_t prod; uint32_t headerType; uint32_t priBusNum; uint32_t secBusNum; uint32_t subBusNum; uint32_t data[256/sizeof(uint32_t)]; uint8_t *bytes = (uint8_t *)&data[0]; for(off = 0; off < 256; off += 4) data[off >> 2] = configRead32(connect, segment, bus, device, fn, off); vendProd = data[0]; vend = vendProd & 0xffff; prod = vendProd >> 16; printf("[%d, %d, %d] 0x%04x, 0x%04x - ", bus, device, fn, vend, prod); service = lookService(segment, bus, device, fn); if (service) { status = IORegistryEntryGetName(service, name); assert(kIOReturnSuccess == status); status = IORegistryEntryGetRegistryEntryID(service, &entryID); assert(kIOReturnSuccess == status); printf("\"%s\", 0x%qx - ", name, entryID); IOObjectRelease(service); } headerType = bytes[kIOPCIConfigHeaderType]; if (maxFn && (0x80 & headerType)) *maxFn = 7; headerType &= 0x7f; if (!headerType) { // device dump printf("class: 0x%x, 0x%x, 0x%x\n", bytes[kIOPCIConfigRevisionID + 3], bytes[kIOPCIConfigRevisionID + 2], bytes[kIOPCIConfigRevisionID + 1]); } else { priBusNum = bytes[kPCI2PCIPrimaryBus]; secBusNum = bytes[kPCI2PCISecondaryBus]; subBusNum = bytes[kPCI2PCISubordinateBus]; printf("bridge: [%d, %d, %d]\n", priBusNum, secBusNum, subBusNum); if (maxBus && (subBusNum > *maxBus)) *maxBus = subBusNum; } dump(bytes, sizeof(data)); printf("\n"); }
/* * Finds PC Card devices currently registered in the system that match any of * the drivers detected in the driver bundle vector. */ static int HPDriversMatchPCCardDevices(HPDriver * driverBundle, HPDeviceList * readerList) { CFDictionaryRef pccMatch = IOServiceMatching("IOPCCard16Device"); if (pccMatch == NULL) { Log1(PCSC_LOG_ERROR, "error getting PCCard match from IOServiceMatching()"); return 1; } io_iterator_t pccIter; kern_return_t kret = IOServiceGetMatchingServices(kIOMasterPortDefault, pccMatch, &pccIter); if (kret != 0) { Log1(PCSC_LOG_ERROR, "error getting iterator from IOServiceGetMatchingServices()"); return 1; } IOIteratorReset(pccIter); io_object_t pccDevice = 0; while ((pccDevice = IOIteratorNext(pccIter))) { char namebuf[1024]; kret = IORegistryEntryGetName(pccDevice, namebuf); if (kret != 0) { Log1(PCSC_LOG_ERROR, "error getting plugin interface from IOCreatePlugInInterfaceForService()"); return 1; } UInt32 vendorId = 0; UInt32 productId = 0; UInt32 pccAddress = 0; CFTypeRef valueRef = IORegistryEntryCreateCFProperty(pccDevice, CFSTR("VendorID"), kCFAllocatorDefault, 0); if (!valueRef) { Log1(PCSC_LOG_ERROR, "error getting vendor"); } else { CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type, &vendorId); } valueRef = IORegistryEntryCreateCFProperty(pccDevice, CFSTR("DeviceID"), kCFAllocatorDefault, 0); if (!valueRef) { Log1(PCSC_LOG_ERROR, "error getting device"); } else { CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type, &productId); } valueRef = IORegistryEntryCreateCFProperty(pccDevice, CFSTR("SocketNumber"), kCFAllocatorDefault, 0); if (!valueRef) { Log1(PCSC_LOG_ERROR, "error getting PC Card socket"); } else { CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type, &pccAddress); } HPDriver *driver = driverBundle; for (; driver->m_vendorId; ++driver) { if ((driver->m_vendorId == vendorId) && (driver->m_productId == productId)) { *readerList = HPDeviceListInsert(*readerList, driver, pccAddress); } } } IOObjectRelease(pccIter); return 0; }
/* * Finds USB devices currently registered in the system that match any of * the drivers detected in the driver bundle vector. */ static int HPDriversMatchUSBDevices(HPDriverVector driverBundle, HPDeviceList * readerList) { CFDictionaryRef usbMatch = IOServiceMatching("IOUSBDevice"); if (0 == usbMatch) { Log1(PCSC_LOG_ERROR, "error getting USB match from IOServiceMatching()"); return 1; } io_iterator_t usbIter; kern_return_t kret = IOServiceGetMatchingServices(kIOMasterPortDefault, usbMatch, &usbIter); if (kret != 0) { Log1(PCSC_LOG_ERROR, "error getting iterator from IOServiceGetMatchingServices()"); return 1; } IOIteratorReset(usbIter); io_object_t usbDevice = 0; while ((usbDevice = IOIteratorNext(usbIter))) { char namebuf[1024]; kret = IORegistryEntryGetName(usbDevice, namebuf); if (kret != 0) { Log1(PCSC_LOG_ERROR, "error getting device name from IORegistryEntryGetName()"); return 1; } IOCFPlugInInterface **iodev; SInt32 score; kret = IOCreatePlugInInterfaceForService(usbDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &iodev, &score); if (kret != 0) { Log1(PCSC_LOG_ERROR, "error getting plugin interface from IOCreatePlugInInterfaceForService()"); return 1; } IOObjectRelease(usbDevice); IOUSBDeviceInterface **usbdev; HRESULT hres = (*iodev)->QueryInterface(iodev, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID *) & usbdev); (*iodev)->Release(iodev); if (hres) { Log1(PCSC_LOG_ERROR, "error querying interface in QueryInterface()"); return 1; } UInt16 vendorId = 0; UInt16 productId = 0; UInt32 usbAddress = 0; kret = (*usbdev)->GetDeviceVendor(usbdev, &vendorId); kret = (*usbdev)->GetDeviceProduct(usbdev, &productId); kret = (*usbdev)->GetLocationID(usbdev, &usbAddress); (*usbdev)->Release(usbdev); #ifdef DEBUG_HOTPLUG Log4(PCSC_LOG_DEBUG, "Found USB device 0x%04X:0x%04X at 0x%X", vendorId, productId, usbAddress); #endif HPDriver *driver; for (driver = driverBundle; driver->m_vendorId; ++driver) { if ((driver->m_vendorId == vendorId) && (driver->m_productId == productId)) { #ifdef DEBUG_HOTPLUG Log4(PCSC_LOG_DEBUG, "Adding USB device %04X:%04X at 0x%X", vendorId, productId, usbAddress); #endif *readerList = HPDeviceListInsert(*readerList, driver, usbAddress); } } } IOObjectRelease(usbIter); return 0; }
//================================================================================================ // // DeviceAdded // // This routine is the callback for our IOServiceAddMatchingNotification. When we get called // we will look at all the devices that were added and we will: // // 1. Create some private data to relate to each device (in this case we use the service's name // and the location ID of the device // 2. Submit an IOServiceAddInterestNotification of type kIOGeneralInterest for this device, // using the refCon field to store a pointer to our private data. When we get called with // this interest notification, we can grab the refCon and access our private data. // //================================================================================================ void DeviceAdded(void *refCon, io_iterator_t iterator) { kern_return_t kr; io_service_t usbDevice; IOCFPlugInInterface **plugInInterface = NULL; SInt32 score; HRESULT res; while ((usbDevice = IOIteratorNext(iterator))) { io_name_t deviceName; CFStringRef deviceNameAsCFString; MyPrivateData *privateDataRef = NULL; UInt32 locationID; printf("Device added.\n"); // // Launch our application system("open /Users/seanwhitsell/development/Pressure/Pressure/build/Debug/Pressure.app"); // Add some app-specific information about this device. // Create a buffer to hold the data. privateDataRef = malloc(sizeof(MyPrivateData)); bzero(privateDataRef, sizeof(MyPrivateData)); // Get the USB device's name. kr = IORegistryEntryGetName(usbDevice, deviceName); if (KERN_SUCCESS != kr) { deviceName[0] = '\0'; } deviceNameAsCFString = CFStringCreateWithCString(kCFAllocatorDefault, deviceName, kCFStringEncodingASCII); // Dump our data to stderr just to see what it looks like. fprintf(stderr, "deviceName: "); CFShow(deviceNameAsCFString); // Save the device's name to our private data. privateDataRef->deviceName = deviceNameAsCFString; // Now, get the locationID of this device. In order to do this, we need to create an IOUSBDeviceInterface // for our device. This will create the necessary connections between our userland application and the // kernel object for the USB Device. kr = IOCreatePlugInInterfaceForService(usbDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); if ((kIOReturnSuccess != kr) || !plugInInterface) { fprintf(stderr, "IOCreatePlugInInterfaceForService returned 0x%08x.\n", kr); continue; } // Use the plugin interface to retrieve the device interface. res = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID*) &privateDataRef->deviceInterface); // Now done with the plugin interface. (*plugInInterface)->Release(plugInInterface); if (res || privateDataRef->deviceInterface == NULL) { fprintf(stderr, "QueryInterface returned %d.\n", (int) res); continue; } // Now that we have the IOUSBDeviceInterface, we can call the routines in IOUSBLib.h. // In this case, fetch the locationID. The locationID uniquely identifies the device // and will remain the same, even across reboots, so long as the bus topology doesn't change. kr = (*privateDataRef->deviceInterface)->GetLocationID(privateDataRef->deviceInterface, &locationID); if (KERN_SUCCESS != kr) { fprintf(stderr, "GetLocationID returned 0x%08x.\n", kr); continue; } else { fprintf(stderr, "Location ID: 0x%x\n\n", locationID); } privateDataRef->locationID = locationID; // Register for an interest notification of this device being removed. Use a reference to our // private data as the refCon which will be passed to the notification callback. kr = IOServiceAddInterestNotification(gNotifyPort, // notifyPort usbDevice, // service kIOGeneralInterest, // interestType DeviceNotification, // callback privateDataRef, // refCon &(privateDataRef->notification) // notification ); if (KERN_SUCCESS != kr) { printf("IOServiceAddInterestNotification returned 0x%08x.\n", kr); } // Done with this USB device; release the reference added by IOIteratorNext kr = IOObjectRelease(usbDevice); } }
//================================================================================================ // // DeviceAdded // // This routine is the callback for our IOServiceAddMatchingNotification. When we get called // we will look at all the devices that were added and we will: // // 1. Create some private data to relate to each device (in this case we use the service's name // and the location ID of the device // 2. Submit an IOServiceAddInterestNotification of type kIOGeneralInterest for this device, // using the refCon field to store a pointer to our private data. When we get called with // this interest notification, we can grab the refCon and access our private data. // //================================================================================================ static void DeviceAdded(void *refCon, io_iterator_t iterator) { kern_return_t kr; io_service_t usbDevice; IOCFPlugInInterface **plugInInterface = NULL; SInt32 score; HRESULT res; while((usbDevice = IOIteratorNext(iterator))) { io_name_t deviceName; CFStringRef deviceNameAsCFString; UInt32 locationID; UInt16 vendorId; UInt16 productId; UInt16 addr; DeviceItem_t* deviceItem = new DeviceItem_t(); // Get the USB device's name. kr = IORegistryEntryGetName(usbDevice, deviceName); if(KERN_SUCCESS != kr) { deviceName[0] = '\0'; } deviceNameAsCFString = CFStringCreateWithCString(kCFAllocatorDefault, deviceName, kCFStringEncodingASCII); if(deviceNameAsCFString) { Boolean result; char deviceName[MAXPATHLEN]; // Convert from a CFString to a C (NUL-terminated) result = CFStringGetCString(deviceNameAsCFString, deviceName, sizeof(deviceName), kCFStringEncodingUTF8); if(result) { deviceItem->deviceParams.deviceName = deviceName; } CFRelease(deviceNameAsCFString); } CFStringRef manufacturerAsCFString = (CFStringRef)IORegistryEntrySearchCFProperty( usbDevice, kIOServicePlane, CFSTR(kUSBVendorString), kCFAllocatorDefault, kIORegistryIterateRecursively ); if(manufacturerAsCFString) { Boolean result; char manufacturer[MAXPATHLEN]; // Convert from a CFString to a C (NUL-terminated) result = CFStringGetCString( manufacturerAsCFString, manufacturer, sizeof(manufacturer), kCFStringEncodingUTF8 ); if(result) { deviceItem->deviceParams.manufacturer = manufacturer; } CFRelease(manufacturerAsCFString); } CFStringRef serialNumberAsCFString = (CFStringRef) IORegistryEntrySearchCFProperty( usbDevice, kIOServicePlane, CFSTR(kUSBSerialNumberString), kCFAllocatorDefault, kIORegistryIterateRecursively ); if(serialNumberAsCFString) { Boolean result; char serialNumber[MAXPATHLEN]; // Convert from a CFString to a C (NUL-terminated) result = CFStringGetCString( serialNumberAsCFString, serialNumber, sizeof(serialNumber), kCFStringEncodingUTF8 ); if(result) { deviceItem->deviceParams.serialNumber = serialNumber; } CFRelease(serialNumberAsCFString); } // Now, get the locationID of this device. In order to do this, we need to create an IOUSBDeviceInterface // for our device. This will create the necessary connections between our userland application and the // kernel object for the USB Device. kr = IOCreatePlugInInterfaceForService(usbDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); if((kIOReturnSuccess != kr) || !plugInInterface) { fprintf(stderr, "IOCreatePlugInInterfaceForService returned 0x%08x.\n", kr); continue; } stDeviceListItem *deviceListItem = new stDeviceListItem(); // Use the plugin interface to retrieve the device interface. res = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID*) &deviceListItem->deviceInterface); // Now done with the plugin interface. (*plugInInterface)->Release(plugInInterface); if(res || deviceListItem->deviceInterface == NULL) { fprintf(stderr, "QueryInterface returned %d.\n", (int) res); continue; } // Now that we have the IOUSBDeviceInterface, we can call the routines in IOUSBLib.h. // In this case, fetch the locationID. The locationID uniquely identifies the device // and will remain the same, even across reboots, so long as the bus topology doesn't change. kr = (*deviceListItem->deviceInterface)->GetLocationID(deviceListItem->deviceInterface, &locationID); if(KERN_SUCCESS != kr) { fprintf(stderr, "GetLocationID returned 0x%08x.\n", kr); continue; } std::stringstream sstream; sstream << std::hex << locationID; deviceItem->deviceParams.locationId = sstream.str(); kr = (*deviceListItem->deviceInterface)->GetDeviceAddress(deviceListItem->deviceInterface, &addr); if(KERN_SUCCESS != kr) { fprintf(stderr, "GetDeviceAddress returned 0x%08x.\n", kr); continue; } deviceItem->deviceParams.deviceAddress = addr; kr = (*deviceListItem->deviceInterface)->GetDeviceVendor(deviceListItem->deviceInterface, &vendorId); if(KERN_SUCCESS != kr) { fprintf(stderr, "GetDeviceVendor returned 0x%08x.\n", kr); continue; } deviceItem->deviceParams.vendorId = vendorId; kr = (*deviceListItem->deviceInterface)->GetDeviceProduct(deviceListItem->deviceInterface, &productId); if(KERN_SUCCESS != kr) { fprintf(stderr, "GetDeviceProduct returned 0x%08x.\n", kr); continue; } deviceItem->deviceParams.productId = productId; // Extract path name as unique key io_string_t pathName; IORegistryEntryGetPath(usbDevice, kIOServicePlane, pathName); deviceNameAsCFString = CFStringCreateWithCString(kCFAllocatorDefault, pathName, kCFStringEncodingASCII); char cPathName[MAXPATHLEN]; if(deviceNameAsCFString) { Boolean result; // Convert from a CFString to a C (NUL-terminated) result = CFStringGetCString( deviceNameAsCFString, cPathName, sizeof(cPathName), kCFStringEncodingUTF8 ); CFRelease(deviceNameAsCFString); } AddItemToList(cPathName, deviceItem); deviceListItem->deviceItem = deviceItem; if(initialDeviceImport == false) { WaitForDeviceHandled(); currentItem = &deviceItem->deviceParams; isAdded = true; uv_async_send(&async_handler); } // Register for an interest notification of this device being removed. Use a reference to our // private data as the refCon which will be passed to the notification callback. kr = IOServiceAddInterestNotification( gNotifyPort, // notifyPort usbDevice, // service kIOGeneralInterest, // interestType DeviceRemoved, // callback deviceListItem, // refCon &(deviceListItem->notification) // notification ); if(KERN_SUCCESS != kr) { printf("IOServiceAddInterestNotification returned 0x%08x.\n", kr); } // Done with this USB device; release the reference added by IOIteratorNext kr = IOObjectRelease(usbDevice); } }
void genIOKitDevice(const io_service_t& device, const io_service_t& parent, const io_name_t plane, int depth, QueryData& results) { Row r; io_name_t name, device_class; auto kr = IORegistryEntryGetName(device, name); if (kr == KERN_SUCCESS) { r["name"] = std::string(name); } // Get the device class. kr = IOObjectGetClass(device, device_class); if (kr == KERN_SUCCESS) { r["class"] = std::string(device_class); } // The entry into the registry is the ID, and is used for children as parent. uint64_t device_id, parent_id; kr = IORegistryEntryGetRegistryEntryID(device, &device_id); if (kr == KERN_SUCCESS) { r["id"] = BIGINT(device_id); } else { r["id"] = "-1"; } kr = IORegistryEntryGetRegistryEntryID(parent, &parent_id); if (kr == KERN_SUCCESS) { r["parent"] = BIGINT(parent_id); } else { r["parent"] = "-1"; } r["depth"] = INTEGER(depth); if (IORegistryEntryInPlane(device, kIODeviceTreePlane)) { io_string_t device_path; kr = IORegistryEntryGetPath(device, kIODeviceTreePlane, device_path); if (kr == KERN_SUCCESS) { // Remove the "IODeviceTree:" from the device tree path. r["device_path"] = std::string(device_path).substr(13); } } // Fill in service bits and busy/latency time. if (IOObjectConformsTo(device, "IOService")) { r["service"] = "1"; } else { r["service"] = "0"; } uint32_t busy_state; kr = IOServiceGetBusyState(device, &busy_state); if (kr == KERN_SUCCESS) { r["busy_state"] = INTEGER(busy_state); } else { r["busy_state"] = "0"; } auto retain_count = IOObjectGetKernelRetainCount(device); r["retain_count"] = INTEGER(retain_count); results.push_back(r); }
void DeviceAdded(void *refCon, io_iterator_t iterator) { kern_return_t kr; io_service_t usbDevice; IOCFPlugInInterface **plugInInterface=NULL; SInt32 score; HRESULT res; while ( (usbDevice = IOIteratorNext(iterator)) ) { io_name_t deviceName; CFStringRef deviceNameAsCFString; MyPrivateData *privateDataRef = NULL; UInt32 locationID; printf("Device 0x%08x added.\n", usbDevice); // Make activity and turn screen on printf("Wake up on Yubikey insertion.\n"); IOPMAssertionID assertionID; IOPMAssertionDeclareUserActivity(CFSTR(""), kIOPMUserActiveLocal, &assertionID); // Add some app-specific information about this device. // Create a buffer to hold the data. privateDataRef = malloc(sizeof(MyPrivateData)); bzero( privateDataRef, sizeof(MyPrivateData)); // In this sample we'll just use the service's name. // kr = IORegistryEntryGetName(usbDevice, deviceName); if (KERN_SUCCESS != kr) { deviceName[0] = '\0'; } deviceNameAsCFString = CFStringCreateWithCString(kCFAllocatorDefault, deviceName, kCFStringEncodingASCII); // Dump our data to stdout just to see what it looks like. // CFShow(deviceNameAsCFString); privateDataRef->deviceName = deviceNameAsCFString; // Now, get the locationID of this device. In order to do this, we need to create an IOUSBDeviceInterface for // our device. This will create the necessary connections between our user land application and the kernel object // for the USB Device. // kr = IOCreatePlugInInterfaceForService(usbDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); if ((kIOReturnSuccess != kr) || !plugInInterface) { printf("unable to create a plugin (%08x)\n", kr); continue; } // I have the device plugin, I need the device interface // res = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID)&privateDataRef->deviceInterface); (*plugInInterface)->Release(plugInInterface); // done with this if (res || !privateDataRef->deviceInterface) { printf("couldn't create a device interface (%08x)\n", (int) res); continue; } // Now that we have the IOUSBDeviceInterface, we can call the routines in IOUSBLib.h // In this case, we just want the locationID. // kr = (*privateDataRef->deviceInterface)->GetLocationID(privateDataRef->deviceInterface, &locationID); if (KERN_SUCCESS != kr) { printf("GetLocationID returned %08x\n", kr); continue; } else { printf("Location ID: 0x%lx\n", (unsigned long)locationID); } privateDataRef->locationID = locationID; // Register for an interest notification for this device. Pass the reference to our // private data as the refCon for the notification. // kr = IOServiceAddInterestNotification( gNotifyPort, // notifyPort usbDevice, // service kIOGeneralInterest, // interestType DeviceNotification, // callback privateDataRef, // refCon &(privateDataRef->notification) // notification ); if (KERN_SUCCESS != kr) { printf("IOServiceAddInterestNotification returned 0x%08x\n", kr); } // Done with this io_service_t // kr = IOObjectRelease(usbDevice); free(privateDataRef); } }
void genIOMediaDevice(const io_service_t& device, std::vector<std::string>& whole_devices, QueryData& results) { Row r; // Get the device properties CFMutableDictionaryRef properties; IORegistryEntryCreateCFProperties( device, &properties, kCFAllocatorDefault, kNilOptions); r["uuid"] = getIOKitProperty(properties, "UUID"); r["name"] = "/dev/" + getIOKitProperty(properties, "BSD Name"); r["size"] = getIOKitProperty(properties, "Size"); auto type = getIOKitProperty(properties, "Whole"); if (type == "1") { // The "Whole" property applies to the entire disk entry, not partitions. whole_devices.push_back(r["name"]); } else { // Otherwise search the list of whole disks to find the node parent. for (const auto& parent : whole_devices) { if (r.at("name").find(parent) == 0) { r["parent"] = parent; } } } // This is the IOKit name, which is the device's label. io_name_t name; auto kr = IORegistryEntryGetName(device, name); if (kr == KERN_SUCCESS && (char*)name != nullptr) { r["label"] = std::string(name); } // Remaining details come from the Disk Arbitration service. DASessionRef session = DASessionCreate(kCFAllocatorDefault); CFDictionaryRef details; if (session != nullptr) { auto disk = DADiskCreateFromIOMedia(kCFAllocatorDefault, session, device); if (disk != nullptr) { details = DADiskCopyDescription(disk); if (details != nullptr) { r["vendor"] = getIOKitProperty((CFMutableDictionaryRef)details, "DADeviceVendor"); r["model"] = getIOKitProperty((CFMutableDictionaryRef)details, "DADeviceModel"); r["type"] = getIOKitProperty((CFMutableDictionaryRef)details, "DADeviceProtocol"); CFRelease(details); } CFRelease(disk); } CFRelease(session); } results.push_back(r); CFRelease(properties); }