设为首页收藏本站
网站公告 | 这是第一条公告
     

 找回密码
 立即注册
缓存时间01 现在时间01 缓存数据 当你走完一段之后回头看,你会发现,那些真正能被记得的事真的是没有多少,真正无法忘记的人屈指可数,真正有趣的日子不过是那么一些,而真正需要害怕的也是寥寥无几。

当你走完一段之后回头看,你会发现,那些真正能被记得的事真的是没有多少,真正无法忘记的人屈指可数,真正有趣的日子不过是那么一些,而真正需要害怕的也是寥寥无几。

查看: 357|回复: 1

Linux USB驱动注册方式

[复制链接]

  离线 

TA的专栏

  • 打卡等级:热心大叔
  • 打卡总天数:229
  • 打卡月天数:1
  • 打卡总奖励:3211
  • 最近打卡:2025-12-14 20:05:53
等级头衔

等級:晓枫资讯-上等兵

在线时间
0 小时

积分成就
威望
0
贡献
408
主题
372
精华
0
金钱
4404
积分
842
注册时间
2023-1-6
最后登录
2025-12-14

发表于 2025-8-29 11:09:04 | 显示全部楼层 |阅读模式
注册接口
  1.   #define usb_register(driver) \
  2.               usb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)
  3.   int usb_register_driver(struct usb_driver *new_driver, struct module *owner,
  4.                      const char *mod_name)
复制代码
注册的结构体是struct usb_driver,主要填充name、probe、disconnect和id_table字段,其中name是驱动名称,到时会在/sys/bus/usb/drivers显示这个驱动名称,probe和disconnect会在USB设备插入和拔出时调用,id_table就是匹配列表,可以通过VID、PID匹配,也可以通过USB设备类型匹配。

示例代码
  1. static int zslusb_probe(struct usb_interface *intf, const struct usb_device_id *id)
  2. {
  3.        struct usb_device *usbdev;
  4.        struct usb_host_interface *interface;
  5.        struct usb_endpoint_descriptor *endpoint;
  6.        int i = 0;

  7.        usbdev = interface_to_usbdev(intf);
  8.        interface = intf->cur_altsetting;

  9.        printk(KERN_INFO "%s:num:%d \n",__func__,interface->desc.bNumEndpoints);

  10.        for (i = 0;i<interface->desc.bNumEndpoints;i++)
  11.        {
  12.               endpoint = &interface->endpoint[0].desc;
  13.               printk(KERN_INFO "%s: %x %x\n",__func__,endpoint->bEndpointAddress,endpoint->bmAttributes);
  14.               printk(KERN_INFO "%s: %x %x %x\n",__func__,interface->desc.bInterfaceClass,interface->desc.bInterfaceSubClass,interface->desc.bInterfaceProtocol);
  15.        }

  16.        return 0;
  17. }

  18. static void zslusb_disconnect(struct usb_interface *intf)
  19. {
  20.        printk(KERN_INFO "%s: \n",__func__);
  21.        dump_stack();
  22. }

  23. static struct usb_device_id zslusb_id_table [] = {
  24.        { USB_DEVICE(0x413D, 0x2113) },
  25.        { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT, USB_INTERFACE_PROTOCOL_KEYBOARD)},
  26.        { }    /* Terminating entry */
  27. };

  28. MODULE_DEVICE_TABLE (usb, zsl_usb_id_table);

  29. static struct usb_driver zslusb_driver = {
  30.        .name            = "zslusb",
  31.        .probe           = zslusb_probe,       /* usb设备插入时,id_table信息匹配成功则调用 */
  32.        .disconnect    = zslusb_disconnect,  /* usb设备拔出时调用 */
  33.        .id_table  = zslusb_id_table,    /* id_table,用于匹配设备描述符 */
  34. };

  35. void zslusb_init(void)
  36. {     
  37.        usb_register(&zslusb_driver);    /* 注册usb设备驱动,不申请设备号 */
  38. }
复制代码
执行后运行,USB设备插入和拔出就会调用zslusb_probe和zslusb_disconnect接口。
结果如下:

  • 插入设备
1.jpeg


  • 拔掉设备
2.jpeg


调用关系

设备注册是调用usb_register接口注册,本质是usb_register_driver,在这个接口里主要是填充struct usb_driver结构体,把bus = &usb_bus_type,然后调用driver_register注册驱动。
设备插入时如果主机控制器处于休眠状态,会先通过 hcd_resume_work 恢复供电,调用 rpm_resume 和 usb_runtime_resume 唤醒 Hub和恢复设备。随后 Hub 检测到端口变化,通过hub工作队列 hub_wq 触发 hub_event,从而usb_new_device初始化新USB设备并device_add把USB设备注册到内核设备树,触发首次总线探测,bus_probe_device里遍历所有驱动,对每个驱动执行__device_attach_driver,通过match匹配到设备后调用通用USB驱动usb_generic_driver_probe,确保设备能被识别成基本USB设备,读取设备描述符和分配资源。配置完成后,为每个接口注册新设备(device_add),触发二次总线探测,匹配后调用入口函数usb_probe_interface。
  1. 设备插入
  2. ├─ 休眠状态? → hcd_resume_work → rpm_resume → usb_runtime_resume → hub_resume
  3. └─ Hub检测 → hub_wq → hub_event → usb_new_device → device_add
  4.     ├─ 首次探测 → usb_generic_driver_probe(基础初始化)
  5.     └─ 接口注册 → device_add → usb_probe_interface(驱动加载)
复制代码
设备拔出是由硬件中断触发hub_irq,标记事件并触发软中断tasklet_hi_action,下半部Tasklet调用 usb_giveback_urb_bh调度hub工作队列 hub_wq触发hub_event,调用usb_disconnect清理USB设备,禁用端点,device_del调用device_release_driver解绑驱动(释放软件资源),禁用设备(停用硬件端点),释放设备内存。
  1. 设备拔出 → hub_irq → tasklet_hi_action → usb_giveback_urb_bh → hub_wq → hub_event
  2.     ├─ usb_disconnect → usb_disable_device(禁用端点+终止URB)
  3.     └─ device_del → device_release_driver → zslusb_disconnect(驱动清理) → usb_put_dev(内存释放)
复制代码
总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持晓枫资讯。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
      1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
      2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
      3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:点击这里给我发消息进行删除处理。
      4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
      5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
22
积分
24
注册时间
2022-12-25
最后登录
2022-12-25

发表于 2025-9-1 12:07:25 | 显示全部楼层
感谢楼主,顶。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~
严禁发布广告,淫秽、色情、赌博、暴力、凶杀、恐怖、间谍及其他违反国家法律法规的内容。!晓枫资讯-社区
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1楼
2楼

手机版|晓枫资讯--科技资讯社区 本站已运行

CopyRight © 2022-2025 晓枫资讯--科技资讯社区 ( BBS.yzwlo.com ) . All Rights Reserved .

晓枫资讯--科技资讯社区

本站内容由用户自主分享和转载自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

如有侵权、违反国家法律政策行为,请联系我们,我们会第一时间及时清除和处理! 举报反馈邮箱:点击这里给我发消息

Powered by Discuz! X3.5

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