libusb使用详解四(USB设备的基本操作)

libusb获取USB设备基本信息详解

我们可以使用libusb_device对象,在不使用libusb_open打开USB设备的情况下获取USB设备的基本信息。其中包括USB Descriptor、USB Configuration、USB Bus ID、USB Device ID和USB Port ID,USB连接速度等。

1. 获取USB Bus ID

函数定义如下:

uint8_t libusb_get_bus_number (libusb_device *dev)

dev:为通过libusb_get_device_list或者libusb_hotplug_callback_fn获取的libusb_device对象,后续不再赘述
返回值:为 bus id

2. 获取USB Device ID

函数定义如下:

uint8_t libusb_get_device_address (libusb_device *dev)

返回值:为device id

3. 获取USB Port ID

函数定义如下:

int libusb_get_port_numbers (
    libusb_device *dev,
    uint8_t *port_numbers,
    int port_numbers_len)

port_numbers:为待返回的port层级ID组成的数组
port_numbers_len:为port_numbers数组长度,当前USB3.0支持最大长度为7
返回值:为填入的ID个数(层级数)。如果传入的port_numbers数组过小,会返回LIBUSB_ERROR_OVERFLOW错误

4. 获取USB连接速度

函数定义如下:

int libusb_get_device_speed (libusb_device *dev)

返回libusb_speed表示的速度值,LIBUSB_SPEED_UNKNOWN表示系统无法侦测连接速度

5. 获取USB Descriptor信息

USB Descriptor信息中包括此设备的PID和VID,Device Class、USB协议版本以及最重要的Configuration数量

函数定义如下:

int libusb_get_device_descriptor (
    libusb_device *dev,
    struct libusb_device_descriptor *desc)

desc:为获取的Device Descriptor信息

返回值:为LIBUSB_SUCESS表示成功,否则返回LIBUSB_ERROR code

其中:
desc->bcdUSB:表示USB版本,0x0110表示USB 1.1,0x0200表示USB 2.0等
desc->bDeviceClass:表示Device Class,由libusb_class_code定义
desc->idVendor:表示Device的VID
desc->idProduct:表示Device的PID
desc->bNumConfigurations:表示Device的Configuration数量

其它的内容,比如:desc->iManufacturer, desc->iProduct和desc->iSerialNumber,分别是厂商名称、产品名称和序列号的description字符串序号。如果不为0,则可以进一步通过libusb_get_string_descriptor_ascii函数获取实际的字符串。

libusb_get_string_descriptor_ascii函数定义如下:

int libusb_get_string_descriptor_ascii (
    libusb_device_handle *dev_handle,
    uint8_t desc_index,
    unsigned char *data,
    int length)

其中:

dev_handle:为USB Device的句柄,所以此接口需要打开USB设备
desc_index: 就是description字符串序号,即iManufacturer, iProduct,iSerialNumber等
data:为待返回字符串的char数组指针
length:为data数组的长度
返回值:为填入的字符个数

6. 获取USB Configuration信息

libusb或者说Linux的USB架构中,USB设备一般包含一个或多个USB Configuration。一个USB Configuration对应一个特定配置。每个配置中同样包含一个或多个接口(Interface),每个接口对应USB设备的一种功能,比如:视频、音频、HID等。最后每个接口可以包含一个或多个端口(Endpoint), USB的传输就是通过这些端口进行的。详细说明可以参考https://blog.youkuaiyun.com/tilblackout/article/details/134046115

获取USB Configuration信息的函数定义如下:

int libusb_get_config_descriptor (
    libusb_device *dev,
    uint8_t config_index,
    struct libusb_config_descriptor **config)

config_index:为configuration的序号,范围为0 - bNumConfiguration-1(bNumConfiguration由libusb_get_device_descriptor 获得)
config:为返回的configuration信息对象

返回值:为LIBUSB_SUCCESS表示成功,LIBUSB_ERROR_NOT_FOUND表示此configuration未找到,还有其它LIBUSB_ERROR code

获取的libusb_config_descriptor信息对象必须通过libusb_free_config_descriptor进行free。
函数libusb_free_config_descriptor的定义如下:

void libusb_free_config_descriptor (struct libusb_config_descriptor *config)

