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
目录
相关文章
|
10月前
|
安全 网络协议 Linux
深入理解Linux内核模块:加载机制、参数传递与实战开发
本文深入解析了Linux内核模块的加载机制、参数传递方式及实战开发技巧。内容涵盖模块基础概念、加载与卸载流程、生命周期管理、参数配置方法,并通过“Hello World”模块和字符设备驱动实例,带领读者逐步掌握模块开发技能。同时,介绍了调试手段、常见问题排查、开发规范及高级特性,如内核线程、模块间通信与性能优化策略。适合希望深入理解Linux内核机制、提升系统编程能力的技术人员阅读与实践。
925 1
|
9月前
|
安全 Linux 网络安全
Nipper 3.9.0 for Windows & Linux - 网络设备漏洞评估
Nipper 3.9.0 for Windows & Linux - 网络设备漏洞评估
253 0
Nipper 3.9.0 for Windows & Linux - 网络设备漏洞评估
|
10月前
|
数据采集 编解码 运维
一文讲完说懂 WowKey -- WowKey 是一款 Linux 类设备的命令行(CLT)运维工具
WowKey 是一款面向 Linux 类设备的命令行运维工具,支持自动登录、批量执行及标准化维护,适用于企业、团队或个人管理多台设备,显著提升运维效率与质量。
|
10月前
|
监控 Ubuntu Linux
什么Linux,Linux内核及Linux操作系统
上面只是简单的介绍了一下Linux操作系统的几个核心组件,其实Linux的整体架构要复杂的多。单纯从Linux内核的角度,它要管理CPU、内存、网卡、硬盘和输入输出等设备,因此内核本身分为进程调度,内存管理,虚拟文件系统,网络接口等4个核心子系统。
1056 0
|
10月前
|
Web App开发 缓存 Rust
|
算法 Linux 调度
深入理解Linux内核调度器:从基础到优化####
本文旨在通过剖析Linux操作系统的心脏——内核调度器,为读者揭开其高效管理CPU资源的神秘面纱。不同于传统的摘要概述,本文将直接以一段精简代码片段作为引子,展示一个简化版的任务调度逻辑,随后逐步深入,详细探讨Linux内核调度器的工作原理、关键数据结构、调度算法演变以及性能调优策略,旨在为开发者与系统管理员提供一份实用的技术指南。 ####
661 4
|
机器学习/深度学习 人工智能 负载均衡
深度解析:Linux内核调度策略的演变与优化
【5月更文挑战第30天】 随着计算技术的不断进步,操作系统的性能调优成为了提升计算机系统效率的关键。在众多操作系统中,Linux因其开源和高度可定制性而备受青睐。本文将深入剖析Linux操作系统的内核调度策略,追溯其历史演变过程,并重点探讨近年来为适应多核处理器和实时性要求而产生的调度策略优化。通过分析比较不同的调度算法,如CFS(完全公平调度器)、实时调度类和批处理作业的调度需求,本文旨在为系统管理员和开发者提供对Linux调度机制深层次理解,同时指出未来可能的发展趋势。
|
缓存 并行计算 Linux
深入解析Linux操作系统的内核优化策略
本文旨在探讨Linux操作系统内核的优化策略,包括内核参数调整、内存管理、CPU调度以及文件系统性能提升等方面。通过对这些关键领域的分析,我们可以理解如何有效地提高Linux系统的性能和稳定性,从而为用户提供更加流畅和高效的计算体验。
721 24
|
缓存 监控 网络协议
Linux操作系统的内核优化与实践####
本文旨在探讨Linux操作系统内核的优化策略与实际应用案例,深入分析内核参数调优、编译选项配置及实时性能监控的方法。通过具体实例讲解如何根据不同应用场景调整内核设置,以提升系统性能和稳定性,为系统管理员和技术爱好者提供实用的优化指南。 ####