久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 2853|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

學(xué)習(xí)筆記-USB數(shù)據(jù)結(jié)構(gòu)和相應(yīng)接口2

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:140343 發(fā)表于 2016-9-24 22:22 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
本帖最后由 51hei小林 于 2016-9-24 22:29 編輯

1、Linux USB架構(gòu)
      
運(yùn)行Linux的USB主機(jī)
   
      
      
   
      
    運(yùn)行Linux的USB設(shè)備      
   
      
USB設(shè)備驅(qū)動(dòng)(*)
   
      
Gadget驅(qū)動(dòng)(*)
   
      
USB核心(Core)
   
      
Gadget API
   
      
USB主控制器驅(qū)動(dòng)(UHCI\OHCI\EHCI)
   
      
UDC驅(qū)動(dòng)
   
      
USB主控制器
   
      
USB主控制器
   
      
||=================== 物理電氣連接 ===============||
   

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

3、USB設(shè)備、配置、接口、端點(diǎn)與驅(qū)動(dòng)之間的關(guān)系。
一個(gè)設(shè)備可能有多個(gè)配置,一個(gè)配置可以擁有多種接口(功能),每個(gè)接口(功能)對(duì)應(yīng)一個(gè)USB驅(qū)動(dòng)。
例如:
    我們要為一個(gè)電視機(jī)增加一個(gè)USB接口,可以通過接入筆記本來播放筆記本中各種視頻或者音樂。那么電視機(jī)就是一個(gè)USB設(shè)備。
    若電視劇具備視頻、音頻兩種功能,那么就可以使用兩個(gè)接口來對(duì)應(yīng)視頻、音頻功能。這兩個(gè)接口使用兩個(gè)USB驅(qū)動(dòng)來編寫,一個(gè)對(duì)應(yīng)視頻子系統(tǒng)、一個(gè)對(duì)應(yīng)音頻子系統(tǒng)。
    對(duì)于端點(diǎn),視頻需要傳輸圖像數(shù)據(jù)、分配率控制等可以通過兩個(gè)端點(diǎn)來負(fù)責(zé)傳輸。音頻需要傳輸音頻、音量、音效等數(shù)據(jù),可以通過三個(gè)端點(diǎn)來負(fù)責(zé)傳輸。
4、Linux USB driver 相關(guān)的數(shù)據(jù)結(jié)構(gòu)




/* USB 驅(qū)動(dòng)結(jié)構(gòu)體,每個(gè)USB驅(qū)動(dòng)都會(huì)需要這個(gè)結(jié)構(gòu)體 */

struct usb_driver {

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

    const char *name;

    // 當(dāng) USB 核心發(fā)現(xiàn)了(id_table)該驅(qū)動(dòng)能夠處理USB接口就會(huì)回調(diào)該函數(shù)。

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

    // 當(dāng)相應(yīng)的 USB 接口被移除時(shí),會(huì)回調(diào)該函數(shù)用于釋放某些資源

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

    // ...

    // 本 USB 驅(qū)動(dòng)能夠處理的設(shè)備列表(只要能符合此設(shè)備列表就會(huì)回調(diào) probe()函數(shù))

    const struct usb_device_id *id_table;

    // ...

};



/* 聲明本驅(qū)動(dòng)所支持的USB類型/設(shè)備 */

struct usb_device_id {

    /* which fields to match against? */

    __u16        match_flags;



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

    // 設(shè)置這組代表是一個(gè)具體的設(shè)備(羅技的鼠標(biāo))

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

    __u16        idProduct;        // 產(chǎn)品 ID

    __u16        bcdDevice_lo;

    __u16        bcdDevice_hi;



    /* Used for device class matches */

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

    __u8        bDeviceClass;    // 指定某種具體的識(shí)別

    __u8        bDeviceSubClass;

    __u8        bDeviceProtocol;



    /* Used for interface class matches */

    __u8        bInterfaceClass;

    __u8        bInterfaceSubClass;

    __u8        bInterfaceProtocol;



    /* not matched against */

    kernel_ulong_t    driver_info;

};


構(gòu)造一個(gè)設(shè)備的宏: USB_DEVICE(vend, prod)
    vend: 廠商ID  由 USB 組織統(tǒng)一給每個(gè)廠商分配
    prod: 產(chǎn)品ID  廠商自行分配
