原文:
blog.csdn.net
(翻译)libusb-api-1.0_David-CSDN博客_libusb_set_option
113-142 minutes
这里先记录一点usb的基础知识:
USB HOST(主机)、USB HID(usb设备)
主机通过各种描述符来识别设备,有设备描述符,配置描述符,接口描述符,端点描述符,字符描述符,报告描述符等。USB描述符就像是USB的“身份证”一样,详细记录这外围设备的相关的一切信息。
usb设备是通过
设备描述符层级:设备(device)->配置(configuration)->接口(interface)->(设置)->端点(endpoint)
一个设备有一个设备描述符,多个配置描述符,一个配置有多个接口描述符,一个接口有多个端点描述符。
设备就是指usb设备;配置可以理解成高速设备还是低速设备;接口就是接的是USB存储设备还是USB视频设备。
一般USB HID可能提供一种或多种配置(//代码效果参考:http://hnjlyzjd.com/hw/wz_25144.html
例如高速、低速),由USBHost选择一个支持的配置才能使设备正常工作,这些配置对设备可执行的操作是相互排斥的;USB
HID以一系列接口的形式公开其功能(例如音频接口、键盘接口、旋钮接口);每个接口包含一个或多个备用设置,默认情况下,选择某个配置会激活该配置中每个接口的首个备用配置;每个备用设置由一组端点组成,USB
HID和USB Host实际是由端点进行通信的,每个端点独立的完成I | O请求,通常情况一个端点只负责I或O,一个端点组成一个I/O管道。
参考:
MSDN - 选择 USB 驱动程序中的 USB 配置
文章目录
1. 库初始化/取消初始化
1.1 数据结构
1.2 类型定义
1.3 枚举
1.4 函数/功能/方法
void libusb_set_debug(libusb_context ctx,int level)
int libusb_set_option(libusb_context ctx,enum libusb_option option,...)
int libusb_init(libusb_context context)
void libusb_exit(struct libusb_context ctx)
2. 设备处理和枚举
设备和设备句柄
设备发现和引用计数
2.1 类型定义
typedef struct libusb_device libusb_device
typedef struct libusb_device_handle libusb_device_handle
2.2 枚举
enum libusb_speed
2.3 函数
ssize_t libusb_get_device_list(libusb_context ctx , libusb_device list)
void libusb_free_device_list(libusb_device list , int unref_devices)
uint8_t libusb_get_bus_number( libusb_device dev)
uint8_t libusb_get_port_number ( libusb_device dev )
int libusb_get_port_numbers (libusb_device dev,uint8_t port_numbers,int ort_numbers_len )
libusb_device libusb_get_parent (libusb_device dev )
uint8_t libusb_get_device_address(libusb_device dev )
int libusb_get_device_speed (libusb_device dev )
int libusb_get_max_packet_size(libusb_device dev,unsigned char endpoint )
int libusb_get_max_iso_packet_size(libusb_device dev,unsigned char endpoint )
libusb_device libusb_ref_device( libusb_device dev)
void libusb_unref_device(libusb_device dev)
int libusb_open (libusb_device dev, libusb_device_handle dev_handle )
libusb_device_handle libusb_open_device_with_vid_pid(libusb_context ctx,uint16_t vendor_id,uint16_t product_id )
void libusb_close(libusb_device_handle dev_handle)
libusb_device libusb_get_device (libusb_device_handle dev_handle)
int libusb_get_configuration(libusb_device_handle dev_handle,int config )
int libusb_set_configuration(libusb_device_handle dev_handle,int configuration)
int libusb_claim_interface(libusb_device_handle dev_handle,int interface_number)
int libusb_release_interface (libusb_device_handle dev_handle,int interface_number)
int libusb_set_interface_alt_setting(libusb_device_handle dev_handle,int interface_number,int alternate_setting)
int libusb_clear_halt(libusb_device_handle dev_handle,unsigned char endpoint)
int libusb_reset_device(libusb_device_handle dev_handle)
int libusb_kernel_driver_active(libusb_device_handle dev_handle,int interface_number)
int libusb_detach_kernel_driver(libusb_device_handle dev_handle,int interface_number)
int libusb_attach_kernel_driver(libusb_device_handle dev_handle,int interface_number)
int libusb_set_auto_detach_kernel_driver(libusb_device_handle dev_handle,int enable)
3. 杂项
3.1 宏定义
#define LIBUSB_CALL
#define LIBUSB_API_VERSION
#define libusb_le16_to_cpu libusb_cpu_to_le16
3.2 枚举
libusb_standard_request
libusb_request_type
libusb_request_recipient
libusb_error
libusb_capability
3.3 函数
int libusb_has_capability(uint32_t capability)
const char libusb_error_name(int error_code)
const struct libusb_version libusb_get_version(void)
static uint16_t libusb_cpu_to_le16(const uint16_t x)
int libusb_setlocale (const char locale)
const char libusb_strerror(enum libusb_error errcode)
3.4 变量
static const char usbi_locale_supported 【】 = { "en", "nl", "fr", "ru" }
4. USB描述符
4.1 数据结构
libusb_device_descriptor
libusb_endpoint_descriptor
libusb_interface_descriptor
libusb_interface
libusb_config_descriptor
libusb_ss_endpoint_companion_descriptor
libusb_bos_dev_capability_descriptor
libusb_bos_descriptor
libusb_usb_2_0_extension_descriptor
libusb_ss_usb_device_capability_descriptor
libusb_container_id_descriptor
4.2 枚举
libusb_class_code
libusb_descriptor_type
libusb_endpoint_direction
libusb_transfer_type
libusb_iso_sync_type
libusb_iso_usage_type
4.3 函数
int libusb_get_device_descriptor (libusb_device dev, struct libusb_device_descriptor desc)
int libusb_get_active_config_descriptor (libusb_device dev, struct libusb_config_descriptor **config)
int libusb_get_config_descriptor (libusb_device dev, uint8_t config_index, struct libusb_config_descriptor config)
int
libusb_get_config_descriptor_by_value (libusb_device *dev, uint8_t
bConfigurationValue, struct libusb_config_descriptor config)
void libusb_free_config_descriptor (struct libusb_config_descriptor config)
int
libusb_get_ss_endpoint_companion_descriptor (struct libusb_context
ctx, const struct libusb_endpoint_descriptor endpoint, struct
libusb_ss_endpoint_companion_descriptor **ep_comp)
void libusb_free_ss_endpoint_companion_descriptor (struct libusb_ss_endpoint_companion_descriptor ep_comp)
int libusb_get_bos_descriptor (libusb_device_handle dev_handle, struct libusb_bos_descriptor **bos)
void libusb_free_bos_descriptor (struct libusb_bos_descriptor bos)
int
libusb_get_usb_2_0_extension_descriptor (struct libusb_context ctx,
struct libusb_bos_dev_capability_descriptor dev_cap, struct
libusb_usb_2_0_extension_descriptor usb_2_0_extension)
void libusb_free_usb_2_0_extension_descriptor (struct libusb_usb_2_0_extension_descriptor usb_2_0_extension)
int
libusb_get_ss_usb_device_capability_descriptor (struct libusb_context
ctx, struct libusb_bos_dev_capability_descriptor *dev_cap, struct
libusb_ss_usb_device_capability_descriptor ss_usb_device_cap)
void libusb_free_ss_usb_device_capability_descriptor (struct libusb_ss_usb_device_capability_descriptor ss_usb_device_cap)
int
libusb_get_container_id_descriptor (struct libusb_context ctx, struct
libusb_bos_dev_capability_descriptor dev_cap, struct
libusb_container_id_descriptor **container_id)
void libusb_free_container_id_descriptor (struct libusb_container_id_descriptor container_id)
int libusb_get_string_descriptor_ascii (libusb_device_handle dev_handle, uint8_t desc_index, unsigned char data, int length)
static
int libusb_get_descriptor (libusb_device_handle dev_handle, uint8_t
desc_type, uint8_t desc_index, unsigned char data, int length)
static
int libusb_get_string_descriptor (libusb_device_handle dev_handle,
uint8_t desc_index, uint16_t langid, unsigned char data, int length)
5 设备热插拔事件通知
5.1 宏定义
LIBUSB_HOTPLUG_MATCH_ANY
5.2 Typedefs
typedef int libusb_hotplug_callback_handle
typedef
int( libusb_hotplug_callback_fn) (libusb_context ctx, libusb_device
device, libusb_hotplug_event event, void user_data)
5.3 枚举
5.3.1 libusb_hotplug_flag
5.3.2 libusb_hotplug_event
5.4 函数
int
libusb_hotplug_register_callback(libusb_context ctx,
libusb_hotplug_event events, libusb_hotplug_flag flags, int vendor_id,
int product_id, int dev_class, libusb_hotplug_callback_fn cb_fn, void
user_data, libusb_hotplug_callback_handle callback_handle)
void libusb_hotplug_deregister_callback (libusb_context ctx, libusb_hotplug_callback_handle callback_handle)
6 异步设备I/O
Transfer Abstraction(传输的抽象)
6.1 数据结构
struct libusb_control_setup
struct libusb_iso_packet_descriptor
struct libusb_transfer
6.2 Typedefs
typedef void( libusb_transfer_cb_fn) (struct libusb_transfer transfer)
6.3 枚举
enum libusb_transfer_status
enum libusb_transfer_flags
6.4 函数
7 轮询和定时器
8 同步设备I/O
8.1 函数
int libusb_control_transfer
int libusb_bulk_transfer
int libusb_interrupt_transfer
1. 库初始化/取消初始化
此部分将会详细描述如何libusb初始化和取消初始化。初始化函数必须在使用其他任一libusb函数之前执行,相同的,任何libusb函数不能在执行取消初始化函数之后调用。
1.1 数据结构
// lisbusb版本信息
struct libusb_version
1
2
1.2 类型定义
typedef struct libusb_context libusb_context
libusb_context对象代表一个会话,两个独立的libusb_context可以独立的使用libusb库。两个libusb_context直接不会互相影响。
libusb_context由libusb_init()函数创建,由libusb_exit()释放。如果程序保证只由一个libusb用户,在需要传入libusb_context对象为参数的函数中赋值为NULL,将会使用默认的libusb_context。
1.3 枚举
enum libusb_log_level
libusb日志输出等级枚举
enum libusb_log_level {
LIBUSB_LOG_LEVEL_NONE = 0, // 不输出日志
LIBUSB_LOG_LEVEL_ERROR = 1, // 只输出error日志到stderr
LIBUSB_LOG_LEVEL_WARNING = 2, // 输出warning等级及以上日志(warning/error)到stderr
LIBUSB_LOG_LEVEL_INFO = 3, // 输出info/warning/error日志到stderr
LIBUSB_LOG_LEVEL_DEBUG =4 // 输出全部等级日志到stderr
}
enum libusb_option
libusb操作枚举
enum libusb_option {
LIBUSB_OPTION_LOG_LEVEL,
LIBUSB_OPTION_USE_USBDK
}
libusb_option是libusb_set_option()可用的选项值
LIBUSB_OPTION_LOG_LEVEL
设置日志输出等级,默认等级是LIBUSB_LOG_LEVEL_NONE,如果要提高日志输出等级,请确定应用程序的stderr输出文件描述符没有关闭。
建议使用LIBUSB_LOG_LEVEL_WARNING,libusb在大多数时候对日志的输出都是很保守的,只有在出现错误或者其他奇怪的情况才会输出日志。
如果在libusb初始化后设置了LIBUSB_DEBUG环境变量,再设置LIBUSB_OPTION_LOG_LEVEL将不会生效。
如果libusb被编译成不打印任何日志,此函数也将无效,将不会由任何日志输出。
如果libusb被编译成打印debug日志,此函数也不会生肖,所有等级的日志都将会被输出。
LIBUSB_OPTION_USE_USBDK
此选项必须在调用libusb_init()之后立即设置,否则可能不会生效。此选项只在Windows上有效。
1.4 函数/功能/方法
void libusb_set_debug(libusb_context ctx,int level)
推荐libusb_set_option()使用LIBUSB_OPTION_LOG_LEVEL选项替代libusb_set_debug。
int libusb_set_option(libusb_context ctx,enum libusb_option option,…)
设置库选项,使用此函数配置库的指定选项,有些选项需要提供一个或多个参数,详细参数要求请参考指定选项的文档。
在1.0.22,LIBUSB_API_VERSION >=0x01000106版本以后:
参数:
ctx 需要操作的libusb_context会话
option 需要设置的选项
… 指定选项需要的参数
返回值:
LIBUSB_SUCCESS 操作成功
LIBUSB_ERROR_INVALID_PARAM 非法参数,参数无效
LIBUSB_ERROR_NOT_SUPPORTED 选项合法,但是此平台不支持
int libusb_init(libusb_context context)
初始化libusb,此函数必须在调用其他任何函数之前调用。如果参数context为NULL,将会创建一个默认的context。如果已经存在一个默认的context,调用此函数将不会创建新的默认context,而是复用此默认context。
参数:
context 可选的输出参数,返回值为0时有效。
返回值:
0 成功;其他 失败,参考LIBUSB_ERROR代码
void libusb_exit(struct libusb_context *ctx)
libusb取消初始化
在程序终止之前需调用此函数关闭所有打开的设备。
参数:
ctx 取消初始化的会话,默认的context为NULL
2. 设备处理和枚举
功能:
枚举当前连接到系统的USB设备
选择软件需要操作的设备
打开和关闭选中的设备
接下来的描述确实使事情听起来比实际上更复杂。以下的函数调用顺序将会适合几乎所有的场景,而且不需要你对资源管理策略有很深入的了解。
// 发现设备
libusb_device list;
libusb_device found =NULL;
ssize_t cnt = libusb_get_device_list(NULL,&list);
ssize_t i = 0;
int err = 0;
if (cnt < 0)
error();
for (i = 0; i < cnt; i++) {
libusb_device device = list【i】;
if (is_interesting(device)) {
found = device;
break;
}
}
if (found) {
libusb_device_handle handle;
err = libusb_open(found, &handle);
if(err)
error();
// ...
}
libusb_free_device_list(list, 1);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
有两个重点:
- 调用libusb_free_device_list()解除设备引用
- 需要在释放设备列表并且解除设备引用之前打开设备
1
2
如果最后获取到了一个设备句柄,你可以继续执行设备I/O。
设备和设备句柄
libusb有一个USB设备的概念,由libusb_device表示一个不透明的概念。device代表一个当前或之前与系统建立连接的USB设备。使用对设备的引用,你可以确定某些关于device的信息(例如:可以读取设备描述信息)。
libusb_get_device_list()函数可以用于获取当前连接到系统的设备列表,这被称为设备发现。
仅仅有设备的引用不意味着设备一定可用。设备可能移除、你可能没有权限操作此设备,或者其他程序或其他正在使用此设备。
当你找到一个你想要操作的设备,你必须使用libusb_open()函数请求libusb打开设备。假设打开成功,libusb将会返回一个设备句柄(libusb_device_handle 指针)。所有真实I/O操作都是在句柄上而不是原始设备指针。
设备发现和引用计数
设备发现(调用libusb_get_device_list())返回一个新分配的设备列表。当你使用完设备列表后必须释放掉。libusb也需要知道什么时候可以释放设备列表。
为了处理这个问题,libusb提供两个独立的选项:
- 释放设备列表的函数
- 设备内置的引用计数系统
1
2
所有libusb_get_device_list()函数列出的新设备的引用计数值都是1。你可以使用libusb_ref_device()和libusb_unref_device()增加或减少引用计数。当设备的引用计数为0时将会被销毁。
根据以上信息,打开设备的过程如下:
使用libusb_get_device_list()发现设备
调用libusb_open()选中想要操作的设备
解除所有被发现的设备列表中的设备
释放被发现的设备列表
顺序非常重要,一定不能在打开设备之前解除引用,因为解除引用后将会释放设备。
libusb_free_device_list()函数包含一个可选的参数解除所有在设备列表中的设备引用,这结合了上面的步骤3和4.
libusb_open()实际上增加了对设备的引用。设备通过libusb_get_device()获得句柄保持可用。在libusb_close()时删除引用。
2.1 类型定义
typedef struct libusb_device libusb_device
表示在系统中检测到的USB设备。这是一个不透明的类型,通常是从libusb_get_device_list()获得的一个指针。
设备可以执行一些操作,但是必须使用libusb_open()获取到设备句柄后才能执行I/O。
设备使用libusb_ref_device()和libusb_unref_device()计算引用,当引用计数为0时被释放。由libusb_get_device_list()获取到的新设备引用计数为1,libusb_free_device_list()可选的减少设备列表中设备的引用计数。libusb_open()也会增加引用,需要libusb_close()来销毁。
typedef struct libusb_device_handle libusb_device_handle
表示USB设备句柄。从libusb_open()获得的不透明类型指针。设备句柄用于执行I/O和其他操作。执行完后需要调用libusb_close()释放。
2.2 枚举
enum libusb_speed
USB设备速度代码。指示设备的运行速度。
Enumerator
LIBUSB_SPEED_UNKNOWN
LIBUSB_SPEED_LOW
LIBUSB_SPEED_FULL
LIBUSB_SPEED_HIGH
LIBUSB_SPEED_SUPER
LIBUSB_SPEED_SUPER_PLUS
2.3 函数
ssize_t libusb_get_device_list(libusb_context ctx , libusb_device list)
获取当前连接到系统的USB设备,这是查找目标设备的入口。
执行完此函数后,你需要解除所有设备的引用,然后使用libusb_free_device_list()释放list设备列表。一定要在打开你需要的设备后再解除所有设备引用。
参数:
ctx
list 输出的设备列表,需要调用libusb_free_device_list()释放
返回值:
获取到的设备数,或libusb_error错误代码
void libusb_free_device_list(libusb_device list , int unref_devices)
释放libusb_get_device_list()获取到的设备。如果设置了unref_devices参数,列表中的每一个设备的引用计数都将减1.
参数:
list 需要释放的设备列表
unref_devices 是否释放列表中的设备
uint8_t libusb_get_bus_number( libusb_device dev)
获取设备连接的总线编号。
参数:
dev 设备
返回值:
总线编号
uint8_t libusb_get_port_number ( libusb_device dev )
获取设备连接的端口号。
参数:
dev 设备
返回值:
端口号(0 设备不可用)
int libusb_get_port_numbers (libusb_device dev,uint8_t port_numbers,int ort_numbers_len )
从root获取指定设备的所有端口号。
自版本1.0.16,LIBUSB_API_VERSION >= 0x01000102
参数:
dev 设备
port_numbers 端口号列表
port_numbers_len 最大序列长度,USB 3.0最大深度限制为7
返回值:
端口号个数,或者 LIBUSB_ERROR_OVERFLOW
libusb_device libusb_get_parent (libusb_device dev )
获取指定设备的父级设备。
必须在调用libusb_get_device_list()之后调用此方法,且在调用libusb_free_device_list()之前访问父级设备。
uint8_t libusb_get_device_address(libusb_device dev )
获取指定设备在总线上的地址。
int libusb_get_device_speed (libusb_device dev )
获取设备协商的连接速度。
int libusb_get_max_packet_size(libusb_device dev,unsigned char endpoint )
用于获取设备指定端点的wMaxPacketSize值。
int libusb_get_max_iso_packet_size(libusb_device dev,unsigned char endpoint )
获取设备指定端点一帧的封包大小最大值。
libusb_device libusb_ref_device( libusb_device dev)
增加设备引用计数。
void libusb_unref_device(libusb_device dev)
减少设备引用计数,当引用计数为0则销毁设备。
int libusb_open (libusb_device dev, libusb_device_handle * dev_handle )
打开设备并获取设备句柄。
libusb_device_handle libusb_open_device_with_vid_pid(libusb_context ctx,uint16_t vendor_id,uint16_t product_id )
通过pid和vid打开设备,并得到设备句柄。
void libusb_close(libusb_device_handle dev_handle)
关闭设备句柄,在程序关闭之前必须调用此函数关闭所有打开的设备。此函数将会销毁libusb_open()获取的设备引用。
非阻塞函数。
libusb_device libusb_get_device (libusb_device_handle dev_handle)
通过设备句柄获取底层设备。
int libusb_get_configuration(libusb_device_handle dev_handle,int config )
获取设备的bConfigurationValue 值。
int libusb_set_configuration(libusb_device_handle dev_handle,int configuration)
激活一个USB配置,在声明接口和执行操作之前,确认激活的是正确的usb配置。
如果你选的配置已经在设备上激活,此调用将会是一个轻量级的操作,重置相关usb设备的状态。
或者你可以先调用libusb_release_interface(),记住如果你这样做请确保dev的auto_detach_kernel_driver值为0,否则在你释放接口(interface)时,内核驱动将会重新附加。
如果其他应用程序或驱动声明了接口,你不能更改或重置usb设备配置。
你应该使这个函数而不是使用自己定义的SET_CONFIGURATION来控制请求。因为底层操作系统需要指定合适发生了改变。
这是一个阻塞的函数。
参数:
~~
dev_handle 设备句柄
~~
configuration 想要激活的配置的值,或-1(设为未配置状态)
返回值:
~~
0 成功
~~
LIBUSB_ERROR_NOT_FOUND 配置不存在
~~
LIBUSB_ERROR_BUSY 已经声明接口
~~
LIBUSB_ERROR_NO_DEVICE 设备断开连接
~~
其他LIBUSB_ERROR代码
int libusb_claim_interface(libusb_device_handle dev_handle,int interface_number)
在给定设备句柄上声明接口。
在操作I/O或其他端点的时候必须先声明接口。
声明已经声明的接口时合法的,函数会返回0但不做任何操作。
如果dev设置auto_detach_kernel_driver值为1,如果有必要内核驱动将会被分离//代码效果参考:http://hnjlyzjd.com/hw/wz_25142.html
,如果分离失败会返回error。声明接口时一个单纯的逻辑操作;不会通过总线发送任何请求。接口声明用于告知底层操作系统你的程序想要取得此接口的所有权。
这是一个非阻塞的函数。
参数:
~~
dev_handle 设备句柄
~~
interface_number 想要声明的接口号bInterfaceNumber
返回值:
~~
0 成功
~~
LIBUSB_ERROR_NOT_FOUND 接口不存在
~~
LIBUSB_ERROR_BUSY 接口忙,被其他程序或驱动声明
~~
LIBUSB_ERROR_NO_DEVICE 设备断开连接
~~
LIBUSB_ERROR 失败
int libusb_release_interface (libusb_device_handle * dev_handle,int interface_number)<button class="cnblogs-to