小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Linux設(shè)備驅(qū)動程序?qū)W習(17)-USB 驅(qū)動程序(二)

 lchjczw 2012-03-19
Linux設(shè)備驅(qū)動程序?qū)W習(17)-USB 驅(qū)動程序(二)
內(nèi)核使用2.6.29.4
USB設(shè)備其實很復雜,但是Linux內(nèi)核提供了一個稱為USB core的子系統(tǒng)來處理了大部分的復雜工作,所以這里所描述的是驅(qū)動程序和USB core之間的接口。
在USB設(shè)備組織結(jié)構(gòu)中,從上到下分為設(shè)備(device)、配置(config)、接口(interface)和端點(endpoint)四個層次。
對于這四個層次的簡單描述如下:
    設(shè)備通常具有一個或多個的配置
    配置經(jīng)常具有一個或多個的接口
    接口通常具有一個或多個的設(shè)置
    接口沒有或具有一個以上的端點

設(shè)備
  很明顯,地代表了一個插入的USB設(shè)備,在內(nèi)核使用數(shù)據(jù)結(jié)構(gòu) struct usb_device來描述整個USB設(shè)備。(include/linux/usb.h)
  struct usb_device {
   int devnum; //設(shè)備號,是在USB總線的地址
   char devpath [16]; //用于消息的設(shè)備ID字符串
   enum usb_device_state state; //設(shè)備狀態(tài):已配置、未連接等等
   enum usb_device_speed speed; //設(shè)備速度:高速、全速、低速或錯誤
  
   struct usb_tt *tt; //處理傳輸者信息;用于低速、全速設(shè)備和高速HUB
   int ttport; //位于tt HUB的設(shè)備口
  
   unsigned int toggle[2]; //每個端點的占一位,表明端點的方向([0] = IN, [1] = OUT)  
   struct usb_device *parent; //上一級HUB指針
   struct usb_bus *bus; //總線指針
   struct usb_host_endpoint ep0; //端點0數(shù)據(jù)
   struct device dev; //一般的設(shè)備接口數(shù)據(jù)結(jié)構(gòu)
 
   struct usb_device_descriptor descriptor; //USB設(shè)備描述符
   struct usb_host_config *config; //設(shè)備的所有配置
   struct usb_host_config *actconfig; //被激活的設(shè)備配置
   struct usb_host_endpoint *ep_in[16]; //輸入端點數(shù)組
   struct usb_host_endpoint *ep_out[16]; //輸出端點數(shù)組
  
   char **rawdescriptors; //每個配置的raw描述符
  
   unsigned short bus_mA; //可使用的總線電流
   u8 portnum; //父端口號
   u8 level; //USB HUB的層數(shù)
  
   unsigned can_submit:1; //URB可被提交標志
   unsigned discon_suspended:1; //暫停時斷開標志
   unsigned persist_enabled:1; //USB_PERSIST使能標志
   unsigned have_langid:1; //string_langid存在標志
   unsigned authorized:1;
   unsigned authenticated:1;
   unsigned wusb:1; //無線USB標志
   int string_langid; //字符串語言ID
  
   /* static strings from the device */ //設(shè)備的靜態(tài)字符串
   char *product; //產(chǎn)品名
   char *manufacturer; //廠商名
   char *serial; //產(chǎn)品串號
  
   struct list_head filelist; //此設(shè)備打開的usbfs文件
  #ifdef CONFIG_USB_DEVICE_CLASS
   struct device *usb_classdev; //用戶空間訪問的為usbfs設(shè)備創(chuàng)建的USB類設(shè)備
  #endif
  #ifdef CONFIG_USB_DEVICEFS
   struct dentry *usbfs_dentry; //設(shè)備的usbfs入口
  #endif
  
   int maxchild; //(若為HUB)接口數(shù)
   struct usb_device *children[USB_MAXCHILDREN];//連接在這個HUB上的子設(shè)備
   int pm_usage_cnt; //自動掛起的使用計數(shù)
   u32 quirks;
   atomic_t urbnum; //這個設(shè)備所提交的URB計數(shù)
  
   unsigned long active_duration; //激活后使用計時
  #ifdef CONFIG_PM //電源管理相關(guān)
   struct delayed_work autosuspend; //自動掛起的延時
   struct work_struct autoresume; //(中斷的)自動喚醒需求
   struct mutex pm_mutex; //PM的互斥鎖 
 
   unsigned long last_busy; //最后使用的時間
   int autosuspend_delay;
   unsigned long connect_time; //第一次連接的時間
  
   unsigned auto_pm:1; //自動掛起/喚醒
   unsigned do_remote_wakeup:1; //遠程喚醒
   unsigned reset_resume:1; //使用復位替代喚醒
   unsigned autosuspend_disabled:1; //掛起關(guān)閉
   unsigned autoresume_disabled:1; //喚醒關(guān)閉
   unsigned skip_sys_resume:1; //跳過下個系統(tǒng)喚醒
  #endif
   struct wusb_dev *wusb_dev; //(如果為無線USB)連接到WUSB特定的數(shù)據(jù)結(jié)構(gòu)
  };
