欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

標題: 學習筆記-USB數據結構和相應接口2 [打印本頁]

作者: 51hei小林    時間: 2016-9-24 22:22
標題: 學習筆記-USB數據結構和相應接口2
本帖最后由 51hei小林 于 2016-9-24 22:29 編輯

1、Linux USB架構
      
運行Linux的USB主機
   
      
      
   
      
    運行Linux的USB設備      
   
      
USB設備驅動(*)
   
      
Gadget驅動(*)
   
      
USB核心(Core)
   
      
Gadget API
   
      
USB主控制器驅動(UHCI\OHCI\EHCI)
   
      
UDC驅動
   
      
USB主控制器
   
      
USB主控制器
   
      
||=================== 物理電氣連接 ===============||
   

2、Linux USB設備驅動程序在Linux所扮演的角色
      
用戶層 (各種基于USB的設備: USB網卡、USB串口、U盤、移動硬盤、USB聲卡)
   
      
VFS layer
   
      
Block layer
      
(U盤)
   
      
Net layer
      
(USB網卡)
   
      
Char layer
   
      
TTY layer
      
(USB串口)
   
      
   
      
USB設備驅動 (位于不同的內核子系統和USB主控制器直接)
   
      
USB核心層 (為USB驅動提供一個訪問和控制USB控制器的軟件接口,使其不必考慮USB硬件控制器)
   
      
USB主控制器
   
      
硬件層
   

3、USB設備、配置、接口、端點與驅動之間的關系。
一個設備可能有多個配置,一個配置可以擁有多種接口(功能),每個接口(功能)對應一個USB驅動。
例如:
    我們要為一個電視機增加一個USB接口,可以通過接入筆記本來播放筆記本中各種視頻或者音樂。那么電視機就是一個USB設備。
    若電視劇具備視頻、音頻兩種功能,那么就可以使用兩個接口來對應視頻、音頻功能。這兩個接口使用兩個USB驅動來編寫,一個對應視頻子系統、一個對應音頻子系統。
    對于端點,視頻需要傳輸圖像數據、分配率控制等可以通過兩個端點來負責傳輸。音頻需要傳輸音頻、音量、音效等數據,可以通過三個端點來負責傳輸。
4、Linux USB driver 相關的數據結構




/* USB 驅動結構體,每個USB驅動都會需要這個結構體 */

struct usb_driver {

    // USB 名字(可以在 /sys/bus/usb/drivers/ 看到)

    const char *name;

    // 當 USB 核心發現了(id_table)該驅動能夠處理USB接口就會回調該函數。

    int (*probe) (struct usb_interface *intf, const struct usb_device_id *id);

    // 當相應的 USB 接口被移除時,會回調該函數用于釋放某些資源

    void (*disconnect) (struct usb_interface *intf);

    // ...

    // 本 USB 驅動能夠處理的設備列表(只要能符合此設備列表就會回調 probe()函數)

    const struct usb_device_id *id_table;

    // ...

};



/* 聲明本驅動所支持的USB類型/設備 */

struct usb_device_id {

    /* which fields to match against? */

    __u16        match_flags;



    /* Used for product specific matches; range is inclusive */

    // 設置這組代表是一個具體的設備(羅技的鼠標)

    __u16        idVendor;        // 制造商 ID 由 USB 組織給某個廠商分配的

    __u16        idProduct;        // 產品 ID

    __u16        bcdDevice_lo;

    __u16        bcdDevice_hi;



    /* Used for device class matches */

    // 設置這組代表是一類設備(例如 USB HID 類型)

    __u8        bDeviceClass;    // 指定某種具體的識別

    __u8        bDeviceSubClass;

    __u8        bDeviceProtocol;



    /* Used for interface class matches */

    __u8        bInterfaceClass;

    __u8        bInterfaceSubClass;

    __u8        bInterfaceProtocol;



    /* not matched against */

    kernel_ulong_t    driver_info;

};


