当前位置: 首页 > news >正文

编写Linux下usb设备驱动方法:probe函数中要完成的任务

一. 简介

前一篇文章简单学习了 Linux下usb设备驱动实现流程,文章如下:

编写Linux下usb设备驱动方法:usb设备驱动实现流程-CSDN博客

本文来学习一下 usb设备驱动的 probe函数要完成的任务。

当usb主控制器检测到设备与 驱动相匹配时,就会执行usb的 probe函数。

二. 如何编写Linux下usb设备驱动

在 Linux 下编写 USB 设备驱动,是嵌入式开发和硬件交互中的核心技能。Linux 提供了完善的 USB 子系统,采用分层架构,开发者只需编写 设备驱动(Client Driver) 层,注册到 USB Core,即可实现与设备的通信。

usb应用与usb驱动框架调用如下图:

1. usb设备驱动的核心概念

(1) USB 设备模型:Linux 内核将 USB 设备抽象为「设备(device)」和「驱动(driver)」,通过总线(bus)进行匹配(基于厂商 ID、产品 ID 等)。

(2) 核心结构体

  • struct usb_driver:驱动的核心结构体,包含驱动名称、匹配规则、探测 / 断开函数等。struct usb_driver 结构体只是负责找到usb设备,管理usb设备连接和断开的作用。
  • struct usb_interface:表示 USB 设备的一个接口(一个设备可能有多个接口)。
  • struct usb_endpoint_descriptor:端点描述符,描述 USB 设备的通信端点(数据传输的通道)。
  • urb(USB Request Block):USB 数据传输的核心结构,用于异步传输数据。

2. 了解目标 USB 设备的信息

在编写驱动前,需通过工具获取设备的关键信息(用于驱动匹配):

  • 厂商 ID(idVendor)和产品 ID(idProduct):通过 lsusb 命令查看(例如:Bus 001 Device 005: ID 1234:5678 VendorName)。
  • 端点配置:通过 "lsusb -v -d 厂商ID:产品ID" 查看端点类型(控制 / 批量 / 中断 / 等时)、地址、最大包大小等。

注意:因为在编写 usb设备驱动时,需要配置 id_table,具体配置usb设备的 PID和 VID值。

三. 编写Linux下usb设备驱动的方法

1. 定义 usb驱动元数据:struct usb_driver

这是驱动的入口,它告诉 这个USB设备驱动驱动支持哪些设备,以及回调函数是什么:

static struct usb_driver my_usb_driver = {.name = "my_usb_driver",    //usb驱动名称.probe = my_probe,          //当驱动匹配时调用的函数.disconnect  = my_disconnect,//当设备断开时调用的函数.id_table = my_id_table,     //该驱动支持的设备ID列表
};

2.  定义支持的设备:id_table

这是一个 struct usb_device_id 数组,用于列出驱动程序支持的所有 USB 设备。内核通过 Vendor ID (VID) 和 Product ID (PID) 来匹配设备:

static struct usb_device_id my_id_table[] = {{ USB_DEVICE(0x1234, 0xa1a2) }, //支持的usb设备VID和PID{}                              //列表结束标志
};
//将设备ID表导出到内核,用于模块加载时内核识别该驱动支持的设备
MODULE_DEVICE_TABLE(usb, my_id_table); 

3. 实现 probe函数

当 USB主控制器驱动发现一个设备与你的 id_table 匹配时,就会调用 probe函数。probe函数的主要任务:

(1) 分配与初始化驱动私有数据结构: 使用 kzalloc 或 devm_kzalloc
  • 分配私有数据内存:使用 kzalloc 分配内存(确保初始化为 0,避免野指针)。
  • 关联核心对象:将 usb_deviceusb_interface 等核心结构体指针存入私有数据(需通过 usb_get_dev 增加设备引用计数,确保设备不被意外释放)。
  • 初始化关键成员:如数据传输缓冲区大小、URB 指针初始化为 NULL 等。

(2) 初始化数据传输机制(URB 准备)

USB 设备的核心功能是数据传输,probe 函数需为传输准备好 URB(USB Request Block,USB 请求块)—— 内核中 USB 传输的 “载体”:

  • 分配 URB:通过 usb_alloc_urb 分配与端点类型匹配的 URB(如中断端点用 usb_alloc_urb(0, ...),等时端点需指定 iso 包数量)。
  • 填充 URB:根据端点类型调用对应的填充函数(如中断端点用 usb_fill_int_urb,批量端点用 usb_fill_bulk_urb),设置传输方向、缓冲区、完成回调函数等。
  • 关联 URB 与私有数据:将私有数据设为 URB 的 context,便于回调函数中访问设备资源。

(3) 注册用户空间接口(可选)

若驱动需要与用户空间程序交互(如通过 ioctl 发送命令、读写数据),probe 函数需注册字符设备、sysfs 节点或其他接口:

字符设备注册:通过 cdev_init、cdev_add 注册字符设备,关联文件操作结构体(file_operations),让用户空间可通过 /dev/xxx 访问。

sysfs 节点创建:通过 sysfs_create_group 等函数创建属性文件,暴露设备状态或配置参数(如 echo 1 > /sys/class/myusb/enable 开启设备)。

(4) 启动数据传输(可选)

对于需要 “设备插入后立即开始工作” 的场景(如传感器设备周期性上报数据),probe函数可在初始化完成后直接提交 URB,启动首次数据传输:

http://www.dtcms.com/a/350512.html

相关文章:

  • 麦特轮巡线避障小车开发
  • IEEE子刊 | 注意缺陷多动障碍的功能连接模式:近红外机器学习研究
  • QML中的QtObject
  • QT新建文件或者项目解释:那些模板分别是什么意思?
  • 前端部署终极详细指南
  • 容器日志收集配置在云服务器环境中的集成方案
  • JWT用户认证后微服务间如何认证?(双向TLS(mTLS)、API网关、Refresh Token刷新Token)微服务间不传递用户认证Token
  • C-JSON接口的使用
  • 【什么是端到端模型】
  • 益莱储@PCIe技术大会
  • Bright Data 代理 + MCP :解决 Google 搜索反爬的完整方案
  • WPF 参数设置界面按模型字段自动生成设置界面
  • Docker:网络连接
  • python面试题目100个(更新中预计10天更完)
  • 深度学习(二):数据集定义、PyTorch 数据集定义与使用(分板块解析)
  • 决策树原理与 Sklearn 实战
  • 【动手学深度学习】7.1. 深度卷积神经网络(AlexNet)
  • 0825 http梳理作业
  • 【慕伏白】CTFHub 技能树学习笔记 -- Web 之信息泄露
  • Linux多线程[生产者消费者模型]
  • python项目中pyproject.toml是做什么用的
  • 【Canvas与标牌】维兰德汤谷公司logo
  • Hadoop MapReduce Task 设计源码分析
  • java-代码随想录第十七天| 700.二叉搜索树中的搜索、617.合并二叉树、98.验证二叉搜索树
  • C++ STL 专家容器:关联式、哈希与适配器
  • 《微服务架构下API网关流量控制Bug复盘:从熔断失效到全链路防护》
  • 精准测试的密码:解密等价类划分,让Bug无处可逃
  • 【C语言16天强化训练】从基础入门到进阶:Day 11
  • 朴素贝叶斯算法总结
  • 互联网大厂Java面试实录:Spring Boot与微服务架构解析