/*参考文件所在路径如下
c:\jz2440开发板总\资料光盘\开发板资料\system\linux-2.6.22.6\linux-2.6.22.6\
drivers\input\keyboard\Gpio_keys.c
功能:了解输入子系统的框架,将我们的驱动程序融入到输入子系统中,就可以实现无缝的移植程序
在输入子系统中我们只需要写硬件层即可。
2016年5月18日22:17:59
*/
#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/irq.h>
#include <linux/gpio_keys.h>
#include <asm/gpio.h>
static struct input_dev * buttons_dev;
static struct pin_desc * irq_pd;
static timer_list buttons_timer;
struct pins_desc{
int irq;
char * name;
unsigned int pin;
unsigned int key_val;
};
/*当按下"s2"时,就会输出L*/
struct pin_desc pins_desc[4] = {
{IRQ_EINT0, "s2", S3C2410_GPF0, KEY_L},
{IRQ_EINT2, "s3", S3C2410_GPF2, KEY_S},
{IRQ_EINT11, "s4", S3C2410_GPG3, KEY_ENTER},
{IRQ_EINT19, "s5", S3C2410_GPG11, KEY_LEFTSHIFT},
};
static void buttons_timer_function(unsigned long data)
{
/*利用设备号来传递引脚号和值*/
struct pin_desc * pindesc = irq_pd;
unsigned int pinval ;
if(!pindesc)
return;
/*读取引脚是0或1*/
pinval = s3c2410_gpio_getpin(pindesc->pin);//系统提供的读取引脚状态的函数
if(pinval)
{
/*按键松开:最后一个参数,0表示松开,1表示按下*/
/* void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
第二个参数表示哪种类型事件(按键类事件),第三个参数code表示哪一个按键,第四个参数表示按下还是松开*/
input_event(buttons_dev,EV_KEY,pindesc->key_val,0);
/*上报同步事件,表示这个事件已经上报完了*/
input_sync(input);
}
else
{
/*按键按下*/
/*input_event函数是上报事件,会从建立联系的由connect创建的handle找到.handler,从而调用handler中的
event函数*/
input_event(buttons_dev,EV_KEY,pindesc->key_val,1);
input_sync(input);
}
}
static irqreturn_t buttons_irq(int irq, void *dev_id)
{
/* 记录下引脚描述 */
irq_pd = (struct pin_desc *)dev_id;
/* 10ms后启动定时器 ,定时器其实是在定时器链表中存放的,
每一个时钟中断都会检查链表中的哪个定时器时间到了,并执行相应的定时器处理函数*/
/*修改定时器的超时时间expires*/
mod_timer(&buttons_timer, jiffies+HZ/100);//HZ可以将理解为1秒
/*闹钟什么时候到,是基于jiffies这个值的,这个值是个全局变量,这个值每隔十毫秒就会有个系统时钟中断
在系统时钟中断里面,jiffies这个值就会累加 HZ是用来定义每一秒有几次timer interrupts。
Jiffies为Linux核心变数(unsigned long),它被用来记录系统自开机以来,已经过了多少tick。每发生一次
timer interrupt,Jiffies变数会被加一*/
/*
LINUX系统时钟频率是一个常数HZ来决定的,通常HZ=100,那么他的精度度就是10ms
(毫秒)。也就是说每10ms一次中断。所以一般来说Linux的精确度是10毫秒
*/
return IRQ_HANDLED;
}
/*入口函数*/
static int buttons_init(void)
{
int i;
/*1.分配input_dev结构体*/
buttons_dev = input_allocate_device();//没有判断是否分配成功与否
/*2.设置*/
/*2.1input_dev中的unsigned long evbit[NBITS(EV_MAX)]; // 表示能产生哪类事件*/
/*设置buttons_dev结构体中的evbit能产生按键类事件,将buttons_dev结构体中的evbit数组
的相应位设置为EV_KEY*/
set_bit(EV_KEY,buttons_dev->evbit);
/*能产生EV_KEY这类事件的哪些事件:L,S,ENTER,LEFTSHIFT这四个按键*/
/*能够产生重复类事件*/
set_bit(EV_REP,buttons_dev->evbit);
/*unsigned long keybit[NBITS(KEY_MAX)]; // 表示能产生哪些按键*/
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_handler结构体一一建立联系*/
/*匹配成功时,input_handler中的connect就会创建input_handle结构体,在创建连接时建立次设备号*/
input_register_device(buttons_dev);
/*4.硬件相关的操作*/
init_timer(&buttons_timer);
buttons_timer.function = buttons_timer_function;
add_timer(&buttons_timer);
for(i=0;i<4;i++)
{
/*通过request_irq最后一个参数dev_id来传递按键值*/
request_irq(pins_desc[i].irq,buttons_irq,IRQT_BOTHEDGE,pins_desc[i].name,&pins_desc[i]);
}
return 0;
}
/*出口函数*/
static void buttons_exit(void)
{
int i ;
for(i = 0;i < 4;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_init);
module_exit(buttons_exit);
MODULE_LICENSE("GPL");
c:\jz2440开发板总\资料光盘\开发板资料\system\linux-2.6.22.6\linux-2.6.22.6\
drivers\input\keyboard\Gpio_keys.c
功能:了解输入子系统的框架,将我们的驱动程序融入到输入子系统中,就可以实现无缝的移植程序
在输入子系统中我们只需要写硬件层即可。
2016年5月18日22:17:59
*/
#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/irq.h>
#include <linux/gpio_keys.h>
#include <asm/gpio.h>
static struct input_dev * buttons_dev;
static struct pin_desc * irq_pd;
static timer_list buttons_timer;
struct pins_desc{
int irq;
char * name;
unsigned int pin;
unsigned int key_val;
};
/*当按下"s2"时,就会输出L*/
struct pin_desc pins_desc[4] = {
{IRQ_EINT0, "s2", S3C2410_GPF0, KEY_L},
{IRQ_EINT2, "s3", S3C2410_GPF2, KEY_S},
{IRQ_EINT11, "s4", S3C2410_GPG3, KEY_ENTER},
{IRQ_EINT19, "s5", S3C2410_GPG11, KEY_LEFTSHIFT},
};
static void buttons_timer_function(unsigned long data)
{
/*利用设备号来传递引脚号和值*/
struct pin_desc * pindesc = irq_pd;
unsigned int pinval ;
if(!pindesc)
return;
/*读取引脚是0或1*/
pinval = s3c2410_gpio_getpin(pindesc->pin);//系统提供的读取引脚状态的函数
if(pinval)
{
/*按键松开:最后一个参数,0表示松开,1表示按下*/
/* void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
第二个参数表示哪种类型事件(按键类事件),第三个参数code表示哪一个按键,第四个参数表示按下还是松开*/
input_event(buttons_dev,EV_KEY,pindesc->key_val,0);
/*上报同步事件,表示这个事件已经上报完了*/
input_sync(input);
}
else
{
/*按键按下*/
/*input_event函数是上报事件,会从建立联系的由connect创建的handle找到.handler,从而调用handler中的
event函数*/
input_event(buttons_dev,EV_KEY,pindesc->key_val,1);
input_sync(input);
}
}
static irqreturn_t buttons_irq(int irq, void *dev_id)
{
/* 记录下引脚描述 */
irq_pd = (struct pin_desc *)dev_id;
/* 10ms后启动定时器 ,定时器其实是在定时器链表中存放的,
每一个时钟中断都会检查链表中的哪个定时器时间到了,并执行相应的定时器处理函数*/
/*修改定时器的超时时间expires*/
mod_timer(&buttons_timer, jiffies+HZ/100);//HZ可以将理解为1秒
/*闹钟什么时候到,是基于jiffies这个值的,这个值是个全局变量,这个值每隔十毫秒就会有个系统时钟中断
在系统时钟中断里面,jiffies这个值就会累加 HZ是用来定义每一秒有几次timer interrupts。
Jiffies为Linux核心变数(unsigned long),它被用来记录系统自开机以来,已经过了多少tick。每发生一次
timer interrupt,Jiffies变数会被加一*/
/*
LINUX系统时钟频率是一个常数HZ来决定的,通常HZ=100,那么他的精度度就是10ms
(毫秒)。也就是说每10ms一次中断。所以一般来说Linux的精确度是10毫秒
*/
return IRQ_HANDLED;
}
/*入口函数*/
static int buttons_init(void)
{
int i;
/*1.分配input_dev结构体*/
buttons_dev = input_allocate_device();//没有判断是否分配成功与否
/*2.设置*/
/*2.1input_dev中的unsigned long evbit[NBITS(EV_MAX)]; // 表示能产生哪类事件*/
/*设置buttons_dev结构体中的evbit能产生按键类事件,将buttons_dev结构体中的evbit数组
的相应位设置为EV_KEY*/
set_bit(EV_KEY,buttons_dev->evbit);
/*能产生EV_KEY这类事件的哪些事件:L,S,ENTER,LEFTSHIFT这四个按键*/
/*能够产生重复类事件*/
set_bit(EV_REP,buttons_dev->evbit);
/*unsigned long keybit[NBITS(KEY_MAX)]; // 表示能产生哪些按键*/
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_handler结构体一一建立联系*/
/*匹配成功时,input_handler中的connect就会创建input_handle结构体,在创建连接时建立次设备号*/
input_register_device(buttons_dev);
/*4.硬件相关的操作*/
init_timer(&buttons_timer);
buttons_timer.function = buttons_timer_function;
add_timer(&buttons_timer);
for(i=0;i<4;i++)
{
/*通过request_irq最后一个参数dev_id来传递按键值*/
request_irq(pins_desc[i].irq,buttons_irq,IRQT_BOTHEDGE,pins_desc[i].name,&pins_desc[i]);
}
return 0;
}
/*出口函数*/
static void buttons_exit(void)
{
int i ;
for(i = 0;i < 4;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_init);
module_exit(buttons_exit);
MODULE_LICENSE("GPL");