構造一個設備的宏: USB_DEVICE(vend, prod)
    vend: 廠商ID  由 USB 組織統一給每個廠商分配
    prod: 產品ID  廠商自行分配
例子: 構造一個具體的 USB OV511 攝像頭
    #define VEND_OMNIVISION 0x05A9   
    #define PROD_OV511        0x0511   
    USB_DEVICE(VEND_OMNIVISION, PROD_OV511)
構造一類設備的宏: USB_INTERFACE_INFO(cl, sc, pr)
    cl: blnterfaceClass value 類
    sc: blnterfaceSubClass value 子類
    pr: blnterfaceProtocol value 所遵循的協議
例子: 構造一個鼠標類型的 USB 驅動
    USB_INTERFACE_INFO(    USB_INTERFACE_CLASS_HID,
                        USB_INTERFACE_SUBCLASS_BOOT,
                        USB_INTERFACE_PROTOCOL_MOUSE)
注冊一個USB驅動:
static inline int usb_register(struct usb_driver *driver)                  
5、usb devices 相關的數據結構

/* USB 設備 */

struct usb_device {

    // USB 設備號

    int        devnum;

    // 設備 ID 字符串

    char        devpath[16];

    u32        route;

    // 設備狀態: 未連接,已配置

    enum usb_device_state    state;

    // 高速\全速\低速

    enum usb_device_speed    speed;

    //...

    struct device dev;

    // USB 設備描述符

    struct usb_device_descriptor descriptor;

    struct usb_host_config *config;

    //...

    /* static strings from the device */

    char *product;            // 產品名

    char *manufacturer;        // 廠商名

    char *serial;            // 設備串號



    //...

};



/* USB 設備描述符 USB 協議規定 261(290/60)頁 */

struct usb_device_descriptor {

    __u8  bLength;//設備描述符的字節數大小,為0x12

    __u8  bDescriptorType;//描述符類型編號,為0x01



    __le16 bcdUSB;//USB版本號

    __u8  bDeviceClass;//USB分配的設備類代碼,0x01~0xfe為標準設備類,0xff為廠商自定義類型



    //0x00不是在設備描述符中定義的,如HID

    __u8  bDeviceSubClass;//usb分配的子類代碼,同上,值由USB規定和分配的

    __u8  bDeviceProtocol;//USB分配的設備協議代碼,同上

    __u8  bMaxPacketSize0;//端點0的最大包的大小

    __le16 idVendor;//廠商編號

    __le16 idProduct;//產品編號

    __le16 bcdDevice;//設備出廠編號

    __u8  iManufacturer;//描述廠商字符串的索引

    __u8  iProduct;//描述產品字符串的索引

    __u8  iSerialNumber;//描述設備序列號字符串的索引

    __u8  bNumConfigurations;//可能的配置數量

} __attribute__ ((packed));



/* 描述一個配置 Linux 特有*/

struct usb_host_config {

    // USB 配置描述符

    struct usb_config_descriptor    desc;



    char *string;        /* iConfiguration string, if present */



    /* List of any Interface Association Descriptors in this

    * configuration. */

    struct usb_interface_assoc_descriptor *intf_assoc[USB_MAXIADS];



    /* the interfaces associated with this configuration,

    * stored in no particular order */

    struct usb_interface *interface[USB_MAXINTERFACES];



    /* Interface information available even when this is not the

    * active configuration */

    struct usb_interface_cache *intf_cache[USB_MAXINTERFACES];



    unsigned char *extra;   /* Extra descriptors */

    int extralen;

};



/* USB 配置描述符 USB協議規定 */

struct usb_config_descriptor {

    __u8  bLength;//設備描述符的字節數大小,為0x12

    __u8  bDescriptorType;//描述符類型編號,為0x01

    __le16 wTotalLength;//配置所返回的所有數量的大小



    __u8  bNumInterfaces;//此配置所支持的接口數量

    __u8  bConfigurationValue;//Set_Configuration命令需要的參數值

