這里先記錄一點usb的基礎知識:
USB HOST(主機)、USB HID(usb設備)
主機通過各種描述符來識別設備,有設備描述符,配置描述符,接口描述符,端點描述符,字符描述符,報告描述符等。USB描述符就像是USB的“身份證”一樣,詳細記錄這外圍設備的相關的一切信息。
usb設備是通過
設備描述符層級:設備(device)->配置(configuration)->接口(interface)->(設置)->端點(endpoint)
一個設備有一個設備描述符,多個配置描述符,一個配置有多個接口描述符,一個接口有多個端點描述符。
設備就是指usb設備;配置可以理解成高速設備還是低速設備;接口就是接的是USB存儲設備還是USB視頻設備。
一般USB HID可能提供一種或多種配置(例如高速、低速),由USB Host選擇一個支持的配置才能使設備正常工作,這些配置對設備可執行的操作是相互排斥的;USB HID以一系列接口的形式公開其功能(例如音頻接口、鍵盤接口、旋鈕接口);每個接口包含一個或多個備用設置,默認情況下,選擇某個配置會激活該配置中每個接口的首個備用配置;每個備用設置由一組端點組成,USB HID和USB Host實際是由端點進行通信的,每個端點獨立的完成I | O請求,通常情況一個端點只負責I或O,一個端點組成一個I/O管道。
參考:
MSDN - 選擇 USB 驅動程序中的 USB 配置
文章目錄
- 1. 庫初始化/取消初始化
- 2. 設備處理和枚舉
- 2.1 類型定義
- 2.2 枚舉
- 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 宏定義
- 3.2 枚舉
- 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 變量
- 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 宏定義
- 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.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
- 7 輪詢和定時器
- 8 同步設備I/O
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,如果有必要內核驅動將會被分離,如果分離失敗會返回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)
釋放libusb_claim_interface()聲明的接口。
在關閉設備句柄前應該釋放所有聲明的接口。
函數將會發送一個SET_INTERFACE控制請求給設備,為第一備用設置重置接口狀態。
此函數是阻塞函數。
如果dev的auto_detach_kernel_driver設置為1,當接口被釋放后內核將會被自動附加。
參數:
~~ dev_handle 設備句柄
~~ interface_number 之前聲明的接口號bInterfaceNumber
返回值:
~~ 0 成功
~~ LIBUSB_ERROR_NOT_FOUND 接口未聲明
~~ LIBUSB_ERROR_NO_DEVICE 設備斷開連接
~~ LIBUSB_ERROR 失敗,參考LIBUSB_ERROR 代碼
int libusb_set_interface_alt_setting(libusb_device_handle * dev_handle,int interface_number,int alternate_setting)
激活/更改接口備用設置。
一個接口實現功能,需要一個相應的驅動;而一個接口有一個或多個備用設置;一個設置對應多個端點,每個端點互相獨立的完成一個輸入或輸出的與Host之間的管道通信;在配置設備的時候將會選擇對應的默認備用設置。
使用此函數前需調用libusb_claim_interface()聲明接口。
應該使用此函數,而不是定制自己的SET_INTERFACE控制請求去更改接口備用設置。因為底層操作系統需要指定聲明時候發送了改變。
這是一個阻塞函數。
參數:
~~ dev_handle 設備句柄
~~ interface_number 之前已聲明的接口編號
~~ 需要激活的備用設置bAlternateSetting
返回值:
~~ 0 成功
~~ LIBUSB_ERROR_NOT_FOUND 接口未聲明
~~ LIBUSB_ERROR_NO_DEVICE 設備斷開連接
~~ LIBUSB_ERROR 失敗,參考LIBUSB_ERROR 代碼
int libusb_clear_halt(libusb_device_handle * dev_handle,unsigned char endpoint)
清除端點的暫停條件。
int libusb_reset_device(libusb_device_handle * dev_handle)
重新初始化USB設備。
int libusb_kernel_driver_active(libusb_device_handle * dev_handle,int interface_number)
確認接口的內核驅動是否處於活躍狀態。
如果接口的內核驅動處於活躍狀態,你不能聲明此接口,也不能執行設備I/O。
此函數再Windows上不可用。
int libusb_detach_kernel_driver(libusb_device_handle * dev_handle,int interface_number)
detach/attach應該如何理解?暫時沒搞懂,先這樣把,等我懂了再詳細寫一下。
從接口卸載內核驅動(接口變為可用狀態?)。
如果成功,你可以聲明接口並執行I/O操作。
此函數在Darwin和Windows上不可用。
注意,libusb自身也通過特殊的內核驅動與設備通信,若此時驅動程序已經連接到設備,調用此函數將不會分離接口並返回LIBUSB_ERROR_NOT_FOUND的錯誤。
int libusb_attach_kernel_driver(libusb_device_handle * dev_handle,int interface_number)
掛載接口內核驅動。
此函數只在Linux上有效,在其他平台上將會返回LIBUSB_ERROR_NOT_SUPPORT的錯誤。
此函數在Darwin和Windows上不可用。
int libusb_set_auto_detach_kernel_driver(libusb_device_handle * dev_handle,int enable)
libusb內核驅動自動卸載使能。
啟用后,聲明接口時內核驅動將會自動卸載;釋放接口后會自動附加。
新打開的設備默認停用內核驅動自動卸載。
3. 雜項
3.1 宏定義
#define LIBUSB_CALL
libusb在windows下的調用約定(calling convention,在生成的匯編代碼中給函數傳遞參數的方式)。
為了匹配Windows API,libusb使用WINAPI約定(stdcall)。公開的頭文件也包含了適當的注釋,所以你的軟件將可以使用正確的約定,即使在你的代碼庫中使用了其他的約定。
需要注意的是所有的libusb回調函數也需要標記未LIBUSB_CALL,使得這些函數可以被正確編譯。
非windows操作系統下,這個宏被定義為空,所以在跨平台時不需要擔心LIBUSB_CALL。
#define LIBUSB_API_VERSION
libusb api版本號(0x01000106),從1.0.13開始,用於檢測不同版本的特性。
#define libusb_le16_to_cpu libusb_cpu_to_le16
將16-bit值從小端字節序轉換為主機字節序格式。
若主機字節序為小端模式,則什么都不做;若為大端字節序,則交換byte。
3.2 枚舉
libusb_standard_request
在USB3.0協議【表9-5】中定義的標准請求。
枚舉 |
---|
LIBUSB_REQUEST_GET_STATUS |
LIBUSB_REQUEST_CLEAR_FEATURE |
LIBUSB_REQUEST_SET_FEATURE |
LIBUSB_REQUEST_SET_ADDRESS |
LIBUSB_REQUEST_GET_DESCRIPTOR |
LIBUSB_REQUEST_SET_DESCRIPTOR |
LIBUSB_REQUEST_GET_CONFIGURATION |
LIBUSB_REQUEST_SET_CONFIGURATION |
LIBUSB_REQUEST_GET_INTERFACE |
LIBUSB_REQUEST_SET_INTERFACE |
LIBUSB_REQUEST_SYNCH_FRAME |
LIBUSB_REQUEST_SET_SEL |
LIBUSB_REQUEST_ISOCH_DELAY |
libusb_request_type
請求類型,控制傳輸
Enumerator |
---|
LIBUSB_REQUEST_TYPE_STANDARD |
LIBUSB_REQUEST_TYPE_CLASS |
LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_REQUEST_TYPE_RESERVED |
libusb_request_recipient
請求的接收者
Enumerator |
---|
LIBUSB_RECIPIENT_DEVICE |
LIBUSB_RECIPIENT_INTERFACE |
LIBUSB_RECIPIENT_ENDPOINT |
LIBUSB_RECIPIENT_OTHER |
libusb_error
錯誤代碼
大部分得libusb函數返回值0代表成功,其他失敗值參考錯誤代碼。也可以調用libusb_error_name()/libusb_strerror()獲取錯誤代碼的字符串含義。
Enumerator |
---|
LIBUSB_SUCCESS |
LIBUSB_ERROR_IO |
LIBUSB_ERROR_INVALID_PARAM |
LIBUSB_ERROR_ACCESS |
LIBUSB_ERROR_NO_DEVICE |
LIBUSB_ERROR_NOT_FOUND |
LIBUSB_ERROR_BUSY |
LIBUSB_ERROR_TIMEOUT |
LIBUSB_ERROR_OVERFLOW |
LIBUSB_ERROR_PIPE |
LIBUSB_ERROR_INTERRUPTED |
LIBUSB_ERROR_NO_MEM |
LIBUSB_ERROR_NOT_SUPPORTED |
LIBUSB_ERROR_OTHER |
libusb_capability
當前系統運行的libusb實例的支持能力。
調用libusb_has_capability()來測試加載的庫是否支持給定的功能。
Enumerator |
---|
LIBUSB_CAP_HAS_CAPABILITY |
LIBUSB_CAP_HAS_HOTPLUG |
LIBUSB_CAP_HAS_HID_ACCESS |
LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER |
3.3 函數
int libusb_has_capability(uint32_t capability)
確認加載的庫是否支持給定的功能。
此函數需再libusb_init()只后執行。
參數:
libusb_capability 的枚舉
返回值:
非0支持,0 不支持
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)
將16bit值從主機的字節序模式轉換為小端模式。
int libusb_setlocale (const char *locale)
語言設置。
如果沒有調用libusb_set_locale(),所有的信息都是英文。
const char * libusb_strerror(enum libusb_error errcode)
獲取錯誤描述。
3.4 變量
static const char * usbi_locale_supported [] = { “en”, “nl”, “fr”, “ru” }
libusb(錯誤描述)支持的語言。
如何添加新的libusb_strerror()翻譯:
- 下載最新的strerror.c(下載libusb源碼,libusb/strerror.c)
- 用支持UTF-8的編輯器打開
- 在usbi_locale_supported[]末尾添加兩個字沒的ISO 639-1代碼,中文添加“zh”:
// 原始
usbi_locale_supported[] = { "en", "nl", "fr" };
// 添加zh
usbi_locale_supported[] = { "en", "nl", "fr", "zh" };
- 1
- 2
- 3
- 4
- 拷貝usbi_localized_errors下的{/* English (en) * / … }節放到最后,修改為
{ /* English (en) */
"Success",
"Input/Output Error",
"Invalid parameter",
"Access denied (insufficient permissions)",
"No such device (it may have been disconnected)",
"Entity not found",
"Resource busy",
"Operation timed out",
"Overflow",
"Pipe error",
"System call interrupted (perhaps due to signal)",
"Insufficient memory",
"Operation not supported or unimplemented on this platform",
"Other error",
},
...
{ /* Chinese (zh) */
"成功",
"I/O錯誤",
"非法參數",
"拒絕訪問 Access denied (insufficient permissions)",
"No such device (it may have been disconnected)",
"Entity not found",
"Resource busy",
"Operation timed out",
"Overflow",
"Pipe error",
"System call interrupted (perhaps due to signal)",
"Insufficient memory",
"Operation not supported or unimplemented on this platform",
"Other error",
},
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 對照英文逐條翻譯
- 保存文件為UTF-8格式。(發送至libusb-devel@lists.sourceforge.net)
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_class_code {
LIBUSB_CLASS_PER_INTERFACE = 0, LIBUSB_CLASS_AUDIO = 1, LIBUSB_CLASS_COMM = 2, LIBUSB_CLASS_HID = 3,
LIBUSB_CLASS_PHYSICAL = 5, LIBUSB_CLASS_PRINTER = 7, LIBUSB_CLASS_PTP = 6, LIBUSB_CLASS_IMAGE = 6,
LIBUSB_CLASS_MASS_STORAGE = 8, LIBUSB_CLASS_HUB = 9, LIBUSB_CLASS_DATA = 10, LIBUSB_CLASS_SMART_CARD = 0x0b,
LIBUSB_CLASS_CONTENT_SECURITY = 0x0d, LIBUSB_CLASS_VIDEO = 0x0e, LIBUSB_CLASS_PERSONAL_HEALTHCARE = 0x0f, LIBUSB_CLASS_DIAGNOSTIC_DEVICE = 0xdc,
LIBUSB_CLASS_WIRELESS = 0xe0, LIBUSB_CLASS_APPLICATION = 0xfe, LIBUSB_CLASS_VENDOR_SPEC = 0xff
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
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)
Get the USB device descriptor for a given device. More...
- 1
int libusb_get_active_config_descriptor (libusb_device *dev, struct libusb_config_descriptor **config)
Get the USB configuration descriptor for the currently active configuration. More...
- 1
int libusb_get_config_descriptor (libusb_device *dev, uint8_t config_index, struct libusb_config_descriptor **config)
Get a USB configuration descriptor based on its index. More...
- 1
int libusb_get_config_descriptor_by_value (libusb_device *dev, uint8_t bConfigurationValue, struct libusb_config_descriptor **config)
Get a USB configuration descriptor with a specific bConfigurationValue. More...
- 1
void libusb_free_config_descriptor (struct libusb_config_descriptor *config)
Free a configuration descriptor obtained from libusb_get_active_config_descriptor() or libusb_get_config_descriptor(). More...
- 1
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)
Get an endpoints superspeed endpoint companion descriptor (if any) More...
- 1
void libusb_free_ss_endpoint_companion_descriptor (struct libusb_ss_endpoint_companion_descriptor *ep_comp)
Free a superspeed endpoint companion descriptor obtained from libusb_get_ss_endpoint_companion_descriptor(). More...
- 1
int libusb_get_bos_descriptor (libusb_device_handle *dev_handle, struct libusb_bos_descriptor **bos)
Get a Binary Object Store (BOS) descriptor This is a BLOCKING function, which will send requests to the device. More...
- 1
void libusb_free_bos_descriptor (struct libusb_bos_descriptor *bos)
Free a BOS descriptor obtained from libusb_get_bos_descriptor(). More...
- 1
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)
Get an USB 2.0 Extension descriptor. More...
- 1
void libusb_free_usb_2_0_extension_descriptor (struct libusb_usb_2_0_extension_descriptor *usb_2_0_extension)
Free a USB 2.0 Extension descriptor obtained from libusb_get_usb_2_0_extension_descriptor(). More...
- 1
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)
Get a SuperSpeed USB Device Capability descriptor. More...
- 1
void libusb_free_ss_usb_device_capability_descriptor (struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_cap)
Free a SuperSpeed USB Device Capability descriptor obtained from libusb_get_ss_usb_device_capability_descriptor(). More...
- 1
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)
Get a Container ID descriptor. More...
- 1
void libusb_free_container_id_descriptor (struct libusb_container_id_descriptor *container_id)
Free a Container ID descriptor obtained from libusb_get_container_id_descriptor(). More...
- 1
int libusb_get_string_descriptor_ascii (libusb_device_handle *dev_handle, uint8_t desc_index, unsigned char *data, int length)
Retrieve a string descriptor in C style ASCII. More...
- 1
static int libusb_get_descriptor (libusb_device_handle *dev_handle, uint8_t desc_type, uint8_t desc_index, unsigned char *data, int length)
Retrieve a descriptor from the default control pipe. More...
- 1
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
LIBUSB_HOTPLUG_MATCH_ANY -1
熱插拔時間通配符。
5.2 Typedefs
typedef int libusb_hotplug_callback_handle
回調句柄。
libusb_hotplug_register_callback()生成的回調句柄,可用於注銷回調。在每一個libusb_context上回調句柄都是唯一的,在已經注銷的回調上調用libusb_hotplug_deregister_callback()是安全的。
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
此章節將詳細描述libusb的異步(非阻塞)操作USB設備I/O的接口。
此章節描述的接口都非常強大,但是也相當復雜。簡單的應用可以考慮使用同步I/O接口。
異步接口圍繞着分離傳輸提交和處理傳輸完成的想法來創建的(同步模式將兩者合一)。在提交和完成之間可能需要很長的時間,然而異步提交函數是非阻塞的,因此會在可能的長時間延遲期間將控制返回到你的應用程序。
Transfer Abstraction(傳輸的抽象)
在異步I/O中,libusb為所有的I/O類型(控制、)實現了通用的傳輸實體概念。
6.1 數據結構
struct libusb_control_setup
用於控制傳輸的設置封包。
struct libusb_iso_packet_descriptor
同步包描述符。
struct libusb_transfer
通用的USB傳輸結構體。
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
此章節描述了libusb同步(阻塞)操作usb設備I/O的接口。
此章節的接口都非常簡單,但是有一些限制。更高級的用戶可以考慮使用異步I/O API。
8.1 函數
int libusb_control_transfer
控制usb傳輸。
從bmRequestType參數推斷傳輸的方向。
wValue,wIndex和wLength參數值需要根據CPU字節序給出。
int libusb_control_transfer ( libusb_device_handle * dev_handle,
uint8_t bmRequestType,
uint8_t bRequest,
uint16_t wValue,
uint16_t wIndex,
unsigned char * data,
uint16_t wLength,
unsigned int timeout
)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
參數:
dev_handle 設備句柄
bmRequestType 數據包傳輸的請求類型
bRequest 數據包的請求字段
wValue 數據包的值
wIndex 數據包的索引
data 合適大小的data buffer,不管是輸入還是輸出(方向根據bmRequestType確定)
wLength data的長度必須不小於此值
timeout 毫秒,I/O超時時間,0:無超時限制
返回值:
成功,返回實際傳輸的字節數
LIBUSB_ERROR_TIMEOUT 傳輸超時
LIBUSB_ERROR_PIPE 設備不支持此請求類型(bRequest)
LIBUSB_ERROR_NO_DEVICE 設備斷開連接
LIBUSB_ERROR_BUSY 設備忙
LIBUSB_ERROR_INVALID_PARAM 非法參數
another LIBUSB_ERROR 參考其他error代碼
int libusb_bulk_transfer
執行usb數據批量傳輸。
傳輸方向從endpoint地址中的direction比特推斷。
批量讀時,length字段表明期望接收的最大的data長度。如果data中收到的數據比期望的少,函數將會返回data數據,務必檢查transferred參數。
在處理超時錯誤時也要檢查transferred參數。libusb可能需要將傳輸的數據分成多個塊以滿足O/S的要求,這意味着在前幾塊完成后有可能超時。小心不要丟失任何可能已經傳輸的數據,不要認為發生超時就表明完全沒有I/O。
int libusb_bulk_transfer ( struct libusb_device_handle * dev_handle,
unsigned char endpoint,
unsigned char * data,
int length,
int * transferred,
unsigned int timeout
)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
參數:
dev_handle 設備句柄
endpoint 合法的通信地址
data 合適大小的輸出/輸出data buffer
length 寫,data長度;讀,data可接收的最大長度
transferred 實際傳輸的比特數量;1.0.21版本以后如果不想接收此信息,允許傳入NULL值
timeout 毫秒,超時時間,0 無限制
返回值:
0 成功(transferred有值)
LIBUSB_ERROR_TIMEOUT 超時(transferred有值)
LIBUSB_ERROR_PIPE endpoint停止
LIBUSB_ERROR_OVERFLOW 數據溢出
LIBUSB_ERROR_NO_DEVICE 設備斷開連接
LIBUSB_ERROR_BUSY 設備忙
其他LIBUSB_ERROR代碼
int libusb_interrupt_transfer
執行usb中斷傳輸。(中斷該如何理解???)
傳輸方向從endpoint地址中的direction比特推斷。
中斷讀,length字段表明期望接收的最大的data長度。如果data中收到的數據比期望的少,函數將會返回data數據,務必檢查transferred參數。
中斷寫,需要檢查transferred參數,可能並不是所有的數據都會被寫入。
處理超時錯誤時需要檢查transferred,libusb可能需要將傳輸的數據分成多個塊以滿足O/S的要求,這意味着在前幾塊完成后有可能超時。小心不要丟失任何可能已經傳輸的數據,不要認為發生超時就表明完全沒有I/O。
默認的endpoint bInterval值被認為是輪詢間隔。
int libusb_interrupt_transfer ( struct libusb_device_handle * dev_handle,
unsigned char endpoint,
unsigned char * data,
int length,
int * transferred,
unsigned int timeout
)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
參數:
dev_handle 設備句柄
endpoint 合法的通信地址
data 合適大小的輸出/輸出data buffer
length 寫,data長度;讀,data可接收的最大長度
transferred 實際傳輸的比特數量;1.0.21版本以后如果不想接收此信息,允許傳入NULL值
timeout 毫秒,超時時間,0 無限制
返回值:
0 成功(transferred有值)
LIBUSB_ERROR_TIMEOUT 超時(transferred有值)
LIBUSB_ERROR_PIPE endpoint停止
LIBUSB_ERROR_OVERFLOW 數據溢出
LIBUSB_ERROR_NO_DEVICE 設備斷開連接
LIBUSB_ERROR_BUSY 設備忙
其他LIBUSB_ERROR代碼