获取的libusb_config_descriptor 对象中有用的信息为:
config->MaxPower:表示此设备需消耗的最大电量,对于HighSpeed设备(可通过libusb_get_device_speed获知),值为2mA的倍数;对于Super Speed设备,值为8 mA的倍数
config->bNumInterfaces: 表示此Configuration中包含的Interface数量
config->interface: 为配置中接口对象libusb_interface的数组,长度由bNumInterfaces决定。

config->interface数组中主要是libusb_interface对象,libusb_interface接口对象只包含了其可配置项对象libusb_interface_descriptor的信息,主要有:
interface->num_altsetting: 表示可配置项个数
interface->altsetting: 可配置项对象数组,其长度由num_altsetting决定

接口(Interface)信息的主要内容就存储在可配置信息libusb_interface_descriptor中,主要包括:
altsetting->bInterfaceNumber:表示此Interface的序号
altsetting->bAlternateSetting: 表示此Interface可配置项的序号
altsetting->bNumEndpoints: 表示此Interface包含端口(Endpoint)的个数
altsetting->endpoint: 表示Interface中端口对象libusb_endpoint_descriptor的数组,长度由bNumEndpoints决定

端口(Endpoint)信息的主要内容存储在端口对象libusb_endpoint_descriptor中,主要包括:
endpoint->bEndpointAddress:表示访问此端口的地址,后续读写操作需要用到,最高位决定此端口是"读"还是"写"端口
endpoint->bmAttributes:表示此端口的属性。
        Bits 0:1表示传输类型(控制(Control)、同步(Isochronous)、块(Bulk)、中断(Interrupt));
        Bit 2:3表示同步传输类型(无、异步、自适应、同步)
        Bit 4:5表示同步传输用途(数据(Data)、反馈(Feedback)、隐式反馈(Implict Feedback))
endpoint->wMaxPacketSize:表示端口一次传输的最大Size
endpoint->bInterval:表示端口传输的间隔时间
关于endpoint定义的详细内容,可参考https://blog.youkuaiyun.com/u013256018/article/details/62087333

遍历Configuration信息的例程如下:

static void print_endpoint(const struct libusb_endpoint_descriptor *endpoint)
{
	printf("      Endpoint:\n");
	printf("        bEndpointAddress:    %02xh\n", endpoint->bEndpointAddress);
	printf("        bmAttributes:        %02xh\n", endpoint->bmAttributes);
	printf("        wMaxPacketSize:      %u\n", endpoint->wMaxPacketSize);
	printf("        bInterval:           %u\n", endpoint->bInterval);
	printf("        bRefresh:            %u\n", endpoint->bRefresh);
	printf("        bSynchAddress:       %u\n", endpoint->bSynchAddress);
}

static void print_altsetting(const struct libusb_interface_descriptor *interface)
{
	uint8_t i;

	printf("    Interface:\n");
	printf("      bInterfaceNumber:      %u\n", interface->bInterfaceNumber);
	printf("      bAlternateSetting:     %u\n", interface->bAlternateSetting);
	printf("      bNumEndpoints:         %u\n", interface->bNumEndpoints);
	printf("      bInterfaceClass:       %u\n", interface->bInterfaceClass);
	printf("      bInterfaceSubClass:    %u\n", interface->bInterfaceSubClass);
	printf("      bInterfaceProtocol:    %u\n", interface->bInterfaceProtocol);
	printf("      iInterface:            %u\n", interface->iInterface);

	for (i = 0; i < interface->bNumEndpoints; i++)
		print_endpoint(&interface->endpoint[i]);
}

static void print_interface(const struct libusb_interface *interface)
{
	int i;

	for (i = 0; i < interface->num_altsetting; i++)
		print_altsetting(&interface->altsetting[i]);
}

static void print_configuration(struct libusb_config_descriptor *config)
{
	uint8_t i;

	printf("  Configuration:\n");
	printf("    wTotalLength:            %u\n", config->wTotalLength);
	printf("    bNumInterfaces:          %u\n", config->bNumInterfaces);
	printf("    bConfigurationValue:     %u\n", config->bConfigurationValue);
	printf("    iConfiguration:          %u\n", config->iConfiguration);
	printf("    bmAttributes:            %02xh\n", config->bmAttributes);
	printf("    MaxPower:                %u\n", config->MaxPower);

	for (i = 0; i < config->bNumInterfaces; i++)
		print_interface(&config->interface[i]);
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值