題目: 基于Linu*的網(wǎng)絡(luò)攝像頭實(shí)現(xiàn)
院(系) 信息科學(xué)與工程學(xué)院
專 業(yè) 電子科學(xué)與技術(shù)
摘要
本項(xiàng)目通過編寫Linu*下的USB攝像頭驅(qū)動,在Linu*下編寫QT程序完成本項(xiàng)目目標(biāo)。Linu*是開源的可移植的操作系統(tǒng)內(nèi)核,QT是一個(gè)跨平臺的C++圖形用戶界面應(yīng)用程序框架,它提供給應(yīng)用程序開發(fā)者建立藝術(shù)級的圖形用戶界面所需的所有功能。QT能將在其上開發(fā)的應(yīng)用程序移植到PC和嵌入式設(shè)備上,進(jìn)而可以實(shí)現(xiàn)嵌入式Linu*上的圖像采集。
本文圍繞USB, Linu*下USB驅(qū)動程序開發(fā),和V4L2框架編程3個(gè)方面進(jìn)行研究。詳細(xì)敘述了USB驅(qū)動原理,Linu*下的USB的驅(qū)動程序數(shù)據(jù)結(jié)構(gòu)和一般驅(qū)動程序的開發(fā)過程,攝像頭驅(qū)動的開發(fā),和V4L2框架下的應(yīng)用程序開發(fā)。
關(guān)鍵字:Linu*,USB,USB驅(qū)動,V4L2,攝像頭驅(qū)動,圖像采集
ABSTRACT
In this item,we chieve the design goal of graduation through writing the USB camera driver of Linu* and the QT software on Linu*.Linu* is an portable open source operation system kernel.QT is a cross platform framwork of C++ GUI application program,providing all API to build artistic GUI for programmer.The program developed on QT can run on PC and embedded device,so we can achieve the goal of video capture on embedded device using this method.
This page focus on USB,USB device driver on Linu* and program on V4L2 framwork three aspects.It discuss on the principle of USB device driver,the data structs of USB device driver on Linu*,the develop process of general Linu* device driver,the camera device driver and application program on V4L2 framwork.
Keywords:Linu*,USB,USB device driver,V4L2,camera device driver,
video capture
目錄
摘要 2
ABSTRACT 3
第一章 USB驅(qū)動原理 5
1.1 USB基礎(chǔ)知識 5
1.1.2 USB 的優(yōu)勢 6
1.1.3 USB 數(shù)據(jù)傳輸 6
1.1.4 USB協(xié)議 7
1.2 USB驅(qū)動結(jié)構(gòu) 8
1.3 USB 主機(jī)控制器驅(qū)動結(jié)構(gòu) 9
1.3.1 主機(jī)控制器驅(qū)動 9
1.4 USB 主機(jī)邏輯組織 13
1.4 USB 驅(qū)動程序重要數(shù)據(jù)結(jié)構(gòu) 16
1.5 URB 18
1.5.1 URB 處理流程 19
1.5.2 簡單的批量和控制 URB 21
1.6 USB 設(shè)備的識別過程 24
1.7 USB 設(shè)備類驅(qū)動 25
第二章USB攝像頭驅(qū)動 27
2.1 攝像頭工作原理 27
2.2通用攝像頭驅(qū)動開發(fā) 28
2.2.1 主要數(shù)據(jù)結(jié)構(gòu) 28
2.2.2 USBD層數(shù)據(jù)結(jié)構(gòu) 29
2.2.3 文件系統(tǒng)數(shù)據(jù)結(jié)構(gòu) 29
2.3 共有功能模塊 30
2.3.1 初始化和卸載函數(shù) 30
2.3.2 模塊初始化 30
2.3.3 模塊卸載 31
2.3.4 即插即用功能函數(shù) 31
2.3.5 上層軟件接口函數(shù) 34
第三章 圖像采集應(yīng)用程序 39
3.1 Video4Linu*2簡介 39
3.2 程序關(guān)鍵步驟介紹 40
3.3 UDP傳輸圖像 43
參考文獻(xiàn) 44
結(jié)論 45
英文翻譯 46
附錄 60
第一章 USB驅(qū)動原理
USB 是英文”Universal Serial Bus”的縮寫,意為”通用串行總線”。是由 compaq(康柏)、DEC、Intel、IBM、NEC、微軟以 及Northern Telecom (北方電訊)等公司于1994年11月共同提出的,主要目的就是為了解決接口標(biāo)準(zhǔn)太多的弊端。USB使用一個(gè)4針插頭作為標(biāo)準(zhǔn)插頭,并通過這個(gè)標(biāo)準(zhǔn)接頭,采用菊花瓣形式把所有外設(shè)連接起來,它采用串行方式傳輸數(shù)據(jù),目前最大數(shù)據(jù)傳輸率為12Mbps,支持多數(shù)據(jù)流和多個(gè)設(shè)備并行操作,允許外設(shè)熱插拔。
USB 攝像頭不但具有體積小、重量輕、功耗小、工作電壓低和抗燒毀等優(yōu)點(diǎn),而且在分辨率、動態(tài)范圍、靈敏度、實(shí)時(shí)傳輸和自掃描等方面的優(yōu)越性,也是其它攝像器件無法比擬的。目前,USB 攝像頭已在航空航天、衛(wèi)星偵察、遙感遙測、天文測量、傳真、靜電復(fù)印、非接觸工業(yè)測量、光學(xué)圖像處理、圖文識別、數(shù)據(jù)存儲等領(lǐng)域得到了廣泛的應(yīng)用。
1.1 USB基礎(chǔ)知識
目前 USB 接口雖然只發(fā)展了 2 代( USB1.0/1.1,USB2.0 ),但是USB綜合了一個(gè)多平臺標(biāo)準(zhǔn)的所有優(yōu)點(diǎn):降低成本,增加兼容性,可連接大量的外部設(shè)備,融合先進(jìn)的功能和品質(zhì)。這些優(yōu)點(diǎn)使得 USB 逐步成為 PC 的接口標(biāo)準(zhǔn),進(jìn)入了高速發(fā)展的階段。
在早期的計(jì)算機(jī)系統(tǒng)上常用串口或并口連接外圍設(shè)備,每個(gè)接口都需要占用計(jì)算機(jī)的系統(tǒng)資源(如中斷,I/O 地址,DMA 通道等)。無論是串口還是并口都是點(diǎn)對點(diǎn)的連接,一個(gè)接口僅支持一個(gè)設(shè)備。因此每添加一個(gè)新的設(shè)備,就需要添加一個(gè) ISA/EISA 或 PCI 卡,同時(shí)系統(tǒng)需要重新啟動才能驅(qū)動新的設(shè)備。而采用 USB 接口則可以避免這類的問題,不但節(jié)省系統(tǒng)的資源而且使用起來非常方便。
USB 第一版的規(guī)范定為 1.1,其最大傳輸速率為12Mbps,最多可支持127個(gè) USB外設(shè)連接到計(jì)算機(jī)系統(tǒng),它的物理結(jié)構(gòu)為星型,也就是說,即使主板上只有一個(gè)USB 接口,只要能找到合適的 USB Hub ,就
……(新文秘網(wǎng)http://m.jey722.cn省略4360字,正式會員可完整閱讀)……
efine HC_STATE_RUNNING (_ _ACTIVE)
#define HC_STATE_QUIESCING (_ _SUSPEND|_ _TRANSIENT|_ _ACTIVE)
#define HC_STATE_RESUMING (_ _SUSPEND|_ _TRANSIENT)
#define HC_STATE_SUSPENDED (_ _SUSPEND)
#define HC_IS_RUNNING(state) ((state) & _ _ACTIVE)
#define HC_IS_SUSPENDED(state) ((state) & _ _SUSPEND)
/* 主機(jī)控制器驅(qū)動的私有數(shù)據(jù) */
unsigned long hcd_priv[0]_ _attribute_ _((aligned(sizeof(unsigned long))));
};
hc_driver 結(jié)構(gòu)體
struct hc_driver
{
const char *description; /* "ehci-hcd" 等 */
const char *product_desc; /* 產(chǎn)品/廠商字符串 */
size_t hcd_priv_size; /* 私有數(shù)據(jù)的大小 */
/* 中斷處理函數(shù) */
irqreturn_t(*irq)(struct usb_hcd *hcd, struct pt_regs *regs);
int flags;
#define HCD_MEMORY 0*0001 /* HC 寄存器使用的內(nèi)存和 I/O */
#define HCD_USB11 0*0010 /* USB 1.1 */
#define HCD_USB2 0*0020 /* USB 2.0 */
/* 被調(diào)用以初始化 HCD 和根 Hub */
int(*reset)(struct usb_hcd *hcd);
int(*start)(struct usb_hcd *hcd);
/* 掛起 Hub 后,進(jìn)入 D3(etc)前被調(diào)用 */
int(*suspend)(struct usb_hcd *hcd, pm_message_t message);
/* 在進(jìn)入 D0(etc)后,恢復(fù) Hub 前調(diào)用 */
int(*resume)(struct usb_hcd *hcd);
/* 使 HCD 停止寫內(nèi)存和進(jìn)行 I/O 操作*/
void(*stop)(struct usb_hcd *hcd);
/* 返回目前的幀數(shù) */
int(*get_frame_number)(struct usb_hcd *hcd);
/* 管理 I/O 請求和設(shè)備狀態(tài) */
int(*urb_enqueue)(struct usb_hcd *hcd, struct usb_host_endpoint *ep, struct urb *urb, gfp_t mem_flags);
int(*urb_dequeue)(struct usb_hcd *hcd, struct urb *urb);
/* 釋放 endpoint 資源 */
void(*endpoint_disable)(struct usb_hcd *hcd, struct usb_host_endpoint *ep);
/* 根 Hub 支持 */
int(*hub_status_data)(struct usb_hcd *hcd, char *buf);
int(*hu不忘初心ontrol)(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wInde*,
char *buf, u16 wLength);
int(*bus_suspend)(struct usb_hcd*);
int(*bus_resume)(struct usb_hcd*);
int(*start_port_reset)(struct usb_hcd *, unsigned port_num);
void(*hub_irq_enable)(struct usb_hcd*);
};
ohci_hcd 結(jié)構(gòu)體
struct ohci_hcd
{
spinlock_t lock;
/* 與主機(jī)控制器通信的 I/O 內(nèi)存( DMA 一致) */
struct ohci_regs _ _iomem *regs;
/* 與主機(jī)控制器通信的主存( DMA 一致) */
struct ohci_hcca *hcca;
dma_addr_t hcca_dma;
struct ed *ed_rm_list; /* 將被移除 */
struct ed *ed_bulktail; /* 批量隊(duì)列尾 */
struct ed *ed_controltail; /* 控制隊(duì)列尾 */
struct ed *periodic[NUM_INTS]; /* int_table“影子” */
/* OTG 控制器和收發(fā)器需要軟件交互,其他的外部收發(fā)器應(yīng)該是軟件透明的*/
struct otg_transceiver *transceiver;
/* 隊(duì)列數(shù)據(jù)的內(nèi)存管理 */
struct dma_pool *td_cache;
struct dma_pool *ed_cache;
struct td *td_hash[TD_HASH_SIZE];
struct list_head pending;
/* driver 狀態(tài) */
int num_ports;
int load[NUM_INTS];
u32 hc_control; /* 主機(jī)控制器控制寄存器的復(fù)制 */
unsigned long ne*t_statechange; /* 掛起/恢復(fù) */
u32 fminterval; /* 被保存的寄存器 */
struct notifier_block reboot_notifier;
unsigned long flags;
};
在 Linu* 內(nèi)核中,使用如下函數(shù)來創(chuàng)建 HCD:
struct usb_hcd *us不忘初心reate_hcd (const struct hc _driver *driver,struct device *dev, char *bus_name);
如下函數(shù)被用來增加和移除 HCD:
int usb_add_hcd(struct usb_hcd *hcd,unsigned int irqnum, unsigned long irqflags);
void usb_remove_hcd(struct usb_hcd *hcd);
使用如下函數(shù)可初始化 OHCI 主機(jī)控制器:
int ohci_init (struct ohci_hcd *ohci);
如下函數(shù)分別用于開啟、停止及復(fù)位 OHCI 控制器:
int ohci_run (struct ohci_hcd *ohci);
void ohci_stop (struct usb_hcd *hcd);
void ohci_usb_reset (struct ohci_hcd *ohci);
1.4 USB 主機(jī)邏輯組織
在USB三層設(shè)備驅(qū)動中的最頂層驅(qū)動,即USB設(shè)備的邏輯組織,包含了設(shè)備、配置、接口3個(gè)層次。
每個(gè) USB 設(shè)備都提供了不同級別的配置信息,可以包含一個(gè)或多個(gè)配置,不同的配置使設(shè)備表現(xiàn)出不同的功能組合(在探測/連接期間需從其中選定一個(gè)),配置由多個(gè)接口組成。
在 USB 協(xié)議中,接口由多個(gè)端點(diǎn)組成,代表一個(gè)基本的功能,是 USB 設(shè)備驅(qū)動程序控制的對象,一個(gè)功能復(fù)雜的 USB 設(shè)備可以具有多個(gè)接口。每個(gè)配置中可以有多個(gè)接口,而設(shè)備接口是端點(diǎn)的匯集(collection)。例如 USB 揚(yáng)聲器可以包含一個(gè)音頻接口以及對旋鈕和按鈕的接口。一個(gè)配置中的所有接口可以同時(shí)有效,并可被不同的驅(qū)動程序連接。每個(gè)接口可以有備用接口,以提供不同質(zhì)量的服務(wù)參數(shù)。
端點(diǎn)是 USB 通信的最基本形式,每一個(gè) USB 設(shè)備接口在主機(jī)看來就是一個(gè)端點(diǎn)的集合。主機(jī)只能通過端點(diǎn)與設(shè)備進(jìn)行通信,以使用設(shè)備的功能。 USB 系統(tǒng)中每一個(gè)端點(diǎn)都有惟一的地址,在這是由設(shè)備地址和端點(diǎn)號給出的。每個(gè)端點(diǎn)都有一定的屬性,其中包括傳輸方式、總線訪問頻率、帶寬、端點(diǎn)號和數(shù)據(jù)包的最大容量等。一個(gè) USB 端點(diǎn)只能在一個(gè)方向承載數(shù)據(jù),或者從主機(jī)到設(shè)備(稱為輸出端點(diǎn)),或者從設(shè)備到主機(jī)(稱為輸入端點(diǎn)),因此端點(diǎn)可看作一個(gè)單向的管道。端點(diǎn) 0 通常為控制端點(diǎn),用于設(shè)備初始化參數(shù)等。只要設(shè)備連接到 USB 上并且上電端點(diǎn) 0 就可以被訪問。端點(diǎn) 1、2 等一般用作數(shù)據(jù)端點(diǎn),存放主機(jī)與設(shè)備間往來的數(shù)據(jù)。
USB 設(shè)備非常復(fù)雜,由許多不同的邏輯單元組成,這些單元之間的關(guān)系如下:
設(shè)備通常有一個(gè)或多個(gè)配置;
配置通常有一個(gè)或多個(gè)接口;
接口通常有一個(gè)或多個(gè)設(shè)置;
接口有零或多個(gè)端點(diǎn)。
這種層次化配置信息在設(shè)備中通過一組標(biāo)準(zhǔn)的描述符來描述,如下所示。
設(shè)備描述符:關(guān)于設(shè)備的通用信息,如供應(yīng)商 ID、產(chǎn)品 ID 和修訂 ID,支持的設(shè)備類、子類和適用的協(xié)議以及默認(rèn)端點(diǎn)的最大包大小等。在 Linu* 內(nèi)核中, USB 設(shè)備用 usb_device 結(jié)構(gòu)體來描述, USB 設(shè)備描述符定義為 usb_device_descriptor 結(jié)構(gòu)體
struct usb_device_descriptor
{
_ _u8 bLength; //描述符長度
_ _u8 bDescriptorType; //描述符類型編號
_ _le16 bcdUSB; //USB 版本號
_ _u8 bDeviceClass; //USB 分配的設(shè)備類 code
_ _u8 bDeviceSubClass;// USB 分配的子類 code
_ _u8 bDeviceProtocol; //USB 分配的協(xié)議 code
_ _u8 bMa*PacketSize0; //endpoint0 最大包大小
_ _le16 idVendor; //廠商編號
_ _le16 idProduct; //產(chǎn)品編號
_ _le16 bcdDevice; //設(shè)備出廠編號
_ _u8 iManufacturer; //描述廠商字符串的索引
_ _u8 iProduct; //描述產(chǎn)品字符串的索引
_ _u8 iSerialNumber; //描述設(shè)備序列號字符串的索引
_ _u8 bNumConfigurations; //可能的配置數(shù)量
} _ _attribute_ _ ((packed));
配置描述符:此配置中的接口數(shù)、支持的掛起和恢復(fù)能力以及功率要求。USB 配置在內(nèi)核中使用 usb_host_config 結(jié)構(gòu)體描述,USB 配置描述符定義為結(jié)構(gòu)體 us不忘初心onfig_descriptor,
struct us不忘初心onfig_descriptor
{
_ _u8 bLength; //描述符長度
_ _u8 bDescriptorType; //描述符類型編號
_ _le16 wTotalLength; //配置所返回的所有數(shù)據(jù)的大小
_ _u8 bNumInterfaces; // 配置所支持的接口數(shù)
_ _u8 bConfigurationValue; //Set_Configuration 命令需要的參數(shù)值
_ _u8 iConfiguration; //描述該配置的字符串的索引值
_ _u8 bmAttributes; //
供電模式的選擇
_ _u8 bMa*Power; //設(shè)備從總線提取的最大電流
} _ _attribute_ _ ((packed));
接口描述符:接口類、子類和適用的協(xié)議,接口備用配置的數(shù)目和端點(diǎn)數(shù)目。USB 接口在內(nèi)核中使用 usb_interface 結(jié)構(gòu)體描述, USB 接口描述符定義為結(jié)構(gòu)體usb_interface_descriptor
struct usb_interface_descriptor
{
_ _u8 bLength;
//描述符長度
_ _u8 bDescriptorType; //描述符類型
_ _u8 bInterfaceNumber;
// 接口的編號
_ _u8 bAlternateSetting; //備用的接口描述符編號
_ _u8 bNumEndpoints;
//該接口使用的端點(diǎn)數(shù),不包括端點(diǎn) 0
_ _u8 bInterfaceClass;
//接口類型
_ _u8 bInterfaceSubClass; //接口子類型
_ _u8 bInterfaceProtocol; //接口所遵循的協(xié)議
_ _u8 iInterface; //描述該接口的字符串索引值
} _ _attribute_ _ ((packed));
端點(diǎn)描述符:端點(diǎn)地址、方向和類型,支持的最大包大小,如果是中斷類型的端點(diǎn)則還包括輪詢頻率。在 Linu* 內(nèi)核中,USB 端點(diǎn)使用 usb_host_endpoint 結(jié)構(gòu)體來描述, USB 端點(diǎn)描述符定義為 usb_endpoint_descriptor 結(jié)構(gòu)體
struct usb_endpoint_descriptor
{
_ _u8 bLength; //描述符長度
_ _u8 bDescriptorType; //描述符類型
_ _u8 bEndpointAddress; //端點(diǎn)地址:0~3 位是端點(diǎn)號,第 7 位是方向(0-OUT,1-IN)
_ _u8 bmAttributes; //端點(diǎn)屬性:bit[0:1] 的值為00 表示控制,為01 表示同步,為02 表示批量,為03 表示中斷
_ _le16 wMa*PacketSize; //// 本端點(diǎn)接收或發(fā)送的最大信息包的大小
_ _u8 bInterval; //輪詢數(shù)據(jù)傳送端點(diǎn)的時(shí)間間隔
//對于批量傳送的端點(diǎn)以及控制傳送的端點(diǎn),此域忽略
//對于同步傳送的端點(diǎn),此域必須為 1
//對于中斷傳送的端點(diǎn),此域值的范圍為 1~255
_ _u8 bRefresh;
_ _u8 bSynchAddress;
} _ _attribute_ _ ((packed));
字符串描述符:在其他描述符中會為某些字段提供字符串索引,它們可被用來檢索描述性字符串,可以以多種語言形式提供。字符串描述符是可選的,有的設(shè)備有,有的設(shè)備沒有,字符串描述符對應(yīng)于 usb_string_descriptor 結(jié)構(gòu)體
struct usb_string_descriptor
{
_ _u8 bLength; //描述符長度
_ _u8 bDescriptorType; //描述符類型
_ _le16 wData[1];
/* 以 UTF-16LE 編碼 */
} _ _attribute_ _ ((packed));
1.4 USB 驅(qū)動程序重要數(shù)據(jù)結(jié)構(gòu)
為了符合 USB 規(guī)范的數(shù)據(jù)傳輸格式,在Linu*中定義了一組用來實(shí)現(xiàn)控制傳輸,中斷傳輸,批量傳輸,等時(shí)傳輸?shù)臄?shù)據(jù)結(jié)構(gòu):[ehci|ohci|uhci]_[itd|sitd|qh|fstn],是三個(gè)主機(jī)驅(qū)動器的核心,潤健要做的事就是把上層設(shè)備驅(qū)動傳下來的數(shù)據(jù)轉(zhuǎn)換成一個(gè)個(gè)的符合這些數(shù)據(jù)結(jié)構(gòu)要求的數(shù)據(jù)并在內(nèi)存中放好,利用這些數(shù)據(jù)結(jié)構(gòu)中定義的指針把數(shù)據(jù)鏈成鏈表,直接通過硬件傳出去。
Split Transaction Isochronous Descriptor(stid)
Isochronous (High-Speed)Transfer Descriptor(itd)
Queue Element Transfer Descriptor(qtd)
Queue Head(qh)
在主機(jī)控制器驅(qū)動上面是 USB 核心,這一塊是USB中最復(fù)雜的一塊,所幸的是與硬件無關(guān),我們只需要知道它提供了什么接口以及如何使用這些接口,不需要知道 USB 核心是如何工作的,只要使用這些 USB 核心層的 API ,把 USB 當(dāng)作通路來使用。
1.5 URB
只有站在 USB 核心層上,才能清晰看到上面提到的端點(diǎn)、接口、管道和四種傳輸類型(控制傳輸、中斷傳輸、批量傳輸、等時(shí)傳輸)等這些邏輯結(jié)構(gòu)。
在 Linu* 的架構(gòu)中,有一種數(shù)據(jù)結(jié)構(gòu)叫 URB(USB Request Block) 封裝了這些概念,作為 USB 設(shè)備驅(qū)動,要使用 USB 通路來傳輸數(shù)據(jù),就只要操控 URB 就可以了。
struct urb
{
/* 私有的:只能由 USB 核心和主機(jī)控制器訪問的字段 */
struct kref kref; /*URB 引用計(jì)數(shù) */
spinlock_t lock; /* URB 鎖 */
void *hcpriv; /* 主機(jī)控制器私有數(shù)據(jù) */
int bandwidth; /* INT/ISO 請求的帶寬 */
atomic_t use_count; /* 并發(fā)傳輸計(jì)數(shù) */
u8 reject; /* 傳輸將失敗*/
/* 公共的: 可以被驅(qū)動使用的字段 */
struct list_head urb_list; /* 鏈表頭*/
struct usb_device *dev; /* 關(guān)聯(lián)的 USB 設(shè)備 */
unsigned int pipe; /* 管道信息 */
int status; /* URB 的當(dāng)前狀態(tài) */
unsigned int transfer_flags; /* URB_SHORT_NOT_OK | ...*/
void *transfer_buffer; /* 發(fā)送數(shù)據(jù)到設(shè)備或從設(shè)備接收數(shù)據(jù)的緩沖區(qū) */
dma_addr_t transfer_dma; /*用來以 DMA 方式向設(shè)備傳輸數(shù)據(jù)的緩沖區(qū) */
int transfer_buffer_length;/*transfer_buffer 或 transfer_dma 指向緩沖區(qū)的大小*/
int actual_length; /* URB 結(jié)束后,發(fā)送或接收數(shù)據(jù)的實(shí)際長度 */
unsigned char *setup_packet; /* 指向控制 URB 的設(shè)置數(shù)據(jù)包的指針*/
dma_addr_t setup_dma; /*控制 URB 的設(shè)置數(shù)據(jù)包的 DMA 緩沖區(qū)*/
int start_frame; /*等時(shí)傳輸中用于設(shè)置或返回初始幀*/
int number_of_packets; /*等時(shí)傳輸中等時(shí)緩沖區(qū)數(shù)據(jù) */
int interval; /* URB 被輪詢到的時(shí)間間隔(對中斷和等時(shí) URB 有效) */
int error_count; /* 等時(shí)傳輸錯誤數(shù)量 */
void *conte*t; /* completion 函數(shù)上下文 */
us不忘初心omplete_t complete; /* 當(dāng) URB 被完全傳輸或發(fā)生錯誤時(shí),被調(diào)用 */
struct usb_iso_packet_descriptor iso_frame_desc[0];
/*單個(gè) URB 一次可定義多個(gè)等時(shí)傳輸時(shí),描述各個(gè)等時(shí)傳輸 */
};
1.5.1 URB 處理流程
USB 設(shè)備中的每個(gè)端點(diǎn)都處理一個(gè) URB 隊(duì)列,在隊(duì)列被清空之前,一個(gè) URB的典型生命周期如下:
(1)被一個(gè) USB 設(shè)備驅(qū)動創(chuàng)建。
創(chuàng)建 URB 結(jié)構(gòu)體的函數(shù)為:
struct urb *usb_alloc_urb(int iso_packets, int mem_flags);
urb 結(jié)構(gòu)體在驅(qū)動中不能靜態(tài)創(chuàng)建,因?yàn)檫@可能破壞 USB 核心給 URB 使用的引用計(jì)數(shù)方法。usb_alloc_urb() 的“反函數(shù)”為:
void usb_free_urb(struct urb *urb);
該函數(shù)用于釋放由 usb_alloc_urb() 分配的 urb 結(jié)構(gòu)體。
(2)初始化,被安排給一個(gè)特定 USB 設(shè)備的特定端點(diǎn)。
對于中斷 urb ,使用 usb_fill_int_urb() 函數(shù)來初始化 urb,如下所示:
void usb_fill_[control|int|bulk]_urb(
struct urb *urb,
struct usb_device *dev,
unsigned int pipe,
unsigned char *setup_packet,
void *transfer_buffer,
int buffer_length,
us不忘初心omplete_t completion_fn,
void *conte*t,
void *conte*t, int interval);
這些初始化函數(shù)使用于控制、中斷和批量數(shù)據(jù)傳輸模式,在等時(shí)傳輸下不能使用此類函數(shù)。
(3)被 USB 設(shè)備驅(qū)動提交給 USB 核心
在邏輯層上把 USB 看著一個(gè)個(gè)的 pipe ,其實(shí)主機(jī)不是與從設(shè)備的硬件直接打交道,而是與從設(shè)備中的 USB 固件( USB 從控制器的驅(qū)動)打交道。
設(shè)備驅(qū)動想要 USB 總線和設(shè)備通信,先初始化 URB 結(jié)構(gòu),把想要傳送的數(shù)據(jù)用系統(tǒng)提供 URB 操作工具填入 URB 中,然后用 usb_submit_urb 向 USB 核心提交。
int usb_submit_urb(struct urb *urb, int mem_flags);
在提交 URB 到 USB 核心后,直到完成函數(shù)被調(diào)用之前,不要能訪問URB中的任何成員。
usb_submit_urb中全調(diào)用usb_hcd_submit_urb,usb_hcd_submit_urb會找到預(yù)先制定的控制器驅(qū)動,即調(diào)用 hcd->driver->urb_equeue() ,如對ehci控制器來說,urb_enqueue 就是 ehci_urb_enqueue() ,數(shù)據(jù)走到 ehci_urb_enqueue ……(未完,全文共68081字,當(dāng)前僅顯示12245字,請閱讀下面提示信息。
收藏《畢業(yè)論文:基于Linu*的網(wǎng)絡(luò)攝像頭實(shí)現(xiàn)》)