日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

usb接口驱动_乾坤合一~Linux设备驱动之USB主机和设备驱动

發(fā)布時間:2024/2/28 linux 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 usb接口驱动_乾坤合一~Linux设备驱动之USB主机和设备驱动 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

  這一章從主機側角度看到的USB 主機控制器驅動和設備驅動從主機側的角度而言,需要編寫的USB 驅動程序包括主機控制器驅動和設備驅動兩類,USB 主機控制器驅動程序控制插入其中的USB 設備,而USB 設備驅動程序控制該設備如何作為從設備與主機通信。

1. Linux USB驅動層次

1.1 主機側與設備側USB 驅動

  USB 采用樹形拓撲結構,每條總線上只有一個主機控制器,負責協(xié)調主機和設備間的通信,而設備不能主動向主機發(fā)送任何消息。

1.2 設備、配置、接口、端點

  在USB 設備的邏輯組織中,包含設備、配置、接口和端點4 個層次,每個USB 設備都提供了不同級別的配置信息,可以包含一個或多個配置,不同的配置使設備表現(xiàn)出不同的功能組合,配置由多個接口組成,接口由多個端點組成,代表一個基本的功能,是USB 設備驅動程序控制的對象,如下圖是USB 設備、配置、接口和端點之間的關系。

  設備描述符:關于設備的通用信息,如供應商ID 、產品ID 和修訂ID,支持的設備類、子類和適用的協(xié)議以及默認端點的最大包大小等。在Linux 內核中,USB 設備用 usb_device 結構體來描述,USB 設備描述符定義為usb_device_descriptor 結構體,其代碼如下:

struct usb device descriptor{_ _u8 bLength; // 述符長度_ _u8 bDescriptorType; // 述符類型編號_ _le16 bcdUSB; //USB版本號_ _u8 bDeviceClass; //USB分配的設備類code_ _u8 bDeviceSubClass;// USB 分配的子類code_ _u8 bDeviceProtocol; //USB 分配的協(xié)議code_ _u8 bMaxPacketSize0; //endpoint0 最大包大小_ _le16 idVendor; //廠商編號_ _le16 idProduct; //產品編號_ _le16 bcdDevice; //設備出廠編號_ _u8 iManufacturer; // 述廠商字符串的索引_ _u8 iProduct; // 述產品字符串的索引_ _u8 iSerialNumber; // 述設備序列號字符串的索引_ _u8 bNumConfigurations; //可能的配置數(shù)量} _ _attribute_ _ ((packed));

  配置描述符:此配置中的接口數(shù)、支持的掛起和恢復能力以及功率要求。USB配置在內核中使用usb_host_config 結構體描述,USB 配置描述符定義為結構體usb_config_descriptor,其代碼如下:

struct usb config descriptor{_ _u8 bLength; // 述符長度_ _u8 bDescriptorType; // 述符類型編號_ _le16 wTotalLength; //配置所返回的所有數(shù)據(jù)的大小_ _u8 bNumInterfaces; // 配置所支持的接口數(shù)_ _u8 bConfigurationValue; //Set Configuration命令需要的參數(shù)值_ _u8 iConfiguration; // 述該配置的字符串的索引值_ _ u8 bmAttributes; //供電模式的選擇_ _u8 bMaxPower; //設備從總線提取的最大電流} _ _attribute_ _ ((packed));

  接口描述符:接口類、子類和適用的協(xié)議,接口備用配置的數(shù)目和端點數(shù)目。USB接口在內核中使用 usb_interface 結構體描述,USB 接口描述符定義為結構體 usb_interface_descriptor,其代碼如下:

struct usb interface descriptor{_ _u8 bLength; // 述符長度_ _u8 bDescriptorType; // 述符類型_ _ u8 bInterfaceNumber; // 接口的編號_ _u8 bAlternateSetting; //備用的接口 述符編號_ _u8 bNumEndpoints; //該接口使用的端點數(shù),不包括端點0_ _ u8 bInterfaceClass; //接口類型_ _ u8 bInterfaceSubClass; //接口子類型_ _ u8 bInterfaceProtocol; //接口所遵循的協(xié)議_ _ u8 iInterface; // 述該接口的字符串索引值} _ _attribute_ _ ((packed));

