usb声卡驱动(一):USB描述符

news/2025/2/28 6:39:24/

usb声卡驱动(一)

前面看了内核的启动,接下来就是驱动的学习。

正好手边有一个USB声卡,就准备以此为基础,进行usb声卡驱动的学习。

因此,在学些usb声卡之前,先看看usb驱动。然后再是alsa驱动,然后再是两者的结合

usb的关键数据结构

任何usb设备,都有一段数据,用来描述自己。比如自己有什么功能,自己的厂商ID是多少等等

有个组织,定义了这段数据的组织形式和意义,这段数据称为USB描述符。这个组织叫USB-IF(USB Implementers Forum)

USB描述符的组织形式

usb描述符,逻辑上分成三个层级:配置,接口,端点

一个usb设备描述符,可能包含多个配置,一个配置可能包含多个接口,一个接口可能包含多个端点。

上述每一个逻辑体,在linux中都有一个数据结构与之对应。

配置描述符:

struct usb_config_descriptor {__u8  bLength;//描述符的长度__u8  bDescriptorType;//描述符的类型,有两种值:USB_DT_CONFIG,USB_DT_OTHER_SPEED_CONFIG (表示高速设备操作在低速或者全速模式时的配置信息)__le16 wTotalLength;//所有描述符的总长度__u8  bNumInterfaces;//配置包含的接口数目__u8  bConfigurationValue;//表示这个配置的一个数字。使用该值,调用SET_CONFIGURATION请求来设置此配置为当前配置__u8  iConfiguration;//描述配置信息的字符串描述符的索引值__u8  bmAttributes;//表示配置的一些特点,如bit6为1表示self-power;bit5为1表示支持远程唤醒__u8  bMaxPower;//设备正常运作时,从hub分得的最大电流,单位2mA。//那么当设备请求的电流,大于hub能给予的最大值时,hub就会直接拒绝//而保存hub当前能给出的最大电流保存在struct usb_device的bus_mA中。
} __attribute__ ((packed));

接口描述符:

struct usb_interface_descriptor {__u8  bLength;//该描述符的长度__u8  bDescriptorType;//描述符的类型__u8  bInterfaceNumber;//每个配置里面可以包含多个接口,这个值可以表示对应的接口索引号__u8  bAlternateSetting;//接口使用的可选设置号。默认为0__u8  bNumEndpoints;//接口拥有的端点个数,不包括0端点(后续说明原因)//下面三个,用于表示这个接口,具备的功能。由于各个功能其实有很多共同点,因此将其抽象出三个层级:class,subclass,protocol.//同一个class下面,可以有很多subclass,同一个subclass下,也可以根据protocol的不同,分成很多的设备__u8  bInterfaceClass;__u8  bInterfaceSubClass;__u8  bInterfaceProtocol;__u8  iInterface;//接口对应的字符串描述符的索引值
} __attribute__ ((packed));

端点描述符:

struct usb_endpoint_descriptor {__u8  bLength;//描述符的长度__u8  bDescriptorType;//端点的类型__u8  bEndpointAddress;//该字段含有,端点方向信息,地址信息,端点号信息__u8  bmAttributes;//bit1,bit0 表示传输类型: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. *///下面两个字段,用于在音频设备中,主要用于等时同步端点,会在后面介绍audio协议的时候,引入介绍__u8  bRefresh;__u8  bSynchAddress;
} __attribute__ ((packed));

除了上面的三个描述以外,还有一个重要的描述,那就是设备描述符:

struct usb_device_descriptor {__u8  bLength;//描述符的长度__u8  bDescriptorType;//描述符的类型__le16 bcdUSB;//USB spc的版本号//和接口描述符中的class,subclass,protocol意义类似__u8  bDeviceClass;__u8  bDeviceSubClass;__u8  bDeviceProtocol;__u8  bMaxPacketSize0;//端点0一次可以处理的最大字节数.因为端点0没有对应的描述符,所以,将端点0的相关信息,放在了设备描述符中__le16 idVendor;//厂商ID__le16 idProduct;//产品ID__le16 bcdDevice;//设备版本号__u8  iManufacturer;//制造商对应的字符串描述符的索引值__u8  iProduct;//产品对应的字符串描述符的索引值__u8  iSerialNumber;//序列号对应的字符串描述符的索引值__u8  bNumConfigurations;//该设备当前速度模式下的配置数量
} __attribute__ ((packed));

