当涉及到USB通信时,可以从最物理层到最高应用层对其内容进行详细说明:
物理层(Physical Layer):
数据链路层(Data Link Layer):
传输层(Transaction Layer):
主机控制器层(Host Controller Layer):
应用层(Application Layer):
当涉及到USB的应用层时,可以进一步展开细说其内容。USB应用层定义了不同的类别和协议,用于实现特定的功能和应用。以下是一些常见的USB应用层类别和协议:
USB存储类(USB Mass Storage Class):USB存储类协议用于连接和传输存储设备。它允许主机系统将USB闪存驱动器、外部硬盘、U盘等存储设备视为逻辑存储单元,并进行数据的读取和写入。
USB音频类(USB Audio Class):USB音频类协议用于连接和传输音频设备。它定义了音频流的格式和通信方式,允许主机系统实现音频输入和输出功能。常见的应用包括USB话筒、耳机、音频接口等。
USB打印机类(USB Printer Class):USB打印机类协议用于连接和控制打印机设备。它定义了打印机命令和数据格式,允许主机系统发送打印任务和接收打印机状态、设置打印参数等。
USB图像类(USB Image Class):USB图像类协议用于连接和传输图像设备,如摄像头(v4l2的使用 详见linux中的USB摄像头驱动(应用层)(基于V4L2) 这篇文章的解释) 、扫描仪等。它定义了图像数据的格式和传输方式,允许主机系统进行图像的捕捉、传输和控制。
USB人机接口设备类(USB Human Interface Device):USB HID协议用于连接和传输人机接口设备,如键盘、鼠标、游戏控制器等。它定义了输入数据的报告格式和通信方式,允许主机系统获取用户的输入数据并进行相应的操作。
CDC(Communications Device Class):CDC用于支持通信类设备,例如调制解调器、串行通信设备和网络适配器等。它提供了一个虚拟串口的功能,使得操作系统可以通过标准的串口接口与设备进行通信
USB HID(Human Interface Device)是一种用于人机交互设备的USB协议,它定义了一组报告格式和通信规范,用于传输输入设备(如键盘、鼠标、游戏控制器等)的数据。
USB HID的工作原理如下:
USB HID数据包的传输过程如下:
USB HID支持不同的速率,常见的有:
原始hid驱动
hid-core.c:这是Linux内核中核心的HID驱动代码文件,位于drivers/hid/hid-core.c。它提供了USB HID设备的通用驱动框架,并处理识别、初始化、输入报告解析和传输等核心功能。
hid-input.c:位于drivers/hid/hid-input.c,它负责处理HID设备中的输入报告,将其转换为标准的Linux输入事件,如按键、鼠标移动等。
hid-generic.c:位于drivers/hid/hid-generic.c,这是一个通用的HID驱动,可以用于不需要特殊处理的HID设备。它通过最小限度的解析报告描述符来驱动大多数USB HID设备。
hiddev.c:位于drivers/hid/usbhid/hiddev.c,它提供了一个用户空间与HID设备之间的接口,允许用户程序通过/dev/hiddevX设备文件读取和写入HID设备的原始数据。
hid.h:位于include/linux/hid.h,它定义了HID设备的结构体和相关的常量,供驱动程序使用。
USB gadget模拟
USB gadget是一种在嵌入式系统中模拟USB设备的功能,将嵌入式设备作为USB设备使用。通过模拟不同类型的USB设备,实现与外部主机的通信和数据交互。
当使用USB gadget模块在Linux系统中模拟USB HID(Human Interface Device)功能时,涉及以下重要的文件和步骤:
usb/gadget/hid.h:这个头文件定义了用于USB HID gadget的相关数据结构和函数接口。
drivers/usb/gadget/function/f_hid.c:这个文件实现了USB Function HID(HID gadget)驱动代码。它负责处理HID相关的请求和功能。
drivers/usb/gadget/configfs.c:这个文件实现了使用configfs接口动态配置USB gadget的相关功能。它负责解析和处理配置对象,并将配置应用于USB gadget设备。
步骤如下:
配置内核:在编译Linux内核时,启用USB gadget和HID gadget相关模块。确保相关驱动程序(如f_hid)被编译为内核模块或静态编译进内核。
定义HID功能:在应用程序中定义HID功能的报告描述符。报告描述符描述了HID设备的功能和数据格式,如输入、输出和特性报告。
注册USB gadget驱动:在嵌入式系统启动时,通过配置文件或程序代码,注册HID gadget驱动(f_hid)并指定相关的报告描述符。
配置HID gadget:使用configfs接口,动态创建和配置HID gadget设备。设置设备的标识符、报告描述符和其他属性。
处理HID请求:HID gadget驱动(f_hid)负责处理来自主机的HID请求。这包括获取设备描述符、设置报告描述符、处理报告数据等。
数据交互:HID gadget驱动通过与gadget核心的交互,接收来自主机的报告数据并传递给应用程序或处理器;同时,也可以发送报告数据给主机。
通过以上步骤,USB gadget成功地将嵌入式系统模拟为一个USB HID设备,实现了HID功能,并能与主机进行通信和交互。主机可以使用标准的USB HID驱动程序与模拟的HID设备进行数据传输和交互。
在Windows中,使用hidsdi.h头文件可以实现USB HID(Human Interface Device)驱动的开发。hidsdi.h提供了一组函数和数据结构,用于与USB HID设备进行通信和操作。
下面是使用hidsdi.h实现USB HID驱动的基本步骤:
与设备建立连接:使用SetupDiGetClassDevs函数获取与USB HID设备相关的设备信息集合。然后使用SetupDiEnumDeviceInterfaces函数遍历设备信息集合,找到所需的USB HID设备。接着,使用CreateFile函数打开与设备的连接。
获取预定义的USB HID功能:通过调用HidD_GetPreparsedData函数,获取USB HID设备的预定义数据。该数据包含了设备的功能和报告描述符。
解析报告描述符:使用HidP_GetCaps函数解析报告描述符,这样就可以了解设备的输入报告、输出报告和特征报告等信息。
读取和写入报告数据:使用HidD_GetInputReport和HidD_SetOutputReport函数,分别读取输入报告和写入输出报告。这样可以与USB HID设备进行双向数据交互。
关闭设备连接:最后,使用CloseHandle函数关闭与USB HID设备的连接。
在linux中则不需要额外编写驱动,插入设备将直接显示节点如/dev/hidrawX
USB CDC(USB Communications Device Class)是一种USB设备类别,旨在将嵌入式系统模拟为通信设备,如串口。相比于USB HID(Human Interface Device)驱动,USB CDC驱动在通信领域有其独特的优势和缺点。
USB CDC的优势:
标准化通信协议:USB CDC定义了标准的通信协议,使得与USB CDC设备进行通信的软件和驱动程序更易于开发和兼容。各种操作系统和应用程序可以通过标准接口与USB CDC设备进行通信。
简化驱动程序开发:USB CDC设备类别提供了标准的通信接口和协议,减少了驱动程序的开发工作量。开发人员可以基于通用的USB CDC驱动程序开发自定义的应用程序和功能。
多平台兼容性:USB CDC驱动程序具有良好的跨平台兼容性。这意味着无论是在Windows、Linux还是Mac等操作系统上,USB CDC设备都可以得到良好的支持和兼容。
多种通信方式:USB CDC支持多种通信方式,包括串口通信(Virtual COM Port)、以太网通信、无线通信等。这使得USB CDC设备可以灵活适应各种通信需求。
USB CDC的缺点:
相对复杂的协议:与USB HID相比,USB CDC的协议相对复杂。这意味着在开发和实现USB CDC驱动程序时,需要更多的技术和开发经验。
通信速率限制:USB CDC的通信速率相对较低,不适用于高速数据传输场景。如果需要高速数据传输,可能需要考虑其他的通信方案。
设备驱动需求:使用USB CDC设备时,需要安装相应的设备驱动程序。在某些情况下,特别是在需要在不同的操作系统上使用设备时,驱动程序的安装和配置可能会带来一些麻烦。
综上所述,USB CDC驱动具有标准化通信协议、简化驱动程序开发和多平台兼容性等优势,但相对复杂的协议和通信速率限制是其缺点之一。根据具体的应用需求和通信需求,选择合适的USB驱动类别。
重要说明:
在Linux中,USB gadget子系统提供了一种通用的框架和接口,用于实现各种USB设备功能,包括USB CDC和USB HID等。使用USB gadget子系统可以更方便地管理和配置USB设备,并通过统一的接口与主机进行通信。
USB HID协议相对简单,并且通常使用单一的报告描述符来描述设备功能。因此,实现USB HID设备时,并不需要像USB CDC那样复杂的功能配置和管理,所以可以在Linux系统中单独实现USB HID驱动,而不依赖于USB gadget子系统。
USB HID设备可以直接使用HID类驱动程序进行描述和操作,而不需要像USB CDC那样需要在USB gadget子系统中进行配置。因此,在Linux中,可以通过使用HID类驱动程序和相关的API(如hidsdi.h)来实现USB HID设备的功能,而不需要依赖于USB gadget子系统。
实现步骤:
在Linux内核中,USB CDC模拟串口功能的实现依赖于以下关键文件:
usb/gadget/cdc.h:这个头文件定义了用于USB CDC模拟串口的相关数据结构和函数接口。
drivers/usb/gadget/function/f_serial.c:这个文件实现了USB Function Serial(CDC模拟串口)驱动代码。它是用于USB CDC模拟串口功能的关键文件。
drivers/usb/gadget/configfs.c:这个文件实现了使用configfs接口动态配置USB gadget相关功能。它负责解析和处理USB CDC模拟串口设备的配置。
下面是USB CDC模拟串口在Linux内核中的基本实现步骤:
配置内核:在编译Linux内核时,确保启用了USB gadget和CDC模块。确保相关的驱动程序(如f_serial)被编译为内核模块或者静态编译进内核。
注册USB Function Serial驱动:在嵌入式系统启动时,通过配置文件或者程序代码,注册USB Function Serial驱动(f_serial)并指定相关设置和属性。
创建USB CDC模拟串口设备:使用configfs接口,动态创建和配置USB CDC模拟串口设备。设置设备的标识符、端口参数和其他相关属性。
处理串口读写操作:USB Function Serial驱动负责处理来自主机的串口读写操作。它提供了相应的接口,以便开发人员可以在应用程序中进行串口数据读取和写入。
设备连接和应用程序交互:在Linux系统中,USB CDC模拟串口设备将在/dev目录下被创建为一个字符设备。应用程序可以通过打开该设备文件并进行读写操作,与模拟的串口进行数据交换和通信。
在Windows系统中实现USB CDC模拟串口, 可以使用Windows Driver Frameworks (WDF) 和Serial Communications (SerCx) 驱动框架及相关的API。
以下是实现USB CDC模拟串口的一般步骤:
定义USB CDC设备描述符:在设备驱动程序中定义USB CDC设备的描述符,包括Vendor ID (VID),Product ID (PID),设备类别,接口描述符等信息。
创建驱动程序:使用Windows驱动开发工具 (如Visual Studio) 创建WDF驱动程序。
配置设备:在驱动程序中使用WDF API (如WdfUsbTargetDeviceSelectConfig) 配置USB设备。
注册驱动程序回调函数:注册WDF回调函数,以响应设备的插拔事件和串口数据传输事件。
打开设备:在驱动程序的插拔事件回调函数中,使用WDF API (如WdfUsbTargetDeviceCreateWithParameters) 打开设备。
配置串口:在设备打开后,使用SerCx API (如SerCx2InitializePort) 配置串口相关参数,如波特率、数据位、停止位等。
接收和发送数据:使用SerCx API (如SerCx2ReadDataAvailable、SerCx2WriteData) 来接收和发送串口数据。
关闭设备:在设备拔出或需要关闭设备时,使用WDF API (如WdfObjectDelete) 关闭设备。
在linux中则不需要额外编写驱动,插入设备将直接显示节点如/dev/ttyusb*
在Linux内核已经内置了对USB存储设备(如U盘)的支持,并提供了相应的USB存储驱动。
以下是Linux中实现USB存储设备驱动的一般步骤:
插入USB存储设备:将USB存储设备(如U盘)插入Linux系统的USB接口。
内核识别设备:Linux内核会自动识别插入的USB存储设备,并为其分配一个设备节点(如/dev/sdX
)。
挂载文件系统:使用挂载命令(如mount
)将USB存储设备上的文件系统挂载到Linux系统的目录中。
访问文件:一旦文件系统被挂载,您可以通过常用的文件操作命令(如cp
、ls
等)或使用文件浏览器在USB存储设备上进行读写操作。
卸载设备:在结束使用USB存储设备后,使用卸载命令(如umount
)卸载文件系统,并安全地将USB存储设备从系统中拔出。
大多数常见的USB存储设备(如U盘、移动硬盘)遵循通用的USB存储协议(USB Mass Storage Class),并且Linux内核已经内置了对这些设备的支持,因此不需要额外的驱动程序。