LINUX系统子系统DEMON,linux输入子系统之按键驱动

这一节,我们来以输入子系统的框架来写一个按键驱动。

问:怎么写符合输入子系统框架的驱动程序?

答:

1. 分配一个input_dev结构体

2. 设置

3. 注册

4. 硬件相关的代码,比如在中断服务程序里上报事件

问:如何分配input_dev结构体?

答:使用input_allocate_device函数

input_dev结构体的重要成员

structinput_dev {

constchar*name;

constchar*phys;

constchar*uniq;

structinput_id id;

unsigned longevbit[NBITS(EV_MAX)];// 表示能产生哪类事件

unsigned longkeybit[NBITS(KEY_MAX)];// 表示能产生哪些按键

unsigned longrelbit[NBITS(REL_MAX)];// 表示能产生哪些相对位移事件, x,y,滚轮

unsigned longabsbit[NBITS(ABS_MAX)];// 表示能产生哪些绝对位移事件, x,y

unsigned longmscbit[BITS_TO_LONGS(MSC_CNT)];

unsigned longledbit[BITS_TO_LONGS(LED_CNT)];

unsigned longsndbit[BITS_TO_LONGS(SND_CNT)];

unsigned longffbit[BITS_TO_LONGS(FF_CNT)];

...

}

问:第二步的设置,应该怎么设置,应该设置什么?

答:举例,在此按键驱动里

/* 2.设置 */

/* 2.1 设置按键能产生哪类事件 */

set_bit(EV_KEY,buttons_dev->evbit);  //按键类事件

set_bit(EV_REP,buttons_dev->evbit);  //重复类事件,比如按下按键L能重复打印L;按下后,能重复帮你上报事件(重复,说明肯定用到定时器)

/* 2.2 设置能产生这类操作的哪些事件 */

set_bit(KEY_L,buttons_dev->keybit);

set_bit(KEY_S,buttons_dev->keybit);

set_bit(KEY_ENTER,buttons_dev->keybit);

set_bit(KEY_LEFTSHIFT,buttons_dev->keybit);

问:有哪些类呢?

答:在input.h里有以下类

#define EV_SYN          0x00    //同步类

#define EV_KEY          0x01    //按键类

#define EV_REL          0x02    //相对位移类

#define EV_ABS          0x03    //绝对位移类

#define EV_MSC          0x04

#define EV_SW           0x05

#define EV_LED          0x11

#define EV_SND          0x12    //声音类

#define EV_REP          0x14    //重复类

#define EV_FF           0x15

#define EV_PWR          0x16

#define EV_FF_STATUS        0x17

#define EV_MAX          0x1f

#define EV_CNT          (EV_MAX+1)

问:如何注册?

答:使用input_register_device(struct input_dev *dev)函数来注册

问:此按键驱动的硬件操作包括哪些操作?

答:申请定时器、申请中断操作

驱动源码:

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include          //class_create

#include        //S3C2410_GPF1

//#include 

#include 

//#include 

#include   //wait_event_interruptible

#include    //poll

#include 

#include 

staticstructpin_desc{

intirq;

unsigned char*name;

unsigned intpin;

unsigned intkey_val;

};

staticstructpin_desc pins_desc[4] = {

{IRQ_EINT1,"K1",S3C2410_GPF1,KEY_L},

{IRQ_EINT4,"K2",S3C2410_GPF4,KEY_S},

{IRQ_EINT2,"K3",S3C2410_GPF2,KEY_ENTER},

{IRQ_EINT0,"K4",S3C2410_GPF0,KEY_LEFTSHIFT},

};

staticstructpin_desc *irq_pd;

staticstructinput_dev *buttons_dev;

staticstructtimer_list buttons_timer;

/* 用户中断处理函数 */

staticirqreturn_t buttons_irq(intirq,void*dev_id)

{

irq_pd = (structpin_desc *)dev_id;

/* 修改定时器定时时间,定时10ms,即10秒后启动定时器

* HZ 表示100个jiffies,jiffies的单位为10ms,即HZ = 100*10ms = 1s

* 这里HZ/100即定时10ms

*/

mod_timer(&buttons_timer, jiffies + (HZ /100));

returnIRQ_HANDLED;

}