  端點描述符:端點地址、方向和類型,支持的最大包大小,如果是中斷類型的端點則還包括輪詢頻率。在 Linux 內核中,U SB 端點使用 usb_host_endpoint 結構體來描述,USB端點描述符定義為 usb_ endpoint_ descriptor 結構體,其代碼如下:

struct usb endpoint descriptor{_ _u8 bLength; // 述符長度_ _u8 bDescriptorType; // 述符類型_ _u8 bEndpointAddress; //端點地址:0 ~3 位是端點號,第 7 位是方向 (0-OUT,1-IN)_ _ u8 bmAttributes; //端點屬性:bit[0:1] 的值為00表示控制,為01表示同步,為02表示批量,為03表示中_ _le16 wMaxPacketSize; 本端點接收或發(fā)送的最大信息包的大小_ _u8 bInterval; //輪詢數(shù)據(jù)傳送端點的時間間隔//對于批量傳送的端點以及控制傳送的端點,此域忽略//對于同步傳送的端點,此域必須為1//對于中 傳送的端點,此域值的范圍為1~255_ _u8 bRefresh;_ _u8 bSynchAddress;} _ _attribute_ _ ((packed));

  字符串描述符:在其他描述符中會為某些字段提供字符串索引,它們被用來檢索描述性字符串,可以以多種語言形式提供。字符串描述符是可選的,有的設備有,有的設備沒有 ,字符 串描述符對應于usb_string_ descriptor 結構體,其代碼如下:

struct usb string descriptor{_ _u8 bLength; // 述符長度_ _u8 bDescriptorType; // 述符類型_ _le16 wData [1]; /* 以UTF-16LE編碼 */} _ _attribute_ _ ((packed));

2 USB主機驅動

USB 主機控制器有 3 種規(guī)格:OHCI (Open Host Controller Interface) 、UHCI (Universal Host Controller Interface) 和EHCI (Enhanced Host Controller Interface) 。

2.1 主機控制器驅動

  在Linux 內核中,用usb_hcd 結構體描述USB 主機控制器驅動,它包含USB 主機控制器的 “家務”信息、硬件資源、狀態(tài)描述和用于操作主機控制器的 hc_driver等,其代碼如下:

struct usb hcd{/* 管理 “家務” */struct usb bus self;const char *product desc; /* 產品/廠商字符串 */char irq descr [24]; /* 驅動 + 總線 # */struct timer list rh timer; /* 根Hub 輪詢 */struct urb *status urb; /* 目前的狀態(tài)urb *//* 硬件信息/狀態(tài) */const struct hc driver *driver; /* 硬件特定的鉤子函數(shù) *//* 需要維護的標志 */unsigned long flags;#define HCD FLAG HW ACCESSIBLE 0x00000001#define HCD FLAG SAW IRQ 0x00000002unsigned rh_registered: 1; /* 根Hub 注冊? *//* 下一個標志的采用只是 “權益之計”,當所有HCDs 支持新的根Hub 輪詢機制后將移除 */unsigned uses new polling: 1;unsigned poll rh: 1; /* 輪詢根Hub 狀態(tài)? */unsigned poll pending: 1; /* 狀態(tài)已經改變? */int irq; /* 被分配的irq */ <br>void _ _iomem *regs; /* 設備內存和I/O */u64 rsrc start; /* 內存和I/O資源開始位置 */u64 rsrc len; /* 內存和I/O資源長度 */unsigned power budget; /* mA, 0 = 無限制 */#define HCD BUFFER POOLS 4struct dma pool *pool[HCD BUFFER POOLS];int state;#define ACTIVE 0x01#define SUSPEND 0x04#define TRANSIENT 0x80#define HC STATE HALT 0#define 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)/* 主機控制器驅動的私有數(shù)據(jù) */ <br>unsigned long hcd priv [0] attribute ((aligned (sizeof(unsigned long))));};

  Linux中采用以下函數(shù)創(chuàng)建HCD:

struct usb hcd *usb create hcd (const struct hc driver *driver, struct device *dev, char *bus name);

