输入服务子系统实例分析(韦东山的视频总结及针对linux-2.6.30.4)
2013-05-26 15:19
423 查看
根据韦东山视频讲解,和自己理解总结的:
1.分配一个input_dev结构体,
2.设置input_dev。
3.注册input_dev结构体。
4.硬件相关的操作。
/*参考/keyboard/corgikbd.c*/
static int __init corgikbd_init(void)
{
return platform_driver_register(&corgikbd_driver);
}
static struct platform_driver corgikbd_driver = {
.probe = corgikbd_probe,
.remove = __devexit_p(corgikbd_remove),
.suspend = corgikbd_suspend,
.resume = corgikbd_resume,
.driver = {
.name = "corgi-keyboard",
.owner = THIS_MODULE,
},
};
static int __devinit corgikbd_probe(struct platform_device *pdev)
{
struct corgikbd *corgikbd;
struct input_dev *input_dev;
int i, err = -ENOMEM;
corgikbd = kzalloc(sizeof(struct corgikbd), GFP_KERNEL);
/*1.分配一个input_dev结构*/
input_dev = input_allocate_device();
if (!corgikbd || !input_dev)
goto fail;
platform_set_drvdata(pdev, corgikbd); corgikbd->input = input_dev;
spin_lock_init(&corgikbd->lock);
/* Init Keyboard rescan timer */
init_timer(&corgikbd->timer);
corgikbd->timer.function = corgikbd_timer_callback;
corgikbd->timer.data = (unsigned long) corgikbd;
/* Init Hinge Timer */
init_timer(&corgikbd->htimer);
corgikbd->htimer.function = corgikbd_hinge_timer;
corgikbd->htimer.data = (unsigned long) corgikbd;
corgikbd->suspend_jiffies=jiffies; (corgikbd->keycode, corgikbd_keycode, sizeof(corgikbd->keycode));
input_dev->name = "Corgi Keyboard";
input_dev->phys = "corgikbd/input0";
input_dev->id.bustype = BUS_HOST;
input_dev->id.vendor = 0x0001;
input_dev->id.product = 0x0001;
input_dev->id.version = 0x0100;
input_dev->dev.parent = &pdev->dev;
/*2.设置input_dev*/
/*2.1设置能产生哪些事件 Event types
*EV_KEY 定义为#define EV_KEY 0x01
*能产生按键类事件
*EV_REP 重复,当按下,不松时能产生多个值
*/
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) |
BIT_MASK(EV_PWR) | BIT_MASK(EV_SW);
input_dev->keycode = corgikbd->keycode;
input_dev->keycodesize = sizeof(unsigned char);
input_dev->keycodemax = ARRAY_SIZE(corgikbd_keycode);
/*2.2设置能产生这类事件的哪些事件*/
for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++)
set_bit(corgikbd->keycode[i], input_dev->keybit);
clear_bit(0, input_dev->keybit);
set_bit(SW_LID, input_dev->swbit);
set_bit(SW_TABLET_MODE, input_dev->swbit);
set_bit(SW_HEADPHONE_INSERT, input_dev->swbit);
/*3.注册 input_dev */
err = input_register_device(corgikbd->input);
if (err)
goto fail;
mod_timer(&corgikbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
/*4.硬件相关的操作*/
/* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) {
pxa_gpio_mode(CORGI_GPIO_KEY_SENSE(i) | GPIO_IN);
/*注册中断*/
if (request_irq(CORGI_IRQ_GPIO_KEY_SENSE(i),corgikbd_interrupt,
IRQF_DISABLED | IRQF_TRIGGER_RISING,"corgikbd",corgikbd))
printk(KERN_WARNING "corgikbd:Can't get IRQ:%d!\n",i);
}
/* Set Strobe lines as outputs - set high */
for (i = 0; i < CORGI_KEY_STROBE_NUM; i++)
pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i)|GPIO_OUT|GPIO_DFLT_HIGH);
/* Setup the headphone jack as an input */
pxa_gpio_mode(CORGI_GPIO_AK_INT | GPIO_IN);
return 0;fail: input_free_device(input_dev);
kfree(corgikbd);
return err;
}
下面我们自己下符合输入子服务系统的程序
/*引脚描述结构体*/
struct pin_dec{
int irq;
char *name;
unsigned int pin;
unsigned int key_val;
};
/*定义的按键的四个引脚描述结构体数组*/
struct pin_dec pins_desc[4] = {
{IRQ_EINT1,"s1",S3C2410_GPF1, KEY_L},
{IRQ_EINT4,"s2",S3C2410_GPF4, KEY_S},
{IRQ_EINT2,"s3",S3C2410_GPF2, KEY_ENTER},
{IRQ_EINT0,"s4",S3C2410_GPF0, KEY_LEFTSHIFT},
};
/*定义一个定时器*/
static struct timer_list buttons_timer;
/*入口函数*/
static int buttons_init(void)
{
int i;
/*1.分配一个input_dev结构体*/
buttons_dev = input_allocate_device();
/*2.设置*/
/*2.1能产生的哪类事件*/
buttons_dev->evbit = BIT_MASK(EV_KEY)|BIT_MASK(EV_REP);
/*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.硬件相关的操作*/
init_timer(&buttons_timer); /*初始化定时器*/
[b]/*指定定时器中断的处理函数*/
buttons_timer.function = buttons_timer_function; [/b]
[b]/*增加一个定时器*/
add_timer(&buttons_timer);
for(i=0;i<4;i++){[/b]
/*注册中断*/
request_irq(pins_desc[i].irq,buttons_irq,IRQ_TYPE_EDGE_BOTH,pins_desc[i].name,
&pins_desc[i]);
}
return 0;
}
static irqreturn_t buttons_irq(int irq, void *dev_id){
/*10ms后启动定时器,消抖*/
irq_pd = (struct pin_dec*)dev_id;
/*修改定时器*/
mod_timer(&buttons_timer,jiffies+HZ/100);
return IRQ_RETVAL(IRQ_HANDLED);
}
/*定时器的处理函数*/
static void buttons_timer_function(unsigned long data)
{
struct pin_dec*pindesc = irq_pd;
unsigned int pinval;
pinval = s3c2410_gpio_getpin(pindesc->pin);
if(pinval){
/*上报事件*/
/*也可以用input_report_key([b]buttons_dev,pindesc->key_val,0)*/[/b]
[b]/*松开时*/[/b]
input_event(buttons_dev,EV_KEY,pindesc->key_val,0);
input_sync(buttons_dev);
}
else
{
[b]/*按下时*/[/b]
[b]/*也可以用input_report_key(buttons_dev,pindesc->key_val,1)*/
input_event(buttons_dev,EV_KEY,pindesc->key_val,1);
input_sync(buttons_dev);
}
}
[/b]
/*出口函数*/
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);
/*注销注册的buttons_dev*/
input_unregister_device(buttons_dev);
/*释放掉buttons_dev占用的内存*/
input_free_device(buttons_dev);
}
1.分配一个input_dev结构体,
2.设置input_dev。
3.注册input_dev结构体。
4.硬件相关的操作。
/*参考/keyboard/corgikbd.c*/
static int __init corgikbd_init(void)
{
return platform_driver_register(&corgikbd_driver);
}
static struct platform_driver corgikbd_driver = {
.probe = corgikbd_probe,
.remove = __devexit_p(corgikbd_remove),
.suspend = corgikbd_suspend,
.resume = corgikbd_resume,
.driver = {
.name = "corgi-keyboard",
.owner = THIS_MODULE,
},
};
static int __devinit corgikbd_probe(struct platform_device *pdev)
{
struct corgikbd *corgikbd;
struct input_dev *input_dev;
int i, err = -ENOMEM;
corgikbd = kzalloc(sizeof(struct corgikbd), GFP_KERNEL);
/*1.分配一个input_dev结构*/
input_dev = input_allocate_device();
if (!corgikbd || !input_dev)
goto fail;
platform_set_drvdata(pdev, corgikbd); corgikbd->input = input_dev;
spin_lock_init(&corgikbd->lock);
/* Init Keyboard rescan timer */
init_timer(&corgikbd->timer);
corgikbd->timer.function = corgikbd_timer_callback;
corgikbd->timer.data = (unsigned long) corgikbd;
/* Init Hinge Timer */
init_timer(&corgikbd->htimer);
corgikbd->htimer.function = corgikbd_hinge_timer;
corgikbd->htimer.data = (unsigned long) corgikbd;
corgikbd->suspend_jiffies=jiffies; (corgikbd->keycode, corgikbd_keycode, sizeof(corgikbd->keycode));
input_dev->name = "Corgi Keyboard";
input_dev->phys = "corgikbd/input0";
input_dev->id.bustype = BUS_HOST;
input_dev->id.vendor = 0x0001;
input_dev->id.product = 0x0001;
input_dev->id.version = 0x0100;
input_dev->dev.parent = &pdev->dev;
/*2.设置input_dev*/
/*2.1设置能产生哪些事件 Event types
*EV_KEY 定义为#define EV_KEY 0x01
*能产生按键类事件
*EV_REP 重复,当按下,不松时能产生多个值
*/
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) |
BIT_MASK(EV_PWR) | BIT_MASK(EV_SW);
input_dev->keycode = corgikbd->keycode;
input_dev->keycodesize = sizeof(unsigned char);
input_dev->keycodemax = ARRAY_SIZE(corgikbd_keycode);
/*2.2设置能产生这类事件的哪些事件*/
for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++)
set_bit(corgikbd->keycode[i], input_dev->keybit);
clear_bit(0, input_dev->keybit);
set_bit(SW_LID, input_dev->swbit);
set_bit(SW_TABLET_MODE, input_dev->swbit);
set_bit(SW_HEADPHONE_INSERT, input_dev->swbit);
/*3.注册 input_dev */
err = input_register_device(corgikbd->input);
if (err)
goto fail;
mod_timer(&corgikbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
/*4.硬件相关的操作*/
/* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) {
pxa_gpio_mode(CORGI_GPIO_KEY_SENSE(i) | GPIO_IN);
/*注册中断*/
if (request_irq(CORGI_IRQ_GPIO_KEY_SENSE(i),corgikbd_interrupt,
IRQF_DISABLED | IRQF_TRIGGER_RISING,"corgikbd",corgikbd))
printk(KERN_WARNING "corgikbd:Can't get IRQ:%d!\n",i);
}
/* Set Strobe lines as outputs - set high */
for (i = 0; i < CORGI_KEY_STROBE_NUM; i++)
pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i)|GPIO_OUT|GPIO_DFLT_HIGH);
/* Setup the headphone jack as an input */
pxa_gpio_mode(CORGI_GPIO_AK_INT | GPIO_IN);
return 0;fail: input_free_device(input_dev);
kfree(corgikbd);
return err;
}
下面我们自己下符合输入子服务系统的程序
/*引脚描述结构体*/
struct pin_dec{
int irq;
char *name;
unsigned int pin;
unsigned int key_val;
};
/*定义的按键的四个引脚描述结构体数组*/
struct pin_dec pins_desc[4] = {
{IRQ_EINT1,"s1",S3C2410_GPF1, KEY_L},
{IRQ_EINT4,"s2",S3C2410_GPF4, KEY_S},
{IRQ_EINT2,"s3",S3C2410_GPF2, KEY_ENTER},
{IRQ_EINT0,"s4",S3C2410_GPF0, KEY_LEFTSHIFT},
};
/*定义一个定时器*/
static struct timer_list buttons_timer;
/*入口函数*/
static int buttons_init(void)
{
int i;
/*1.分配一个input_dev结构体*/
buttons_dev = input_allocate_device();
/*2.设置*/
/*2.1能产生的哪类事件*/
buttons_dev->evbit = BIT_MASK(EV_KEY)|BIT_MASK(EV_REP);
/*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.硬件相关的操作*/
init_timer(&buttons_timer); /*初始化定时器*/
[b]/*指定定时器中断的处理函数*/
buttons_timer.function = buttons_timer_function; [/b]
[b]/*增加一个定时器*/
add_timer(&buttons_timer);
for(i=0;i<4;i++){[/b]
/*注册中断*/
request_irq(pins_desc[i].irq,buttons_irq,IRQ_TYPE_EDGE_BOTH,pins_desc[i].name,
&pins_desc[i]);
}
return 0;
}
static irqreturn_t buttons_irq(int irq, void *dev_id){
/*10ms后启动定时器,消抖*/
irq_pd = (struct pin_dec*)dev_id;
/*修改定时器*/
mod_timer(&buttons_timer,jiffies+HZ/100);
return IRQ_RETVAL(IRQ_HANDLED);
}
/*定时器的处理函数*/
static void buttons_timer_function(unsigned long data)
{
struct pin_dec*pindesc = irq_pd;
unsigned int pinval;
pinval = s3c2410_gpio_getpin(pindesc->pin);
if(pinval){
/*上报事件*/
/*也可以用input_report_key([b]buttons_dev,pindesc->key_val,0)*/[/b]
[b]/*松开时*/[/b]
input_event(buttons_dev,EV_KEY,pindesc->key_val,0);
input_sync(buttons_dev);
}
else
{
[b]/*按下时*/[/b]
[b]/*也可以用input_report_key(buttons_dev,pindesc->key_val,1)*/
input_event(buttons_dev,EV_KEY,pindesc->key_val,1);
input_sync(buttons_dev);
}
}
[/b]
/*出口函数*/
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);
/*注销注册的buttons_dev*/
input_unregister_device(buttons_dev);
/*释放掉buttons_dev占用的内存*/
input_free_device(buttons_dev);
}
相关文章推荐
- 输入服务子系统框架代码分析(韦东山的视频总结及针对linux-2.6.30.4)
- POLL机制分析(韦东山的视频总结及针对linux-2.6.30.4)
- linux中断机制及中断注册2(韦东山的视频总结及针对linux-2.6.30.4)
- arm驱动程序——手动设备节点 (韦东山的视频总结及针对linux-2.6.30.4)
- linux中断机制及中断注册1(韦东山的视频总结及针对linux-2.6.30.4)
- arm驱动程序——按键程序6_互斥—信号量(韦东山的视频总结及针对linux-2.6.30)
- linux 输入子系统(2)----简单实例分析系统结构(input_dev层)
- arm驱动程序——点亮led(韦东山的视频总结及针对linux-2.6.30)
- arm驱动程序——按键程序5_异步通信(韦东山的视频总结及针对linux-2.6.30)
- arm驱动程序——按键程序3_定时器消抖(韦东山的视频总结及针对linux-2.6.30)
- linux input输入子系统分析《三》:S3C2440的触摸屏驱动实例
- arm驱动程序——点亮led-利用次设备号(韦东山的视频总结及针对linux-2.6.30)
- linux input输入子系统分析《三》:S3C2440的触摸屏驱动实例
- linux驱动—input输入子系统—The simplest example(一个最简单的实例)分析(1)
- linux驱动—input输入子系统—The simplest example(一个最简单的实例)分析(2)
- linux input输入子系统分析《三》:S3C2440的触摸屏驱动实例
- arm驱动程序——按键程序2(韦东山的视频总结及针对linux-2.6.30)
- arm驱动程序——按键程序2(韦东山的视频总结及针对linux-2.6.30)
- arm驱动程序——按键程序6_互斥—信号量(韦东山的视频总结及针对linux-2.6.30)
- arm驱动程序——按键程序1(韦东山的视频总结及针对linux-2.6.30)