• Linux USB驱动学习总结(二)---- USB设备驱动


    USB 设备驱动:

    一、USB 描述符:(存在于USB 的E2PROM里面)

    1、  设备描述符:struct usb_device_descriptor

    2、  配置描述符:struct usb_config_descriptor

    3、  接口描述符:struct usb_interface_descriptor

    4、  端点描述符:struct usb_endpoint_descriptor

    通过命令lsusb 列出系统中所有的USB设备:

    通过命令lsusb -v 列出系统中所有的USB设备的各个描述符信息:

    设备描述符:

    struct usb_device_descriptor {
        __u8  bLength; ///长度
        __u8  bDescriptorType; ///描述符类型
    
        __le16 bcdUSB;
        __u8  bDeviceClass;///设备类型
        __u8  bDeviceSubClass;///设备子类型
        __u8  bDeviceProtocol;///协议
        __u8  bMaxPacketSize0;///最大传输大小
        __le16 idVendor;///厂商 ID
        __le16 idProduct;///设备 ID
        __le16 bcdDevice;///
        __u8  iManufacturer;
        __u8  iProduct;
        __u8  iSerialNumber;///序列号
        __u8  bNumConfigurations;///包含的配置数目(每个USB设备会对应多个配置)
    } __attribute__ ((packed));

    配置描述符:

    struct usb_config_descriptor {         ///USB 配置描述符
    
             __u8  bLength;
    
             __u8  bDescriptorType;
    
     
    
             __le16 wTotalLength;///总长度
    
             __u8  bNumInterfaces;///接口数目(每个接口代表一种功能)
    
             __u8  bConfigurationValue;///
    
             __u8  iConfiguration;
    
             __u8  bmAttributes;
    
             __u8  bMaxPower;
    
    } __attribute__ ((packed));

    接口描述符:

    struct usb_interface_descriptor { ///USB 接口描述符
    
             __u8  bLength;
    
             __u8  bDescriptorType;
    
     
    
             __u8  bInterfaceNumber;
    
             __u8  bAlternateSetting;
    
             __u8  bNumEndpoints;
    
             __u8  bInterfaceClass;
    
             __u8  bInterfaceSubClass;
    
             __u8  bInterfaceProtocol;
    
             __u8  iInterface;
    
    } __attribute__ ((packed));

    端点描述符:

    struct usb_endpoint_descriptor {   ///USB 端点描述符(每个USB设备最多有16个端点)
    
             __u8  bLength; ///描述符的字节长度
    
             __u8  bDescriptorType;///描述符类型,对于端点就是USB_DT_ENDPOINT
    
     
    
             __u8  bEndpointAddress;///bit0~3表示端点地址,bit8 表示方向,输入还是输出
    
             __u8  bmAttributes;///属性(bit0、bit1构成传输类型,00--控制,01--等时,10--批量,11--中断)
    
             __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的传输方式:(不同的设备对于传输的数据各有各的要求)

    1、  控制传输---获取/配置设备

    2、  中断传输---例如USB鼠标、USB键盘(这里说的中断和硬件上下文的中断不一样,它不是设备主动发送一个中断请求,而是主控制器在保证不大于某个时间间隔interval内安排的一次数据传输)

    3、  批量传输---用于大容量数据传输,没有固定的传输速率,例如usb打印机、扫描仪、U盘等,对应的端点就叫批量端点

    4、  等时传输---可以传输大批量数据,但是对数据是否到达没有保证,对实时性要求很高, 例如音频、视频等设备(USB摄像头、USB话筒),对应的端点就叫等时端点

    三、URB(usb request block),USB请求块

    urb 是usb数据传输机制使用的核心数据结构,urb供usb协议栈使用;

    struct urb { //由主机控制器发送给USB设备
        struct kref kref;        /* reference count of the URB */
        void *hcpriv;            /* private data for host controller */
        atomic_t use_count;        /* concurrent submissions counter */
        atomic_t reject;        /* submissions will fail */
    
        struct list_head urb_list;    /* list head for use by the urb's
                         * current owner */
        struct list_head anchor_list;    /* the URB may be anchored */
        struct usb_anchor *anchor;
        struct usb_device *dev;        /* (in) pointer to associated device */ ///urb所发送的目标指针,在urb可以被发送到USB核心之前必须由USB驱动程序初始化
        struct usb_host_endpoint *ep;    /* (internal) pointer to endpoint */
        unsigned int pipe;    //通过端点的number来得到,决定了主机数据要发送给哪一个设备
        unsigned int stream_id;        /* (in) stream ID */
        int status;            /* (return) non-ISO status */
        unsigned int transfer_flags;    /* (in) URB_SHORT_NOT_OK | ...*/
        void *transfer_buffer;        /* (in) associated data buffer */ ///in---接收数据buffer,out----发送数据buffer
        dma_addr_t transfer_dma;    /* (in) dma addr for transfer_buffer *////存在于支持DMA的设备
        struct scatterlist *sg;        /* (in) scatter gather buffer list */
        int num_mapped_sgs;        /* (internal) mapped sg entries */
        int num_sgs;            /* (in) number of entries in the sg list */
        u32 transfer_buffer_length;    /* (in) data buffer length */
        u32 actual_length;        /* (return) actual transfer length */
        unsigned char *setup_packet;    /* (in) setup packet (control only) */
        dma_addr_t setup_dma;        /* (in) dma addr for setup_packet */
        int start_frame;        /* (modify) start frame (ISO) */
        int number_of_packets;        /* (in) number of ISO packets */
        int interval;            /* (modify) transfer interval ///主机轮询的时间间隔
        void *context;            /* (in) context for completion *////上下文
        usb_complete_t complete;    /* (in) completion routine *////完成例程(回调)--当主机发送完urb,设备返回回应信号时执行
    };

    urb的使用方法:

    1、  分配urb

    struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags);  //driversusbcoreurb.c

    2、  初始化urb

    void usb_fill_[control | int | bulk]_urb{ } ///对应控制传输、中断传输、批量传输

    3、  提交urb(提交给主控制器,由主控制器发送给USB设备)

    (1)  异步提交urb,提交完成后执行通过usb_fill_[control | int | bulk]_urb 传入的回调函数

    int usb_submit_urb(struct urb *urb, gfp_t mem_flags); //driversusbcoreurb.c

    (2) 同步提交urb

    int  usb_[control | interrupt | bulk]_msg ()  //driversusbcoreMessage.c

    四、usb驱动数据结构 usb_device

     1 struct usb_device {  ///描述一个USB 设备
     2     int        devnum;
     3     char        devpath[16];
     4     u32        route;
     5     enum usb_device_state    state;
     6     enum usb_device_speed    speed;
     7 
     8     struct usb_tt    *tt;
     9     int        ttport;
    10 
    11     unsigned int toggle[2];
    12 
    13     struct usb_device *parent;
    14     struct usb_bus *bus;
    15     struct usb_host_endpoint ep0;
    16 
    17     struct device dev;
    18 
    19     struct usb_device_descriptor descriptor;
    20     struct usb_host_bos *bos;
    21     struct usb_host_config *config;
    22 
    23     struct usb_host_config *actconfig;
    24     struct usb_host_endpoint *ep_in[16];
    25     struct usb_host_endpoint *ep_out[16];
    26 
    27     char **rawdescriptors;
    28 
    29     unsigned short bus_mA;
    30     u8 portnum;
    31     u8 level;
    32 
    33     unsigned can_submit:1;
    34     unsigned persist_enabled:1;
    35     unsigned have_langid:1;
    36     unsigned authorized:1;
    37     unsigned authenticated:1;
    38     unsigned wusb:1;
    39     unsigned lpm_capable:1;
    40     unsigned usb2_hw_lpm_capable:1;
    41     unsigned usb2_hw_lpm_besl_capable:1;
    42     unsigned usb2_hw_lpm_enabled:1;
    43     unsigned usb2_hw_lpm_allowed:1;
    44     unsigned usb3_lpm_enabled:1;
    45     int string_langid;
    46 
    47     /* static strings from the device */
    48     char *product;
    49     char *manufacturer;
    50     char *serial;
    51 
    52     struct list_head filelist;
    53 
    54     int maxchild;
    55 
    56     u32 quirks;
    57     atomic_t urbnum;
    58 
    59     unsigned long active_duration;
    60 
    61 #ifdef CONFIG_PM
    62     unsigned long connect_time;
    63 
    64     unsigned do_remote_wakeup:1;
    65     unsigned reset_resume:1;
    66     unsigned port_is_suspended:1;
    67 #endif
    68     struct wusb_dev *wusb_dev;
    69     int slot_id;
    70     enum usb_device_removable removable;
    71     struct usb2_lpm_parameters l1_params;
    72     struct usb3_lpm_parameters u1_params;
    73     struct usb3_lpm_parameters u2_params;
    74     unsigned lpm_disable_count;
    75 };

    五、  管道

    每个端点通过管道和usb主控制器连接,管道包括以下几个部分:

    (1)     端点地址

    (2)     数据传输方向(in 或 out)

    (3)     数据传输模式

    usb_[rcv| snd| ctrl| int| bulk| isoc ]pipe

    根据端点地址、传输方式和传输方向创建不同的pipe:

    #define usb_sndctrlpipe(dev, endpoint)    
        ((PIPE_CONTROL << 30) | __create_pipe(dev, endpoint))
    #define usb_rcvctrlpipe(dev, endpoint)    
        ((PIPE_CONTROL << 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)
    #define usb_sndisocpipe(dev, endpoint)    
        ((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev, endpoint))
    #define usb_rcvisocpipe(dev, endpoint)    
        ((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)
    #define usb_sndbulkpipe(dev, endpoint)    
        ((PIPE_BULK << 30) | __create_pipe(dev, endpoint))
    #define usb_rcvbulkpipe(dev, endpoint)    
        ((PIPE_BULK << 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)
    #define usb_sndintpipe(dev, endpoint)    
        ((PIPE_INTERRUPT << 30) | __create_pipe(dev, endpoint))
    #define usb_rcvintpipe(dev, endpoint)    
        ((PIPE_INTERRUPT << 30) | __create_pipe(dev, endpoint) | USB_DIR_IN
  • 相关阅读:
    java线程池,工作窃取算法
    java线程池,阿里为什么不允许使用Executors?
    CMakeLists 的使用,大型工程使用cmake 的构件过程
    ieee文献免费下载办法
    欧式距离、标准化欧式距离、马氏距离、余弦距离
    sliding window:"Marginalization","Schur complement","First estimate jacobin"
    机器学习中的线性代数之矩阵求导
    opencv中滤波方法学习
    opencv关于Mat类中的Scalar()---颜色赋值
    C/C++预处理指令#define,#ifdef,#ifndef,#endif…
  • 原文地址:https://www.cnblogs.com/EaIE099/p/5102601.html
Copyright © 2020-2023  润新知