本文檔描述libusb的API,以及如何開發USB應用。
1 介紹
1.1 概覽
本文檔描述libusb-0.1的API和USB相關內容。
1.2 當前OS支持
Linux 2.2或以上
FreeBSD/NetBSD/OpenBSD
Darwin/MacOSX
2 API
2.1 設備與接口
一個設備可能有多個接口,所以一個句柄可以返回多個接口實例。不要忘記調用 usb_claim_interface() 。
2.2 超時
總是以毫秒為單位。
2.3 數據類型
同時使用有抽象結構和非抽象結構來保持可移植性。
2.4 同步
所有libusb v0.1的函數都是同步的,這意味著操作完成或超時前不會返回。異步操作從libusb v1.0開始支持。
2.5 返回值
libusb v0.1有兩種返回值。一種是 usb_open() 返回的句柄,另一種是整數int,返回負數表示錯誤。
3 函數
3.1 核心函數
void usb_init(void);
初始化libusb。
int usb_find_busses(void);
查找所有總線,返回上次調用以後改變的數量(包括新增的和移除的總線)。
int usb_find_devices(void);
尋找每個總線上的所有設備。應該在 usb_find_busses() 之後調用。返回上次調用後改變的數量(包括新增和移除的設備)。
struct usb_bus *usb_get_busses(void);
簡單的返回全局變量 usb_busses 。這僅對支持C調用規范和可以使用共享庫的語言,但是不支持C全局變量的(例如Delphi)。
3.2 設備操作
這組函數用於操作設備。允許你打開關閉設備,設置配置、輪換設置、干淨的關閉和重置設備。它也提供OS級別的操作,如認領(claim)和釋放接 口。
usb_dev_handle *usb_open(struct *usb_device dev);
打開設備以供使用,返回設備句柄。
int usb_close(usb_dev_handle *dev);
關閉設備,返回0成功,負數失敗。
int usb_set_configuration(usb_dev_handle *dev, int configuration);
設置活躍配置。configuration參數是描述符bConfigurationValue字段的值。返回0成功,負數失敗。
int usb_set_altinterface(usb_dev_handle *dev, int alternate);
設置當前接口的活躍輪換設置。alternate參數是描述符bAlternateSetting字段的值。返回0成功,負數失敗。
int usb_resetep(usb_dev_handle *dev, unsigned int ep);
重置指定端點的所有狀態。ep參數是描述符的bEndpointAddress字段的值。返回0稱公,負數失敗。
該接口不建議使用,你可能需要的是 usb_clear_halt() 。
int usb_clear_halt(usb_dev_handle *dev, unsigned int ep);
清理端點所有停止狀態,ep是描述符bEndpointAddress字段的值。返回0成功,負數失敗。
int usb_reset(usb_dev_handle *dev);
重置指定設備,通過發送RESET指令過去。返回0成功,負數失敗。
在執行該函數之後,需要重新列舉,找到設備。當前的句柄無法再工作了。
int usb_claim_interface(usb_dev_handle *dev, int interface);
通過OS認領一個接口。interface參數是描述符的bInterfaceNumber字段。返回0成功,負數失敗。
必須在任何接口相關操作(如 usb_set_altinterface() 、 usb_bulk_write() 等)之前調用。
返回碼:
EBUSY :接口無效,無法被認領
ENOMEM :內存不足
int usb_release_interface(usb_dev_handle *dev, int interface);
釋放之前認領的接口。interface參數是描述符的bInterfaceNumber字段。返回0成功,負數失敗。
3.3 控制傳輸
發送消息到缺省控制管道。
int usb_control_msg(usb_dev_handle *dev, int requesttype, int request, int value, int index, char *bytes, int size, int timeout);
發送控制請求到設備的缺省控制管道。參數對應USB規范中的同名類型。返回讀寫字節數,負數失敗。
int usb_get_string(usb_dev_handle *dev, int index, int langid, char *buf, size_t buflen);
獲取設備的字符串描述,通過index和langdi索引。返回Unicode字符串到buf中。返回實際寫入buf的字節數,負數失敗。
int usb_get_string_simple(usb_dev_handle *dev, int index, char *buf, size_t buflen);
包裝了 usb_get_string() 函數,返回第一種語言指定index索引的字符串描述,並轉換到C風格的ASCII。返回寫入buf字節數,負數失敗。
int usb_get_descriptor(usb_dev_handle *dev, unsigned char type, unsigned char index, void *buf, int size);
獲取設備缺省控制管道的描述符,通過type和index索引。返回實際寫入buf的字節數,負數失敗。
參考 usb_get_descriptor_by_endpoint() 了解允許指定控制端點的。
int usb_get_descriptor_by_endpoint(usb_dev_handle *dev, int ep, unsigned char type, unsigned char index, void *buf, int size);
從設備獲取描述符,以type和index索引,以ep標志的控制管道。返回讀取字節數,負數失敗。
3.4 塊傳輸
這部分允許應用從數據塊管道發送和接收數據。
int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout);
寫入一塊數據到端點ep,返回寫入成功字節數,負數失敗。
int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout);
讀取一塊數據,從端點ep,返回讀取成功字節數,負數失敗。
3.5 中斷傳輸
這組函數允許應用發送和接收數據通過中斷管道。
int usb_interrupt_write(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout);
執行對端點ep的中斷寫入,返回實際寫入字節數,負數失敗。
int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout);
執行對中斷端點ep的讀取,返回實際讀取字節數,負數失敗。
3.6 不可移植
這些函數是不可移植的。有些是暴露了OS USB API之類的。他們都回加上函數名後綴 _np 。
一個C預處理器宏會定義實現的函數。形式是 LIBUSB_HAS_ 加上函數名,沒有 usb_ 前綴。例如, usb_get_driver_np() 實現了,就會定義 LIBUSB_HAS_GET_DRIVER_NP 。
int usb_get_driver_np(usb_dev_handle *dev, int interface, char *name, int namelen);
這個函數獲取接口驅動的名字。成功返回0,失敗負數。
只在Linux有實現。
int usb_detach_kernel_driver_np(usb_dev_handle *dev, int interface);
這個函數從接口剝離內核驅動。使用了libusb的應用可以隨即重新認領接口。返回0成功,負數失敗。
只在Linux有實現。
4 例子
4.1 簡單例子
與設備通信前要先找到它。需要先找到所有總線(busses),然後找到所有設備:
struct usb_bus *busses;
usb_init();
usb_find_busses();
usb_find_devices();
busses=usb_get_busses();
在這之後,應用應該手動輪詢所有總線和設備,匹配其所要的:
struct usb_bus *bus;
int c,i,a;
for (bus=busses; bus; bus=bus->next) {
struct usb_device *dev;
for (dev=bus->devices; dev; dev=dev->next) {
if (dev->descriptor.bDeviceClass==7) {
/*打開設備,認領接口,然後操作*/
}
/*循環遍歷所有配置*/
for (c=0; c< dev->descriptor.bNumConfigurations; c++) {
/*循環遍歷所有接口*/
for (i=0; i< dev->config[c].bNumInterfaces; i++) {
/*循環遍歷所有輪換設置*/
for (a=0; a< dev->config[c].interface[i].num_altsetting; a++) {
/*檢查接口是否是打印機*/
if (dev->config[c].interface[i].altsetting[a].bInterfaceClass==7) {
/*打開設備,設置輪換配置,認領接口,然後操作*/
}
}
}
}
}
}
4.2 源碼包的例子
tests目錄有個程序叫 testlibusb.c 。它簡單的調用libusb尋找所有設備,然後遍歷並打印描述符。其結果很簡單,不過用處有限。倒是可以作為很好的入門。
4.3 其他應用
其他應用就參考其他的項目吧:
gPhoto :使用libusb與相機通信
rio500 :使用libusb與SONICblue Rio 500播放器