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

发布于 2024-12-07 18:28:37 字数 1931 浏览 3 评论 0原文

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

我编写了一个xcode程序使用 I/O 套件框架,当我们提供该设备的产品 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 探测器中所示)作为输出

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

提前致谢...

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

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.

/*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;

}

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.

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

Thanks in advance...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

情场扛把子 2024-12-14 18:28:37

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

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

这里是下载IOUSBFamily源代码的链接,里面有USBProber。
http://opensource.apple.com/tarballs/IOUSBFamily/

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

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

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

℉絮湮 2024-12-14 18:28:37

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

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

但我没有找到获取 iManufactureriProductiSerial 的方法code>、bMaxPacketSize0bcdUSB

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

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

  1. 使用 bmRequestType = Device | 进行控制传输标准|在中,bRequest = USB_GET_DESCRIPTOR_REQUESTwValue = (USB_DEVICE_DESCRIPTOR_TYPE << 8)wIndex = 0wLength = 2 。这会失败,因为描述符长于 2,但它会为您获取包含其长度的描述符标头。

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

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

您可以用更少的请求来完成此操作,因为您提前知道描述符的大小,但我喜欢这样做,因为这样您就可以将其包装在一个非常通用的 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..现在可以了。 :-)

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

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->...

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

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

But I don't see a way to get iManufacturer, iProduct, iSerial, bMaxPacketSize0, or 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:

  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.

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.

In theory you can do it as simply as this:

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 for some reason that is giving me a kIOUSBPipeStalled error. Not sure why.

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

二智少女 2024-12-14 18:28:37

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

  • 文档(注释)说所有设备请求都需要打开的 USB 设备,并且您可能没有这样做的权限对于所有设备(文档可能是错误的,至少对于描述符请求来说是错误的,但我不能保证这一点,而且最好还是遵循它)
  • 一段不确定的时间
  • 设备请求可能会阻塞制造商、产品和序列号 数字字符串(由在此请求中不会检索设备描述符(但从技术上讲不是它的一部分)

The header IOKit/usb/USBSpec.h has 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:

  • 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
拧巴小姐 2024-12-14 18:28:37

为了获取设备描述符和配置描述符,我们可以使用 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/

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

Link: 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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文