Linux中USB描述符详解-wxc-2018-03-31
USB命令(请求)及标准描述符等相关归纳介绍
![USB命令(请求)及标准描述符等相关归纳介绍](https://img.taocdn.com/s3/m/ccd332c3ce2f0066f53322e9.png)
当USB设备第一次连接到主机上时,要接收主机的枚举和配置,目的就是让主机知道该设备具有什么功能、是哪一类的USB设备、需要占用多少USB的资源、使用了哪些传输方式以及传输的数据量多大等等。
只有主机完全确认了这些信息后,设备才能真正开始工作。
这些信息是通过存储在设备中的USB描述符来体现的。
USB设备的属性包括很多内容,为了便于管理,USB协议1.1将这些信息做了分类,定义了很多种描述符,其中标准的描述符包括:设备描述符、配置描述符、接口描述符、端点描述符、字符串描述符。
这些描述符之间具有一定的关系,设备描述符是最高级的描述符,而端点描述符是最低级的描述符。
每一个设备只有一个设备描述符,但设备描述符可以包含多个配置描述符;而一个配置描述符又可包含多个接口描述符;一个接口使用了几个端点,就有几个端点描述符。
字符串描述符是可选的。
所有的命令虽然有不同的数据和使用目的,有的USB命令结构是一样的。
控制传输的“初始设置步骤”中包含了1个8字节的DATA0数据包,这8字节的数据包是主机用来发送控制阶段中的请求命令的,而这些请求命令是主机配置USB设备的关键。
这里就来详细分析这8字节请求命令的结构和内容:上表中bRequest为命令编码值,含意见表3:4bNumberInterfaces1所支持的接口数5bConfigurationValue1配置值6iConfiguration1配置字符串描述符索引值7bmAttributes1配置特性8bMaxPower1所需要的最大总线电流(Value*2mA)报告描述符:HID设备的报告描述符比较复杂也比较难理解。
报告描述符的语法不同于USB标准描述符,它是以项目(Items)方式排列而成,无一定的长度。
HID的报告描述符已经不是简单的描述某个值对应的某个固定的意义了,它已经能组合出多种情况,并且需要PC驱动程序提供parser解释器来对描述的设备情形进行重新解释,进而组合生成本HID硬件设备独特的数据流格式。
LINUX操作系统USB驱动程序
![LINUX操作系统USB驱动程序](https://img.taocdn.com/s3/m/1318d01655270722192ef71a.png)
一、引言USB(Universal Serial Bus)即通用串行总线,是一种全新的双向同步传输的支持热插拔的数据传输总线,其目的是为了提供一种兼容不同速度的、可扩充的并且使用方便的外围设备接口,同时也是为了解决计算机接口的太多的弊端而设计的。
一个USB系统主要有三部分组成:USB互连、USB主机、USB设备三部分组成的,其结构如图1所示。
在编写USB设备驱动程序设计时,可以分为三部分编写:主机端设备驱动程序、主机控制器驱动程序设计和设备端驱动程序三部分,在本文中重点介绍主机端驱动程序的设计。
二、USB设备驱动程序的设计USB设备驱动程序的设计包括主机端设备驱动程序设计、主机控制器驱动程序设计和设备端驱动程序设计三部分组成。
主机端设备驱动程序就是通常说的设备驱动程序,它是主机环境中为用户应用程序提供一个访问USB外设的接口。
Linux为这部分驱动程序提供编程接口,驱动程序设计者只要按照需求编写驱动程序框架,通过调用操作系统提供的API接口函数可以完成对USB外设的特定访问。
主机控制驱动主要是对USB主机控制器的驱动,在大多数PC环境下,主机控制器都是由操作系统提供。
嵌入式设备一般都没有USB主机控制器,只是工作在Slave模式下。
如果要使USB具有主机功能,那么设备中需要选用一个带主机控制器的USB接口控制芯片,同时自己还要有实现该主机控制器的驱动程序。
目前Linux内核中只提供USB主机控制器的开放主机控制器和通用主机控制器接口两种规格,而这两种规格主要用在PC架构中。
USB主机端驱动程序与主机控制器的结构如图2所示。
其中USB核是Linux的一个子模块,集中定义了一组USB相关的数据结构、宏以及API函数。
USB设备驱动程序是常说的设备固件程序的一部分,提供设备信息与主机的通信接口。
设备端USB驱动程序设计由以下几部分处理程序组成。
初始化例程:完成描述符指针、端点、配置改变等操作。
数据传输例程:完成控制传输、批量传输、中断传输及同步传输等传输方式下的数据收发工作。
linux 添加usb设备规则
![linux 添加usb设备规则](https://img.taocdn.com/s3/m/6434e1534531b90d6c85ec3a87c24028915f8520.png)
linux 添加usb设备规则摘要:1.Linux 添加USB 设备的方法B 设备规则的配置3.实例:添加USB 摄像头和U 盘正文:在Linux 系统中,添加USB 设备需要进行一定的配置。
这里我们将介绍如何在Linux 系统中添加USB 摄像头和U 盘,并配置相应的设备规则。
一、Linux 添加USB 设备的方法1.插上USB 设备后,系统会自动识别并分配一个设备文件节点。
2.通过lsusb 命令查看已连接的USB 设备。
3.若要查看USB 设备的详细信息,可以使用lsusb -v 命令。
二、USB 设备规则的配置1.在/etc/fstab文件中添加USB设备的挂载点。
例如,对于一个U 盘,可以添加如下内容:```/dev/sdb1 /mnt/usbpoint ntfs defaults 0 0```其中,/dev/sdb1 是U 盘的设备文件节点,/mnt/usbpoint 是挂载点,ntfs 是文件系统类型,defaults 表示使用默认的挂载选项。
2.若要在系统启动时自动挂载USB 设备,可以将上述内容添加到/etc/fstab 文件中。
3.若要手工挂载USB 设备,可以使用以下命令:```sudo mount /dev/sdb1 /mnt/usbpoint```三、实例:添加USB 摄像头和U 盘1.对于USB 摄像头,首先需要安装相应的驱动程序。
例如,对于一个Linux 兼容的USB 摄像头,可以使用以下命令安装驱动:```sudo modprobe bcm2835```2.安装摄像头的图像处理软件。
例如,可以使用以下命令安装gphoto2:```sudo apt-get install gphoto2```3.启动gphoto2,并使用如下命令设置摄像头的设备文件节点:```gphoto2 --set-config /dev/video0```4.至此,USB 摄像头已经成功添加到Linux 系统中。
Linux下的硬件驱动——USB设备
![Linux下的硬件驱动——USB设备](https://img.taocdn.com/s3/m/63a7448fa0c7aa00b52acfc789eb172dec639949.png)
Linux下的硬件驱动——USB设备什么是USB设备?USB即Universal Serial Bus,翻译过来就是通用串行总线。
它是一种规范化的、快速的、热插拔的串行输入/输出接口。
USB接口常被用于连接鼠标、键盘、打印机、扫描仪、音频设备、存储设备等外围设备。
Linux下的USB驱动在Linux系统中,每个USB设备都需要一个相应的驱动程序来驱动。
从Linux 2.4开始,内核提供了完整的USB设备支持。
对于每个USB设备,内核都会自动加载对应的驱动程序。
Linux下的USB设备驱动程序主要分为以下几个部分:USB核心驱动程序USB核心驱动程序是操作系统内核中处理USB设备的核心模块,负责与各种类型的USB设备进行通信,包括主机控制器、USB总线、USB设备等。
它与驱动程序和应用程序之间起到了桥梁的作用,为驱动程序提供了USB设备的基础支持。
USB设备驱动程序USB设备驱动程序是与特定USB设备相对应的驱动程序,为USB设备提供具体的读写功能和其他控制功能。
USB核心驱动程序和USB设备驱动程序之间的接口USB核心驱动程序和USB设备驱动程序之间的接口是指USB层和应用程序层之间的接口,负责传递各种USB操作的命令和数据。
如何编译一个USB设备驱动编译一个USB设备驱动程序需要按照以下步骤进行:步骤一:安装必要的软件包首先需要安装编译和调试USB设备驱动所需的软件包,包括编译工具链、内核源代码、内核头文件等。
sudo apt-get install build-essential linux-source linux-headers-`una me -r`步骤二:编写代码现在可以编写USB设备驱动程序的代码,此处不做详细介绍。
步骤三:编译代码在终端窗口中进入USB设备驱动程序所在的目录下,输入以下命令进行编译:make此命令将会编译USB设备驱动程序,并生成一个将驱动程序与内核进行连接的模块文件。
Linux系统中列出PCI设备和USB设备的命令详解
![Linux系统中列出PCI设备和USB设备的命令详解](https://img.taocdn.com/s3/m/eafd479a85868762caaedd3383c4bb4cf7ecb7c6.png)
Linux系统中列出PCI设备和USB设备的命令详解lspciNAMElspci - 列出所有PCI设备 [[ ]]总览 SYNOPSISlspci [ options ] [[ ]]描述 DESCRIPTIONlspci 是⼀个⽤来显⽰系统中所有PCI总线设备或连接到该总线上的所有设备的⼯具。
为了能使⽤这个命令所有功能,你需要有 linux 2.1.82 或以上版本,⽀持 /proc/bus/pci 接⼝的内核。
在旧版本内核中,PCI⼯具必须使⽤只有root才能执⾏的直接硬件访问,⽽且总是出现竞争状况以及其他问题。
如果你要报告 PCI 设备驱动中,或者是 lspci ⾃⾝的 bugs,请在报告中包含 "lspci -vvx" 的输出。
[[ ]]选项 OPTIONS-v使得 lspci 以冗余模式显⽰所有设备的详细信息。
-vv使得 lspci 以过冗余模式显⽰更详细的信息 (事实上是 PCI 设备能给出的所有东西)。
这些数据的确切意义没有在此⼿册页中解释,如果你想知道更多,请参照 /usr/include/linux/pci.h 或者 PCI 规范。
-n以数字形式显⽰ PCI ⽣产⼚商和设备号,⽽不是在 PCI ID 数据库中查找它们。
-x以⼗六进制显⽰ PCI 配置空间 (configuration space) 的前64个字节映象 (标准头部信息)。
此参数对调试驱动和 lspci 本⾝很有⽤。
-xxx以⼗六进制显⽰所有 PCI 配置空间的映象。
此选项只有 root 可⽤,并且很多 PCI 设备在你试图读取配置空间的未定义部分时会崩溃 (此操作可能不违反PCI标准,但是它⾄少⾮常愚蠢)。
-b以总线为中⼼进⾏查看。
显⽰所有 IRQ 号和内存地址,就象 PCI 总线上的卡看到的⼀样,⽽不是内核看到的内容。
-t以树形⽅式显⽰包含所有总线、桥、设备和它们的连接的图表。
-s [[<bus>]:][<slot>][.[<func>]]仅显⽰指定总线、插槽上的设备或设备上的功能块信息。
usb描述符含义
![usb描述符含义](https://img.taocdn.com/s3/m/321955540a4e767f5acfa1c7aa00b52acfc79cc6.png)
usb描述符含义
USB(Universal Serial Bus)描述符是在USB设备和主机之间进行通信时使用的数据结构。
USB 描述符包含有关USB设备或设备的某个接口的信息,例如设备的厂商ID、产品ID、设备类别、端点信息等。
USB描述符通常由设备在被连接到主机时发送给主机。
以下是常见的USB描述符及其含义:
1. 设备描述符(Device Descriptor):
-包含设备的基本信息,如USB规范版本、设备类别、厂商ID、产品ID、设备版本号等。
2. 配置描述符(Configuration Descriptor):
-描述设备的一个或多个配置,每个配置可能包含一个或多个接口。
3. 接口描述符(Interface Descriptor):
-描述一个配置中的一个接口,包括接口的数量、接口的类别、子类别和协议。
4. 端点描述符(Endpoint Descriptor):
-描述接口上的每个端点(endpoint),包括端点的地址、传输类型(控制、批量、等等)、最大数据包大小等信息。
5. 字符串描述符(String Descriptor):
-包含设备的可读字符串信息,例如制造商名称、产品名称等。
这些描述符是通过设备的控制端点(Control Endpoint)进行交互的,控制端点使用标准的USB控制请求(Control Requests)来获取有关设备和接口的信息。
USB描述符是为了让主机能够正确地配置和与USB设备进行通信而设计的,它们提供了有关设备和接口的重要信息,以确保设备与主机之间的兼容性。
LinuxUSB3.0驱动分析(一)——USB设备基础概念
![LinuxUSB3.0驱动分析(一)——USB设备基础概念](https://img.taocdn.com/s3/m/c881dda9f424ccbff121dd36a32d7375a417c6f8.png)
LinuxUSB3.0驱动分析(⼀)——USB设备基础概念⼀.基础概念在终端⽤户看来,USB设备为主机提供了多种多样的附加功能,如⽂件传输,声⾳播放等,但对USB主机来说,它与所有USB设备的接⼝都是⼀致的。
⼀个USB设备由3个功能模块组成:USB总线接⼝、USB逻辑设备和功能单元:a -- 这⾥的USB总线接⼝指的是USB设备中的串⾏接⼝引擎(SIE);b -- USB逻辑设备被USB系统软件看作是⼀个端点的集合;c -- 功能单元被客户软件看作是⼀个接⼝的集合。
SIE、端点和接⼝都是USB设备的组成单元;为了更好地描述USB设备的特征,USB提出了设备架构的概念。
从这个⾓度来看,可以认为USB设备是由⼀些配置、接⼝和端点组成,即⼀个USB设备可以含有⼀个或多个配置,在每个配置中可含有⼀个或多个接⼝,在每个接⼝中可含有若⼲个端点。
其中,配置和接⼝是对USB设备功能的抽象,实际的数据传输由端点来完成。
在使⽤USB设备前,必须指明其采⽤的配置和接⼝。
这个步骤⼀般是在设备接⼊主机时设备进⾏枚举时完成的这些单元之间的关系如下:设备通常有⼀个或多个配置;配置通常有⼀个或多个接⼝;接⼝通常有⼀个或多个设置;接⼝有零或多个端点。
这样的概念太抽象了,可以这样看:有⼀个设备,如⽀持视频和⾳频的⼀个播放器。
那么,对于上⾯提到的4个描述符,对它们设置的时候,它们分别对于哪⼀个描述符呢?从我现在的理解来看,这样⼀个设备对应⼀个设备描述符,⽀持视频的功能对应⼀个接⼝描述符,⽀持⾳频功能的对应⼀个接⼝描述符。
为了⽀持视频,在下层有多个端⼝同时⼯作为提供视频数据传输的⽀持,所以有多个端点描述符。
⼆.USB描述符USB设备使⽤各种描述符来说明其设备架构,包括设备描述符、配置描述符、接⼝描述符、端点描述符和字符串描述符,他们通常被保存在USB设备的固件程序中。
路径:include/uapi/linux/usb/ch9.h1、设备描述符设备代表⼀个USB设备,它由⼀个或多个配置组成。
Linux USB驱动框架分析(二)
![Linux USB驱动框架分析(二)](https://img.taocdn.com/s3/m/a2fc86b405a1b0717fd5360cba1aa81144318f0a.png)
Linux USB驱动框架分析(二)好,了解过USB一些规范细节之后,我们现在来看看Linux的驱动框架。
事实上,Linux的设备驱动,特别是这种hotplug的USB设备驱动,会被编译成模块,然后在需要时挂在到内核。
要写一个Linux的模块并不复杂,以一个helloworld为例:#include <linux/init.h>#include <linux/module.h>MODULE_LICENSE(“GPL”);static int hello_init(void){printk(KERN_ALERT “Hello World!\n”);return 0;}static int hello_exit(void){printk(KERN_ALERT “GOODBYE!\n”);}module_init(hello_init);module_exit(hello_exit);这个简单的程序告诉大家应该怎么写一个模块,MODULE_LICENSE告诉内核该模块的版权信息,很多情况下,用GPL或者BSD,或者两个,因为一个私有模块一般很难得到社区的帮助。
module_init和module_exit用于向内核注册模块的初始化函数和模块推出函数。
如程序所示,初始化函数是hello_init,而退出函数是hello_exit。
另外,要编译一个模块通常还需要用到内核源码树中的makefile,所以模块的Makefile可以写成:ifneq ($(KERNELRELEASE),)obj-m:= hello.o#usb-dongle.oelseKDIR:= /usr/src/linux-headers-$(shell uname -r)BDIR:= $(shell pwd)default:$(MAKE) -C $(KDIR) M=$(PWD) modules.PHONY: cleanclean:make -C $(KDIR) M=$(BDIR) cleanendif可以用insmod跟rmmod来验证模块的挂在跟卸载,但必须用root的身份登陆命令行,用普通用户加su或者sudo在Ubuntu上的测试是不行的。
USB的描述符详解总结
![USB的描述符详解总结](https://img.taocdn.com/s3/m/cd6a38585f0e7cd1842536cf.png)
USB的描述符与命令请求详解一、描述符1.什么是描述符所谓描述符,就是用于描述设备特性的具有特定格式排列的一种数据组织结构。
2.描述符的作用描述符的作用在于设备向主机汇报自己的信息、特征,主机根据这些信息从而加载相应的驱动程序。
3.描述符的分类描述符分为三大类:标准描述符、设备类描述符、厂商描述符。
除字符串描述符可选外,任何设备都必须包含剩下的几种标准描述符。
在USB1.0中规定了5种标准的描述符:设备描述符配置描述符接口描述符端点描述符字符串描述符规定的设备类描述符有:集线器类描述符、人机接口类描述符。
下表是三种描述符的类型值:4.使用的几种类设备类DeviceClass下表是设备类值的含义。
接口类InterfaceClass下表是接口类值的含义。
类的交叉与独享在描述符中,只有设备描述符和接口描述符中会有类别之分,即只有设备和接口会分类使用,不过有些类别的使用只需经过设备或接口的区分就可彻底清楚明白,这说明在设备类别和接口类别的定义上会有共同的类别名称。
而有些类别则是设备或接口独享的,下表是与使用设备相关的类别划分交叉或共享情况:(此表也适用于标准命令Get_Descriptor中wValue域高字节的取值含义)【说明:】在设备或接口分类上均可彻底分清使用的(Usage = Both),即在任一处描述符中定义即可的分清楚使用的类(Usage = Both)的基本类有:02h ------------- 通信及CDC控制类;DCh ------------ 诊断设备类;EFh ------------- 混杂设备类;FFh ------------- 厂商定义的设备类。
5.标准描述符设备描述符【说明1:】当设备类型bDeviceClass = 0时,说明类型将由接口描述符中定义的为准。
【说明2:】从设备描述符表格中可知,有3个索引值:厂商信息索引、产品信息索引、设备序列号索引,这意味着,将有3个字符串描述符为其准备。
linux usb设备驱动和通信原理
![linux usb设备驱动和通信原理](https://img.taocdn.com/s3/m/0c055c3c02d8ce2f0066f5335a8102d276a2619b.png)
linux usb设备驱动和通信原理Linux USB设备驱动和通信原理一、介绍USB(Universal Serial Bus,通用串行总线)是一种常见的外部设备连接标准,可以连接各种设备,如打印机、键盘、鼠标、摄像头等。
在Linux系统中,USB设备驱动是用于管理和控制USB设备的软件模块。
本文将介绍Linux USB设备驱动的基本原理和USB设备与主机之间的通信过程。
二、USB设备驱动1. 驱动模型在Linux系统中,USB设备驱动使用一种称为USB核心(USB Core)的模型来管理和控制USB设备。
USB核心提供了一组功能强大的API,供驱动程序使用。
驱动程序通过注册到USB核心,并提供一组回调函数来处理USB设备的各种事件和请求。
2. 驱动加载当插入一个USB设备时,Linux内核会自动加载与之对应的驱动程序。
内核根据设备的厂商ID(Vendor ID)和产品ID(Product ID)来匹配设备和驱动程序。
如果找到匹配的驱动程序,内核会加载该驱动程序,并调用其初始化函数。
3. 驱动程序结构一个USB设备驱动程序通常由以下几个部分组成:- 初始化函数:用于初始化驱动程序的数据结构和资源。
- 描述符匹配函数:用于匹配设备的描述符和驱动程序。
- 事件处理函数:用于处理设备的插入、拔出等事件。
- 控制请求处理函数:用于处理来自主机的控制请求。
- 数据传输函数:用于处理设备和主机之间的数据传输。
三、USB设备与主机通信原理1. 设备描述符USB设备在与主机通信之前,需要提供一个设备描述符,用于描述设备的基本信息,如设备类别、厂商ID、产品ID等。
主机通过设备描述符来识别和配置设备。
2. 端点和传输类型USB设备与主机之间的通信是通过端点(Endpoint)来实现的。
一个USB设备通常包含多个端点,每个端点都有一个唯一的端点地址和传输类型。
主机通过端点地址来选择要与之通信的端点,通过传输类型来确定数据传输的方式,如控制传输、批量传输、中断传输和等时传输。
linux 设备树 usb相关解读
![linux 设备树 usb相关解读](https://img.taocdn.com/s3/m/5a92a308ff4733687e21af45b307e87101f6f884.png)
linux 设备树usb相关解读摘要:1.Linux设备树概述B设备在Linux系统中的识别与使用3.Linux系统中的USB设备驱动程序4.详细解析i2c-adapter和设备树的关联5.Linux系统中的USB设备管理正文:一、Linux设备树概述Linux设备树(Device Tree,简称DTS)是一种描述硬件资源的数据结构,它起源于Open Firmware项目。
在Linux系统中,设备树提供了一种标准的方式来描述硬件设备及其属性,使得操作系统能够正确地识别和管理硬件设备。
二、USB设备在Linux系统中的识别与使用在Linux系统中,USB设备的识别和使用主要依赖于设备树。
当USB设备插入电脑时,Linux系统会根据设备树中的信息来识别设备类型、驱动程序等信息。
此外,Linux系统还提供了umount、df等命令来查看和操作USB设备。
三、Linux系统中的USB设备驱动程序在Linux系统中,USB设备驱动程序负责管理和操作USB设备。
驱动程序根据设备树中的信息来初始化设备,进行数据传输和控制。
对于不同的USB设备,Linux系统提供了相应的驱动程序,如i2c-adapter。
四、详细解析i2c-adapter和设备树的关联i2c-adapter是Linux系统中一种常用的USB设备驱动程序。
在设备树中,i2c-adapter关联到i2c总线,负责管理i2c设备。
i2c-adapter的probe 部分会在/dev目录下创建文件,用于与设备进行通信。
五、Linux系统中的USB设备管理Linux系统提供了丰富的命令和工具来管理USB设备,如usb-util、lsusb 等。
用户可以通过这些命令查看USB设备的状态、信息等。
此外,Linux系统还支持通过设备树动态加载和卸载USB设备驱动程序,使得USB设备的管理更加灵活。
总结:Linux系统中的USB设备管理依赖于设备树和驱动程序。
linux 设备树 usb相关解读
![linux 设备树 usb相关解读](https://img.taocdn.com/s3/m/73b7fcb9760bf78a6529647d27284b73f2423687.png)
linux 设备树usb相关解读摘要:1.设备树的概念及作用2.Linux 内核对USB 设备的识别和加载过程B 设备在Linux 系统中的识别和加载过程4.i2c-adapter 与设备树的关系5.结语正文:一、设备树的概念及作用设备树是Linux 系统中一种描述硬件设备信息和驱动的机制。
它以树状结构组织设备,并提供了统一的接口,方便内核和用户空间进行设备操作。
在设备树中,每个节点表示一个硬件设备或驱动,节点下的属性用于描述设备的具体信息,如设备类型、驱动参数等。
通过设备树,Linux 内核可以自动识别并加载对应的设备驱动,从而使设备能够正常工作。
二、Linux 内核对USB 设备的识别和加载过程1.当我们插入一个USB 设备时,USB 控制器会检测到电压变化并发出一个中断信号。
2.这个中断信号被送到处理器上的USB 控制器中断线上,告诉Linux 内核有新的USB 设备插入。
3.当内核接收到USB 控制器发出的中断信号时,它会调用USB 子系统中的模块,该模块负责检测新的USB 设备并加载相应的驱动程序。
4.模块首先会检测设备的描述符,这个描述符包括设备的厂商ID、产品ID、类别码等信息。
5.如果已经存在一个匹配的驱动程序,那么模块就会加载这个驱动程序。
如果没有匹配的驱动程序,则会尝试加载一个通用的驱动程序,这个驱动程序能够支持大多数USB 设备。
6.一旦正确的驱动程序被加载,它会向USB 子系统注册并告诉它自己可以处理哪些设备。
三、USB 设备在Linux 系统中的识别和加载过程在Linux 系统中,USB 设备的识别和加载过程主要分为以下几个步骤:1.插入USB 设备后,USB 控制器发送中断信号,通知Linux 内核有新设备接入。
2.Linux 内核调用USB 子系统模块,开始检测新设备并加载相应的驱动程序。
B 模块通过查询设备描述符,获取设备的厂商ID、产品ID 和类别码等信息。
4.根据设备信息,内核会加载对应的设备驱动程序。
Linux的USB总线驱动分析
![Linux的USB总线驱动分析](https://img.taocdn.com/s3/m/463379476bec0975f565e241.png)
USB大存储设备这里所说的大存储设备包括U盘、读卡器、USB接口的光驱等其他块存储设备。
USB接口大存储设备操作流程它们被看做是SCSI接口设备。
当用户从设备上读写数据时,文件系统将读写操作传送到SCSI协议层,SCSI协议层将读写请求封装成USB请求块(URB)通过USB接口传递给设备,USB设备从URB中解析处SCSI协议命令后再操作块设备。
USB接口大存储设备设计思路设计一个控制线程,注册这个线程为虚拟SCSI控制器,这个线程无论在设备插入或删除时都是作为一个SCSI节点存在。
这样的话,设备在移去然后再重新插上时对应/dev 中的同一个节点。
当一个设备被接入时,控制线程从SCSI中间层代码得到命令。
控制线程接受命令,再检查后送命令到协议处理函数。
这些处理函数负责再写命令到设备可以接受的形式,然后送到传输处理函数。
传输处理函数负责将命令送到设备、交换数据,并接着得到设备的状态。
Bulk-Only传输协议和SCSI命令块集是具有Linux系统的嵌入设备的两种模式。
1.Bulk-Only传输协议Bulk-Only传输协议是USB大容量存储器类中的USB批量数据传输协议,它定义了仅通过批量端点传输的命令、数据和状态。
命令块数据包裹器CBW发送命令,使用命令状态数据包裹器接受返回的状态。
CBW是一个包含命令块和相关信息的数据包。
格式是这样的:Byte Bit 7 6 5 4 3 2 1 00~3 dCBWSignature4~7 dCBWTag8~11dCBWTataTransfenLength(08h~0Bh)12bmCBWFlags(0Ch)13Reserved(0) bCBWLUN(0Dh)14Reserved(0) bCBWCBLength(0Eh)15~30CBWCB(0Fh~1Eh)它用buld_cb_wrap的数据结构描述(drivers/usb/storage/)sturct bulk_cb_wrap{域SCSI设备服务分发子系统目标器启动器服务分发接口连接子系统任务管理器LUN 应用客户设备服务器任务集(队列)wner = THIS_MODULE,.name = “usb_storage”,.probe = storage_probe, isconnect = storage_disconnect, d_table = storage_usb_ids,};在usb_device_id结构类型数组中storage_usb_ids定义了设备类、子类及命令块集的协议类型探测函数探测函数storage_probe探测是否能驱动一个新连接的USB设备。
Linux环境下USB的原理、驱动和配置
![Linux环境下USB的原理、驱动和配置](https://img.taocdn.com/s3/m/1cc30cfe0242a8956bece4f3.png)
Linux环境下USB的原理、驱动和配置随着生活水平的提高,人们对USB设备的使用也越来越多,鉴于Linux在硬件配置上尚不能全部即插即用,因此关于Linux如何配置和使用,成为困扰我们的一大问题。
什么是USB?USB是英文Univer sal Ser ial Bus的缩写,意为通用串行总线。
USB最初是为了替代许多不同的低速总线(包括并行、串行和键盘连接)而设计的,它以单一类型的总线连接各种不同的类型的设备。
USB的发展已经超越了这些低速的连接方式,它现在可以支持几乎所有可以连接到PC上的设备。
最新的USB规范修订了理论上高达480Mbps的高速连接。
Linux内核支持两种主要类型的USB驱动程序:宿主系统上的驱动程序和设备上的驱动程序,从宿主的观点来看(一个普通的宿主也就是一个PC机),宿主系统的USB设备驱动程序控制插入其中的USB设备,而USB设备的驱动程序控制该设备如何作为一个USB设备和主机通信。
USB的具体构成在动手写USB驱动程序这前,让我们先看看写的USB驱动程序在内核中的结构,如下图:USB驱动程序存在于不同的内核子系统和USB硬件控制器之间,USB核心为USB驱动程序提供了一个用于访问和控制USB硬件的接口,而不必考虑系统当前存在的各种不同类型的USB硬件控制器。
USB是一个非常复杂的设备,linux内核为我们提供了一个称为USB的核心的子系统来处理大部分的复杂性,USB设备包括配置(configur ation)、接口(inter face)和端点(endpoint),USB设备绑定到接口上,而不是整个USB设备。
如下图所示:USB通信最基本的形式是通过端点(USB端点分中断、批量、等时、控制四种,每种用途不同),USB 端点只能往一个方向传送数据,从主机到设备或者从设备到主机,端点可以看作是单向的管道(pipe)。
所以我们可以这样认为:设备通常具有一个或者更多的配置,配置经常具有一个或者更多的接口,接口通常具有一个或者更多的设置,接口没有或具有一个以上的端点。
Linux usb
![Linux usb](https://img.taocdn.com/s3/m/0cb2220dcc17552707220850.png)
ok, 先看一个usb2com 的driver,在/Linux/drivers/usb/serial/下有个zio.c, 乍一看应该是最小的driver。
为什么这么几行就能drive一个usb2com?ok,其实usb core and usb serial core在这背后做了大量工作。
这就是模块化编程的好处,尽量降低重复劳动。
首先,看id_table[],这是driver匹配hardware用的,一般在struct usb_driver中我们有必要写清楚id_table,那么当hotplug or new usb driver register 发生时,hotplug device or the register driver所在的bus(也就是 usb_bus_type)会通过bus->match来遍历判断是否有成功的匹配,而匹配的规则就是根据driver的id_table是否等于device的id。
接下来是 struct usb_serial_driver zio_device,它是在 struct usb_driver上抽象出来的一类driver,可以理解为struct usb_driver的子类。
从代码上看,目前这个struct usb_serial_driver 中的内容还不丰富,他其中的关键数据会在接下来的对这个driver的注册中初始化,例如open,close,ioctl等操作。
ok,接下来就是对struct usb_serial_driver zio_device 的register这个宏调用usb_serial_register_drivers,now we begin to use the services fromusb serial core(usb-serial.c),一般的register driver都是先初始化driver结构体,然后挂到bus上match一下,match到了就通过driver的probe来走近一步的check并建立一些dev,来represent now we have a driver to drive a device。
USB 开发基础--USB 命令(请求)和USB 描述符
![USB 开发基础--USB 命令(请求)和USB 描述符](https://img.taocdn.com/s3/m/3136377927284b73f2425026.png)
类型 标准描述符
表 5、USB 描述符的类型值 描述符 设备描述符(Device Descriptor) 配置描述符(Configuration Descriptor) 字符串描述符(String Descriptor) 接口描述符(Interface Descriptor) 端点描述符(EndPont Descriptor)
一、USB 命令
在 USB 规范里,对命令一词提供的单词为“Request”,但这里为了更好的理解主机与 设备之间的主从关系,将它定义成“命令”。
所有的 USB 设备都要求对主机发给自己的控制命令作出响应,USB 规范定义了 11 个 标准命令,它们分别是:Clear_Feature、Get_Configuration、Get_Descriptor、 Get_Interface、Get_Status、Set_Address、Set_Configuration、Set_Descriptor、 Set_Interface、Set_Feature、Synch_Frame。所有 USB 设备都必须支持这些命令(个 别命令除外,如 Set_Descriptor、Synch_Frame)。
USB 设备通过描述符反映自己的设备特性。USB 描述符是由特定格式排列的一组数据 结构组成。
在 USB 设备枚举过程中,主机端的协义软件需要解析从 USB 设备读取的所有描述符 信息。在 USB 主向设备发送读取描述符的请求后,USB 设备将所有的描述符以连续的数据 流方式传输给 USB 主机。主机从第一个读到的字符开始,根据双方规定好的数据格式,顺 序地解析读到的数据流。
偏移量 0 1 2
域 bLength bDecriptorType bcdUSB
表 4、USB 设备描述符的结构
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
USB描述符的作用USB 设备第一次连接到主机时, 要接收主机枚举( Enumera tion) 和配置(Configuration) , 目的是让主机知道设备功能、是哪一类的USB 设备、占用多少资源、使用了哪些传输方式以及传输的数据量等等。
只有主机完全确认了这些信息后, 设备才能真正开始工作。
这些信息是通过存储在设备中的USB 描述符来体现的。
因此, 这种USB 描述符也可以看作是USB 设备的身份证明。
描述符(Descriptor )是一个完整的数据结构, 存储在USB 设备中, 用于描述一个USB 设备的所有属性。
USB主机通过一系列命令要求设备发送这些信息。
USB描述符的种类描述符分为三大类:标准描述符、设备类描述符、厂商描述符。
三种描述符的类型值bDescriptorType:设备的类别bDeviceClass接口类别bInterfaceClassLinux中各种描述符的定义在include/linux/usb/Ch9.h中定义USB设备描述符:struct usb_device_descripto r {__u8 bLength; //此描述符的字节数__u8 bDescriptorType; //描述符的类型(此处应为0x01,即设备描述符) __le16 bcdUSB; // USB版本号(BCD 码)__u8 bDeviceClass; //设备的类别---可查看上表格__u8 bDeviceSubClass; //设备子类码:这些码值的具体含义根据bDeviceClass 域来看。
__u8 bDeviceProtocol;/*协议码这些码的值视bDeviceClass 和bDeviceSubClass 的值而定。
如果设备支持设备类相关的协议,此码标志了设备类的值。
如果此域的值为零,则此设备不支持设备类相关的协议,然而,可能它的接口支持设备类相关的协议。
如果此域的值为FFH,此设备使用厂商定义的议。
*/ __u8 bMaxPacketSize0; //端点0的最大包大小(仅8,16,32,64为合法值)__le16 idVendor; //厂商标志(由USB-IF组织赋值)__le16 idProduct; //产品标志(由厂商赋值)__le16 bcdDevice; //设备版本号(BCD 码)__u8 iManufacturer; //描述厂商信息的字符串描述符的索引值。
__u8 iProduct; //描述产品信息的字串描述符的索引值。
__u8 iSerialNumber; //描述设备序列号信息的字串描述符的索引值。
__u8 bNumConfigurations; //可能的配置描述符数目}USB配置描述符配置描述符中包含了配置描述符本身的长度、所有配置信息的总长度、供电方式及远程唤醒、供电量。
如果主机发出标准命令Get_Descriptor要求获得设备的某个配置描述符时,该配置应用的所有信息都将发给主机,它包括:该标准配置符本身、该配置所包含的所有接口、端点描述符及设备类描述符和厂商描述符。
struct usb_config_descriptor {__u8 bLength; //此描述符的字节数__u8 bDescriptorType; //配置描述表类型(此处为0x02)__le16 wTotalLength; //此配置信息的总长(包括配置,接口,端点和设备类及厂商定义的描述符),即:将要返回的配置信息总长度。
__u8 bNumInterfaces; //此配置所支持的接口个数__u8 bConfigurationValue;//在SetConfiguration()请求中用作参数来选定此配置。
__u8 iConfiguration;//描述此配置的字串描述符的索引__u8 bmAttributes;/*配置特性:D7:保留(设为1)D6:自给电源D5:远程唤醒D4..0:保留(设为1)一个既用总线电源又有自给电源的设备会在MaxPower域指出需要从总线取的电量。
并设置D6为1。
运行时期的实际电源模式可由GetStatus(DEVICE) 请求得到。
*/__u8 bMaxPower; //在此配置下的总线电源耗费量。
以2mA 为一个单位。
}【说明1:】配置描述符也包含了个用于描述符该配置的字符串描述符索引iConfiguration,这说明将有个字符串描述符为其准备。
【说明2:】枚举的过程可分为4个状态阶段:接入状态阶段、缺省状态阶段、地址状态阶段、设置状态阶段,各状态阶段任务如下:接入状态阶段-----------主机检测到新设备接入后,将复位总线(释放总线于空闲状态)。
缺省状态阶段-----------主机利用0x00地址访问新接入的设备,读取部分描述符后,会分配个设备地址。
地址状态阶段-----------主机再次复位总线,然后用新分配的地址获取设备所有的描述符。
设置状态阶段-----------主机根据设备的描述符,会对设备作些相关的配置。
【说明3:】bCongfigurationValue-----------USB设备的配置值。
用于存放主机执行SetConfiguration 命令的设置值。
当主机发送GetConfiguration命令时,设备将向主机返回1个字节的配置值。
然而,USB 设备处于不同的状态时,对GetConfigration的请求也有不同的响应:1.> 在枚举阶段,若设备处于地址状态时,对GetConfigration的请求返回为0;2.> 在枚举阶段,若设备处于默认状态(缺省状态)时,对GetConfigration的请求视为无效;3.> 在枚举阶段,若设备处于配置状态时,对GetConfigration的请求将返回bConfigurationValue字段的值(该值可能是配置描述符的默认值,也可能是USB主机的设置值,这要看在执行GetConfigration命令前是否执行了SetConfigration命令)。
因为主机要执行SetConfigration命令,所以bCongfigurationValue的默认值没什么用。
实际上主机给bCongfigurationValue赋值后,bCongfigurationValue值就充当配置描述符的编号,用以区分不同的配置,因为一个设备可能有多个配置。
USB接口描述符struct usb_interface_descriptor {__u8 bLength; //描述符的size__u8 bDescriptorType; //描述符的类型,接口描述符类型为0x04__u8 bInterfaceNumber; //接口号__u8 bAlternateSetting;//可替换接口描述符编号。
实际就是接口的描述符的编号。
__u8 bNumEndpoints; //本接口对于的端口的数量__u8 bInterfaceClass; //本接口属于哪一个类__u8 bInterfaceSubClass; //接口子类__u8 bInterfaceProtocol; //协议码__u8 iInterface; //字符串描述符中本接口描述符的索引}【说明1:】接口描述符中用到接口编号bInterfaceNumber,以区分在同一配置下的不同的接口。
同时还有该接口描述符的索引iInterface,这意味着将为其准备准备一个字符串描述符。
【说明2:】接口描述符中有一项:可替换的接口描述符编号bAlternateSetting,表示对某一接口进行描述的描述符编号。
虽然,USB设备的配置与配置描述符是一一对应的,即一个配置只能由一个配置描述来描述它,但一个接口却允许有多种描述符来描述它,尽管接口描述符的编号还是唯一一个。
说白了就是:一个接口有唯一的一个接口编号,但一个接口却可以有多个不同的描述符编号,而这些不同的接口描述符的编号值就是bAlternateSetting。
所以,通过bInterfaceNumber可以选定一个唯一的接口,然后再通过bAlternateSetting选择想要的对该接口的描述。
主机通过GetInterface可以获取当前正在使用的接口及接口描述,通过SetInerface可以选定某接口及其使用的描述符。
USB端点描述符struct usb_endpoint_descriptor {__u8 bLength; //端点描述符字节数大小__u8 bDescriptorType; //端点描述符类型编号,描述符类型(此处应为0x05)__u8 bEndpointAddress; //端点地址及输入输出属性__u8 bmAttributes; //端点的传输类型属性__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;}【说明1:】端点的传输类型字节bmAttributes,描述了该端点的传输特性:0~1bit定义了传输类型---------00=控制传输、01=同步传输、10=批量传输、11=中断传输。
【说明2:】周期端点的访问周期字节bInterval,定义了该端点被主机的访问周期,此域值对于批量传输和控制传输毫无意义。
对于同步传输,其值必须为1,即1ms为标准的同步帧周期。
对于中断传输,该值为1~255,即1ms~255ms。
USB字符串描述符struct usb_string_descriptor {__u8 bLength; //端点描述符字节数大小__u8 bDescriptorType; //端点描述符类型编号,描述符类型(此处应为0x03)__le16 wData[1]; /* UTF-16LE encoded */ //字符串}显示语言的字符串描述符与显示信息的字符串描述符的区别在于Strings项的不同,对于显示语言的字符串描述符来说Strings项由多个wLANGID[n]数组元素组成,每个wLANGID[n]是一个双字节的代表语言的ID值。
而对于显示信息的字符串描述符而言,Strings则是描述信息后的一组UNICODE编码。
为什么会出现这两种情况,原因在于访问字符串描述符的过程,主机请求访问某个字符串描述符的步骤分成两步:第一步:获取语言信息---------------首先主机向设备发送标准请求命令Get_Descriptor,其参数为:描述符类型=字符串描述符,字符串的索引值=0,语言=0,这样设备将返回显示语言的字符串描述符,从而主机知道了设备能支持哪些语言。