1. BUS/DEV/DRV 模型
"USB 接口"是邏輯上的 USB 設(shè)備 ,編寫(xiě)的 usb_driver 驅(qū)動(dòng)程序,支持的是"USB 接口":
- USB 控制器或 Hub 識(shí)別出 USB 設(shè)備后,會(huì)創(chuàng)建、注冊(cè) usb_device
- usb_device 被"driversusbcoregeneric.c" 驅(qū)動(dòng)認(rèn)領(lǐng)后,會(huì)選擇、設(shè)置某個(gè)配置
- 這個(gè)配置下面的接口,都會(huì)分配、設(shè)置、注冊(cè)一個(gè) usb_interface
- 左邊的 usb_driver 和右邊的 usb_interface 如果匹配,則調(diào)用 usb_driver.probe
2. 接口函數(shù)
在 USB 設(shè)備驅(qū)動(dòng)程序中,能使用的 USB 函數(shù)都在這個(gè)頭文件里:includelinuxusb.h
。
2.1 pipe
使用這些接口函數(shù)的主要目的是傳輸數(shù)據(jù),傳輸數(shù)據(jù)的對(duì)象是 USB 設(shè)備里的某個(gè) endpoint,這被稱為 pipe:
/* Create various pipes... */
#define usb_sndctrlpipe(dev, endpoint)
((PIPE_CONTROL < < 30) | __create_pipe(dev, endpoint))
#define usb_rcvctrlpipe(dev, endpoint)
((PIPE_CONTROL < < 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)
#define usb_sndisocpipe(dev, endpoint)
((PIPE_ISOCHRONOUS < < 30) | __create_pipe(dev, endpoint))
#define usb_rcvisocpipe(dev, endpoint)
((PIPE_ISOCHRONOUS < < 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)
#define usb_sndbulkpipe(dev, endpoint)
((PIPE_BULK < < 30) | __create_pipe(dev, endpoint))
#define usb_rcvbulkpipe(dev, endpoint)
((PIPE_BULK < < 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)
#define usb_sndintpipe(dev, endpoint)
((PIPE_INTERRUPT < < 30) | __create_pipe(dev, endpoint))
#define usb_rcvintpipe(dev, endpoint)
((PIPE_INTERRUPT < < 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)
2.2 同步傳輸函數(shù)
對(duì)于控制傳輸、批量傳輸、中斷傳輸,有 3 個(gè)同步函數(shù)可以用來(lái)直接發(fā)起傳輸。這些函數(shù)內(nèi)部會(huì)創(chuàng)建、填充、提交一個(gè) URB("usb request block"),并等待它完成或超時(shí)。
函數(shù)原型如下:
int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request,
__u8 requesttype, __u16 value, __u16 index, void *data,
__u16 size, int timeout);
int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
void *data, int len, int *actual_length, int timeout);
int usb_interrupt_msg(struct usb_device *usb_dev, unsigned int pipe,
void *data, int len, int *actual_length, int timeout);
2.3 異步傳輸函數(shù)
使用 URB 進(jìn)行傳輸時(shí),它是異步方式:需要先分配、構(gòu)造、提交一個(gè) URB("usb request block"),當(dāng)傳輸完成后,它的回調(diào)函數(shù)被調(diào)用。
關(guān)鍵就在于需要填充 URB:
- dev:跟誰(shuí)傳輸數(shù)據(jù)
- pipe:跟哪個(gè) pipe 傳輸數(shù)據(jù)
- buffer:里面存有要發(fā)送的數(shù)據(jù),或者用來(lái)接收要讀取的數(shù)據(jù)
- 數(shù)據(jù)長(zhǎng)度
- 回調(diào)函數(shù)
2.3.1 分配和釋放 URB
函數(shù)原型如下:
struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags);
void usb_free_urb(struct urb *urb);
2.3.2 分配/釋放 DMA Buffer
發(fā)起 USB 傳輸時(shí),數(shù)據(jù)保存在 buffer 里。這個(gè) buffer 可以是一般的 buffer,也可以是 DMA Buffer。
對(duì)于一般的 buffer,在提交 URB 時(shí)會(huì)臨時(shí)分配一個(gè) DMA Buffer:
- 發(fā)送數(shù)據(jù)時(shí):函數(shù)內(nèi)部會(huì)先從一般 buffer 中把數(shù)據(jù)復(fù)制到 DMA Buffer,在提交給 USB 控制器
- 讀取數(shù)據(jù)時(shí):USB 控制器先把數(shù)據(jù)傳到 DMA Buffer,函數(shù)內(nèi)部在把 DMA Buffer 的數(shù)據(jù)復(fù)制到一般 buffer
- 中間增加了一次數(shù)據(jù)的拷貝,效率低
我們可以直接使用 DMA Buffer,函數(shù)原型如下:
void *usb_alloc_coherent(struct usb_device *dev, size_t size, gfp_t mem_flags,dma_addr_t *dma);
void usb_free_coherent(struct usb_device *dev, size_t size, void *addr,dma_addr_t dma);
2.3.3 填充 URB
對(duì)于控制傳輸、批量傳輸、中斷傳輸,分別有如下函數(shù):
static inline void usb_fill_control_urb(struct urb *urb,
struct usb_device *dev,
unsigned int pipe,
unsigned char *setup_packet,
void *transfer_buffer,
int buffer_length,
usb_complete_t complete_fn,
void *context);
static inline void usb_fill_bulk_urb(struct urb *urb,
struct usb_device *dev,
unsigned int pipe,
void *transfer_buffer,
int buffer_length,
usb_complete_t complete_fn,
void *context);
static inline void usb_fill_int_urb(struct urb *urb,
struct usb_device *dev,
unsigned int pipe,
void *transfer_buffer,
int buffer_length,
usb_complete_t complete_fn,
void *context,
int interval);
如果 URB 使用 DMA Buffer,那么還需要設(shè)置一個(gè) flag 表明這點(diǎn):
urb- >transfer_dma = DMA address of buffer; // usb_alloc_coherent的輸出參數(shù)
urb- >transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
2.3.4 提交 URB
構(gòu)造好 URB 后,需要提交到 USB 系統(tǒng)里,才能啟動(dòng)傳輸。
int usb_submit_urb(struct urb *urb, gfp_t mem_flags);
2.3.5 取消 URB
已經(jīng)提交的 URB,可以取消它,有 2 個(gè)函數(shù):
- usb_kill_urb:這是一個(gè)同步函數(shù),它會(huì)等待 URB 結(jié)束
- usb_unlink_urb:這是一個(gè)異步函數(shù),它不會(huì)等待 URB 結(jié)束,USB 控制器驅(qū)動(dòng)會(huì)調(diào)用它的回調(diào)函數(shù)
void usb_kill_urb(struct urb *urb);
int usb_unlink_urb(struct urb *urb);
-
usb
+關(guān)注
關(guān)注
60文章
8179瀏覽量
272754 -
驅(qū)動(dòng)
+關(guān)注
關(guān)注
12文章
1916瀏覽量
86905 -
鼠標(biāo)
+關(guān)注
關(guān)注
6文章
593瀏覽量
40755
發(fā)布評(píng)論請(qǐng)先 登錄
嵌入式Linux下的USB設(shè)備驅(qū)動(dòng)技術(shù)

嵌入式Linux下的USB設(shè)備驅(qū)動(dòng)
詳解linux設(shè)備驅(qū)動(dòng)模型架構(gòu)
基于Linux的USB設(shè)備驅(qū)動(dòng)方法有什么優(yōu)點(diǎn)?
基于USB設(shè)備的Linux網(wǎng)絡(luò)驅(qū)動(dòng)程序開(kāi)發(fā)
Linux環(huán)境下USB的原理、驅(qū)動(dòng)和配置
嵌入式Linux的USB驅(qū)動(dòng)設(shè)計(jì)

Linux設(shè)備驅(qū)動(dòng)模型摘抄
《Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解》第20章、USB主機(jī)與設(shè)備驅(qū)動(dòng)

Linux下的硬件驅(qū)動(dòng)—USB設(shè)備(上)
Linux下的硬件驅(qū)動(dòng)—USB設(shè)備(下)
如何使用Linux內(nèi)核實(shí)現(xiàn)USB驅(qū)動(dòng)程序框架

基于ARM的USB無(wú)線網(wǎng)卡Linux設(shè)備驅(qū)動(dòng)設(shè)計(jì)

評(píng)論