微软交流社区

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 106|回复: 0

linux os 下编写USB驱动必备知识

[复制链接]

2

主题

2

帖子

6

积分

新手上路

Rank: 1

积分
6
发表于 2023-4-10 06:24:20 | 显示全部楼层 |阅读模式
基础知识

应用
存储设备
打印机
USB转ethernet
USB摄像头
鼠标、键盘、others


线制







理论


  • USB传输速率
USB 1.x:USB 1.x包括USB 1.0、USB 1.1两种规格,最大传输速度为12Mbps。
USB 2.0:USB 2.0最大传输速度为480Mbps,它向下兼容USB 1.x设备。
USB 3.x:USB 3.x包括USB 3.0、USB 3.1和USB 3.2三种规格,最大传输速度分别为5Gbps、10Gbps和20Gbps。它向下兼容USB 2.0和USB 1.x设备。

  • USB主从结构
USB总线是一种主从结构的总线。在USB总线中,有一个主机(Host)设备,它控制总线上的所有设备,并负责管理总线上的数据传输和通信。同时,还有多个从机(Device)设备,它们依赖于主机设备进行通信和数据传输。
主机设备通常是计算机或其他控制设备,而从机设备通常是外部设备,如打印机、鼠标、键盘、存储设备等。当从机设备被连接到总线上时,主机设备会识别并与它们通信,以确定设备的类型和功能,并确定如何与该设备进行通信。
总之,USB总线采用主从结构,其中主机设备控制和管理总线上的所有设备,并与从机设备进行通信和数据传输。

  • USB终端设备数据传输方式
控制传输(Control Transfer):用于传输设备的控制信息,如设备的状态、描述符信息等。控制传输是USB传输类型中最基本的传输类型,每个USB设备都必须支持控制传输。控制传输是使用USB协议进行设备初始化和配置的关键步骤。
常规传输(Bulk Transfer、Interrupt Transfer和Isochronous Transfer):用于传输设备的数据信息。常规传输主要分为三种传输类型:

  • 批量传输(Bulk Transfer):用于传输大量的数据,如U盘中存储的文件等。
  • 中断传输(Interrupt Transfer):用于传输小量的数据,如鼠标、键盘等设备传输的数据。
  • 同步传输(Isochronous Transfer):用于传输实时性要求高的数据,如音频、视频等。同步传输不保证数据的可靠性,但保证传输的实时性。
USB驱动框架

确定驱动类型:Linux 有两种 USB 驱动类型,一种是主机控制器驱动(Host Controller Driver, HCD),负责管理 USB 总线上的设备,另一种是设备驱动(Device Driver),负责管理 USB 设备。
确定硬件和接口:需要确定要编写驱动的硬件和接口类型,例如 USB 1.x、USB 2.0、USB 3.x 等。
编写驱动框架:驱动框架是驱动程序的主体部分,负责与硬件进行通信和处理请求。需要使用 C 语言编写驱动程序,需要使用 Linux 内核提供的 API 和数据结构,例如 usb_driver 结构体、usb_interface 结构体等。
实现设备接口:设备接口是驱动程序与用户空间进行通信的接口,需要使用 Linux 提供的字符设备接口(Char Device Interface)或网络设备接口(Network Device Interface)等。
编写中断处理程序:USB 设备经常会触发中断请求,需要编写中断处理程序来响应这些请求,可以使用 Linux 内核提供的中断处理函数。
注册驱动程序:使用 usb_register函数注册驱动程序,告诉 Linux 内核有一个新的 USB 驱动程序可用。
测试驱动程序:编写完驱动程序后需要进行测试,可以使用各种 USB 设备进行测试,例如 USB 鼠标、USB 键盘、USB 存储设备等。
USB host controller驱动框架



HCD(Host Controller Driver)驱动程序:这是针对特定的 USB 主机控制器硬件的驱动程序,负责管理 USB 主机控制器,包括 USB 总线上的数据传输、流程控制和错误处理等。HCD 驱动程序的主要任务是将 USB 设备的数据从主机控制器传输到内存中,或者将数据从内存传输到 USB 设备中。
USB 核心驱动程序:这是 USB 驱动程序的核心组件,负责实现 USB 总线枚举和管理功能,以及处理 USB 总线消息。USB 核心驱动程序通过与其他部分交互,使得操作系统能够识别 USB 设备并与之通信。
USB 设备驱动程序:这是针对特定的 USB 设备硬件的驱动程序,负责管理 USB 设备,包括控制设备的功能、处理设备的事件和数据传输等。USB 设备驱动程序通过 HCD 驱动程序和 USB 核心驱动程序与操作系统进行通信
USB从设备




  • device
有效的USB设备都包含一个或多个配置。
数据结构 usb_device usb_device_descriptor

  • config
USB设备的配置类似于配置文件,其中默认的配置文件是常用的配置文件。因此,Linux只支持每台设备的一种配置——默认配置。
数据结构 usb_device usb_host_config usb_config_descriptor

  • interface
