• 【Linux开发】linux设备驱动归纳总结(八):4.总线热插拔


    linux设备驱动归纳总结(八):4.总线热插拔


    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    上一节介绍设备管理中的分层思想和面向对象思想(名字是我自己瞎编的)。接下来说一下热插拔的操作。

    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


    一、热插拔的实现


    我不知道在这里用热插拔这样的名字是否合适,在之前的代码,需要我自己手动去加载驱动和设备的模块,但在现实的情况下,一般是当设备一被插入,系统自己会注册设备,并调用合适的驱动。

    所以,接下来我要实现的是,在加载了usb总线和usb鼠标驱动的前提下,当有usb鼠标插入,系统自己进行设备的操作。当然,上面的usb鼠标是我自己想象出来的,当我一按下按键(对应中断E_INT1),就代表有usb鼠标插入。

    这样看来,要实现的代码就简单,稍稍修改一下程序就可以了,将之前由devie.ko实现的操作交由中断处理函数来执行,当我按下按键,触发中断自动执行


    driver.c不用修改,并且把device.c删掉,将代码移到bus.c中:

    /*8th_devModule_4/1st/bus.c*/

    9 struct work_struct my_work;

    。。。。。

    56 /**************

    57 * 设备注册

    58 *************/

    59 void usb_dev_release(struct device *dev) //卸载函数没有干具体的事情

    60 {

    61     printk(" release ");

    62 }

    63 /*结构体中不需要指定总线的成员,交由usb_device_register来完成*/

    64 struct usb_device mouse_dev = {

    65     .dev = {

    66         .bus_id = "usb_mouse",

    67         .release = usb_dev_release,

    68     },

    69 };

    70

    71 irqreturn_t hotplug_handler(int irqno, void *dev_id)

    72 {

    73     printk("usb mouse device insert ");

    74     schedule_work(&my_work); //调度到中断下半部执行

    75     return IRQ_HANDLED;

    76 }

    77 void work_func(struct work_struct *work)//中断下半部处理函数

    78 {

    79     /*假设从硬件读取厂商编号和设备编号*/

    80     mouse_dev.VendorID = 0x1122;

    81     mouse_dev.DeviceID = 0x3344;

    82     /*在中断函数中注册设备*/

    83     usb_device_register(&mouse_dev);

    84 }

    85

    86 static int __init usb_bus_init(void)

    87 {

    88     int ret;

    89     /*初始化中断下文struct work_struct为工作队列类型*/

    90     INIT_WORK(&my_work, work_func); 

    91     /*设置IRQ_EINT1的中断*/

    92     ret = request_irq(IRQ_EINT1, hotplug_handler, IRQF_TRIGGER_FALLING, "usb irq", NULL);

    93     if(ret){

    94         printk("irq failed ");

    95         return ret;

    96     }

    97

    98       /*总线注册,必须检测返回值*/

    99       ret = bus_register(&usb_bus);

    100     if(ret){

    101         printk("bus register failed! ");

    102         return ret;

    103     }

    104

    105     printk("usb bus init ");

    106     return 0;

    107 }

    108

    109 static void __exit usb_bus_exit(void)

    110 {

    111     bus_unregister(&usb_bus);

    112     free_irq(IRQ_EINT1, NULL); //释放IRQ_EINT1的中断源

    113     printk("usb bus bye! ");

    114 }

    上面的代码可以看到,函数将原来在device.c中实现的操作放在了中断函数来执行,一旦usb鼠标被插入(这里是我假设的,其实就是按下按键,触发E_INT1中断),就会执行注册设备的操作。

    看效果:

    [root: 1st]# insmod bus.ko //先加载总线

    usb bus init

    [root: 1st]# insmod driver.ko //再加载驱动

    usb driver init

    [root: 1st]# usb mouse device insert //当我按下按键,触发中断,假设鼠标被插入

    match success //配对成功

    init usb mouse //初始化设备

    当然,我的函数很多的bug,譬如你再次按下按键,那就会出现错误。但撇来这些不考虑,基本效果就出来了,当设备一插入,内核自动注册设备。


    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


    二、总结


    第八章的设备模型基本上就介绍完了,我在这里没有介绍kobject、kset等这一类内核中用于管理设备模型的结构体,有兴趣可以自己去看看。

    接着就会介绍平台类总线设备,到时候你会发现,平台类总线设备其实就是总线的一个封装。


    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    源代码: 8th_devModule_4.rar   

  • 相关阅读:
    【原创】极简的软件功能自动化测试
    重温归并排序
    vue中嵌入echarts关系图
    KDE 应用设置开机自启
    教大聪明学Linux
    支持Windows \Linux\Mac 平台制作系统启动盘的软件
    Linux命令man文档改为中文
    在Linux上使用企业微信提供的API发送信息给成员
    数字的放重新放置 #abc>bac #取数字 / % * #三步取
    frp内网穿透
  • 原文地址:https://www.cnblogs.com/huty/p/8518555.html
Copyright © 2020-2023  润新知