Linux内核中USB设备驱动实现

简介: Linux内核中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); //\drivers\usb\core\urb.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); //\drivers\usb\core\urb.c

(2) 同步提交urb

int usb_[control | interrupt | bulk]_msg () //\drivers\usb\core\Message.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
目录
相关文章
|
15天前
|
算法 Linux 调度
深入理解Linux内核调度器:从基础到优化####
本文旨在通过剖析Linux操作系统的心脏——内核调度器,为读者揭开其高效管理CPU资源的神秘面纱。不同于传统的摘要概述,本文将直接以一段精简代码片段作为引子,展示一个简化版的任务调度逻辑,随后逐步深入,详细探讨Linux内核调度器的工作原理、关键数据结构、调度算法演变以及性能调优策略,旨在为开发者与系统管理员提供一份实用的技术指南。 ####
54 4
|
4天前
|
缓存 网络协议 Linux
深入探索Linux操作系统的内核优化策略####
本文旨在探讨Linux操作系统内核的优化方法,通过分析当前主流的几种内核优化技术,结合具体案例,阐述如何有效提升系统性能与稳定性。文章首先概述了Linux内核的基本结构,随后详细解析了内核优化的必要性及常用手段,包括编译优化、内核参数调整、内存管理优化等,最后通过实例展示了这些优化技巧在实际场景中的应用效果,为读者提供了一套实用的Linux内核优化指南。 ####
16 1
|
9天前
|
算法 Linux 开发者
Linux内核中的锁机制:保障并发控制的艺术####
本文深入探讨了Linux操作系统内核中实现的多种锁机制,包括自旋锁、互斥锁、读写锁等,旨在揭示这些同步原语如何高效地解决资源竞争问题,保证系统的稳定性和性能。通过分析不同锁机制的工作原理及应用场景,本文为开发者提供了在高并发环境下进行有效并发控制的实用指南。 ####
|
16天前
|
缓存 负载均衡 Linux
深入理解Linux内核调度器
本文探讨了Linux操作系统核心组件之一——内核调度器的工作原理和设计哲学。不同于常规的技术文章,本摘要旨在提供一种全新的视角来审视Linux内核的调度机制,通过分析其对系统性能的影响以及在多核处理器环境下的表现,揭示调度器如何平衡公平性和效率。文章进一步讨论了完全公平调度器(CFS)的设计细节,包括它如何处理不同优先级的任务、如何进行负载均衡以及它是如何适应现代多核架构的挑战。此外,本文还简要概述了Linux调度器的未来发展方向,包括对实时任务支持的改进和对异构计算环境的适应性。
37 6
|
17天前
|
缓存 运维 网络协议
深入Linux内核架构:操作系统的核心奥秘
深入Linux内核架构:操作系统的核心奥秘
36 2
|
14天前
|
监控 Linux
如何检查 Linux 内存使用量是否耗尽?这 5 个命令堪称绝了!
本文介绍了在Linux系统中检查内存使用情况的5个常用命令:`free`、`top`、`vmstat`、`pidstat` 和 `/proc/meminfo` 文件,帮助用户准确监控内存状态,确保系统稳定运行。
103 6
|
15天前
|
Linux
在 Linux 系统中,“cd”命令用于切换当前工作目录
在 Linux 系统中,“cd”命令用于切换当前工作目录。本文详细介绍了“cd”命令的基本用法和常见技巧,包括使用“.”、“..”、“~”、绝对路径和相对路径,以及快速切换到上一次工作目录等。此外,还探讨了高级技巧,如使用通配符、结合其他命令、在脚本中使用,以及实际应用案例,帮助读者提高工作效率。
57 3
|
15天前
|
监控 安全 Linux
在 Linux 系统中,网络管理是重要任务。本文介绍了常用的网络命令及其适用场景
在 Linux 系统中,网络管理是重要任务。本文介绍了常用的网络命令及其适用场景,包括 ping(测试连通性)、traceroute(跟踪路由路径)、netstat(显示网络连接信息)、nmap(网络扫描)、ifconfig 和 ip(网络接口配置)。掌握这些命令有助于高效诊断和解决网络问题,保障网络稳定运行。
47 2
|
23天前
|
缓存 监控 Linux
|
10天前
|
运维 监控 网络协议
运维工程师日常工作中最常用的20个Linux命令,涵盖文件操作、目录管理、权限设置、系统监控等方面
本文介绍了运维工程师日常工作中最常用的20个Linux命令,涵盖文件操作、目录管理、权限设置、系统监控等方面,旨在帮助读者提高工作效率。从基本的文件查看与编辑,到高级的网络配置与安全管理,这些命令是运维工作中的必备工具。
40 3