对于每一个配置,设备可能有一个或多个接口。接口对应于设备提供的功能。设备提供的独立功能有多少,接口就有多少。
所以,假设一台MFD(多功能设备)USB打印机可以打印、扫描和传真,那么它很可能至少有三个接口——每个接口对应一个功能。因此,与其他设备驱动程序不同,USB设备驱动程序通常是为每个接口关联/编写的,而不是整个设备——这意味着一个USB设备可能有多个设备驱动程序。当然一个接口最多只能有一个驱动程序。
数据结构usb_host_interface usb_interface_descriptor

  • endpoints
USB(通用串行总线)端点是USB设备内唯一的通信通道,用于在设备和主机系统之间传输数据。
数据结构usb_device usb_host_endpoint usb_endpoint_descriptor
USB设备可能有多个端点,每个端点都有不同的用途,例如向设备传输数据或从设备发送和接收控制消息。
有三种类型的USB端点:

  • 控制端点:用于主机和设备之间发送和接收控制消息。控制消息用于配置设备和发起请求,例如获取设备描述符或设置设备配置。
  • 中断端点:用于低延迟、高优先级的数据传输,例如从鼠标或键盘输入。
  • 批量终端:用于传输大量数据,如文件传输或流媒体。
每个端点都有一个唯一的端点编号,用于在数据传输过程中寻址端点。此外,每个端点都有一个特定的最大数据有效负载大小,这是在单个事务中可以传输的数据量。
USB驱动编写示例

代码框架



USB驱动程序是一个内核模块,负责连接应用程序和USB子系统之间的接口。USB子系统是一个包含了多个模块的子系统,包括USB核心模块、USB设备模块、USB主机模块、USB Gadget模块等等。USB控制器则是硬件层面的实现,负责管理USB设备与主机之间的通信。

  • 头文件引入:引入相关的头文件,包括Linux内核头文件和USB子系统的头文件。
  • 模块初始化和卸载函数:定义驱动程序的初始化函数和卸载函数,这些函数在驱动程序被加载或卸载时被调用。
  • 设备匹配函数:定义一个函数来匹配特定的USB设备,通常会根据设备的vendor ID和product ID进行匹配。
  • USB设备注册函数:注册一个新的USB设备,将其添加到系统的设备列表中。
  • USB设备连接函数:定义一个函数来处理USB设备的连接事件,当USB设备被插入时,该函数将被调用。
  • USB设备断开函数:定义一个函数来处理USB设备的断开事件,当USB设备被拔出时,该函数将被调用。
  • USB数据传输函数:定义一个函数来处理USB设备和主机之间的数据传输,包括读和写操作。
  • 控制传输函数:定义一个函数来处理USB设备和主机之间的控制传输,包括设备描述符、配置描述符、接口描述符等。
linux os下USB设备识别过程


  • 硬件上(USB2.0) USB主机端D-和D+接有15K下拉电阻, 未接USB设备时为低电平. USB设备端D-或D+接有1.5K上拉电阻. 当USB设备插入USB主机端口时, 就会把D-或D+拉高, 让主机知道有设备接入了 把D-拉高是低速设备, 把D+拉高是高速设备
  • 软件上
当 USB 设备被插入计算机时,Linux 内核会启动 USB 子系统并开始进行 USB 总线的枚举。
内核会扫描 USB 总线上的设备并为每个设备分配一个地址。
然后,内核会向设备发送一些初始化命令以检测设备的类型和功能。

  • 如果设备是一个存储设备,内核将加载相应的驱动程序,并将设备挂载到文件系统上,以使用户能够访问它。
  • 如果设备是一个输入设备(如键盘或鼠标),内核会加载相应的驱动程序,并将设备添加到输入子系统中。
  • 如果设备是一个网络适配器,内核将加载相应的驱动程序,并将设备添加到网络子系统中。
  • 如果设备是一个音频设备,内核将加载相应的驱动程序,并将设备添加到音频子系统中。
总之,Linux 操作系统会根据设备的类型和功能,加载相应的驱动程序,并将设备添加到相应的子系统中。这使得用户能够轻松地使用各种 USB 设备,并为每个设备提供必要的功能支持。
代码示例

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/usb.h>
static int pen_probe(struct usb_interface *interface, const struct usb_device_id *id){
    printk(KERN_INFO "Pen drive (%04X:%04X) plugged\n", id->idVendor,
                                id->idProduct);
return 0;
}
static void pen_disconnect(struct usb_interface *interface){
    printk(KERN_INFO "Pen drive removed\n");
}
static struct usb_device_id pen_table[] =
{
    { USB_DEVICE(0x058F, 0x6387) },
    {} /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, pen_table);
static struct usb_driver pen_driver =
{
    .name = "pen_driver",
    .id_table = pen_table,
    .probe = pen_probe,
    .disconnect = pen_disconnect,
};
static int __init pen_init(void){
return usb_register(&pen_driver);
}
static void __exit pen_exit(void){
    usb_deregister(&pen_driver);
}
module_init(pen_init);
module_exit(pen_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("xx xx <xx@xx.com>");
MODULE_DESCRIPTION("USB Pen Registration Driver");The end!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|微软交流社区

GMT+8, 2025-1-22 00:50 , Processed in 0.075976 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表