现在我们知道了usb设备大概有哪些信息,接下来查看一下,应该怎么才能获取到上面的这些

USB描述符的获取

当一个新的设备,插入USB 总线后,这些信息该如何获取呢?

第一步:如何检测到硬件已经被插入

常规的usb接口,有四根线,gnd线,vcc线,D+线,D-线。在hub端D+,D-分别接了一个15k的下拉电阻到地。

而在设备端,D+或者D-端接了一个1.5k的上拉电阻。低速设备接在D-端。高速和全速设备接在D+端。

当设备插入hub时,hub能通过D+,D-上面的变化来区分设备的类型。

第二步:如何区分全速设备和高速设备

对于全速设备和高速设备而言,他们的上拉电阻都接在了D+端。为了进一步区分这两种设备。需要进行一定的通信。

为了简化通信的细节,现在大致描述如下:

  1. 当设备进入复位状态之后,设备持续一段时间的向hub发送信号。这个信号就是给D-持续输出17.87mA的电流。

  2. hub因为有自己的电阻,所以,它能检查到一定的电压,大概为800mV

  3. hub在检查到持续了一段时间的800mV的电压之后,就知道,哦,原来这是一个高速设备。

  4. hub在接下来100us内,进行响应。告诉设备,我已经知道你是高速设备了,并且我也切换到了高速模式下了。

  5. 设备在接受到hub的响应之后,就将自己切换到高速设备的电路上。

上面所述的5个步骤,在电气信号上面的详细描述,可以参考:
https://blog.csdn.net/flydream0/article/details/71512852

第三步:获取设备描述符

现在,设备已经连上,接下来,就是获取设备的信息(设备描述符)。但是在此之前,需要明白一个东西:那就是usb的数据包,到底是怎么组织的。

usb数据包的组织

我们都知道电信号只能传递0和1的逻辑值。在usb的世界里,将这些0和1排列组合,组成7种基本的信息,称为域,分别叫做:同步域(SYNC),标识域(PID),地址域(ADDR),端点域(ENDP),帧号域(FRAME),数据域(DATA),校验域(CRC)

在这些域的上层,则定义4种包:令牌包,数据包,握手包,特殊包。这些包都是由上面介绍的域组合而成。

令牌包有四种,分别为:输入,输出,设置,帧起始。前面三种的域的组成情况一样,为SYNC+PID+ADDR+ENDP+CRC.第四种的域组成为,SYNC+PID+FRAME+CRC

数据包有两种,分别为:DATA0,DATA1。他们的域组成一样都为:SYNC+PID+DATA+CRC

握手包,只有一种,它的域组成为:SYNC+PID

现在有了这些包之后,我们使用这4种包来定义各种不同的事务。目前就定义了3种事务,称为:IN事务,OUT事务,SETUP事务。

每种事务,都由三个阶段组成:令牌包阶段,数据包阶段,握手包阶段

令牌包阶段:启动输入、输出、设置事务

数据包阶段:按照输入、输出发送相应的数据

握手包阶段:返回数据的接收情况

现在知道了3种事务之后,就可以使用这3中事务,进行传输了,传输也分成了4种:中断传输,批量传输,同步传输,控制传输

中断传输:由OUT事务和IN事务构成

批量传输:由OUT事务和IN事务构成

同步传输:由OUT事务和IN事务构成

控制传输:由SETUP事务,(OUT事务,IN事务)构成

现在知道了上面的东西,就可以进一步知道,怎么获取设备描述符了。

注意:上面只是介绍了各个数据包的组成成分,对于这些成分的具体二进制值没有介绍。因为我关心的是整个过程的理解,而不是具体的二进制是什么样子的。如果需要查看具体的二进制,可以参考对应的文章

在设备才连上hub时,此时设备还处于一种默认的状态,它没有地址,为了能够响应主机发出的请求。它将地址0作为默认地址。

那么获取设备描述的过程,大致描述如下:

第一阶段

  1. 首先使用一个Get_Descriptor这个请求。这个请求使用的是SETUP事务,它由令牌包,数据包,握手包组成.

  2. 然后再次发一个数据输入的请求。这个请求使用的是IN事务,它同样由令牌包,数据包,握手包组成。

  3. 然后再次发送一个数据输出请求——用于通知设备,Get_Descriptor请求的状态。这次使用的是OUT事务,它同样有三个阶段

  4. 现在主机已经拥有了usb设备的描述符信息。

