Example #1
0
/* 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;
}
Example #5
0
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;
}
Example #6
0
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;
}
Example #8
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);
    }
}
Example #9
0
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);
        }
    }
}
Example #10
0
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()
Example #11
0
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 */
}
Example #12
0
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);

	}