libusb 是跨平台的 USB 裝置存取庫,支援 Linux、FreeBSD、NetBSD、OpenBSD、macOS。本文基於 libusb-0.1 API,涵蓋核心函式、裝置操作、控制/批量/中斷傳輸、平台專屬擴充。
// 1. 初始化
usb_init();
// 2. 掃描總線與裝置
usb_find_busses();
usb_find_devices();
// 3. 取得總線鏈表
struct usb_bus *busses = usb_get_busses();
// 4. 遍歷尋找目標裝置
for (struct usb_bus *bus = busses; bus; bus = bus->next) {
for (struct usb_device *dev = bus->devices; dev; dev = dev->next) {
// 比對 VID/PID、類別等
if (dev->descriptor.idVendor == MY_VID && dev->descriptor.idProduct == MY_PID) {
// 找到目標
}
}
}
| 函式 | 用途 | 備註 |
|---|---|---|
usb_open(dev) | 開啟裝置取得 handle | 後續操作需此 handle |
usb_close(handle) | 關閉裝置 | 釋放資源 |
usb_set_configuration(handle, cfg) | 設定作用配置 | 對應 bConfigurationValue |
usb_claim_interface(handle, iface) | 認領介面 | 任何介面操作前必須呼叫 |
usb_release_interface(handle, iface) | 釋放介面 | 對應 bInterfaceNumber |
usb_set_altinterface(handle, alt) | 設定替代設定 | 對應 bAlternateSetting |
usb_clear_halt(handle, ep) | 清除端點暫停 | 優於 deprecated usb_resetep |
usb_reset(handle) | 重置裝置 | 需重新掃描與開啟 |
// 標準控制請求 int usb_control_msg(handle, requesttype, request, value, index, bytes, size, timeout); // 取得字串描述符 int usb_get_string_simple(handle, index, buf, buflen); // 回傳 ASCII // 取得通用描述符 int usb_get_descriptor(handle, type, index, buf, size);
int usb_bulk_write(handle, ep, bytes, size, timeout); // 發送資料 int usb_bulk_read(handle, ep, bytes, size, timeout); // 接收資料
適用大量資料、無即時性要求(如大量儲存、印表機)。
int usb_interrupt_write(handle, ep, bytes, size, timeout); int usb_interrupt_read(handle, ep, bytes, size, timeout);
適用低延遲、小封包、週期性輪詢(鍵盤、滑鼠、手柄)。
int:< 0 表示錯誤(負錯誤碼),>=0 為傳輸位元組數或成功碼。usb_open 回傳 handle,失敗回傳 NULL。EBUSY(介面被佔用)、ENOMEM(記憶體不足)、EPIPE(端點暫停)。// Linux 專屬 int usb_get_driver_np(handle, interface, name, namelen); // 取得核心驅動名稱 int usb_detach_kernel_driver_np(handle, interface); // 脫離核心驅動,供 user-space 使用
使用前檢查巨集 LIBUSB_HAS_GET_DRIVER_NP 等。
usb_init();
usb_find_busses();
usb_find_devices();
struct usb_bus *bus;
for (bus = usb_get_busses(); bus; bus = bus->next) {
struct usb_device *dev;
for (dev = bus->devices; dev; dev = dev->next) {
// 檢查裝置類別
if (dev->descriptor.bDeviceClass == 7) { // Printer class
usb_dev_handle *h = usb_open(dev);
if (h) {
usb_set_configuration(h, 1);
usb_claim_interface(h, 0);
// ... 進行列印操作 ...
usb_release_interface(h, 0);
usb_close(h);
}
}
}
}
新專案**強烈建議直接使用 libusb-1.0**,提供:
libusb-0.1 僅供維護舊專案參考。掌握 USB 協定層級(描述符、請求、端點)比熟悉 API 更重要,建議配合《USB 2.0/3.0 規格書》閱讀。