    __u8  iConfiguration;//描述該配置的字符串的索引值

    __u8  bmAttributes;//供電模式的選擇

    __u8  bMaxPower;//設備從總線提取的最大電流

} __attribute__ ((packed));



/*Linux kernel 使用此結構來描述 USB 接口*/

struct usb_interface {

    // 本接口對應的所有的設置(與配置不是一個概念)

    struct usb_host_interface *altsetting;

    struct usb_host_interface *cur_altsetting;//當前活躍的設置

    unsigned num_altsetting; //可選設置的數量



    /* If there is an interface association descriptor then it will list

    * the associated interfaces */

    struct usb_interface_assoc_descriptor *intf_assoc;



    int minor; //本接口綁定的次設備號

    enum usb_interface_condition condition; //接口是否綁定

    unsigned sysfs_files_created: 1; /* 文件系統存在的文件的屬性 */

    unsigned ep_devs_created: 1; /* endpoint "devices" exist */

    unsigned unregistering: 1; /* 標識卸載interface */

    unsigned needs_remote_wakeup: 1; /* 驅動要求遠程喚醒 */

    unsigned needs_altsetting0: 1; /* 當設置0被推遲時標識 */

    unsigned needs_binding: 1; /* needs delayed unbind/rebind */

    unsigned reset_running: 1;

    unsigned resetting_device: 1; /* true: bandwidth alloc after reset */



    struct device dev;  /* interface specific device info */



    //當接口被綁定到usb主設備號的時候,它指向文件系統中表示的usb設備

    struct device *usb_dev;

    atomic_t pm_usage_cnt;  /* usage counter for autosuspend */

    struct work_struct reset_ws; /* for resets in atomic context */

};



/* 描述一個接口的設置 */

struct usb_host_interface {

    struct usb_interface_descriptor    desc;



    /* array of desc.bNumEndpoint endpoints associated with this

    * interface setting.  these will be in no particular order.

    */

    struct usb_host_endpoint *endpoint;



    char *string;        /* iInterface string, if present */

    unsigned char *extra;   /* Extra descriptors */

    int extralen;

};



/* USB 接口描述符 USB協議規定 268(296/650)頁 */

struct usb_interface_descriptor {

    __u8  bLength;//設備描述符的字節數大小,為0x12

    __u8  bDescriptorType;//描述符類型編號,為0x01



    __u8  bInterfaceNumber;//接口的編號

    __u8  bAlternateSetting;//備用的接口描述符編號

    __u8  bNumEndpoints;//該接口使用端點數,不包括端點0

    __u8  bInterfaceClass;//接口類型

    __u8  bInterfaceSubClass;//接口子類型

    __u8  bInterfaceProtocol;//接口所遵循的協議

    __u8  iInterface;//描述該接口的字符串索引值

} __attribute__ ((packed));



/* Linux 內核使用此結構體來對USB端點描述符 */

struct usb_host_endpoint {

struct usb_endpoint_descriptor  desc; //端口描述符

struct usb_ss_ep_comp_descriptor ss_ep_comp;//超快速端口描述符

struct list_head  urb_list; //本端口對應的urb鏈表

void    *hcpriv;

struct ep_device  *ep_dev; /* For sysfs info */



unsigned char *extra;   /* Extra descriptors */

int extralen;

int enabled;//使能的話urb才能被提交到此端口

};



/* USB 端點描述符 USB協議規定 */

struct usb_endpoint_descriptor {

    __u8  bLength;//設備描述符的字節數大小,為0x12

    __u8  bDescriptorType;//描述符類型編號,為0x01



    __u8  bEndpointAddress;//端點地址及輸入輸出屬性

    __u8  bmAttributes;//端點的傳輸類型屬性

    __le16 wMaxPacketSize;//端點收、發的最大包的大小

    __u8  bInterval;//主機查詢端點的時間間隔



    /* NOTE:   these two are _only_ in audio endpoints. */

    /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */

    __u8  bRefresh;

