input子系统

s5pc_gpio_dvr:

#include<linux/init.h>
#include<linux/module.h>
#include<asm/io.h>
#include<linux/irqreturn.h>
#include<linux/slab.h>
#include<linux/input.h>
#include<linux/interrupt.h>
#include<linux/platform_device.h>
#include"gpio.h"

/*构建一个本地结构体*/
struct gpio_device{
struct input_dev *s5pc_input;
void __iomem *gpio_base;
};

static struct gpio_device *s5pc_gpio_dev;

static irqreturn_t buttons_irq(int irq,void *dev_id)
{
unsigned long val;
struct button_key *cur_button=(struct button_key *)dev_id;

/*1.判断是按下还是松开*/
val=readl(s5pc_gpio_dev->gpio_base+0x04)&(0x1<<cur_button->pin_bit);//读GPH0DAT寄存器里面的数据
if(val){
//松开,提交松开事件 1-表示按下 0-表示松开
input_event(s5pc_gpio_dev->s5pc_input,cur_button->type,cur_button->code,0);
input_sync(s5pc_gpio_dev->s5pc_input);
}else{
//按下,提交按下事件
input_event(s5pc_gpio_dev->s5pc_input,cur_button->type,cur_button->code,1);
input_sync(s5pc_gpio_dev->s5pc_input);
}
return IRQ_HANDLED;
}

static int gpio_probe(struct platform_device *pdev)
{
int ret;
int i;
struct resource *res;
struct gpio_platdata *pdata;
struct button_key *button;
int type;

s5pc_gpio_dev=kmalloc(sizeof(struct gpio_device), GFP_KERNEL);
if(s5pc_gpio_dev==NULL){
dev_err(&pdev->dev,"no memory for alloc!\n");
return -ENOMEM;
}

/*1.获取平台数据资源*/
pdata =pdev->dev.platform_data;
if(pdata==NULL){
dev_err(&pdev->dev,"no platform data!\n");
ret =-EFAULT;
goto output0;
}

/*获取IO内存地址资源*/
res =platform_get_resource(pdev,IORESOURCE_MEM,0);
s5pc_gpio_dev->gpio_base=ioremap(res->start, res->end-res->start+1);

/*2.构建一个struct input_dev*/
/*3.分配空间*/
s5pc_gpio_dev->s5pc_input=input_allocate_device();
if(!s5pc_gpio_dev->s5pc_input){
dev_err(&pdev->dev,"no memory for alloc!\n");
ret =-ENOMEM;
goto outpout1;
}

for(i=0;i<pdata->num_buttons;i++){
button =&pdata->buttons[i];
if(button==NULL)
continue;

type =button->type?button->type:EV_KEY;

/*4.设置input_dev*/
/*4.1 设置input_dev能产生哪类事件*/
//__set_bit(type,s5pc_gpio_dev->s5pc_input->evbit);
set_bit(type, s5pc_gpio_dev->s5pc_input->evbit);

/*4.2 设置input_dev能产生哪些事件*/
set_bit(button->code,s5pc_gpio_dev->s5pc_input->keybit);

printk("%s():%d----%d\n",__func__,__LINE__,button->irq);

/*4.3 硬件相关的操作*/
/*4.3.1 注册中断*/
ret=request_irq(button->irq, buttons_irq, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,button->name, button);
if(ret){
dev_err(&pdev->dev,"request irq failed %d\n",button->irq);
ret =-EINVAL;
goto outpout2;
}
}

/*5.注册input_dev*/
ret=input_register_device(s5pc_gpio_dev->s5pc_input);
if (ret) {
dev_err(&pdev->dev, "Unable to register input device, error\n");
goto output3;
}

platform_set_drvdata(pdev, pdata); //dev->p->driver_data = pdata;

return 0;

output3:
input_free_device(s5pc_gpio_dev->s5pc_input);
outpout2:
while(i--)
free_irqbutton(->irq, button);
outpout1:
output0:
kfree(s5pc_gpio_dev);
return ret;
}

static int gpio_remove(struct platform_device *pdev)
{
int i;
struct gpio_platdata *pdata =platform_get_drvdata(pdev); //pdata=dev->p->driver_data
input_free_device(s5pc_gpio_dev->s5pc_input);
for(i=0;i<pdata->num_buttons;i++){
free_irq(pdata->buttons[i].irq, &pdata->buttons[i]);
}
input_unregister_device(s5pc_gpio_dev->s5pc_input);
kfree(s5pc_gpio_dev);
return 0;
}

struct platform_driver s5pc_gpio_driver={
.probe =gpio_probe,
.remove =gpio_remove,
.driver ={
.owner =THIS_MODULE,
.name ="s5pc-gpio",
},
};

static int __init s5pc_gpio_drv_init(void)
{
platform_driver_register(&s5pc_gpio_driver);
return 0;
}

