[libusb] 是一個 user-space 的 USB 程式庫,在 embedded linux 應用實作上,我們會使用 libusb 實作一個 host 端的應用程式,並透過 USB 介面存取或控制 target device。
找到所有 USB bus 與 USB device要撰寫一支 user-space 的 USB device 控制程式,最首要的工作就是找到自己的 USB 裝置。這個工作主要透過以下 4 個函數來進行:
程式一開始必須先呼叫 usb_init 將 libusb 做初始化,這是 libusb 程式第一個要呼叫的函數。接著依序呼叫 usb_find_busses 與 usb_find_devices 找到所有的 USB bus 與 USB device。
最後,呼叫 usb_get_busses 取得所有找到的 USB bus。程式如下:
usb_init(); usb_find_busses(); usb_find_devices(); struct usb_bus *busses; busses = usb_get_busses();
*busses 指向一個串列資料結構(struct usb_bus),訪問這個串列即可找到所有的 USB 裝置。
偵測 USB 裝置接下來,我們要在所有的 USB bus 上偵測系統是否有我們的 USB device。以下是這段程式的框架:
struct usb_bus *bus; for (bus = busses; bus; bus = bus->next) { struct usb_device *dev; for (dev = bus->devices; dev; dev = dev->next) { struct usb_device_descriptor *desc; desc = &(dev->descriptor); printf("Vendor/Product ID: %04x:%04x\n", desc->idVendor, desc->idProduct); } }
這段演算法可以將系統上所有 USB device 的 vendor id 與 product id 印出來。假如,我們想找到特定的 USB 裝置,這時就可以設計一個這樣的函數(假設我們想要找的 USB 裝置是 0xffff/0x0001):
struct usb_device *usbio_probe() { struct usb_bus *busses, *bus; int c, i, a; usb_init(); usb_find_busses(); usb_find_devices(); busses = usb_get_busses(); for (bus = busses; bus; bus = bus->next) { struct usb_device *dev; for (dev = bus->devices; dev; dev = dev->next) { struct usb_device_descriptor *desc; desc = &(dev->descriptor); printf("Vendor/Product ID: %04x:%04x\n", desc->idVendor, desc->idProduct); if ((desc->idVendor == 0xffff) && (desc->idProduct == 0x0001)) { return dev; } } } return NULL; }開始操作 USB 裝置
找到我們的 USB device 後,接著就可以對它進行操作(讀/寫)。如同操作檔案般,我們要先對 USB device 做開啟的動作,方式是呼叫 usb_open 函數:
usb_dev_handle *usb_open(struct *usb_device dev);
開啟成功後,會傳回此裝置的 handle。
第一個 libusb 程式以下提供學習 libusb 的第一個範例程式:
/* * findusb.c - A libusb sample program. * * Authored by Jollen Chen* * Copyright (C) 2008 www.jollen.org * Copyright (C) 2008 Jollen's Consulting, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Public License as published by * the Free Software Foundation; version 2 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser Public License for more details. * */ #include <stdio.h> #include <stdlib.h> #include <usb.h> #include <libusb.h> void usbio_main(struct usb_device *dev) { usb_dev_handle *dev_handle; dev_handle = usb_open(dev); if (dev_handle == NULL) { printf("USB IO open failed.\n"); return; } usb_close(dev_handle); } struct usb_device *usbio_probe() { struct usb_bus *busses, *bus; int c, i, a; usb_init(); usb_find_busses(); usb_find_devices(); busses = usb_get_busses(); for (bus = busses; bus; bus = bus->next) { struct usb_device *dev; for (dev = bus->devices; dev; dev = dev->next) { struct usb_device_descriptor *desc; desc = &(dev->descriptor); printf("Vendor/Product ID: %04x:%04x\n", desc->idVendor, desc->idProduct); if ((desc->idVendor == 0xffff) && (desc->idProduct == 0x0001)) { return dev; } } } return NULL; } int main() { struct usb_device *dev; struct usb_device_descriptor *desc; dev = usbio_probe(); desc = &(dev->descriptor); if (dev == NULL) { printf("USB IO Card not found.\n"); return -1; } printf("SUB IO Card found.\n"); printf("Vendor/Product ID: %04x:%04x\n", desc->idVendor, desc->idProduct); usbio_main(dev); }
檔案可由 [http://tw.jollen.org/findusb/] 下載。這裡提供一個 Makefile 檔案;編譯時,請記得安裝 libusb 並與 libusb 做連結。
網路資源* libusb API 文件. http://libusb.sourceforge.net/doc/
Jollen's Blog 使用 Github issues 與讀者交流討論。請點擊上方的文章專屬 issue,或 open a new issue
您可透過電子郵件 jollen@jollen.org,或是 Linkedin 與我連絡。更歡迎使用微信,請搜尋 WeChat ID:jollentw