Linux下USB從裝置使用gadget API

來源:互聯網
上載者:User

http://www.linuxidc.com/Linux/2007-12/10106.htm

 

最近在做Linux下USB從裝置的驅動,程式寫的差不多了,做一個整理小結。歡迎交流,如有錯誤請指正,謝謝!--Jason

一、USB從裝置驅動介紹

USB匯流排上主要有三類裝置:主控制器(Host Controller, such as EHCI、UHCI、OHCI)、集線器(hub)和裝置(device)。Host controller(HC)負責匯流排的管理,是匯流排的指揮官,匯流排上一切傳輸都是由HC發起的,支援OTG的Device也能發起傳輸;Hub是匯流排的節點,用來擴充匯流排上可接入裝置的數量,對於驅動來說是透明的;Device就是各種各樣的裝置了,每個裝置都有自己的功能,比如隨身碟、USB網路攝影機等等。

Linux下主機端USB裝置的驅動(device driver)編寫的資料有很多,LDD3中有相應的介紹。主要是通過核心中USB core這個模組與裝置互動。本文只介紹運行Linux的嵌入式USB裝置驅動的編寫。因為Host端已經使用了device driver一詞,為了避免混淆,使用USB gadget driver一次表示從裝置驅動。In USB protocol interactions, the device driver is the master (or client driver) and the gadget driver is the slave (or function driver).

Linux USB gadget driver API定義了一個通用的gadget driver的介面,gadget driver通過API與底層USB controller driver通訊。該API屏蔽了底層硬體的不同,使gadget driver注重功能的實現,盡量與硬體無關。Slave端系統的架構如所示:

其中,gadgetfs提供給使用者空間程式直接與USB device controller互動的能力。

二、相關資料

USB gadget API Layer的相關資料:

1. http://www.linux-usb.org/gadget/

2. 核心中/KernelDoc/gadget/目錄下的文檔

3.最重要的就是/include/linux/usb_gadget.h檔案,該檔案中有gadget API介面資料結構和方法的詳細定義及注釋。

Gadget Driver的例子:

4. 核心/drivers/usb/gadget/目錄下有一些gadget driver的例子,zero.c為最簡單的例子,file_storage.c是存放裝置的gadget driver。

三、gadget API

要瞭解gadget API,只需要理解標頭檔(usb_gadget.h)中幾個重要的資料結構就可以了。詳細的欄位介紹看h檔案注釋。

(1)

struct usb_gadget {

const struct usb_gadget_ops *ops;

struct usb_ep                *ep0;

struct list_head              ep_list;

enum usb_device_speed        speed;

unsigned                is_dualspeed:1;

unsigned                is_otg:1;

unsigned                is_a_peripheral:1;

unsigned                b_hnp_enable:1;

unsigned                a_hnp_support:1;

unsigned                a_alt_hnp_support:1;

const char                    *name;

struct device                 dev;

};

該結構表示一個USB device controller(UDC),在udc driver中初始化,它對gadget driver是唯讀。

(2)

struct usb_gadget_driver {

char               *function;

enum usb_device_speed speed;

int                  (*bind)(struct usb_gadget *);

void               (*unbind)(struct usb_gadget *);

int                  (*setup)(struct usb_gadget *,

const struct usb_ctrlrequest *);

void               (*disconnect)(struct usb_gadget *);

void               (*suspend)(struct usb_gadget *);

void               (*resume)(struct usb_gadget *);

struct device_driver       driver;

};

這個結構表示我們的gadget驅動,其中的函數需要在gadget driver中實現,是編碼的重點之一。具體實現可參考zero.c檔案,下面簡單介紹一下各個函數的功能:

Bind中主要執行gadget driver的初始化,它會被usb_gadget_register_driver函數調用,而usb_gadget_register_driver 一般在模組初始化時調用。usb_gadget_register_driver執行完之後,device可以被主機探測到。

Unbind與bind相反,被usb_gadget_unregister_driver調用。

Setup處理主機發過來的request,例如讀decriptors,配置configuration等。因此,setup函數中一般包含switch,case語句。

Disconnect在裝置與主機斷開時被調用。

(3)

struct usb_request {

void               *buf;

unsigned         length;

dma_addr_t           dma;

unsigned         no_interrupt:1;

unsigned         zero:1;

unsigned         short_not_ok:1;

void               (*complete)(struct usb_ep *ep,

struct usb_request *req);

void               *context;

struct list_head       list;

int                  status;

unsigned         actual;

};

usb_request 表示一個傳輸的請求,與host端的urb很相似。它有一個complete欄位,指定當request完成時的回呼函數。

(4)

struct usb_ep {

void               *driver_data;

const char             *name;

const struct usb_ep_ops       *ops;

struct list_head       ep_list;

unsigned         maxpacket:16;

};

struct usb_ep 表示一個端點(EP),usb_gadget中有所有EP的list。

(5)

struct usb_ep_ops {

int (*enable) (struct usb_ep *ep,

const struct usb_endpoint_descriptor *desc);

int (*disable) (struct usb_ep *ep);

struct usb_request *(*alloc_request) (struct usb_ep *ep,

gfp_t gfp_flags);

void (*free_request) (struct usb_ep *ep, struct usb_request *req);

void *(*alloc_buffer) (struct usb_ep *ep, unsigned bytes,

dma_addr_t *dma, gfp_t gfp_flags);

void (*free_buffer) (struct usb_ep *ep, void *buf, dma_addr_t dma,

unsigned bytes);

// NOTE:  on 2.6, drivers may also use dma_map() and

// dma_sync_single_*() to directly manage dma overhead.

int (*queue) (struct usb_ep *ep, struct usb_request *req,

gfp_t gfp_flags);

int (*dequeue) (struct usb_ep *ep, struct usb_request *req);

int (*set_halt) (struct usb_ep *ep, int value);

int (*fifo_status) (struct usb_ep *ep);

void (*fifo_flush) (struct usb_ep *ep);

};

struct usb_ep_ops表示端點的操作,其中queue函數將一個usb_request提交給某個EndPoint,是進行資料轉送的關鍵函數。

四、總結

本文是自己對學習使用Gadget API的一些總結,記錄下來以防時間一長就忘記了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.