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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7606975/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 22:03:34  来源:igfitidea点击:

How to get device descriptor and configuration descriptor of usb device in Mac?

xcodemacosusbiokit

提问by Dili

I have minimum exposure to xcode and I/Okit framework. I have seen device descriptor and configuration descriptor of a usb device in USB prober.enter image description here

我对 xcode 和 I/Okit 框架的接触最少。我在 USB 探测器中看到了 USB 设备的设备描述符和配置描述符。在此处输入图片说明

I have written an xcode program using I/O kit framework which gives the usb device name as output, when we give product id and vendor id of that device as input.

我已经使用 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] = '
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->...
'; } printf("\ndeviceName:%s",deviceName); /*Free the reference taken before continuing to the next item */ IOObjectRelease(device); } /*Release the iterator */ IOObjectRelease(iter); return 0;

}

}

I need to modify this, so that on giving vendor and product id of usb device, i will get the device descriptor and configuration descriptor( as shown in USB prober) as output.

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

Here i just gave an example, code can change but the output must be the descriptor( atleast the device decriptor).

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

Thanks in advance...

提前致谢...

回答by Ivan

I think u should download the source code of USBProber rather than figure it out by yourself.

我认为你应该下载 USBProber 的源代码而不是自己弄清楚。

All the information presents in the USBProber u could get sooner or later by analyzing the source code.

通过分析源代码,您迟早会获得 USBProber 中提供的所有信息。

Here is link to download the source code of IOUSBFamily, with USBProber inside it. http://opensource.apple.com/tarballs/IOUSBFamily/

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

回答by Timmmm

To get the configuration descriptors you can use code like this:

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

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);

Unfortunately there doesn't seem to be a function to get the device descriptor. There are functions to get someof it:

不幸的是,似乎没有获取设备描述符的函数。有一些函数可以获取其中的一些

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);

But I don't see a way to get iManufacturer, iProduct, iSerial, bMaxPacketSize0, or bcdUSB.

但我看不到获取iManufacturer, iProduct, iSerial, bMaxPacketSize0, 或 的方法bcdUSB

There is a way around this - instead of using the built-in functions you can just do a control request to get the device descriptor (and configuration descriptors if you like) manually using a control transfer.

有一种方法可以解决这个问题 - 而不是使用内置函数,您只需执行控制请求即可使用控制传输手动获取设备描述符(以及配置描述符,如果您愿意)。

The USB 2.0 spec describes how to do this. Basically you:

USB 2.0 规范描述了如何做到这一点。基本上你:

  1. Do a control transfer with bmRequestType = Device | Standard | In, bRequest = USB_GET_DESCRIPTOR_REQUEST, wValue = (USB_DEVICE_DESCRIPTOR_TYPE << 8), wIndex = 0, wLength = 2. That will fail because the descriptor is longer than 2, but it gets you the descriptor header which includes its length.

  2. Repeat that request but with the correct length.

  3. For configuration descriptors, do a third request with length wTotalLength.

  1. 使用bmRequestType = Device | Standard | In, bRequest = USB_GET_DESCRIPTOR_REQUEST, wValue = (USB_DEVICE_DESCRIPTOR_TYPE << 8), wIndex = 0,进行控制转移wLength = 2。这将失败,因为描述符长于 2,但它会为您提供包含其长度的描述符标头。

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

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

You can do it with one less request since you know the size of the descriptors in advance, but I like to do it like that because then you can wrap it up in a very general getDescriptor()method.

您可以减少一个请求,因为您事先知道描述符的大小,但我喜欢这样做,因为这样您就可以用一种非常通用的getDescriptor()方法将其包装起来。

In theory you can do it as simply as this:

从理论上讲,您可以像这样简单地做到这一点:

##代码##

But for some reason that is giving me a kIOUSBPipeStallederror. Not sure why.

但出于某种原因,这给了我一个kIOUSBPipeStalled错误。不知道为什么。

Edit: I forgot the << 8. Now it works. :-)

编辑:我忘记了<< 8. 现在它起作用了。:-)

回答by apophis42

The header IOKit/usb/USBSpec.hhas a documented list of property keys corresponding to values inside the different descriptors. You can use those with IORegistryEntrySearchCFProperty(or similar functions) to get the descriptor values. This way you don't need a device request from an IOUSBDeviceInterface, which is advantageous because:

标头IOKit/usb/USBSpec.h有一个记录的属性键列表,对应于不同描述符中的值。您可以使用具有IORegistryEntrySearchCFProperty(或类似功能)的那些来获取描述符值。这样您就不需要来自 的设备请求IOUSBDeviceInterface,这是有利的,因为:

  • the documentation (comments) say that all device requests require an opened USB device and you may not have permission to do that for all devices (it's possible the documentation is wrong, at least for descriptor requests, but I have no guarantee of that and it seems better to follow it anyway)
  • device requests can block for an indeterminate amount of time
  • the manufacturer, product, and serial number strings (which are referenced by the device descriptor, but are not technically part of it) are not retrieved in this request
  • 文档(评论)说所有设备请求都需要一个打开的 USB 设备,您可能没有权限为所有设备这样做(文档可能是错误的,至少对于描述符请求,但我不能保证这一点,它无论如何似乎更好地遵循它)
  • 设备请求可能会阻塞一段不确定的时间
  • 制造商、产品和序列号字符串(由设备描述符引用,但在技术上不是它的一部分)未在此请求中检索

回答by Dili

For getting device descriptor and configuration decriptor, we can use functions in IOUSBDeviceInterface class

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

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

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

For getting interface descriptor and end point descriptor, we can use functions in IOUSBInterfaceInterface class

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

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

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