  以下函數(shù)用來增加和移除:

int usb add hcd (struct usb hcd *hcd, unsigned int irqnum, unsigned long irqflags); void usb remove hcd (struct usb hcd *

2.2 OHCI 主機控制器驅動

  OHCI HCD 驅動屬于HCD 驅動的實例,它定義了一個ohci_hcd 結構體,使用如下內聯(lián)函數(shù)可實現(xiàn)usb_hcd 和ohci_hcd 的相互轉換:

struct ohci hcd *hcd to ohci (struct usb hcd *hcd); struct usb hcd *ohci to hcd (const struct ohci hcd *ohci);

  從usb_hcd 得到ohci_hcd 只是取得“私有”數(shù)據(jù),而從ohci_hcd 得到usb_hcd 則是通過container_of()從結構體成員獲得結構體指,使用如下函數(shù)可初始化OHCI 主機控制器:

int ohci init (struct ohci hcd *ohci);

如下函數(shù)分別用于開啟、停止及復位OHCI 控制器:

int ohci run (struct ohci hcd *ohci); void ohci stop (struct usb hcd *hcd); void ohci usb reset (struct ohci hcd *ohci);

3 USB設備驅動

3.1 USB設備驅動整體結構

有以下設備類

  • 音頻設備類。
  • 通信設備類。
  • HID (人機接口)設備類。
  • 顯示設備類。
  • 海量存儲設備類。
  • 電源設備類。
  • 打印設備類。
  • 集線器設備類。

  Linux 內核為各類USB 設備分配了相應的設備號,內核中提供了USB 設備文件系統(tǒng) (usbdevfs,Linux 2.6 改為usbfs,即USB 文件系統(tǒng)),它和/proc 類似,都是動態(tài)產生的。通過在/etc/fstab 文件中添加如下一行:

none /proc/bus/usb usbfs defaults

或者輸入命令:

mount -t usbfs none /proc/bus/usb

可以實現(xiàn)USB 設備文件系統(tǒng)的掛載。

  此外,在sysfs 文件系統(tǒng)中,同樣包含了USB 相關信息的描述,但只限于接口級別。USB 設備和USB 接口在sysfs 中均表示為單獨的USB 設備,其目錄命名規(guī)則如下:

根集線器-集線器端口號 (-集線器端口號-...):配置.接口。

3.2 USB請求塊(URB)

  USB 請求塊 (USB request block,urb )是USB 設備驅動中用來描述與USB 設備通信所用的基本載體和核心數(shù)據(jù)結構,非常類似于網絡設備驅動中的sk_buff 結構體,是USB 主機與設備通信的 “電波”,urb 結構體,代碼如下:

struct urb{/* 私有的:只能由USB核心和主機控制器訪問的字段 */struct kref kref; /*urb 引用計數(shù) */spinlock t lock; /* urb鎖 */void *hcpriv; /* 主機控制器私有數(shù)據(jù) */int bandwidth; /* INT/ISO請求的帶寬 */atomic t use count; /* 并發(fā)傳輸計數(shù) */u8 reject; /* 傳輸將失敗*//* 公共的: 可以被驅動使用的字段 */struct list head urb list; /* 鏈表頭*/struct usb device *dev; /* 關聯(lián)的USB 設備 */unsigned int pipe; /* 管道信息 */int status; /* URB 的當前狀態(tài) */ unsigned int transfer flags; /* URB SHORT NOT OK | ...*/void *transfer buffer; /* 發(fā)送數(shù)據(jù)到設備或從設備接收數(shù)據(jù)的緩沖區(qū) */dma addr t transfer dma; /*用來以DMA 方式向設備傳輸數(shù)據(jù)的緩沖區(qū) */int transfer buffer length;/*transfer buffer 或 transfer dma 指向緩沖區(qū)的大小 */ int actual length; /* URB 結束后,發(fā)送或接收數(shù)據(jù)的實際長度 */unsigned char *setup packet; /* 指向控制URB 的設置數(shù)據(jù)包的指針*/dma addr t setup dma; /*控制URB 的設置數(shù)據(jù)包的DMA 緩沖區(qū)*/int start frame; /*等時傳輸中用于設置或返回初始幀*/int number of packets; /*等時傳輸中等時緩沖區(qū)數(shù)據(jù) */int interval; /* URB被輪詢到的時間間隔 (對中 和等時urb 有效) */int error count; /* 等時傳輸錯誤數(shù)量 */void *context; /* completion 函數(shù)上下文 */usb complete t complete; /* 當URB 被完全傳輸或發(fā)生錯誤時,被調用 */struct usb iso packet descriptor iso frame desc[0];/*單個URB 一次可定義多個等時傳輸時,描述各個等時傳輸 */};

  USB 設備中的每個端點都處理一個urb 隊列,在隊列被清空之前,一個urb 的典型生命周期有以下幾個過程:

  • 被一個 USB設備驅動創(chuàng)建
  • 初始化,被安排給一個特定USB 設備的特定端點
  • 被USB 設備驅動提交給USB
  • 提交由USB 核心指定的USB 主機控制器驅動。
  • 被USB 主機控制器處理,進行一次到USB 設備的傳送。
  • 當urb 完成,USB 主機控制器驅動通知USB 設備驅動
  • 3.3 簡單的批量與控制URB

    1)usb_bulk_msg()