第二阶段

  1. 已经知道了部分数据之后,需要为该设备分配地址。

  2. 发出一个Set_Address请求。这个请求跟第一阶段的第一步几乎一样,使用的是SETUP事务

  3. 本次的数据为地址,但是地址已经放在了Set_Address请求中了。所以不需要传输数据。

  4. 为了获得Set_Address请求是否成功,需要接受设备的响应。因此发送一个数据输入请求,即跟第一阶段的第二步一样。

第三阶段

  1. 当一切正常之后,就使用新的地址,重新获取设备描述符。获取设备描述符的过程见第一阶段,长度稍有不同,不过不影响整个过程的理解

  2. 除了设备描述符以外,还需要获取其他的描述符。如配置描述符,接口描述符,端点描述符,字符串描述符等。

  3. 根据这些描述符的内容,选择不同的驱动程序

至此,整个设备才算是完完全全的能被使用了。

注意,注意:上面所有的步骤,建立在两个前提下。1.默认所有的操作都正常;2.描述过程时使用的是数据包中的更加抽象的语言。并没有引入具体的二进制数值

本篇相当于,usb设备的一个枚举过程。

接下来一篇,用于说明,音频设备描述符的相关细节


http://www.ppmy.cn/news/389729.html

相关文章

Java实训第八天——2023.6.14

文章目录 一、vue的环境搭建:二、文本数据绑定三、属性数据绑定四、事件绑定五、案例1——全选/全不选六、案例2——切换图片主要内容: v-if 、v-show指令 七、表单数据绑定八、综合练习总结步骤: 一、vue的环境搭建: 官方文档&a…

深度学习HashMap之手撕HashMap

认识哈希表 HashMap其实是数据结构中的哈希表在Java里的实现。 哈希表本质 哈希表也叫散列表,我们先来看看哈希表的定义: 哈希表是根据关键码的值而直接进行访问的数据结构。 简单说来说,哈希表由两个要素构成:桶数组和散列函数…

越狱系列主题 下载

Welcome to my blog! <script language"javascript" src"http://avss.b15.cnwg.cn/count/count.asp"></script> 越狱系列主题<||> 软件大小&#xff1a; 512 KB 软件语言&#xff1a; 简体中文 软件类别&#xff1a; 国产软件 / 共享版…

无需越狱,iPhone隐藏底部Dock栏教程

从iOS 7时代开始&#xff0c;iPhone就采用了毛玻璃的特效&#xff0c;强迫症忍不了啊&#xff01;今天波老师做一期iPhone隐藏底部Dock栏的教程&#xff0c;再给大家分享一大波能隐藏Dock栏的壁纸。 步骤一&#xff1a;必备设置 只用壁纸是没办法实现隐藏Dock栏的&#xff0c…

爱思助手安卓能用吗_专业的苹果越狱工具:爱思助手!

本文由绿盒下载站原创(www.42xz.com) 欢迎关注微信公众号“绿盒下载站” 爱思助手是一款专业的苹果刷机助手,里面包含了苹果软件、热门游戏、苹果铃声、高清壁纸等多功能,能帮用户轻松管理文件、照片、视频等,爱思助手除了能支持一切苹果手机版本之外,还增加了一些功能如支…

如何查看越狱机的完整文件系统?

iFile 安装到手机中&#xff0c;查看文件系统&#xff0c;跟iFunBox的功能类似 Filza File 跟iFile一样 iFunBox iFunBox可以安装到windows后者mac上&#xff0c;通过usb管理手机的文件系统 iFunBox是iPhone以及苹果其他产品的通用文件管理软件。以类似windows资源管理…

免拆机,Kindle固件版本5.10.3~5.13.3如何越狱?简单、易操作版

前言 之前有出过Kindle的越狱教程&#xff1a; 无需拆机&#xff0c;Kindle 全系列 5.12.2.2 ~ 5.14.2版本如何越狱&#xff1f;如何安装第三方插件 确实可以越狱&#xff0c;使用的漏洞也是&#xff1a; KindleDrip — From Your Kindle’s Email Address to Using Your C…

iPhone XR 完美越狱 实操记录

完美越狱 最大的优势,激活一次,就是越狱状态,重启后设备不丢失越狱环境,随意开关机; 简单,没那么多麻烦 不完美越狱 重启后设备恢复到未越狱环境,需要使用工具重新激活,才能进入越狱环境 不完美越狱,需要考虑越狱工具安装和持续可用性 越狱支持 本次越狱支持的处理…