libusb 簡介與第一個範例

jollen 發表於 January 25, 2008 3:49 PM

[libusb] 是一個 user-space 的 USB 程式庫,在 embedded linux 應用實作上,我們會使用 libusb 實作一個 host 端的應用程式,並透過 USB 介面存取或控制 target device。

找到所有 USB bus 與 USB device

要撰寫一支 user-space 的 USB device 控制程式,最首要的工作就是找到自己的 USB 裝置。這個工作主要透過以下 4 個函數來進行:

  • usb_init: 初始化 libusb
  • usb_find_busses: 尋找系統裡的所有 USB bus
  • usb_find_devices: 尋找所有的 USB bus 上的所有 USB device
  • usb_get_busses: 傳回找到的 USB bus

程式一開始必須先呼叫 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