配置
  
一個USB設(shè)備可以有多個配置,并可在它們之間轉(zhuǎn)換以改變設(shè)備的狀態(tài)。比如一個設(shè)備可以通過下載固件(firmware)的方式改變設(shè)備的使用狀態(tài)(我
感覺類似FPGA或CPLD),那么USB設(shè)備就要切換配置,來完成這個工作。一個時刻只能有一個配置可以被激活。Linux使用結(jié)構(gòu) struct
usb_host_config
來描述USB配置。我們編寫的USB設(shè)備驅(qū)動通常不需要讀寫這些結(jié)構(gòu)的任何值??稍趦?nèi)核源碼的文件include/linux/usb.h中找到對它們的
描述。
struct usb_host_config {
    struct usb_config_descriptor desc; //配置描述符
    char *string; /* 配置的字符串指針(如果存在) */
    struct usb_interface_assoc_descriptor *intf_assoc[USB_MAXIADS]; //配置的接口聯(lián)合描述符鏈表
    struct usb_interface *interface[USB_MAXINTERFACES]; //接口描述符鏈表
    struct usb_interface_cache *intf_cache[USB_MAXINTERFACES];
    unsigned char *extra; /* 額外的描述符 */
    int extralen;
};
接口
USB
端點被綁為接口,USB接口只處理一種USB邏輯連接。一個USB接口代表一個基本功能,每個USB驅(qū)動控制一個接口。所以一個物理上的硬件設(shè)備可能需要
一個以上的驅(qū)動程序。這可以在“暈到死 差屁”系統(tǒng)中看出,有時插入一個USB設(shè)備后,系統(tǒng)會識別出多個設(shè)備,并安裝相應多個的驅(qū)動。
USB 接口可以有其他的設(shè)置,它是對接口參數(shù)的不同選擇. 接口的初始化的狀態(tài)是第一個設(shè)置,編號為0。 其他的設(shè)置可以以不同方式控制獨立的端點。
USB接口在內(nèi)核中使用 struct usb_interface 來描述。USB 核心將其傳遞給USB驅(qū)動,并由USB驅(qū)動負責后續(xù)的控制。
struct usb_interface {
    struct usb_host_interface *altsetting; /* 包含所有可用于該接口的可選設(shè)置的接口結(jié)構(gòu)數(shù)組。每個 struct usb_host_interface 包含一套端點配置(即struct usb_host_endpoint結(jié)構(gòu)所定義的端點配置。這些接口結(jié)構(gòu)沒有特別的順序。*/
    struct usb_host_interface *cur_altsetting; /* 指向altsetting內(nèi)部的指針,表示當前激活的接口配置*/
    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; /* 如果綁定到這個接口的 USB 驅(qū)動使用 USB 主設(shè)備號, 這個變量包含由 USB 核心分配給接口的次設(shè)備號. 這只在一個成功的調(diào)用 usb_register_dev后才有效。*/
    /*以下的數(shù)據(jù)在我們寫的驅(qū)動中基本不用考慮,系統(tǒng)會自動設(shè)置*/
    enum usb_interface_condition condition; /* state of binding */
    unsigned is_active:1; /* the interface is not suspended */
    unsigned sysfs_files_created:1; /* the sysfs attributes exist */
    unsigned ep_devs_created:1; /* endpoint "devices" exist */
    unsigned unregistering:1; /* unregistration is in progress */
    unsigned needs_remote_wakeup:1; /* driver requires remote wakeup */
    unsigned needs_altsetting0:1; /* switch to altsetting 0 is pending */
    unsigned needs_binding:1; /* needs delayed unbind/rebind */
    unsigned reset_running:1;
    struct device dev; /* 接口特定的設(shè)備信息 */
    struct device *usb_dev;
    int 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; //接口描述符
    struct usb_host_endpoint *endpoint; /* 這個接口的所有端點結(jié)構(gòu)體的聯(lián)合數(shù)組*/
    char *string; /* 接口描述字符串 */
    unsigned char *extra; /* 額外的描述符 */
    int extralen;
};
端點
USB 通訊的最基本形式是通過一個稱為端點的東西。一個USB端點只能向一個方向傳輸數(shù)據(jù)(從主機到設(shè)備(稱為輸出端點)或者從設(shè)備到主機(稱為輸入端點))。端點可被看作一個單向的管道。
一個 USB 端點有 4 種不同類型, 分別具有不同的數(shù)據(jù)傳送方式:
控制CONTROL

