/* Main method. */ int main (int argc, const char * argv[]) { kern_return_t err; mach_port_t masterPort = 0; bool suspend; SInt32 productId, vendorId; SInt32 count; CFMutableDictionaryRef matcher; CFNumberRef numberRef; io_iterator_t iterator; io_service_t usbService; IOCFPlugInInterface **pluginInterface; IOUSBDeviceInterface245 **deviceInterface; SInt32 score; // Display usage info if(argc != 4) { printf("Usage:\n" " usbpower suspend <product id> <vendor id>\n" " usbpower resume <product id> <vendor id>\n" "\n" "Vendor and product IDs can be obtained by running the command:\n" " system_profiler SPUSBDataType\n" "\n" "They must be given as four-digit hexadecimal numbers beginning with 0x\n" "(as shown by the above command).\n" "\n" "Example:\n" " usbpower suspend 0x0040 0x045e\n" "\n" "Copyright 2009 Samuel Marshall - http://www.leafdigital.com/software/\n" "Released under Gnu Public License v3.\n"); return 0; } // Check first parameter if(strcmp(argv[1], "suspend") == 0) { suspend = true; } else if(strcmp(argv[1], "resume") == 0) { suspend = false; } else { fprintf(stderr, "Invalid argument '%s': expecting suspend, resume\n", argv[1]); return -1; } // Check other two parameters productId = convertHexId(argv[2]); if(productId == -1) { fprintf(stderr, "Invalid product id '%s': expecting four-digit hexadecimal e.g. 0x0040\n", argv[2]); return -1; } vendorId = convertHexId(argv[3]); if(vendorId == -1) { fprintf(stderr, "Invalid vendor id '%s': expecting four-digit hexadecimal e.g. 0x045e\n", argv[3]); return -1; } // Allocate master IO port err = IOMasterPort(MACH_PORT_NULL, &masterPort); CHECKRETURN(err, "Failed to open master port"); // Create matching dictionary matcher = IOServiceMatching(kIOUSBDeviceClassName); if(!matcher) { fprintf(stderr, "Failed to create matching dictionary\n"); return -1; } // Create number references and add to dictionary numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &productId); if(!numberRef) { fprintf(stderr, "Failed to create number reference for product ID\n"); return -1; } CFDictionaryAddValue(matcher, CFSTR(kUSBProductID), numberRef); CFRelease(numberRef); numberRef = 0; numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vendorId); if(!numberRef) { fprintf(stderr, "Failed to create number reference for vendor ID\n"); return -1; } CFDictionaryAddValue(matcher, CFSTR(kUSBVendorID), numberRef); CFRelease(numberRef); numberRef = 0; // Get matches from dictionary (this eats the dictionary) err = IOServiceGetMatchingServices(masterPort, matcher, &iterator); CHECKRETURN(err, "Failed to get matching servivces"); matcher = 0; count = 0; while((usbService = IOIteratorNext(iterator))) { // Get plugin interface err = IOCreatePlugInInterfaceForService( usbService, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &pluginInterface, &score); CHECKRETURN(err, "Failed to create plugin interface for service"); if(!pluginInterface) { fprintf(stderr, "Service did not return plugin interface\n"); return -1; } // Now query for suitable USB device interface err = (*pluginInterface)->QueryInterface(pluginInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID245), (LPVOID)&deviceInterface); IODestroyPlugInInterface(pluginInterface); // Open device err = (*deviceInterface)->USBDeviceOpen(deviceInterface); CHECKRETURN(err, "Error opening device"); // Suspend or resume device err = (*deviceInterface)->USBDeviceSuspend(deviceInterface, suspend); CHECKRETURN(err, "Error suspending or resuming device"); // Close device err = (*deviceInterface)->USBDeviceClose(deviceInterface); CHECKRETURN(err, "Error closing device"); err = (*deviceInterface)->Release(deviceInterface); CHECKRETURN(err, "Error releading device interface"); // Release service IOObjectRelease(usbService); count++; } // Release iterator IOObjectRelease(iterator); iterator = 0; // Free master IO port mach_port_deallocate(mach_task_self(), masterPort); // Check count if(!count) { fprintf(stderr, "Device with product ID 0x%04x and vendor ID 0x%04x not found\n", productId, vendorId); return -1; } return 0; }
/** Try out the given device and see if there's a match. Returns 0 on * success, -1 on failure. */ static int try_device(io_service_t device, usb_handle *handle) { kern_return_t kr; IOCFPlugInInterface **plugin = NULL; IOUSBDeviceInterface182 **dev = NULL; SInt32 score; HRESULT result; UInt8 serialIndex; UInt32 locationId; // Create an intermediate plugin. kr = IOCreatePlugInInterfaceForService(device, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugin, &score); if ((kr != 0) || (plugin == NULL)) { ERR("Unable to create a plug-in (%08x)\n", kr); goto error; } // Now create the device interface. result = (*plugin)->QueryInterface(plugin, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID*) &dev); if ((result != 0) || (dev == NULL)) { ERR("Couldn't create a device interface (%08x)\n", (int) result); goto error; } /* * We don't need the intermediate interface after the device interface * is created. */ IODestroyPlugInInterface(plugin); // So, we have a device, finally. Grab its vitals. kr = (*dev)->USBDeviceOpen(dev); if (kr != 0) { WARN("USBDeviceOpen"); goto out; } kr = (*dev)->GetDeviceVendor(dev, &handle->info.dev_vendor); if (kr != 0) { ERR("GetDeviceVendor"); goto error; } kr = (*dev)->GetDeviceProduct(dev, &handle->info.dev_product); if (kr != 0) { ERR("GetDeviceProduct"); goto error; } kr = (*dev)->GetDeviceClass(dev, &handle->info.dev_class); if (kr != 0) { ERR("GetDeviceClass"); goto error; } kr = (*dev)->GetDeviceSubClass(dev, &handle->info.dev_subclass); if (kr != 0) { ERR("GetDeviceSubClass"); goto error; } kr = (*dev)->GetDeviceProtocol(dev, &handle->info.dev_protocol); if (kr != 0) { ERR("GetDeviceProtocol"); goto error; } kr = (*dev)->GetLocationID(dev, &locationId); if (kr != 0) { ERR("GetLocationId"); goto error; } snprintf(handle->info.device_path, sizeof(handle->info.device_path), "usb:%" PRIu32 "X", (unsigned int)locationId); kr = (*dev)->USBGetSerialNumberStringIndex(dev, &serialIndex); if (serialIndex > 0) { IOUSBDevRequest req; UInt16 buffer[256]; req.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice); req.bRequest = kUSBRqGetDescriptor; req.wValue = (kUSBStringDesc << 8) | serialIndex; //language ID (en-us) for serial number string req.wIndex = 0x0409; req.pData = buffer; req.wLength = sizeof(buffer); kr = (*dev)->DeviceRequest(dev, &req); if (kr == kIOReturnSuccess && req.wLenDone > 0) { int i, count; // skip first word, and copy the rest to the serial string, changing shorts to bytes. count = (req.wLenDone - 1) / 2; for (i = 0; i < count; i++) handle->info.serial_number[i] = buffer[i + 1]; handle->info.serial_number[i] = 0; } } else { // device has no serial number handle->info.serial_number[0] = 0; } handle->info.writable = 1; if (try_interfaces(dev, handle)) { goto error; } out: (*dev)->USBDeviceClose(dev); (*dev)->Release(dev); return 0; error: if (dev != NULL) { (*dev)->USBDeviceClose(dev); (*dev)->Release(dev); } return -1; }
/** Try out all the interfaces and see if there's a match. Returns 0 on * success, -1 on failure. */ static int try_interfaces(IOUSBDeviceInterface182 **dev, usb_handle *handle) { IOReturn kr; IOUSBFindInterfaceRequest request; io_iterator_t iterator; io_service_t usbInterface; IOCFPlugInInterface **plugInInterface; IOUSBInterfaceInterface190 **interface = NULL; HRESULT result; SInt32 score; UInt8 interfaceNumEndpoints; UInt8 configuration; // Placing the constant KIOUSBFindInterfaceDontCare into the following // fields of the IOUSBFindInterfaceRequest structure will allow us to // find all of the interfaces request.bInterfaceClass = kIOUSBFindInterfaceDontCare; request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare; request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare; request.bAlternateSetting = kIOUSBFindInterfaceDontCare; // SetConfiguration will kill an existing UMS connection, so let's // not do this if not necessary. configuration = 0; (*dev)->GetConfiguration(dev, &configuration); if (configuration != 1) (*dev)->SetConfiguration(dev, 1); // Get an iterator for the interfaces on the device kr = (*dev)->CreateInterfaceIterator(dev, &request, &iterator); if (kr != 0) { ERR("Couldn't create a device interface iterator: (%08x)\n", kr); return -1; } while ((usbInterface = IOIteratorNext(iterator))) { // Create an intermediate plugin kr = IOCreatePlugInInterfaceForService( usbInterface, kIOUSBInterfaceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); // No longer need the usbInterface object now that we have the plugin (void) IOObjectRelease(usbInterface); if ((kr != 0) || (!plugInInterface)) { WARN("Unable to create plugin (%08x)\n", kr); continue; } // Now create the interface interface for the interface result = (*plugInInterface)->QueryInterface( plugInInterface, CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID*) &interface); // No longer need the intermediate plugin (*plugInInterface)->Release(plugInInterface); if (result || !interface) { ERR("Couldn't create interface interface: (%08x)\n", (unsigned int) result); // continue so we can try the next interface continue; } /* * Now open the interface. This will cause the pipes * associated with the endpoints in the interface descriptor * to be instantiated. */ /* * TODO: Earlier comments here indicated that it was a bad * idea to just open any interface, because opening "mass * storage endpoints" is bad. However, the only way to find * out if an interface does bulk in or out is to open it, and * the framework in this application wants to be told about * bulk in / out before deciding whether it actually wants to * use the interface. Maybe something needs to be done about * this situation. */ kr = (*interface)->USBInterfaceOpen(interface); if (kr != 0) { WARN("Could not open interface: (%08x)\n", kr); (void) (*interface)->Release(interface); // continue so we can try the next interface continue; } // Get the number of endpoints associated with this interface. kr = (*interface)->GetNumEndpoints(interface, &interfaceNumEndpoints); if (kr != 0) { ERR("Unable to get number of endpoints: (%08x)\n", kr); goto next_interface; } // Get interface class, subclass and protocol if ((*interface)->GetInterfaceClass(interface, &handle->info.ifc_class) != 0 || (*interface)->GetInterfaceSubClass(interface, &handle->info.ifc_subclass) != 0 || (*interface)->GetInterfaceProtocol(interface, &handle->info.ifc_protocol) != 0) { ERR("Unable to get interface class, subclass and protocol\n"); goto next_interface; } handle->info.has_bulk_in = 0; handle->info.has_bulk_out = 0; // Iterate over the endpoints for this interface and see if there // are any that do bulk in/out. for (UInt8 endpoint = 1; endpoint <= interfaceNumEndpoints; endpoint++) { UInt8 transferType; UInt16 maxPacketSize; UInt8 interval; UInt8 number; UInt8 direction; kr = (*interface)->GetPipeProperties(interface, endpoint, &direction, &number, &transferType, &maxPacketSize, &interval); if (kr == 0) { if (transferType != kUSBBulk) { continue; } if (direction == kUSBIn) { handle->info.has_bulk_in = 1; handle->bulkIn = endpoint; } else if (direction == kUSBOut) { handle->info.has_bulk_out = 1; handle->bulkOut = endpoint; } if (handle->info.ifc_protocol == 0x01) { handle->zero_mask = maxPacketSize - 1; } } else { ERR("could not get pipe properties for endpoint %u (%08x)\n", endpoint, kr); } if (handle->info.has_bulk_in && handle->info.has_bulk_out) { break; } } if (handle->callback(&handle->info) == 0) { handle->interface = interface; handle->success = 1; /* * Clear both the endpoints, because it has been observed * that the Mac may otherwise (incorrectly) start out with * them in bad state. */ if (handle->info.has_bulk_in) { kr = (*interface)->ClearPipeStallBothEnds(interface, handle->bulkIn); if (kr != 0) { ERR("could not clear input pipe; result %x, ignoring...\n", kr); } } if (handle->info.has_bulk_out) { kr = (*interface)->ClearPipeStallBothEnds(interface, handle->bulkOut); if (kr != 0) { ERR("could not clear output pipe; result %x, ignoring....\n", kr); } } return 0; } next_interface: (*interface)->USBInterfaceClose(interface); (*interface)->Release(interface); } return 0; }
static stDeviceListItem* GetSerialDevices() { kern_return_t kernResult = KERN_FAILURE; io_iterator_t serialPortIterator; char bsdPath[MAXPATHLEN]; kernResult = FindModems(&serialPortIterator); io_service_t modemService; kernResult = KERN_FAILURE; Boolean modemFound = false; // Initialize the returned path *bsdPath = '\0'; stDeviceListItem* devices = NULL; stDeviceListItem* lastDevice = NULL; int length = 0; while ((modemService = IOIteratorNext(serialPortIterator))) { CFTypeRef bsdPathAsCFString; bsdPathAsCFString = IORegistryEntrySearchCFProperty(modemService, kIOServicePlane, CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, kIORegistryIterateRecursively); if (bsdPathAsCFString) { Boolean result; // Convert the path from a CFString to a C (NUL-terminated) result = CFStringGetCString((CFStringRef) bsdPathAsCFString, bsdPath, sizeof(bsdPath), kCFStringEncodingUTF8); CFRelease(bsdPathAsCFString); if (result) { stDeviceListItem *deviceListItem = (stDeviceListItem*) malloc(sizeof(stDeviceListItem)); stSerialDevice *serialDevice = &(deviceListItem->value); strcpy(serialDevice->port, bsdPath); memset(serialDevice->locationId, 0, sizeof(serialDevice->locationId)); memset(serialDevice->vendorId, 0, sizeof(serialDevice->vendorId)); memset(serialDevice->productId, 0, sizeof(serialDevice->productId)); serialDevice->manufacturer[0] = '\0'; serialDevice->serialNumber[0] = '\0'; deviceListItem->next = NULL; deviceListItem->length = &length; if (devices == NULL) { devices = deviceListItem; } else { lastDevice->next = deviceListItem; } lastDevice = deviceListItem; length++; modemFound = true; kernResult = KERN_SUCCESS; uv_mutex_lock(&list_mutex); io_registry_entry_t device = GetUsbDevice(bsdPath); if (device) { CFStringRef manufacturerAsCFString = (CFStringRef) IORegistryEntrySearchCFProperty(device, 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) { strcpy(serialDevice->manufacturer, manufacturer); } CFRelease(manufacturerAsCFString); } CFStringRef serialNumberAsCFString = (CFStringRef) IORegistryEntrySearchCFProperty(device, 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) { strcpy(serialDevice->serialNumber, serialNumber); } CFRelease(serialNumberAsCFString); } IOCFPlugInInterface **plugInInterface = NULL; SInt32 score; HRESULT res; IOUSBDeviceInterface **deviceInterface = NULL; kernResult = IOCreatePlugInInterfaceForService(device, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); if ((kIOReturnSuccess != kernResult) || !plugInInterface) { continue; } // Use the plugin interface to retrieve the device interface. res = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID*) &deviceInterface); // Now done with the plugin interface. (*plugInInterface)->Release(plugInInterface); if (res || deviceInterface == NULL) { continue; } // Extract the desired Information ExtractUsbInformation(serialDevice, deviceInterface); // Release the Interface (*deviceInterface)->Release(deviceInterface); // Release the device (void) IOObjectRelease(device); } uv_mutex_unlock(&list_mutex); } } // Release the io_service_t now that we are done with it. (void) IOObjectRelease(modemService); } IOObjectRelease(serialPortIterator); // Release the iterator. return devices; }
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; }
qint32 QUsbDevice::open() { IOCFPlugInInterface** plugin; io_iterator_t iterator = 0; io_service_t usbRef = 0; qint32 ret = 0; qint32 score = 0; CFDictionaryAddValue(mMatchingDictionary, CFSTR(kUSBVendorID), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &mFilter.vid)); CFDictionaryAddValue(mMatchingDictionary, CFSTR(kUSBProductID), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &mFilter.pid)); IOServiceGetMatchingServices(kIOMasterPortDefault, mMatchingDictionary, &iterator); usbRef = IOIteratorNext(iterator); if (usbRef == 0) { qWarning("Device not found"); return -1; } IOObjectRelease(iterator); IOCreatePlugInInterfaceForService(usbRef, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugin, &score); IOObjectRelease(usbRef); ret = (*plugin)->QueryInterface(plugin, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID300), (LPVOID)&mUsbInterface); (*plugin)->Release(plugin); if (ret || !mUsbInterface) { qWarning("Could not get interface (error: %x)\n", ret); return -2; } ret = (*mUsbDevice)->USBDeviceOpen(mUsbDevice); if (ret == kIOReturnSuccess) { // set first configuration as active ret = (*mUsbDevice)->GetConfigurationDescriptorPtr(mUsbDevice, 0, &config); if (ret != kIOReturnSuccess) { qWarning("Could not set active configuration (error: %x)\n", ret); return -3; } (*mUsbDevice)->SetConfiguration(mUsbDevice, config->bConfigurationValue); } else if (ret == kIOReturnExclusiveAccess) { // this is not a problem as we can still do some things } else { qWarning("Could not open device (error: %x)\n", ret); return -4; } ret = (*mUsbInterface)->USBInterfaceOpen(mUsbInterface); if (ret != kIOReturnSuccess) { qWarning("Could not open interface (error: %x)\n", ret); return -5; } 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; }
void RawDeviceAdded(void *refCon, io_iterator_t iterator) { kern_return_t kr; io_service_t usbDevice; IOCFPlugInInterface **plugInInterface = NULL; IOUSBDeviceInterface **dev = NULL; HRESULT result; SInt32 score; UInt16 vendor; UInt16 product; UInt16 release; while (usbDevice = IOIteratorNext(iterator)) { //Create an intermediate plug-in kr = IOCreatePlugInInterfaceForService(usbDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); //Don’t need the device object after intermediate plug-in is created kr = IOObjectRelease(usbDevice); if ((kIOReturnSuccess != kr) || !plugInInterface) { printf("Unable to create a plug-in (%08x)\n", kr); continue; } //Now create the device interface result = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID *)&dev); //Don’t need the intermediate plug-in after device interface //is created (*plugInInterface)->Release(plugInInterface); if (result || !dev) { printf("Couldn’t create a device interface (%08x)\n", (int) result); continue; } //Check these values for confirmation kr = (*dev)->GetDeviceVendor(dev, &vendor); kr = (*dev)->GetDeviceProduct(dev, &product); kr = (*dev)->GetDeviceReleaseNumber(dev, &release); if ((vendor != kOurVendorID) || (product != kOurProductID) || (release != 1)) { printf("Found unwanted device (vendor = %d, product = %d)\n", vendor, product); printf("(or the release was not equal to 1: release = %d)\n", release); (void) (*dev)->Release(dev); continue; } //Open the device to change its state kr = (*dev)->USBDeviceOpen(dev); if (kr != kIOReturnSuccess) { printf("Unable to open device: %08x\n", kr); (void) (*dev)->Release(dev); continue; } //Configure device kr = ConfigureDevice(dev); if (kr != kIOReturnSuccess) { printf("Unable to configure device: %08x\n", kr); (void) (*dev)->USBDeviceClose(dev); (void) (*dev)->Release(dev); continue; } /* //Download firmware to device kr = DownloadToDevice(dev); if (kr != kIOReturnSuccess) { printf("Unable to download firmware to device: %08x\n", kr); (void) (*dev)->USBDeviceClose(dev); (void) (*dev)->Release(dev); continue; } */ //Close this device and release object kr = (*dev)->USBDeviceClose(dev); kr = (*dev)->Release(dev); } }
static void AndroidInterfaceAdded(void *refCon, io_iterator_t iterator) { kern_return_t kr; io_service_t usbDevice; io_service_t usbInterface; IOCFPlugInInterface **plugInInterface = NULL; IOUSBInterfaceInterface220 **iface = NULL; IOUSBDeviceInterface197 **dev = NULL; HRESULT result; SInt32 score; UInt16 vendor; UInt16 product; UInt8 serialIndex; char serial[256]; while ((usbInterface = IOIteratorNext(iterator))) { //* Create an intermediate interface plugin kr = IOCreatePlugInInterfaceForService(usbInterface, kIOUSBInterfaceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); IOObjectRelease(usbInterface); if ((kIOReturnSuccess != kr) || (!plugInInterface)) { DBG("ERR: Unable to create an interface plug-in (%08x)\n", kr); continue; } //* This gets us the interface object result = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID) &iface); //* We only needed the plugin to get the interface, so discard it (*plugInInterface)->Release(plugInInterface); if (result || !iface) { DBG("ERR: Couldn't query the interface (%08x)\n", (int) result); continue; } //* this gets us an ioservice, with which we will find the actual //* device; after getting a plugin, and querying the interface, of //* course. //* Gotta love OS X kr = (*iface)->GetDevice(iface, &usbDevice); if (kIOReturnSuccess != kr || !usbDevice) { DBG("ERR: Couldn't grab device from interface (%08x)\n", kr); continue; } plugInInterface = NULL; score = 0; //* create an intermediate device plugin kr = IOCreatePlugInInterfaceForService(usbDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); //* only needed this to find the plugin (void)IOObjectRelease(usbDevice); if ((kIOReturnSuccess != kr) || (!plugInInterface)) { DBG("ERR: Unable to create a device plug-in (%08x)\n", kr); continue; } result = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID) &dev); //* only needed this to query the plugin (*plugInInterface)->Release(plugInInterface); if (result || !dev) { DBG("ERR: Couldn't create a device interface (%08x)\n", (int) result); continue; } //* Now after all that, we actually have a ref to the device and //* the interface that matched our criteria kr = (*dev)->GetDeviceVendor(dev, &vendor); kr = (*dev)->GetDeviceProduct(dev, &product); kr = (*dev)->USBGetSerialNumberStringIndex(dev, &serialIndex); if (serialIndex > 0) { IOUSBDevRequest req; UInt16 buffer[256]; UInt16 languages[128]; memset(languages, 0, sizeof(languages)); req.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice); req.bRequest = kUSBRqGetDescriptor; req.wValue = (kUSBStringDesc << 8) | 0; req.wIndex = 0; req.pData = languages; req.wLength = sizeof(languages); kr = (*dev)->DeviceRequest(dev, &req); if (kr == kIOReturnSuccess && req.wLenDone > 0) { int langCount = (req.wLenDone - 2) / 2, lang; for (lang = 1; lang <= langCount; lang++) { memset(buffer, 0, sizeof(buffer)); memset(&req, 0, sizeof(req)); req.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice); req.bRequest = kUSBRqGetDescriptor; req.wValue = (kUSBStringDesc << 8) | serialIndex; req.wIndex = languages[lang]; req.pData = buffer; req.wLength = sizeof(buffer); kr = (*dev)->DeviceRequest(dev, &req); if (kr == kIOReturnSuccess && req.wLenDone > 0) { int i, count; // skip first word, and copy the rest to the serial string, // changing shorts to bytes. count = (req.wLenDone - 1) / 2; for (i = 0; i < count; i++) serial[i] = buffer[i + 1]; serial[i] = 0; break; } } } } (*dev)->Release(dev); DBG("INFO: Found vid=%04x pid=%04x serial=%s\n", vendor, product, serial); usb_handle* handle = CheckInterface((IOUSBInterfaceInterface**)iface, vendor, product); if (handle == NULL) { DBG("ERR: Could not find device interface: %08x\n", kr); (*iface)->Release(iface); continue; } DBG("AndroidDeviceAdded calling register_usb_transport\n"); register_usb_transport(handle, (serial[0] ? serial : NULL), 1); // Register for an interest notification of this device being removed. // Pass the reference to our private data as the refCon for the // notification. kr = IOServiceAddInterestNotification(notificationPort, usbInterface, kIOGeneralInterest, AndroidInterfaceNotify, handle, &handle->usbNotification); if (kIOReturnSuccess != kr) { DBG("ERR: Unable to create interest notification (%08x)\n", kr); } } }
bool wxHIDDevice::Create (int nClass, int nType, int nDev) { //Create the mach port wxIOCHECK(IOMasterPort(bootstrap_port, &m_pPort), "Could not create mach port"); //Dictionary that will hold first //the matching dictionary for determining which kind of devices we want, //then later some registry properties from an iterator (see below) CFMutableDictionaryRef pDictionary; //Create a dictionary //The call to IOServiceMatching filters down the //the services we want to hid services (and also eats the //dictionary up for us (consumes one reference)) wxVERIFY((pDictionary = IOServiceMatching(kIOHIDDeviceKey)) != NULL ); //Here we'll filter down the services to what we want if (nType != -1) { CFNumberRef pType = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &nType); CFDictionarySetValue(pDictionary, CFSTR(kIOHIDPrimaryUsageKey), pType); CFRelease(pType); } if (nClass != -1) { CFNumberRef pClass = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &nClass); CFDictionarySetValue(pDictionary, CFSTR(kIOHIDPrimaryUsagePageKey), pClass); CFRelease(pClass); } //Now get the maching services io_iterator_t pIterator; wxIOCHECK(IOServiceGetMatchingServices(m_pPort, pDictionary, &pIterator), "No Matching HID Services"); wxASSERT_MSG(pIterator != 0, wxT("No devices found!")); //Now we iterate through them io_object_t pObject; while ( (pObject = IOIteratorNext(pIterator)) != 0) { if(--nDev != 0) continue; wxVERIFY(IORegistryEntryCreateCFProperties(pObject, &pDictionary, kCFAllocatorDefault, kNilOptions) == KERN_SUCCESS); //Just for sanity :) wxASSERT(CFGetTypeID(CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDProductKey))) == CFStringGetTypeID()); /* kIOHIDTransportKey; kIOHIDVendorIDKey; kIOHIDProductIDKey; kIOHIDVersionNumberKey; kIOHIDManufacturerKey; kIOHIDSerialNumberKey; if !kIOHIDLocationIDKey kUSBDevicePropertyLocationID kIOHIDPrimaryUsageKey kIOHIDPrimaryUsagePageKey idProduct idVendor USB Product Name */ //Get [product] name m_szProductName = wxMacCFStringHolder( (CFStringRef) CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDProductKey)), false ).AsString(); CFNumberRef nref = (CFNumberRef) CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDProductIDKey)); if (nref) CFNumberGetValue( nref, kCFNumberIntType, &m_nProductId ); nref = (CFNumberRef) CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDVendorIDKey)); if (nref) CFNumberGetValue( nref, kCFNumberIntType, &m_nManufacturerId ); //Create the interface (good grief - long function names!) SInt32 nScore; IOCFPlugInInterface** ppPlugin; wxIOCHECK(IOCreatePlugInInterfaceForService(pObject, kIOHIDDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &ppPlugin, &nScore), ""); //Now, the final thing we can check before we fall back to asserts //(because the dtor only checks if the device is ok, so if anything //fails from now on the dtor will delete the device anyway, so we can't break from this). //Get the HID interface from the plugin to the mach port wxSCHECK((*ppPlugin)->QueryInterface(ppPlugin, CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), (void**) &m_ppDevice), ""); //release the plugin (*ppPlugin)->Release(ppPlugin); //open the HID interface... wxVERIFY((*m_ppDevice)->open(m_ppDevice, 0) == S_OK); // //Now the hard part - in order to scan things we need "cookies" - // wxCFArray CookieArray = CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDElementKey)); BuildCookies(CookieArray); //cleanup CFRelease(pDictionary); IOObjectRelease(pObject); break; } //iterator cleanup IOObjectRelease(pIterator); return true; }//end Create()
void InitJoystick() { mach_port_t masterPort = NULL; io_iterator_t hidObjectIterator = NULL; IOReturn result = IOMasterPort (bootstrap_port, &masterPort); if(result != kIOReturnSuccess) return; CFMutableDictionaryRef hidMatchDictionary = IOServiceMatching (kIOHIDDeviceKey); if(!hidMatchDictionary) return; result = IOServiceGetMatchingServices (masterPort, hidMatchDictionary, &hidObjectIterator); if(result != kIOReturnSuccess) return; // find the first joystick/gamepad on the USB for(;;) { IOHIDDeviceInterface **device; io_object_t ioHIDDeviceObject = IOIteratorNext(hidObjectIterator); if(!ioHIDDeviceObject) break; CFMutableDictionaryRef hidProperties = 0; long kresult = IORegistryEntryCreateCFProperties(ioHIDDeviceObject, &hidProperties, kCFAllocatorDefault, kNilOptions); if(kresult == KERN_SUCCESS && hidProperties) { CFTypeRef refCF = 0; refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDProductKey)); if(CFGetTypeID(refCF) == CFStringGetTypeID()) { CFIndex bufferSize = CFStringGetLength (refCF) + 1; char * buffer = (char *)malloc (bufferSize); if (buffer) { if (CFStringGetCString (refCF, buffer, bufferSize, CFStringGetSystemEncoding ())) strncpy(gJoystickName, buffer, MaxJoystickNameLen); free(buffer); } } refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDPrimaryUsagePageKey)); long usage, usagePage; CFNumberGetValue (refCF, kCFNumberLongType, &usagePage); refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDPrimaryUsageKey)); CFNumberGetValue (refCF, kCFNumberLongType, &usage); if ( (usagePage == kHIDPage_GenericDesktop) && ((usage == kHIDUsage_GD_Joystick || usage == kHIDUsage_GD_GamePad)) ) { CFTypeRef refElementTop = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDElementKey)); if (refElementTop) { CFTypeID type = CFGetTypeID (refElementTop); if (type == CFArrayGetTypeID()) /* if element is an array */ { CFRange range = {0, CFArrayGetCount (refElementTop)}; /* CountElementsCFArrayHandler called for each array member */ CFArrayApplyFunction (refElementTop, range, HIDGetElementsCFArrayHandler, NULL); IOCFPlugInInterface ** ppPlugInInterface = NULL; S32 score; IOReturn result = IOCreatePlugInInterfaceForService (ioHIDDeviceObject, kIOHIDDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &ppPlugInInterface, &score); if (result == kIOReturnSuccess) { // Call a method of the intermediate plug-in to create the device interface (*ppPlugInInterface)->QueryInterface (ppPlugInInterface, CFUUIDGetUUIDBytes (kIOHIDDeviceInterfaceID), (void *) &device); if(device) { result = (*device)->open(device, 0); gController.device = device; gJoystickInit = true; } (*ppPlugInInterface)->Release (ppPlugInInterface); } } } } CFRelease(hidProperties); } IOObjectRelease(ioHIDDeviceObject); if(gJoystickInit) break; } IOObjectRelease (hidObjectIterator); /* release the iterator */ }
bool OpenPortalHandleFromGUID(CFUUIDBytes guid, IOUSBDeviceInterface300*** phPortalHandle) { io_iterator_t iterator = 0; io_service_t usbRef; bool bResult = true; SInt32 score; HDEVINFO hDevInfo; SP_DEVICE_INTERFACE_DATA deviceInterfaceData; IOUSBConfigurationDescriptorPtr config; IOCFPlugInInterface** plugin; HIDD_ATTRIBUTES attributes; CFMutableDictionaryRef matchingDict = NULL; ULONG requiredLength=0; //Set up matching dictionary for class IOUSBDevice and its subclasses matchingDict = IOServiceMatching(kIOUSBDeviceClassName); if (!matchingDict) { printf("Couldn’t create a USB matching dictionary\n"); return false; } IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &iterator); usbRef = IOIteratorNext(iterator); *phPortalHandle = NULL; while (usbRef != 0) { IOCreatePlugInInterfaceForService(usbRef, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugin, &score); IOObjectRelease(usbRef); (*plugin)->QueryInterface(plugin, guid, (LPVOID)phPortalHandle); (*plugin)->Release(plugin); if(guid == xbox_guid) { break; // we are done. xbox_guid does not have HID attributes } if (*phPortalHandle != NULL) { UInt16 VendorID, ProductID; (**phPortalHandle)->GetDeviceVendor(*phPortalHandle, &VendorID); (**phPortalHandle)->GetDeviceProduct(*phPortalHandle, &ProductID); if (((VendorID == 0x12ba) || (VendorID == 0x54c)) || (VendorID == 0x1430)) { if ((ProductID == 0x150) || (ProductID == 0x967)) { (**phPortalHandle)->USBDeviceOpen(*phPortalHandle); ret = (**phPortalHandle)->GetConfigurationDescriptorPtr(*phPortalHandle, 0, &config); (**phPortalHandle)->SetConfiguration(*phPortalHandle, config->bConfigurationValue); break; // found the portal. leave the handle open } } } (**phPortalHandle)->Release(*phPortalHandle); *phPortalHandle = NULL; } usbRef = IOIteratorNext(iterator); }