    __u8  bSynchAddress;

} __attribute__ ((packed));



/* USB 字符串描述符 USB協議規定 */

struct usb_string_descriptor {

    __u8  bLength;//設備描述符的字節數大小,為0x12

    __u8  bDescriptorType;//描述符類型編號,為0x01



    __le16 wData[1];        /* UTF-16LE encoded */

} __attribute__ ((packed));


USB 配置 與 Linux 設置關系: 一個配置包含一個或多個接口、一個接口包含一個或多個設置(功能選項)
: 一個手機可以有多種配置(功能組合),比如可以作為電話,可以接在 PC 作為一個U盤,這兩種情況就屬于不同的配置。假如該手機選擇電話接口(電話功能),那么會有情景模式(室外模式、會議模式等)可以改變,每種場景就算是一個設置。
6、USB通信載體 --- URB
URB -> USB 請求塊,是 USB 設備驅動中用來描述與 USB 設備通信所用的基本載體和核心數據結構。
也就是說每次 USB 設備驅動都是通過構造一個 URB 的請求塊通過 USB Core 傳遞給 USB 主控制器驅動程序解析,將請求塊的數據發送到請求塊指定的 USB 設備。
7、URB 處理流程
a)USB 設備驅動程序創建并初始化一個訪問 USB 設備特定端點的 URB ,并提交給 USB Core。
b)USB Core 提交該 URB 到 USB 主控制器驅動程序。
c)USB 主控制器驅動程序根據該 URB 描述的信息來訪問指定的 USB 設備中具體的端點。
d)當設備訪問結束后,USB 主控制器驅動程序會通過回調函數來通知 USB 設備驅動程序。
8、URB 相關的接口
a)創建 URB
struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags);
iso_packets: URB 所包含的等時數據包的個數(如果是等時傳輸才會用到,如果不是則為0)
mem_flags: 內存分配標識(如 GFP_KERNEL),參考 kmalloc.
b)初始化 URB
i.對于中斷 URB
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: 要初始化的 urb 指針
dev: urb 所要訪問的設備,指明你要與哪個 USB 設備通訊。
pipe: 要訪問的端點所對應的管道,使用 usb_sndintpipe() 或者 usb_rcvintpipe()創建
      管道: 驅動程序的數據緩沖區與一個端點的連接。
transfer_buffer: 要傳輸的數據的緩沖區。
buffer_length: transfer_buffer 所指緩沖區長度。
Complete_fn: 回調函數。當完成該 urb 所請求的操作時,會調用此回調函數。
Context: Complete_fn()函數所需的上下文,通常取值dev。
interval: urb被調度的時間間隔。
ii.對于批量 URB
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);
iii.對于控制 URB
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)
iv.對于 URB 沒有像中斷、控制和批量 URB 那樣的初始化函數,我們只能手動地初始化URB。例如等時傳輸 URB 。
c)提交URB
int usb_submit_urb(struct urb *urb, gfp_t mem_flags);
urb: 執行創建好的 urb 的指針
mem_flags: 內存分配標識,它用于告知 USB 核心如何分配內存緩沖區
9、URB 被提交到USB核心后,USB核心指定USB主控制驅動程序會處理該有三種情況會被認為處理完成。
a)URB被成功發送給設備,并且是設備返回正確的的確認。如果 urb->status == 0 ,意味著對于一個輸出類型 urb,請求數據被成功發送。對于一個輸入類型 urb,請求的數據被成功收到。
b)如果發送數據到設備或從設備接受數據時發生了錯誤,urb->status 會記錄錯誤值。
c)urb 被“取消”,這發生在驅動通過 usb_unlink_urb() 或 usb_kill_urb() 函數取消 urb,或 urb 雖然已經提交,而 USB 設備被拔出的情況下。
d)當 urb 處理完成后,urb 完成函數將會被調用。









歡迎光臨 (http://www.raoushi.com/bbs/) Powered by Discuz! X3.1