/* 定时器处理函数 */

staticvoidbuttons_timer_function(unsignedlongdata)

{

structpin_desc *pindesc = irq_pd;

unsigned intpinval;

pinval = s3c2410_gpio_getpin(pindesc->pin);

if(pinval)

{

/* 松开 最后一个参数: 0-松开, 1-按下 */

input_event(buttons_dev,EV_KEY,pindesc->key_val,0);

input_sync(buttons_dev);

}

else

{

/* 按下 */

input_event(buttons_dev,EV_KEY,pindesc->key_val,1);

input_sync(buttons_dev);

}

}

/* 驱动入口函数 */

staticintbuttons_input_init(void)

{

inti;

/* 1.分配一个input_dev结构体 */

buttons_dev = input_allocate_device();

/* 2.设置 */

/* 2.1 设置按键能产生哪类事件 */

set_bit(EV_KEY,buttons_dev->evbit);

set_bit(EV_REP,buttons_dev->evbit);

/* 2.2 设置能产生这类操作的哪些事件 */

set_bit(KEY_L,buttons_dev->keybit);

set_bit(KEY_S,buttons_dev->keybit);

set_bit(KEY_ENTER,buttons_dev->keybit);

set_bit(KEY_LEFTSHIFT,buttons_dev->keybit);

/* 3.注册 */

input_register_device(buttons_dev);

/* 4.硬件相关的设置 */

/* 4.1 定时器相关的操作 */

init_timer(&buttons_timer);

buttons_timer.function = buttons_timer_function;

add_timer(&buttons_timer);

/* 4.2 申请中断 */

for(i = 0;i 

{

request_irq(pins_desc[i].irq, buttons_irq, IRQ_TYPE_EDGE_BOTH, pins_desc[i].name, &pins_desc[i]);

}

return0;

}

/* 驱动出口函数 */

staticvoidbuttons_input_exit(void)

{

inti;

for(i = 0;i 

{

free_irq(pins_desc[i].irq, &pins_desc[i]);

}

del_timer(&buttons_timer);

input_unregister_device(buttons_dev);

input_free_device(buttons_dev);

}

module_init(buttons_input_init);  //用于修饰入口函数

module_exit(buttons_input_exit);  //用于修饰出口函数

MODULE_AUTHOR("LWJ");

MODULE_DESCRIPTION("Just for Demon");

MODULE_LICENSE("GPL");//遵循GPL协议

测试步骤方法一:

[WJ2440]# ls

Qt                  first_test          second_test

TQLedtest           fourth_drv.ko       sixth_drv.ko

app_test            fourth_test         sixth_test

bin                 home                sixthdrvtest

buttons_all_drv.ko  lib                 sys

buttons_all_test    linuxrc             third_drv.ko

buttons_input.ko    mnt                 third_test

dev                 opt                 tmp

driver_test         proc                udisk

etc                 root                usr

fifth_drv.ko        sbin                var

fifth_test          sddisk              web

first_drv.ko        second_drv.ko

[WJ2440]# ls /dev/event* -l

crw-rw----    1 root     root       13,  64 Jan  2 06:04 /dev/event0

[WJ2440]# insmod buttons_input.ko

input: Unspecified device as /devices/virtual/input/input1

[WJ2440]# ls /dev/event* -l

crw-rw----    1 root     root       13,  64 Jan  2 06:04 /dev/event0

crw-rw----    1 root     root       13,  65 Jan  2 06:06 /dev/event1

[WJ2440]# cat /dev/tty1

[WJ2440]# cat /dev/tty1

ls

ls

输入cat /dev/tty1命令后,顺序按下K1,K2,K3则会显示ls

2. 如果没有启动QT:

cat /dev/tty1

按:s2,s3,s4

就可以得到ls

或者:

exec 0

然后可以使用按键来输入

3. 如果已经启动了QT:    ( 因为启动了qt之后,串口返回的是乱码)

可以点开记事本

然后按:s2,s3,s4

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值