static void __exit s5pc_gpio_drv_exit(void)
{
platform_driver_unregister(&s5pc_gpio_driver);
}

module_init(s5pc_gpio_drv_init);
module_exit(s5pc_gpio_drv_exit);
MODULE_LICENSE("GPL");

 

 gpio_dev.c:

#include<linux/init.h>
#include<linux/module.h>
#include<linux/ioport.h>
#include<linux/input.h>
#include<mach/irqs.h>
#include<linux/platform_device.h>
#include"gpio.h"

struct resource s5pc_gpio_resource[]={
[0] ={
.start =S5PC100_PA_BUTTON,
.end =S5PC100_PA_BUTTON +SZ_8 -1,
.flags =IORESOURCE_MEM,
},
};

struct button_key s5pc_buttons[]={
[0]={
.type =EV_KEY,
.code =KEY_1,
.name ="k1",
//.gpio =S5PC100_GPH0(1);
.irq =IRQ_EINT(1),
.pin_bit =1,
},
[1]={
.type =EV_KEY,
.code =KEY_2,
.name ="k2",
//.gpio =S5PC100_GPH0(2);
.irq =IRQ_EINT(2),
.pin_bit=2,
},
[2]={
.type =EV_KEY,
.code =KEY_3,
.name ="k3",
//.gpio =S5PC100_GPH0(3);
.irq =IRQ_EINT(3),
.pin_bit=3,
},
[3]={
.type =EV_KEY,
.code =KEY_4,
.name ="k4",
//.gpio =S5PC100_GPH0(4);
.irq =IRQ_EINT(4),
.pin_bit=4,
},
[4]={
.type =EV_KEY,
.code =KEY_5,
.name ="k5",
//.gpio =S5PC100_GPH0(6);
.irq =IRQ_EINT(6),
.pin_bit=6,
},
[5]={
.type =EV_KEY,
.code =KEY_6,
.name ="k6",
//.gpio =S5PC100_GPH0(7);
.irq =IRQ_EINT(7),
.pin_bit=7,
},
};

struct gpio_platdata s5pc_gpio_cfg ={
.buttons =s5pc_buttons,
.num_buttons =6,
};

static void gpio_release(struct device *dev)
{

}

struct platform_device s5pc_gpio_device={
.name ="s5pc-gpio",
.id =-1,
.num_resources =ARRAY_SIZE(s5pc_gpio_resource),
.resource =s5pc_gpio_resource,
.dev ={
.release =gpio_release,
.platform_data =&s5pc_gpio_cfg,
},
};

static int __init s5pc_gpio_dev_init(void)
{
platform_device_register(&s5pc_gpio_device);
return 0;
}

static void __exit s5pc_gpio_dev_exit(void)
{
platform_device_unregister(&s5pc_gpio_device);
}

module_init(s5pc_gpio_dev_init);
module_exit(s5pc_gpio_dev_exit);
MODULE_LICENSE("GPL");

 

 

test:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <linux/input.h>

int main(int argc,char **argv)
{
int fd;
struct input_event *input;
fd =open("/dev/event0",O_RDWR);
if(fd<0){
perror("open failed");
exit(1);
}

input=malloc(sizeof(struct input_event));

if(read(fd,input,sizeof(struct input_event))!=sizeof(struct input_event)){
perror("read failed");
exit(1);
}
printf("type =%d\n",input->type);

switch(input->code){
case KEY_1:
if(input->value){
printf("k1 pressed!\n");
}else{
printf("k1 released!\n");
}
break;
case KEY_2:
if(input->value){
printf("k2 pressed!\n");
}else{
printf("k2 released!\n");
}
break;
case KEY_3:
if(input->value){
printf("k3 pressed!\n");
}else{
printf("k3 released!\n");
}
break;
case KEY_4:
if(input->value){
printf("k4 pressed!\n");
}else{
printf("k4 released!\n");
}
break;
case KEY_5:
if(input->value){
printf("k5 pressed!\n");
}else{
printf("k5 released!\n");
}
break;
case KEY_6:
if(input->value){
printf("k6 pressed!\n");
}else{
printf("k6 released!\n");
}
break;
}

close(fd);
return 0;
}

 

 

gpio.h:

#ifndef __ASM_ARM_GPIO_H
#define __ASM_ARM_GPIO_H

#define S5PC100_PA_BUTTON 0xE0300C00
#define SZ_8 0x00000008

/*封装一个按键结构体*/
struct button_key{
int type; //事件类型
int code; //事件码
char *name; //名字
//int gpio; //管脚
int irq;
int pin_bit;
};

/*封装一个平台数据结构体*/
struct gpio_platdata{
struct button_key *buttons;
int num_buttons;
};

#endif

 

posted on 2013-12-26 21:52  weat  阅读(449)  评论(0编辑  收藏  举报