題目: 基于Linu*的網(wǎng)絡(luò)攝像頭實(shí)現(xiàn)
院(系) 信息科學(xué)與工程學(xué)院
專(zhuān) 業(yè) 電子科學(xué)與技術(shù)
摘要
本項(xiàng)目通過(guò)編寫(xiě)Linu*下的USB攝像頭驅(qū)動(dòng),在Linu*下編寫(xiě)QT程序完成本項(xiàng)目目標(biāo)。Linu*是開(kāi)源的可移植的操作系統(tǒng)內(nèi)核,QT是一個(gè)跨平臺(tái)的C++圖形用戶(hù)界面應(yīng)用程序框架,它提供給應(yīng)用程序開(kāi)發(fā)者建立藝術(shù)級(jí)的圖形用戶(hù)界面所需的所有功能。QT能將在其上開(kāi)發(fā)的應(yīng)用程序移植到PC和嵌入式設(shè)備上,進(jìn)而可以實(shí)現(xiàn)嵌入式Linu*上的圖像采集。
本文圍繞USB, Linu*下USB驅(qū)動(dòng)程序開(kāi)發(fā),和V4L2框架編程3個(gè)方面進(jìn)行研究。詳細(xì)敘述了USB驅(qū)動(dòng)原理,Linu*下的USB的驅(qū)動(dòng)程序數(shù)據(jù)結(jié)構(gòu)和一般驅(qū)動(dòng)程序的開(kāi)發(fā)過(guò)程,攝像頭驅(qū)動(dòng)的開(kāi)發(fā),和V4L2框架下的應(yīng)用程序開(kāi)發(fā)。
關(guān)鍵字:Linu*,USB,USB驅(qū)動(dòng),V4L2,攝像頭驅(qū)動(dòng),圖像采集
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ū)動(dòng)原理 5
1.1 USB基礎(chǔ)知識(shí) 5
1.1.2 USB 的優(yōu)勢(shì) 6
1.1.3 USB 數(shù)據(jù)傳輸 6
1.1.4 USB協(xié)議 7
1.2 USB驅(qū)動(dòng)結(jié)構(gòu) 8
1.3 USB 主機(jī)控制器驅(qū)動(dòng)結(jié)構(gòu) 9
1.3.1 主機(jī)控制器驅(qū)動(dòng) 9
1.4 USB 主機(jī)邏輯組織 13
1.4 USB 驅(qū)動(dòng)程序重要數(shù)據(jù)結(jié)構(gòu) 16
1.5 URB 18
1.5.1 URB 處理流程 19
1.5.2 簡(jiǎn)單的批量和控制 URB 21
1.6 USB 設(shè)備的識(shí)別過(guò)程 24
1.7 USB 設(shè)備類(lèi)驅(qū)動(dòng) 25
第二章USB攝像頭驅(qū)動(dòng) 27
2.1 攝像頭工作原理 27
2.2通用攝像頭驅(qū)動(dòng)開(kāi)發(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簡(jiǎn)介 39
3.2 程序關(guān)鍵步驟介紹 40
3.3 UDP傳輸圖像 43
參考文獻(xiàn) 44
結(jié)論 45
英文翻譯 46
附錄 60
第一章 USB驅(qū)動(dòng)原理
USB 是英文”Universal Serial Bus”的縮寫(xiě),意為”通用串行總線(xiàn)”。是由 compaq(康柏)、DEC、Intel、IBM、NEC、微軟以 及Northern Telecom (北方電訊)等公司于1994年11月共同提出的,主要目的就是為了解決接口標(biāo)準(zhǔn)太多的弊端。USB使用一個(gè)4針插頭作為標(biāo)準(zhǔn)插頭,并通過(guò)這個(gè)標(biāo)準(zhǔn)接頭,采用菊花瓣形式把所有外設(shè)連接起來(lái),它采用串行方式傳輸數(shù)據(jù),目前最大數(shù)據(jù)傳輸率為12Mbps,支持多數(shù)據(jù)流和多個(gè)設(shè)備并行操作,允許外設(shè)熱插拔。
USB 攝像頭不但具有體積小、重量輕、功耗小、工作電壓低和抗燒毀等優(yōu)點(diǎn),而且在分辨率、動(dòng)態(tài)范圍、靈敏度、實(shí)時(shí)傳輸和自?huà)呙璧确矫娴膬?yōu)越性,也是其它攝像器件無(wú)法比擬的。目前,USB 攝像頭已在航空航天、衛(wèi)星偵察、遙感遙測(cè)、天文測(cè)量、傳真、靜電復(fù)印、非接觸工業(yè)測(cè)量、光學(xué)圖像處理、圖文識(shí)別、數(shù)據(jù)存儲(chǔ)等領(lǐng)域得到了廣泛的應(yīng)用。
1.1 USB基礎(chǔ)知識(shí)
目前 USB 接口雖然只發(fā)展了 2 代( USB1.0/1.1,USB2.0 ),但是USB綜合了一個(gè)多平臺(tái)標(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 通道等)。無(wú)論是串口還是并口都是點(diǎn)對(duì)點(diǎn)的連接,一個(gè)接口僅支持一個(gè)設(shè)備。因此每添加一個(gè)新的設(shè)備,就需要添加一個(gè) ISA/EISA 或 PCI 卡,同時(shí)系統(tǒng)需要重新啟動(dòng)才能驅(qū)動(dòng)新的設(shè)備。而采用 USB 接口則可以避免這類(lèi)的問(wèn)題,不但節(jié)省系統(tǒng)的資源而且使用起來(lái)非常方便。
USB 第一版的規(guī)范定為 1.1,其最大傳輸速率為12Mbps,最多可支持127個(gè) USB外設(shè)連接到計(jì)算機(jī)系統(tǒng),它的物理結(jié)構(gòu)為星型,也就是說(shuō),即使主板上只有一個(gè)USB 接口,只要能找到合適的 USB Hub ,就
……(新文秘網(wǎng)http://m.jey722.cn省略4360字,正式會(huì)員可完整閱讀)……
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ū)動(dòng)的私有數(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)品/廠(chǎng)商字符串 */
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 停止寫(xiě)內(nèi)存和進(jìn)行 I/O 操作*/
void(*stop)(struct usb_hcd *hcd);
/* 返回目前的幀數(shù) */
int(*get_frame_number)(struct usb_hcd *hcd);
/* 管理 I/O 請(qǐng)求和設(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ù)來(lái)創(chuàng)建 HCD:
struct usb_hcd *us不忘初心reate_hcd (const struct hc _driver *driver,struct device *dev, char *bus_name);
如下函數(shù)被用來(lái)增加和移除 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ù)分別用于開(kāi)啟、停止及復(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ū)動(dòng)中的最頂層驅(qū)動(dòng),即USB設(shè)備的邏輯組織,包含了設(shè)備、配置、接口3個(gè)層次。
每個(gè) USB 設(shè)備都提供了不同級(jí)別的配置信息,可以包含一個(gè)或多個(gè)配置,不同的配置使設(shè)備表現(xiàn)出不同的功能組合(在探測(cè)/連接期間需從其中選定一個(gè)),配置由多個(gè)接口組成。
在 USB 協(xié)議中,接口由多個(gè)端點(diǎn)組成,代表一個(gè)基本的功能,是 USB 設(shè)備驅(qū)動(dòng)程序控制的對(duì)象,一個(gè)功能復(fù)雜的 USB 設(shè)備可以具有多個(gè)接口。每個(gè)配置中可以有多個(gè)接口,而設(shè)備接口是端點(diǎn)的匯集(collection)。例如 USB 揚(yáng)聲器可以包含一個(gè)音頻接口以及對(duì)旋鈕和按鈕的接口。一個(gè)配置中的所有接口可以同時(shí)有效,并可被不同的驅(qū)動(dòng)程序連接。每個(gè)接口可以有備用接口,以提供不同質(zhì)量的服務(wù)參數(shù)。
端點(diǎn)是 USB 通信的最基本形式,每一個(gè) USB 設(shè)備接口在主機(jī)看來(lái)就是一個(gè)端點(diǎn)的集合。主機(jī)只能通過(guò)端點(diǎn)與設(shè)備進(jìn)行通信,以使用設(shè)備的功能。 USB 系統(tǒng)中每一個(gè)端點(diǎn)都有惟一的地址,在這是由設(shè)備地址和端點(diǎn)號(hào)給出的。每個(gè)端點(diǎn)都有一定的屬性,其中包括傳輸方式、總線(xiàn)訪(fǎng)問(wèn)頻率、帶寬、端點(diǎn)號(hào)和數(shù)據(jù)包的最大容量等。一個(gè) USB 端點(diǎn)只能在一個(gè)方向承載數(shù)據(jù),或者從主機(jī)到設(shè)備(稱(chēng)為輸出端點(diǎn)),或者從設(shè)備到主機(jī)(稱(chēng)為輸入端點(diǎn)),因此端點(diǎn)可看作一個(gè)單向的管道。端點(diǎn) 0 通常為控制端點(diǎn),用于設(shè)備初始化參數(shù)等。只要設(shè)備連接到 USB 上并且上電端點(diǎn) 0 就可以被訪(fǎng)問(wèn)。端點(diǎn) 1、2 等一般用作數(shù)據(jù)端點(diǎn),存放主機(jī)與設(shè)備間往來(lái)的數(shù)據(jù)。
USB 設(shè)備非常復(fù)雜,由許多不同的邏輯單元組成,這些單元之間的關(guān)系如下:
設(shè)備通常有一個(gè)或多個(gè)配置;
配置通常有一個(gè)或多個(gè)接口;
接口通常有一個(gè)或多個(gè)設(shè)置;
接口有零或多個(gè)端點(diǎn)。
這種層次化配置信息在設(shè)備中通過(guò)一組標(biāo)準(zhǔn)的描述符來(lái)描述,如下所示。
設(shè)備描述符:關(guān)于設(shè)備的通用信息,如供應(yīng)商 ID、產(chǎn)品 ID 和修訂 ID,支持的設(shè)備類(lèi)、子類(lèi)和適用的協(xié)議以及默認(rèn)端點(diǎn)的最大包大小等。在 Linu* 內(nèi)核中, USB 設(shè)備用 usb_device 結(jié)構(gòu)體來(lái)描述, USB 設(shè)備描述符定義為 usb_device_descriptor 結(jié)構(gòu)體
struct usb_device_descriptor
{
_ _u8 bLength; //描述符長(zhǎng)度
_ _u8 bDescriptorType; //描述符類(lèi)型編號(hào)
_ _le16 bcdUSB; //USB 版本號(hào)
_ _u8 bDeviceClass; //USB 分配的設(shè)備類(lèi) code
_ _u8 bDeviceSubClass;// USB 分配的子類(lèi) code
_ _u8 bDeviceProtocol; //USB 分配的協(xié)議 code
_ _u8 bMa*PacketSize0; //endpoint0 最大包大小
_ _le16 idVendor; //廠(chǎng)商編號(hào)
_ _le16 idProduct; //產(chǎn)品編號(hào)
_ _le16 bcdDevice; //設(shè)備出廠(chǎng)編號(hào)
_ _u8 iManufacturer; //描述廠(chǎng)商字符串的索引
_ _u8 iProduct; //描述產(chǎn)品字符串的索引
_ _u8 iSerialNumber; //描述設(shè)備序列號(hào)字符串的索引
_ _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; //描述符長(zhǎng)度
_ _u8 bDescriptorType; //描述符類(lèi)型編號(hào)
_ _le16 wTotalLength; //配置所返回的所有數(shù)據(jù)的大小
_ _u8 bNumInterfaces; // 配置所支持的接口數(shù)
_ _u8 bConfigurationValue; //Set_Configuration 命令需要的參數(shù)值
_ _u8 iConfiguration; //描述該配置的字符串的索引值
_ _u8 bmAttributes; //
供電模式的選擇
_ _u8 bMa*Power; //設(shè)備從總線(xiàn)提取的最大電流
} _ _attribute_ _ ((packed));
接口描述符:接口類(lèi)、子類(lèi)和適用的協(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;
//描述符長(zhǎng)度
_ _u8 bDescriptorType; //描述符類(lèi)型
_ _u8 bInterfaceNumber;
// 接口的編號(hào)
_ _u8 bAlternateSetting; //備用的接口描述符編號(hào)
_ _u8 bNumEndpoints;
//該接口使用的端點(diǎn)數(shù),不包括端點(diǎn) 0
_ _u8 bInterfaceClass;
//接口類(lèi)型
_ _u8 bInterfaceSubClass; //接口子類(lèi)型
_ _u8 bInterfaceProtocol; //接口所遵循的協(xié)議
_ _u8 iInterface; //描述該接口的字符串索引值
} _ _attribute_ _ ((packed));
端點(diǎn)描述符:端點(diǎn)地址、方向和類(lèi)型,支持的最大包大小,如果是中斷類(lèi)型的端點(diǎn)則還包括輪詢(xún)頻率。在 Linu* 內(nèi)核中,USB 端點(diǎn)使用 usb_host_endpoint 結(jié)構(gòu)體來(lái)描述, USB 端點(diǎn)描述符定義為 usb_endpoint_descriptor 結(jié)構(gòu)體
struct usb_endpoint_descriptor
{
_ _u8 bLength; //描述符長(zhǎng)度
_ _u8 bDescriptorType; //描述符類(lèi)型
_ _u8 bEndpointAddress; //端點(diǎn)地址:0~3 位是端點(diǎn)號(hào),第 7 位是方向(0-OUT,1-IN)
_ _u8 bmAttributes; //端點(diǎn)屬性:bit[0:1] 的值為00 表示控制,為01 表示同步,為02 表示批量,為03 表示中斷
_ _le16 wMa*PacketSize; //// 本端點(diǎn)接收或發(fā)送的最大信息包的大小
_ _u8 bInterval; //輪詢(xún)數(shù)據(jù)傳送端點(diǎn)的時(shí)間間隔
//對(duì)于批量傳送的端點(diǎn)以及控制傳送的端點(diǎn),此域忽略
//對(duì)于同步傳送的端點(diǎn),此域必須為 1
//對(duì)于中斷傳送的端點(diǎn),此域值的范圍為 1~255
_ _u8 bRefresh;
_ _u8 bSynchAddress;
} _ _attribute_ _ ((packed));
字符串描述符:在其他描述符中會(huì)為某些字段提供字符串索引,它們可被用來(lái)檢索描述性字符串,可以以多種語(yǔ)言形式提供。字符串描述符是可選的,有的設(shè)備有,有的設(shè)備沒(méi)有,字符串描述符對(duì)應(yīng)于 usb_string_descriptor 結(jié)構(gòu)體
struct usb_string_descriptor
{
_ _u8 bLength; //描述符長(zhǎng)度
_ _u8 bDescriptorType; //描述符類(lèi)型
_ _le16 wData[1];
/* 以 UTF-16LE 編碼 */
} _ _attribute_ _ ((packed));
1.4 USB 驅(qū)動(dòng)程序重要數(shù)據(jù)結(jié)構(gòu)
為了符合 USB 規(guī)范的數(shù)據(jù)傳輸格式,在Linu*中定義了一組用來(lái)實(shí)現(xiàn)控制傳輸,中斷傳輸,批量傳輸,等時(shí)傳輸?shù)臄?shù)據(jù)結(jié)構(gòu):[ehci|ohci|uhci]_[itd|sitd|qh|fstn],是三個(gè)主機(jī)驅(qū)動(dòng)器的核心,潤(rùn)健要做的事就是把上層設(shè)備驅(qū)動(dòng)傳下來(lái)的數(shù)據(jù)轉(zhuǎn)換成一個(gè)個(gè)的符合這些數(shù)據(jù)結(jié)構(gòu)要求的數(shù)據(jù)并在內(nèi)存中放好,利用這些數(shù)據(jù)結(jié)構(gòu)中定義的指針把數(shù)據(jù)鏈成鏈表,直接通過(guò)硬件傳出去。
Split Transaction Isochronous Descriptor(stid)
Isochronous (High-Speed)Transfer Descriptor(itd)
Queue Element Transfer Descriptor(qtd)
Queue Head(qh)
在主機(jī)控制器驅(qū)動(dòng)上面是 USB 核心,這一塊是USB中最復(fù)雜的一塊,所幸的是與硬件無(wú)關(guān),我們只需要知道它提供了什么接口以及如何使用這些接口,不需要知道 USB 核心是如何工作的,只要使用這些 USB 核心層的 API ,把 USB 當(dāng)作通路來(lái)使用。
1.5 URB
只有站在 USB 核心層上,才能清晰看到上面提到的端點(diǎn)、接口、管道和四種傳輸類(lèi)型(控制傳輸、中斷傳輸、批量傳輸、等時(shí)傳輸)等這些邏輯結(jié)構(gòu)。
在 Linu* 的架構(gòu)中,有一種數(shù)據(jù)結(jié)構(gòu)叫 URB(USB Request Block) 封裝了這些概念,作為 USB 設(shè)備驅(qū)動(dòng),要使用 USB 通路來(lái)傳輸數(shù)據(jù),就只要操控 URB 就可以了。
struct urb
{
/* 私有的:只能由 USB 核心和主機(jī)控制器訪(fǎng)問(wèn)的字段 */
struct kref kref; /*URB 引用計(jì)數(shù) */
spinlock_t lock; /* URB 鎖 */
void *hcpriv; /* 主機(jī)控制器私有數(shù)據(jù) */
int bandwidth; /* INT/ISO 請(qǐng)求的帶寬 */
atomic_t use_count; /* 并發(fā)傳輸計(jì)數(shù) */
u8 reject; /* 傳輸將失敗*/
/* 公共的: 可以被驅(qū)動(dòng)使用的字段 */
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; /*用來(lái)以 DMA 方式向設(shè)備傳輸數(shù)據(jù)的緩沖區(qū) */
int transfer_buffer_length;/*transfer_buffer 或 transfer_dma 指向緩沖區(qū)的大小*/
int actual_length; /* URB 結(jié)束后,發(fā)送或接收數(shù)據(jù)的實(shí)際長(zhǎng)度 */
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 被輪詢(xún)到的時(shí)間間隔(對(duì)中斷和等時(shí) URB 有效) */
int error_count; /* 等時(shí)傳輸錯(cuò)誤數(shù)量 */
void *conte*t; /* completion 函數(shù)上下文 */
us不忘初心omplete_t complete; /* 當(dāng) URB 被完全傳輸或發(fā)生錯(cuò)誤時(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ū)動(dòng)創(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ū)動(dòng)中不能靜態(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)。
對(duì)于中斷 urb ,使用 usb_fill_int_urb() 函數(shù)來(lái)初始化 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í)傳輸下不能使用此類(lèi)函數(shù)。
(3)被 USB 設(shè)備驅(qū)動(dòng)提交給 USB 核心
在邏輯層上把 USB 看著一個(gè)個(gè)的 pipe ,其實(shí)主機(jī)不是與從設(shè)備的硬件直接打交道,而是與從設(shè)備中的 USB 固件( USB 從控制器的驅(qū)動(dòng))打交道。
設(shè)備驅(qū)動(dòng)想要 USB 總線(xiàn)和設(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)用之前,不要能訪(fǎng)問(wèn)URB中的任何成員。
usb_submit_urb中全調(diào)用usb_hcd_submit_urb,usb_hcd_submit_urb會(huì)找到預(yù)先制定的控制器驅(qū)動(dòng),即調(diào)用 hcd->driver->urb_equeue() ,如對(duì)ehci控制器來(lái)說(shuō),urb_enqueue 就是 ehci_urb_enqueue() ,數(shù)據(jù)走到 ehci_urb_enqueue ……(未完,全文共68081字,當(dāng)前僅顯示12245字,請(qǐng)閱讀下面提示信息。
收藏《畢業(yè)論文:基于Linu*的網(wǎng)絡(luò)攝像頭實(shí)現(xiàn)》)