制端點被用來控制對 USB 設(shè)備的不同部分訪問. 通常用作配置設(shè)備、獲取設(shè)備信息、發(fā)送命令到設(shè)備或獲取設(shè)備狀態(tài)報告。這些端點通常較小。每個
USB 設(shè)備都有一個控制端點稱為"端點 0", 被 USB 核心用來在插入時配置設(shè)備。USB協(xié)議保證總有足夠的帶寬留給控制端點傳送數(shù)據(jù)到設(shè)備.
中斷INTERRUPT
每當 USB 主機向設(shè)備請求數(shù)據(jù)時,中斷端點以固定的速率傳送小量的數(shù)據(jù)。此為USB 鍵盤和鼠標的主要的數(shù)據(jù)傳送方法。它還用以傳送數(shù)據(jù)到 USB 設(shè)備來控制設(shè)備。通常不用來傳送大量數(shù)據(jù)。USB協(xié)議保證總有足夠的帶寬留給中斷端點傳送數(shù)據(jù)到設(shè)備.
批量BULK

量端點用以傳送大量數(shù)據(jù)。這些端點常比中斷端點大得多. 它們普遍用于不能有任何數(shù)據(jù)丟失的數(shù)據(jù)。USB
協(xié)議不保證傳輸在特定時間范圍內(nèi)完成。如果總線上沒有足夠的空間來發(fā)送整個BULK包,它被分為多個包進行傳輸。這些端點普遍用于打印機、USB
Mass Storage和USB網(wǎng)絡設(shè)備上。
等時ISOCHRONOUS
等時端點也批量傳送大量數(shù)據(jù), 但是這個數(shù)據(jù)不被保證能送達。這些端點用在可以處理數(shù)據(jù)丟失的設(shè)備中,并且更多依賴于保持持續(xù)的數(shù)據(jù)流。如音頻和視頻設(shè)備等等。
控制和批量端點用于異步數(shù)據(jù)傳送,而中斷和同步端點是周期性的。這意味著這些端點被設(shè)置來在固定的時間連續(xù)傳送數(shù)據(jù),USB 核心為它們保留了相應的帶寬。
端點在內(nèi)核中使用結(jié)構(gòu) struct usb_host_endpoint 來描述,它所包含的真實端點信息在另一個結(jié)構(gòu)中:struct usb_endpoint_descriptor(端點描述符,包含所有的USB特定數(shù)據(jù))。
struct usb_host_endpoint {
    struct usb_endpoint_descriptor desc; //端點描述符
    struct list_head urb_list; //此端點的URB對列,由USB核心維護
    void *hcpriv;
    struct ep_device *ep_dev; /* For sysfs info */
    unsigned char *extra; /* Extra descriptors */
    int extralen;
    int enabled;
};
/*-------------------------------------------------------------------------*/
/* USB_DT_ENDPOINT: Endpoint descriptor */
struct usb_endpoint_descriptor {
    __u8 bLength;
    __u8 bDescriptorType;
    __u8 bEndpointAddress; /*這個特定端點的 USB 地址,這個8位數(shù)據(jù)包含端點的方向,結(jié)合位掩碼 USB_DIR_OUT 和 USB_DIR_IN 使用, 確定這個端點的數(shù)據(jù)方向。*/
    __u8 bmAttributes; //這是端點的類型,位掩碼如下
    __le16 wMaxPacketSize; /*端點可以一次處理的最大字節(jié)數(shù)。驅(qū)動可以發(fā)送比這個值大的數(shù)據(jù)量到端點, 但是當真正傳送到設(shè)備時,數(shù)據(jù)會被分為 wMaxPakcetSize 大小的塊。對于高速設(shè)備, 通過使用高位部分幾個額外位,可用來支持端點的高帶寬模式。*/
    __u8 bInterval; //如果端點是中斷類型,該值是端點的間隔設(shè)置,即端點的中斷請求間的間隔時間,以毫秒為單位
    /* NOTE: these two are _only_ in audio endpoints. */
    /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
    __u8 bRefresh;
    __u8 bSynchAddress;
} __attribute__ ((packed));
#define USB_DT_ENDPOINT_SIZE 7
#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */
/*
* Endpoints
*/
#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress 端點的 USB 地址掩碼 */
#define USB_ENDPOINT_DIR_MASK 0x80 /* in bEndpointAddress 數(shù)據(jù)方向掩碼 */
#define USB_DIR_OUT 0 /* to device */
#define USB_DIR_IN 0x80 /* to host */
#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* bmAttributes 的位掩碼*/
#define USB_ENDPOINT_XFER_CONTROL 0
#define USB_ENDPOINT_XFER_ISOC 1
#define USB_ENDPOINT_XFER_BULK 2
#define USB_ENDPOINT_XFER_INT 3
#define USB_ENDPOINT_MAX_ADJUSTABLE 0x80
/*-------------------------------------------------------------------------*/
USB 和 sysfs
由于單個 USB 物理設(shè)備的復雜性,設(shè)備在 sysfs 中的表示也非常復雜。物理 USB 設(shè)備(通過 struct usb_device 表示)和單個 USB 接口(由 struct usb_interface 表示)都作為單個設(shè)備出現(xiàn)在 sysfs 中,這是因為這兩個結(jié)構(gòu)都包含一個 struct device結(jié)構(gòu)。以下內(nèi)容是我的USB鼠標在 sysfs 中的目錄樹:   
/sys/devices/pci0000:00/0000:00:1a.0/usb3/3-1 表示 usb_device 結(jié)構(gòu))
.
|-- 3-1:1.0 (鼠標所對應的usb_interface)
| |-- 0003:046D:C018.0003
| | |-- driver -> ../../../../../../../bus/hid/drivers/generic-usb
| | |-- power
| | | `-- wakeup
| | |-- subsystem -> ../../../../../../../bus/hid
| | `-- uevent
| |-- bAlternateSetting
| |-- bInterfaceClass
| |-- bInterfaceNumber
| |-- bInterfaceProtocol
| |-- bInterfaceSubClass
| |-- bNumEndpoints
| |-- driver -> ../../../../../../bus/usb/drivers/usbhid
| |-- ep_81 -> usb_endpoint/usbdev3.4_ep81
| |-- input
| | `-- input6
| | |-- capabilities
| | | |-- abs
| | | |-- ev
| | | |-- ff
| | | |-- key
| | | |-- led
| | | |-- msc
| | | |-- rel
| | | |-- snd
| | | `-- sw
| | |-- device -> ../../../3-1:1.0
| | |-- event3
| | | |-- dev
| | | |-- device -> ../../input6
| | | |-- power
| | | | `-- wakeup
| | | |-- subsystem -> ../../../../../../../../../class/input
| | | `-- uevent
| | |-- id
| | | |-- bustype
| | | |-- product
| | | |-- vendor
| | | `-- version
| | |-- modalias
| | |-- mouse1
| | | |-- dev
| | | |-- device -> ../../input6
| | | |-- power
| | | | `-- wakeup
| | | |-- subsystem -> ../../../../../../../../../class/input
| | | `-- uevent
| | |-- name
| | |-- phys
| | |-- power
| | | `-- wakeup
| | |-- subsystem -> ../../../../../../../../class/input
| | |-- uevent
| | `-- uniq
| |-- modalias
| |-- power
| | `-- wakeup
| |-- subsystem -> ../../../../../../bus/usb
| |-- supports_autosuspend
| |-- uevent
| `-- usb_endpoint
| `-- usbdev3.4_ep81
| |-- bEndpointAddress
| |-- bInterval
| |-- bLength
| |-- bmAttributes
| |-- dev
| |-- device -> ../../../3-1:1.0
| |-- direction
| |-- interval
| |-- power
| | `-- wakeup
| |-- subsystem -> ../../../../../../../../class/usb_endpoint
| |-- type
| |-- uevent
| `-- wMaxPacketSize
|-- authorized
|-- bConfigurationValue
|-- bDeviceClass
|-- bDeviceProtocol
|-- bDeviceSubClass
|-- bMaxPacketSize0
|-- bMaxPower
|-- bNumConfigurations
|-- bNumInterfaces
|-- bcdDevice
|-- bmAttributes
|-- busnum
|-- configuration
|-- descriptors
|-- dev
|-- devnum
|-- driver -> ../../../../../bus/usb/drivers/usb
|-- ep_00 -> usb_endpoint/usbdev3.4_ep00
|-- idProduct
|-- idVendor
|-- manufacturer
|-- maxchild
|-- power
| |-- active_duration
| |-- autosuspend
| |-- connected_duration
| |-- level
| |-- persist
| `-- wakeup
|-- product
|-- quirks
|-- speed
|-- subsystem -> ../../../../../bus/usb
|-- uevent
|-- urbnum
|-- usb_endpoint
| `-- usbdev3.4_ep00
| |-- bEndpointAddress
| |-- bInterval
| |-- bLength
| |-- bmAttributes
| |-- dev
| |-- device -> ../../../3-1
| |-- direction
| |-- interval
| |-- power
| | `-- wakeup
| |-- subsystem -> ../../../../../../../class/usb_endpoint
| |-- type
| |-- uevent
| `-- wMaxPacketSize
`-- version
38 directories, 91 files
    USB sysfs 設(shè)備命名方法是: root_hub-hub_port:config.interface
    隨著USB集線器層次的增加, 集線器端口號被添加到字符串中緊隨著鏈中之前的集線器端口號。對一個 2 層的樹, 設(shè)備為: root_hub-hub_port-hub_port:config.interface ,以此類推。

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多