    usb_bulk_msg()函數(shù)創(chuàng)建一個USB 批量urb 并將它發(fā)送到特定設備,這個函數(shù)是同步的,它一直等待urb 完成后才返回。usb_bulk_msg()函數(shù)的原型為:

    int usb bulk msg (struct usb device *usb dev, unsigned int pipe, void *data, int len, int *actual length, int timeout); //usb_dev 參數(shù)為批量消息要發(fā)送的USB //設備的指 ,pipe 為批量消息要發(fā)送到的 USB 設備的端點,data 參數(shù)為指向要發(fā)送或接收的數(shù)據(jù) //緩沖區(qū)的指 ,len 參數(shù)為data 參數(shù)//所指向的緩沖區(qū)的長度,actual_length 用于返回實際發(fā)送 //或接收的字節(jié)數(shù),timeout 是發(fā)送超時,以ji ffies 為單位,0 意味著永遠等待。 // 如果函數(shù)調用成功,返回0 ;否則,返回1 個負的錯誤值。

    2 )usb_control_msg()函數(shù)

    usb_control_msg() 函數(shù)與 usb_bulk_msg() 函數(shù)類似,不過它提供驅動發(fā)送和結束USB 控制信息而非批量信息的能力,該函數(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); //dev 指向控制消息發(fā)往的USB 設備,pipe 是控制消息要發(fā)往的USB 設備的端點, request 是這個控制消息的USB 請求值,requesttype 是這個控制消息的USB 請求類型, //value 是這個控制消息的USB 消息值,index 是這個控制消息的USB 消息索引值,data 指向要發(fā)送或接收的數(shù)據(jù)緩沖區(qū),size

    3) 探測和斷開函數(shù)

    在USB 設備驅動usb_driver 結構體的探測函數(shù)中,應該完成如下工作:

    • 探測設備的端點地址、緩沖區(qū)大小,初始化任何可能用于控制 USB 設備的數(shù)據(jù)結構。
    • 把已初始化數(shù)據(jù)結構的指 保存到接口設備中
    • 注冊USB 設備

      對探測函數(shù)的調用發(fā)生在USB 設備被安裝且USB 核心認為該驅動程序與安裝的USB 設備對應時 (usb_driver 的id_table 成員在此時發(fā)揮作用),而對斷開函數(shù)的調用則發(fā)生在驅動因為種種原因不再控制該設備的時候。對這兩個函數(shù)的調用都是在內核線程中進行的.

    4) USB 骨架程序

      Linux 內核源代碼中的 driver/usb/usb-skeleton.c 文件為我們提供了一個最基礎的USB 驅動程序,即USB 骨架程序,可被看做一個最簡單的USB 設備驅動實例。盡管USB驅動驅動程序千差萬別,但是骨架程序萬變不離其宗。這里我也不多介紹啦~

    總結

    以上是生活随笔為你收集整理的usb接口驱动_乾坤合一~Linux设备驱动之USB主机和设备驱动的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。