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