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

编写Linux下usb设备驱动方法:probe函数中要进行的工作

一. 简介

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

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

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

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

二. 编写Linux下usb设备驱动的方法:probe函数中要进行的工作

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

(1) 验证设备基本信息(合法性检查)

在进行资源分配前,需先确认设备的硬件特性是否符合驱动预期,避免对不兼容设备进行错误初始化:

  • 检查设备描述符:验证设备的接口数量、端点类型、传输能力等是否与驱动支持的范围匹配(例如驱动只支持中断端点,需检查设备是否存在中断端点)。
  • 确认端点参数:通过 usb_interface 的 cur_altsetting 成员获取当前接口的端点描述符,检查端点地址、最大包长(wMaxPacketSize)、中断间隔(bInterval)等是否符合驱动设计(例如确保缓冲区大小不超过端点最大包长)。
  • 检查设备版本 / 功能:对于复杂设备(如带多个配置的 USB 设备),可能需要验证设备固件版本、支持的功能集等。

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

(3) 初始化数据传输机制(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,便于回调函数中访问设备资源。

usb四种传输类型中,控制传输和批量传输,可以不用进行URB传输块的分配,填充,关联等刚工作。可以使用 usb内核提供的函数接口进行传输:

控制传输可以使用 usb_control_msg()函数进行传输,批量传输可以使用 usb_bulk_msg() 函数进行传输(在使用 usb_control_msg()函数或 usb_bulk_msg()函数进行 USB 控制传输时,USB 内核已经封装了 URB(USB Request Block)的分配、填充、提交和释放等底层工作,开发者无需手动操作 URB 结构)。

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

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

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

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

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

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

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

相关文章:

  • css新特性
  • openharmony之DRM开发:数字知识产权保护揭秘
  • 智能体框架CAMEL-第三章
  • 学习嵌入式的第二十五天——哈希表和内核链表
  • 基于SpringBoot的物资管理系统【2026最新】
  • Linux网络服务(六)——iptables Forward实现内网服务暴露与访问外网
  • 直播美颜SDK技术解析:人脸美型功能的算法原理与实现方案
  • linux环境下 - 如何干净地卸载掉nvidia驱动
  • 工业通信协议综合调研报告
  • 深入浅出 ArrayList:从基础用法到底层原理的全面解析(上)
  • vue-Router中通过路由地址path中的数据转换为props传参,不建议添加多个可选参数
  • More Effective C++ 条款07:不要重载、和,操作符
  • linux的conda配置与应用阶段的简单指令备注
  • Typora + PicList + Gitee 图床完整配置教程
  • 《P1656 炸铁路》
  • C++ 编译链接杂谈——前向声明
  • JavaScript 类中静态变量与私有变量的区别及用法
  • eniac:世界上第一台通用电子计算机的传奇
  • 开发避坑指南(36):Java字符串Base64编码实战指南
  • 深度学习-----《PyTorch深度学习核心应用解析:从环境搭建到模型优化的完整实践指南》
  • 初步了解多线程
  • 交换机是如何同时完成帧统计与 BER/FEC 分析的
  • 【应急响应工具教程】SPECTR3:通过便携式 iSCSI 实现远程证据的只读获取与分析
  • [pilot智驾系统] 模型守护进程(modeld)
  • rbio1:以生物学世界模型为软验证器训练科学推理大语言模型
  • 面试八股文之——JAVA基础
  • 深度学习梯度下降与交叉熵损失
  • 重塑企业沟通与增长:云蝠智能大模型如何成为您的智能语音中枢
  • 大模型(一)什么是 MCP?如何使用 Charry Studio 集成 MCP?
  • SQL查询-设置局部变量(PostgreSQL、MySQL)