例子: 構(gòu)造一個(gè)具體的 USB OV511 攝像頭
    #define VEND_OMNIVISION 0x05A9   
    #define PROD_OV511        0x0511   
    USB_DEVICE(VEND_OMNIVISION, PROD_OV511)
構(gòu)造一類設(shè)備的宏: USB_INTERFACE_INFO(cl, sc, pr)
    cl: blnterfaceClass value 類
    sc: blnterfaceSubClass value 子類
    pr: blnterfaceProtocol value 所遵循的協(xié)議
例子: 構(gòu)造一個(gè)鼠標(biāo)類型的 USB 驅(qū)動(dòng)
    USB_INTERFACE_INFO(    USB_INTERFACE_CLASS_HID,
                        USB_INTERFACE_SUBCLASS_BOOT,
                        USB_INTERFACE_PROTOCOL_MOUSE)
注冊(cè)一個(gè)USB驅(qū)動(dòng):
static inline int usb_register(struct usb_driver *driver)                  
5、usb devices 相關(guān)的數(shù)據(jù)結(jié)構(gòu)

/* USB 設(shè)備 */

struct usb_device {

    // USB 設(shè)備號(hào)

    int        devnum;

    // 設(shè)備 ID 字符串

    char        devpath[16];

    u32        route;

    // 設(shè)備狀態(tài): 未連接,已配置

    enum usb_device_state    state;

    // 高速\全速\低速

    enum usb_device_speed    speed;

    //...

    struct device dev;

    // USB 設(shè)備描述符

    struct usb_device_descriptor descriptor;

    struct usb_host_config *config;

    //...

    /* static strings from the device */

    char *product;            // 產(chǎn)品名

    char *manufacturer;        // 廠商名

    char *serial;            // 設(shè)備串號(hào)



    //...

};



/* USB 設(shè)備描述符 USB 協(xié)議規(guī)定 261(290/60)頁 */

struct usb_device_descriptor {

    __u8  bLength;//設(shè)備描述符的字節(jié)數(shù)大小,為0x12

    __u8  bDescriptorType;//描述符類型編號(hào),為0x01



    __le16 bcdUSB;//USB版本號(hào)

    __u8  bDeviceClass;//USB分配的設(shè)備類代碼,0x01~0xfe為標(biāo)準(zhǔn)設(shè)備類,0xff為廠商自定義類型



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

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

    __u8  bDeviceProtocol;//USB分配的設(shè)備協(xié)議代碼,同上

    __u8  bMaxPacketSize0;//端點(diǎn)0的最大包的大小

    __le16 idVendor;//廠商編號(hào)

    __le16 idProduct;//產(chǎn)品編號(hào)

    __le16 bcdDevice;//設(shè)備出廠編號(hào)

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

    __u8  iProduct;//描述產(chǎn)品字符串的索引

    __u8  iSerialNumber;//描述設(shè)備序列號(hào)字符串的索引

    __u8  bNumConfigurations;//可能的配置數(shù)量

} __attribute__ ((packed));



/* 描述一個(gè)配置 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協(xié)議規(guī)定 */

struct usb_config_descriptor {

    __u8  bLength;//設(shè)備描述符的字節(jié)數(shù)大小,為0x12

    __u8  bDescriptorType;//描述符類型編號(hào),為0x01

    __le16 wTotalLength;//配置所返回的所有數(shù)量的大小



    __u8  bNumInterfaces;//此配置所支持的接口數(shù)量

    __u8  bConfigurationValue;//Set_Configuration命令需要的參數(shù)值

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

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

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

} __attribute__ ((packed));



/*Linux kernel 使用此結(jié)構(gòu)來描述 USB 接口*/

struct usb_interface {

    // 本接口對(duì)應(yīng)的所有的設(shè)置(與配置不是一個(gè)概念)

    struct usb_host_interface *altsetting;

    struct usb_host_interface *cur_altsetting;//當(dāng)前活躍的設(shè)置

    unsigned num_altsetting; //可選設(shè)置的數(shù)量



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

    * the associated interfaces */

    struct usb_interface_assoc_descriptor *intf_assoc;



    int minor; //本接口綁定的次設(shè)備號(hào)

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

