Chinaunix首页 | 论坛 | 博客
  • 博客访问: 226261
  • 博文数量: 80
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 781
  • 用 户 组: 普通用户
  • 注册时间: 2014-11-08 10:41
个人简介

爱莉清

文章分类

全部博文(80)

文章存档

2018年(1)

2017年(18)

2016年(49)

2015年(7)

2014年(5)

我的朋友

分类: LINUX

2015-07-04 21:45:49

    Linux有许多子系统,usb、video、input...input 就是今天的主角--输入子系统的相关代码位于 driver目录下的input文件夹。 打开Kconifg文件,第12行开始有这样一段话 “Say Y here if you have any input device (mouse,  keyboard, tablet,joystick, steering wheel ...)...”。 这段话有几层意思,鼠标、键盘、游戏手柄等等 这些都属于输入设备;这些输入设备的驱动都是 通过输入子系统来实现的(当然,这些设备也依 赖于usb子系统)。所有这些输入设备都各有不同,那么 输入子系统也就只能实现他们的共性, 差异性则由设备驱动来实现。差异性 又体现在哪里?最直观的就表现在这 些设备功能上的不同了。对于我们写 驱动的人来说在设备驱动中就只要使 用输入子系统提供的工具(也就是函 数)来完成这些“差异”就行了,其他 的则是输入子系统的工作。这个思想 不仅存在于输入子系统,其他子系统 也是一样。

    既然完成“差异性”是我们写设备驱动的人的工 作,那么这些工作具体包含哪些内容

    两个关键函数:
        一、入口函数:buttons_init
        二、出口函数:buttons_exit
一、buttons_init函数:在module_init的修饰下,buttons_init成为了驱动的入口函 数,对于我们 写驱动的人来说最重要的就是这个函数了。我们 做的大部分工作都是在这个函数内完成的。主要分为5个部分:
    1、分配核心结构体input_dev。
    2、3、填充结构体成员。
    4、注册input_dev结构体
    5、硬件相关的设置
实现方式:buttons_init
    1、分配一个input_dev结构体 ==》buttons_dev = input_allocate_device();
    如果你了解过更多的子系统你会发现,几 乎每一个子系统都有一个结构体需要你创 
    建,这个结构体里面有各种各样的成员,随 后会调用各种接口来填充这个结构体,最后 
    会把这个结构体注册进内核。
    input_allocate_device这个函数不仅申请和初始化了相应的内存,同时还初始化了部分
    input结构体成员。
    有兴趣的可以看一下内核源码了解input结 构体每一个成员代表的含义。input结构体定 
    义位于include\linux\input.h
    
    2、设置能产生哪类事件
    set_bit(EV_KEY, buttons_dev->evbit);
    set_bit(EV_REP, buttons_dev->evbit);

    3、设置能产生这类事件中的哪些事件
    set_bit(KEY_L, buttons_dev->keybit);  /* 将这个按键按下当做键盘的 L 来处理,下同 */
    set_bit(KEY_ENTER, buttons_dev->keybit);
    
    4、注册input_dev结构体
     input_register_device(buttons_dev);
     “事件”是输入子系统的核心,首先要告诉 内核我这个设备能够产生哪些事件,比如按 
        键、绝对位移等等。然后还需要在按键产生 后手动将事件上报给内核。看完输入子系统 
        可以看看触摸屏驱动,你会对输入子系统有 更加深刻的了解。

    5、硬件相关的操作
    初始化、注册定时器
    init_timer(&buttons_timer);
    buttons_timer.function = buttons_timer_function;
    add_timer(&buttons_timer);
    注册中断
    request_irq(pins_desc[i].irq, buttons_irq, IRQT_BOTHEDGE, pins_desc[i].name, &pins_desc[i]);


出口函数:buttons_exit
    在module_exit的修饰下,buttons_exit成为了驱动的出口函 数,很多人对这个函数不重视,其实它很重要。
    它完成了很多 清理工作,比如:
    1、释放中断
    2、卸载定时器
    3、卸载input_dev
    4、释放内存
    不同的设备驱动在硬件设置这一部分会有 很大的区别,这需要你对驱动框架有一定的 
    了解。最好的办法还是去看内核自带的驱动 源码。 
     有人会问这个驱动用到了按键驱动,为什 么没有看到对GPIO的初始化,那是因为这个 
    工作被request_irq这个函数完成了,有兴趣 的同学可以看一下它的具体实现。 
     别忘了在入口函数最后一定要有返回值, 不然你的驱动会时好时坏。

    buttons_exit
    以上4步分别是由以下4个函数完成的:
     free_irq(pins_desc[i].irq, &pins_desc[i]);
    del_timer(&buttons_timer);
    input_unregister_device(buttons_dev);
    input_free_device(buttons_dev);

    这几个函数从参数上看要比之前的函数简单, 虽然简单但是很重要。而且他们是一一对应的, 
    你用了什么函数来注册,就得调用对应的函数来 卸载;你用了什么函数来申请内存,就得调用对 
    应的函数来释放它。
    Linux的这种思想也告诉我们一个道理:做事 要有始有终。



这些函数很重要:

    函数input_allocate_device,用来分配并初始化内 存空间,同时初始化部分input_dev结构体成员,与 
    它对应的函数是input_free_device;
    函数input_register_device,用于注册input_dev结 构体,与它对于的函数是input_unregister_device; 
    函数input_event用于上报事件;
    函数del_timer用于卸载定时器。



阅读(1351) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~