如何在Mac中获取USB设备的设备描述符和配置描述符?

时间:2011-09-30 07:00:28

标签: xcode macos usb iokit

我最少接触xcode和I / Okit框架。我在USB探测器中看到了USB设备的设备描述符和配置描述符。enter image description here

我使用I / O工具包框架编写了一个xcode程序,当我们将该设备的产品ID和供应商ID作为输入时,它将usb设备名称作为输出。

/*Take the vendor and product id from console*/

printf("\nEnter the vendor id : ");
scanf("%lx",&usbVendor);

printf("\nEnter the product id :");
scanf("%lx",&usbProduct);


/* Set up a matching dictionary for the class */
matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
if (matchingDict == NULL)
{
    return -1; // fail
}
// Create a CFNumber for the idVendor and set the value in the dictionary
numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbVendor);
CFDictionarySetValue(matchingDict, 
                     CFSTR(kUSBVendorID), 
                     numberRef);
CFRelease(numberRef);

// Create a CFNumber for the idProduct and set the value in the dictionary
numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbProduct);
CFDictionarySetValue(matchingDict, 
                     CFSTR(kUSBProductID), 
                     numberRef);
CFRelease(numberRef);
numberRef = NULL;

/*Get an iterator.*/
kr = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &iter);
if (kr != KERN_SUCCESS)
{
    return -1;// fail
}

/* iterate */
while ((device = IOIteratorNext(iter)))
{
    /*Display the device names */

    io_name_t       deviceName;
    kr = IORegistryEntryGetName(device, deviceName);
    if (KERN_SUCCESS != kr) {
        deviceName[0] = '\0';
    }


    printf("\ndeviceName:%s",deviceName);

    /*Free the reference taken before continuing to the next item */
    IOObjectRelease(device);
}

/*Release the iterator */
IOObjectRelease(iter);
return 0;

}

我需要对此进行修改,以便在提供usb设备的供应商和产品ID时,我将获得设备描述符和配置描述符(如USB prober中所示)作为输出。

这里我举了一个例子,代码可以改变,但输出必须是描述符(至少是设备描述符)。

提前致谢...

4 个答案:

答案 0 :(得分:5)

我想你应该下载USBProber的源代码,而不是自己搞清楚。

通过分析源代码,USBProber中提供的所有信息迟早都可以得到。

这是下载IOUSBFamily源代码的链接,其中包含USBProber。 http://opensource.apple.com/tarballs/IOUSBFamily/

答案 1 :(得分:1)

要获取配置描述符,您可以使用以下代码:

IOUSBDeviceInterface650** dev = ...;
IOUSBConfigurationDescriptor* configDesc = nullptr;

// Get the configuration descriptor for the first configuration (configuration 0).
kern_return_t kr = (*dev)->GetConfigurationDescriptorPtr(dev, 0, &configDesc);
if (kr != kIOReturnSuccess)
    return an_error;

// Now use configDesc->...

不幸的是,似乎没有获取设备描述符的功能。有一些功能可以一些

kr = (*dev)->GetDeviceClass(dev, &desc.bDeviceClass);
kr = (*dev)->GetDeviceSubClass(dev, &desc.bDeviceSubClass);
kr = (*dev)->GetDeviceProtocol(dev, &desc.bDeviceProtocol);
kr = (*dev)->GetDeviceVendor(dev, &desc.idVendor);
kr = (*dev)->GetDeviceProduct(dev, &desc.idProduct);
kr = (*dev)->GetDeviceReleaseNumber(dev, &desc.bcdDevice);
kr = (*dev)->GetNumberOfConfigurations(dev, &desc.bNumConfigurations);

但我没有办法获得iManufactureriProductiSerialbMaxPacketSize0bcdUSB

有一种解决方法 - 不使用内置函数,您只需执行控制请求即可手动使用控件传输来获取设备描述符(以及配置描述符)。

USB 2.0规范描述了如何执行此操作。基本上你:

  1. 使用bmRequestType = Device | Standard | InbRequest = USB_GET_DESCRIPTOR_REQUESTwValue = (USB_DEVICE_DESCRIPTOR_TYPE << 8)wIndex = 0wLength = 2进行控件转移。这将失败,因为描述符长于2,但它会获得包含其长度的描述符标题。

  2. 重复该请求,但长度正确。

  3. 对于配置描述符,请执行长度为wTotalLength的第三个请求。

  4. 由于您事先知道了描述符的大小,因此您可以少用一个请求来执行此操作,但我喜欢这样做,因为这样您可以将它包装在非常通用的getDescriptor()方法中。

    从理论上讲,你可以这样做:

    IOUSBDeviceDescriptor devDesc;
    
    IOUSBDevRequest request;
    request.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
    request.bRequest = kUSBRqGetDescriptor;
    request.wValue = kUSBDeviceDesc << 8;
    request.wIndex = 0;
    request.wLength = sizeof(devDesc); // 18
    request.pData = &devDesc;
    request.wLenDone = 0;
    
    kern_return_t kr = (*dev)->DeviceRequest(dev, &request);
    

    但由于某些原因,我发现kIOUSBPipeStalled错误。不知道为什么。

    编辑:我忘记了<< 8。现在它有效。 : - )

答案 2 :(得分:0)

为了获取设备描述符和配置描述符,我们可以使用IOUSBDeviceInterface类中的函数

链接:http://developer.apple.com/library/mac/#documentation/Darwin/Reference/IOKit/IOUSBLib_h/Classes/IOUSBDeviceInterface/index.html#//apple_ref/doc/com/intfm/IOUSBDeviceInterface/

为了获取接口描述符和端点描述符,我们可以使用IOUSBInterfaceInterface类中的函数

链接:http://developer.apple.com/library/mac/#documentation/Darwin/Reference/IOKit/IOUSBLib_h/Classes/IOUSBInterfaceInterface/

答案 3 :(得分:0)

头文件IOKit/usb/USBSpec.h具有记录的属性键列表,这些属性键与不同描述符中的值相对应。您可以将它们与IORegistryEntrySearchCFProperty(或类似函数)一起使用以获取描述符值。这样,您就不需要来自IOUSBDeviceInterface的设备请求,这是有优势的,因为:

  • 文档(注释)说,所有设备请求都需要一个打开的USB设备,您可能没有权限对所有设备执行此操作(文档可能有误,至少对于描述符请求是错误的,但我不能保证这样,无论如何都应该遵循它)
  • 设备请求可能会阻塞一段不确定的时间
  • 在此请求中未检索制造商,产品和序列号字符串(由设备描述符引用,但在技术上不属于其中)