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
目录
相关文章
|
6天前
|
安全 Linux 测试技术
Intel Linux 内核测试套件-LKVS介绍 | 龙蜥大讲堂104期
《Intel Linux内核测试套件-LKVS介绍》(龙蜥大讲堂104期)主要介绍了LKVS的定义、使用方法、测试范围、典型案例及其优势。LKVS是轻量级、低耦合且高代码覆盖率的测试工具,涵盖20多个硬件和内核属性,已开源并集成到多个社区CICD系统中。课程详细讲解了如何使用LKVS进行CPU、电源管理和安全特性(如TDX、CET)的测试,并展示了其在实际应用中的价值。
|
19天前
|
Ubuntu Linux 开发者
Ubuntu20.04搭建嵌入式linux网络加载内核、设备树和根文件系统
使用上述U-Boot命令配置并启动嵌入式设备。如果配置正确,设备将通过TFTP加载内核和设备树,并通过NFS挂载根文件系统。
68 15
|
1月前
|
算法 Linux
深入探索Linux内核的内存管理机制
本文旨在为读者提供对Linux操作系统内核中内存管理机制的深入理解。通过探讨Linux内核如何高效地分配、回收和优化内存资源,我们揭示了这一复杂系统背后的原理及其对系统性能的影响。不同于常规的摘要,本文将直接进入主题,不包含背景信息或研究目的等标准部分,而是专注于技术细节和实际操作。
|
1月前
|
存储 缓存 网络协议
Linux操作系统的内核优化与性能调优####
本文深入探讨了Linux操作系统内核的优化策略与性能调优方法,旨在为系统管理员和高级用户提供一套实用的指南。通过分析内核参数调整、文件系统选择、内存管理及网络配置等关键方面,本文揭示了如何有效提升Linux系统的稳定性和运行效率。不同于常规摘要仅概述内容的做法,本摘要直接指出文章的核心价值——提供具体可行的优化措施,助力读者实现系统性能的飞跃。 ####
|
1月前
|
缓存 监控 网络协议
Linux操作系统的内核优化与实践####
本文旨在探讨Linux操作系统内核的优化策略与实际应用案例,深入分析内核参数调优、编译选项配置及实时性能监控的方法。通过具体实例讲解如何根据不同应用场景调整内核设置,以提升系统性能和稳定性,为系统管理员和技术爱好者提供实用的优化指南。 ####
|
2月前
|
算法 Linux 调度
深入理解Linux内核调度器:从基础到优化####
本文旨在通过剖析Linux操作系统的心脏——内核调度器,为读者揭开其高效管理CPU资源的神秘面纱。不同于传统的摘要概述,本文将直接以一段精简代码片段作为引子,展示一个简化版的任务调度逻辑,随后逐步深入,详细探讨Linux内核调度器的工作原理、关键数据结构、调度算法演变以及性能调优策略,旨在为开发者与系统管理员提供一份实用的技术指南。 ####
95 4
|
1月前
|
监控 算法 Linux
Linux内核锁机制深度剖析与实践优化####
本文作为一篇技术性文章,深入探讨了Linux操作系统内核中锁机制的工作原理、类型及其在并发控制中的应用,旨在为开发者提供关于如何有效利用这些工具来提升系统性能和稳定性的见解。不同于常规摘要的概述性质,本文将直接通过具体案例分析,展示在不同场景下选择合适的锁策略对于解决竞争条件、死锁问题的重要性,以及如何根据实际需求调整锁的粒度以达到最佳效果,为读者呈现一份实用性强的实践指南。 ####
|
2月前
|
缓存 并行计算 Linux
深入解析Linux操作系统的内核优化策略
本文旨在探讨Linux操作系统内核的优化策略,包括内核参数调整、内存管理、CPU调度以及文件系统性能提升等方面。通过对这些关键领域的分析,我们可以理解如何有效地提高Linux系统的性能和稳定性,从而为用户提供更加流畅和高效的计算体验。
54 2
|
2月前
|
缓存 网络协议 Linux
深入探索Linux操作系统的内核优化策略####
本文旨在探讨Linux操作系统内核的优化方法,通过分析当前主流的几种内核优化技术,结合具体案例,阐述如何有效提升系统性能与稳定性。文章首先概述了Linux内核的基本结构,随后详细解析了内核优化的必要性及常用手段,包括编译优化、内核参数调整、内存管理优化等,最后通过实例展示了这些优化技巧在实际场景中的应用效果,为读者提供了一套实用的Linux内核优化指南。 ####
61 1
|
2月前
|
缓存 资源调度 安全
深入探索Linux操作系统的心脏——内核配置与优化####
本文作为一篇技术性深度解析文章,旨在引领读者踏上一场揭秘Linux内核配置与优化的奇妙之旅。不同于传统的摘要概述,本文将以实战为导向,直接跳入核心内容,探讨如何通过精细调整内核参数来提升系统性能、增强安全性及实现资源高效利用。从基础概念到高级技巧,逐步揭示那些隐藏在命令行背后的强大功能,为系统管理员和高级用户打开一扇通往极致性能与定制化体验的大门。 --- ###
89 9