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----发送数据bufferdma_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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/649490.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Deeplabv3+】Ubutu18.04中使用pytorch复现Deeplabv3+第三步)-----CityscapesScripts生成自己的标签

本文是在前面两篇文章的基础上&#xff0c;讲解如何更改训练数据集颜色&#xff0c;需要与前面两篇文章连起来看。 本文用于修改cityscapes数据集的标签颜色与Semankitti数据集的标签一致&#xff0c;对修改后的数据集进行训练。需要下载两个开发工具包和一个数据集&#xff0…

Git标签推送

标签默认属于本地分支&#xff0c;推送分支的时候并不会上传。需要自己手动推送 通过命令 git push origin <tagname>推送指定的标签 通过命令git push origin --tags批量推送所有的标签 在VS里打开git命令行窗口的方法&#xff1a;Git更改-操作-打开命令行提示符 对于…

1.19信息学,信息熵(wordle)

所谓均方误差实际上就是方差 分析&#xff1a;对单词进行编码后&#xff0c;采用聚类方法&#xff0c;可以将单词难度分为三类或者更多&#xff0c;如困难、一般、简单。然后对每一类的单词可视化分析&#xff0c;并描述数据得出结论。 聚类算法较多&#xff0c;在论文中可以…

Docker镜像

创建镜像有三种方法&#xff0c;分别为基于已有镜像创建、基于本地模板创建以及基于Dockerfile创建。 基于现有镜像创建 首先启动一个镜像&#xff0c;在容器里做修改 然后将修改后的容器提交为新的镜像&#xff0c;需要使用该容器的 ID 号创建新镜像 常用选项&#xff1a; -…

【Unity】【游戏开发】Pico打包后项目出现运行时错误如何Debug

【背景】 开发过程中的报错可以通过控制台查看&#xff0c;但是PICO项目这类依赖特定设备环境的应用往往存在打包后在设备端发生运行时错误。这时如何能查看到Debug信息呢&#xff1f; 【分析】 Pico也是安卓系统&#xff0c;所以这个问题就可以泛化为Unity有哪些在安卓端运…

C++实现推箱子游戏

推箱子游戏 运行之后的效果如视频所示&#xff0c;在完成游戏后播放音乐 准备工作&#xff1a;建立一个新的文件夹&#xff0c;并在文件夹中任意增加一张背景图片&#xff0c;以及各个部件的照片文件 因为这里用到了贴图技术&#xff0c;要使用graphic.h这个函数&#xff0c…

海外云手机三大优势

在全球化潮流下&#xff0c;企业因业务需求对海外手机卡等设备的需求不断攀升&#xff0c;推动了海外云手机业务的蓬勃发展。相较于自行置备手机设备&#xff0c;海外云手机不仅能够降低成本&#xff0c;还具备诸多优势&#xff0c;让我们深入探讨其中的三大黄金优势。 经济实惠…

【Linux】进程概述

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

统计学-R语言-8.1

文章目录 前言方差分析方差分析的原理什么是方差分析误差分解 单因子方差分析数学模型效应检验 练习 前言 本片开始介绍有关方差分析的知识。 方差分析 方差分析的基本原理是在20世纪20年代由英国统计学家Ronald A.Fisher在进行实验设计时为解释实验数据而首先引入的。方差分…

最新多功能PHP图床源码 /兰空图床Lsky Pro开源版v2.1/ 单纯的图床程序源码

源码介绍&#xff1a; Lsky Pro 是一个用于在线上传、管理图片的图床程序&#xff0c;中文名&#xff1a;兰空图床&#xff0c;你可以将它作为自己的云上相册&#xff0c;亦可以当作你的写作贴图库。 该程序的最初版本诞生于2017年10月&#xff0c;由ThinkPHP 5框架精心打造而…

【Linux 基础】常用基础指令(上)

文章目录 一、 创建新用户并设置密码二、ls指令ls指令基本概念ls指令的简写操作 三、pwd指令四、cd指令五、touch指令六、rm指令七、mkdir指令八、rmdir 指令 一、 创建新用户并设置密码 ls /home —— 查看存在多少用户 whoami —— 查看当前用户名 adduser 用户名 —— 创建新…

08 BGP 华为官方文档 十一条选路原则

BGP 华为官方文档 十一条选路原则 丢弃下一跳不可达的路由 1&#xff09;比较“协议首选值-pref-val”属性&#xff0c;数值越大越好&#xff0c;默认值是0&#xff0c;只在本设备生效&#xff0c;不在网络中传递 2&#xff09;比较“本地优先级-local_pref”属性&#xff0c;…

Ceph分布式存储自动化运维平台开发实践

文章目录 1. 背景介绍1.1 什么是Ceph&#xff1f;1.1.1 Ceph的核心组件1.1.2 Ceph的优势 1.2 自动化运维的需求目标 2. 平台架构设计和组件版本2.1 平台架构设计2.2 组件版本2.3 模块划分&#xff08;已经脱敏处理&#xff09;2.3.1 当前版本V1.0支持功能2.3.2 前后端代码结构t…

利用 “diart“ 和 OpenAI 的 Whisper 简化实时转录

利用 "diart" 和 OpenAI 的 Whisper 简化实时转录 工作原理 Diart 是一个基于人工智能的 Python 库&#xff0c;用于实时记录说话者语言&#xff08;即 "谁在什么时候说话"&#xff09;&#xff0c;它建立在 pyannote.audio 模型之上&#xff0c;专为实时…

微信小程序 仿微信聊天界面

1. 需求效果图 2. 方案 为实现这样的效果&#xff0c;首先要解决两个问题&#xff1a; 2.1.点击输入框弹出软键盘后&#xff0c;将已有的少许聊天内容弹出&#xff0c;导致看不到的问题 点击输入框弹出软键盘后&#xff0c;将已有的少许聊天内容弹出&#xff0c;导致看不到的问…

银行数据仓库体系实践(8)--主数据模型设计

主数据区域中保留了数据仓库的所有基础数据及历史数据&#xff0c;是数据仓库中最重要的数据区域之一&#xff0c;那主数据区域中主要分为近源模型区和整合&#xff08;主题&#xff09;模型区。上一节讲到了模型的设计流程如下图所示。那近源模型层的设计在第2.3和3这两个步骤…

85 总结一下最近遇到的一些 jar发布 相关的知识

前言 呵呵 最近有一些构建服务, 发布服务的一些需求 我们这里的服务 一般来说是 java application, spring boot application 针对发布, 当然最好是 增量发布, 尽量的减少需要传递给 发布服务器 的资源的大小 比如 我的这个 java application, 可能会存在很多依赖, 常规…

探讨Go语言在构建HTTP代理时的优势和挑战

亲爱的读者&#xff0c;让我们一起来探讨一下Go语言在构建HTTP代理时的优势和挑战。 首先&#xff0c;让我们来谈谈Go语言在构建HTTP代理时的优势。Go语言是一种高性能的编程语言&#xff0c;它具有简洁、高效的特点&#xff0c;非常适合构建高效的代理服务器。使用Go语言&…

springboot第52集:微服务分布式架构,统一验证,oauth,订单,地区管理周刊

在计算机领域中&#xff0c;FGC 通常代表 Full Garbage Collection&#xff0c;即全垃圾收集。垃圾收集是一种自动管理内存的机制&#xff0c;它负责回收不再被程序使用的内存&#xff0c;以便释放资源和提高程序性能。 当系统执行 Full Garbage Collection 时&#xff0c;它会…

【代码随想录-数组】二分查找

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…