    unsigned sysfs_files_created: 1; /* 文件系統(tǒng)存在的文件的屬性 */

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

    unsigned unregistering: 1; /* 標(biāo)識(shí)卸載interface */

    unsigned needs_remote_wakeup: 1; /* 驅(qū)動(dòng)要求遠(yuǎn)程喚醒 */

    unsigned needs_altsetting0: 1; /* 當(dāng)設(shè)置0被推遲時(shí)標(biāo)識(shí) */

    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 */



    //當(dāng)接口被綁定到usb主設(shè)備號(hào)的時(shí)候,它指向文件系統(tǒng)中表示的usb設(shè)備

    struct device *usb_dev;

    atomic_t pm_usage_cnt;  /* usage counter for autosuspend */

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

};



/* 描述一個(gè)接口的設(shè)置 */

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協(xié)議規(guī)定 268(296/650)頁 */

struct usb_interface_descriptor {

    __u8  bLength;//設(shè)備描述符的字節(jié)數(shù)大小,為0x12

    __u8  bDescriptorType;//描述符類型編號(hào),為0x01



    __u8  bInterfaceNumber;//接口的編號(hào)

    __u8  bAlternateSetting;//備用的接口描述符編號(hào)

    __u8  bNumEndpoints;//該接口使用端點(diǎn)數(shù),不包括端點(diǎn)0

    __u8  bInterfaceClass;//接口類型

    __u8  bInterfaceSubClass;//接口子類型

    __u8  bInterfaceProtocol;//接口所遵循的協(xié)議

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

} __attribute__ ((packed));



/* Linux 內(nèi)核使用此結(jié)構(gòu)體來對(duì)USB端點(diǎn)描述符 */

struct usb_host_endpoint {

struct usb_endpoint_descriptor  desc; //端口描述符

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

struct list_head  urb_list; //本端口對(duì)應(yīng)的urb鏈表

void    *hcpriv;

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



unsigned char *extra;   /* Extra descriptors */

int extralen;

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

};



/* USB 端點(diǎn)描述符 USB協(xié)議規(guī)定 */

struct usb_endpoint_descriptor {

    __u8  bLength;//設(shè)備描述符的字節(jié)數(shù)大小,為0x12

    __u8  bDescriptorType;//描述符類型編號(hào),為0x01



    __u8  bEndpointAddress;//端點(diǎn)地址及輸入輸出屬性

    __u8  bmAttributes;//端點(diǎn)的傳輸類型屬性

    __le16 wMaxPacketSize;//端點(diǎn)收、發(fā)的最大包的大小

    __u8  bInterval;//主機(jī)查詢端點(diǎn)的時(shí)間間隔



    /* 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協(xié)議規(guī)定 */

struct usb_string_descriptor {

    __u8  bLength;//設(shè)備描述符的字節(jié)數(shù)大小,為0x12

    __u8  bDescriptorType;//描述符類型編號(hào),為0x01



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

} __attribute__ ((packed));


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




分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 欧美一区二区三区在线观看 | 在线看av网址 | 久久亚 | 男人天堂色 | 久久久久久久久91 | 99成人| 国产大片一区 | av国产精品毛片一区二区小说 | 黄色一级毛片 | 久久久精品一区二区三区 | 久久极品| 亚洲视频一区二区三区 | 高清18麻豆 | 欧美久久视频 | 欧洲一级黄 | 欧美一级久久 | 欧美日韩在线观看一区 | 91在线精品秘密一区二区 | 欧美日韩亚洲国产 | 欧美三级在线 | 日日骚网 | 人人色视频 | 精品久久久久久亚洲综合网 | 亚洲国产成人久久综合一区,久久久国产99 | 99精品视频在线 | 国产资源视频 | 国产日韩精品一区 | 毛片在线免费 | 精品国产乱码久久久久久久久 | 拍真实国产伦偷精品 | 国产精品视频一区二区三区不卡 | 影音先锋欧美资源 | www视频在线观看 | 国产成视频在线观看 | 久久成人精品视频 | 久久综合一区二区三区 | 成人av免费在线观看 | 中文字幕精品视频 | 围产精品久久久久久久 | 成人av一区 | 成人久久18免费网站麻豆 |