交叉编译是arm-linux-gcc 4.4.1 内核是linux-2.6.28.6
#include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/input.h> #include <linux/poll.h> #include <linux/irq.h> #include <asm/irq.h> #include <asm/io.h> #include <linux/interrupt.h> #include <asm/uaccess.h> #include <mach/hardware.h> #include <linux/platform_device.h> #include <linux/cdev.h> #include <linux/miscdevice.h> #include <mach/map.h>
#include <plat/gpio-cfg.h> #include <plat/regs-clock.h> #include <plat/regs-gpio.h> #include <mach/gpio.h>
#include <plat/gpio-bank-n.h>
MODULE_AUTHOR("HaNdAEr"); MODULE_LICENSE("GPL");
struct input_dev* button_devp; static char *name = "s3c6410_buttons";
struct button_irq_desc{ int irq; //int pin; int number; char *name; };
static struct button_irq_desc button_irqs[] = { { IRQ_EINT(0), /*S3C64XX_GPN(0), */ 0, "KEY1"}, { IRQ_EINT(1), /*S3C64XX_GPN(1), */ 1, "KEY2"}, { IRQ_EINT(2), /*S3C64XX_GPN(2), */ 2, "KEY3"}, { IRQ_EINT(3), /*S3C64XX_GPN(3), */ 3, "KEY4"}, { IRQ_EINT(4), /*S3C64XX_GPN(4), */ 4, "KEY5"}, { IRQ_EINT(5), /*S3C64XX_GPN(5), */ 5, "KEY6"}, { IRQ_EINT(19), /*S3C64XX_GPL(11),*/ 11, "KEY7"}, { IRQ_EINT(20), /*S3C64XX_GPL(12),*/ 12, "KEY8"}, };
static irqreturn_t button_interrupt(int irq, void* dev_id) {
struct button_irq_desc *button_irqs = (struct button_irq_desc*)dev_id; int updown,reportval; if(button_irqs->number <0){ return -1; }
if(button_irqs->number <=5){ updown = readl(S3C64XX_GPNDAT) & ( 0x1 << button_irqs->number); }
if(button_irqs->number == 11 || button_irqs->number == 12){ updown = readl(S3C64XX_GPLDAT) & ( 0x1 << button_irqs->number); }
reportval = updown ? 0 : 1;
switch(button_irqs->number) { case IRQ_EINT(0): input_report_key(button_devp, BTN_0, reportval); break; case IRQ_EINT(1): input_report_key(button_devp, BTN_1, reportval); break; case IRQ_EINT(2): input_report_key(button_devp, BTN_2, reportval); break; case IRQ_EINT(3): input_report_key(button_devp, BTN_3, reportval); break; case IRQ_EINT(4): input_report_key(button_devp, BTN_4, reportval); break; case IRQ_EINT(5): input_report_key(button_devp, BTN_5, reportval); break; case IRQ_EINT(19): input_report_key(button_devp, BTN_6, reportval); break; case IRQ_EINT(20): input_report_key(button_devp, BTN_7, reportval); break; default: break; } input_sync(button_devp); return IRQ_RETVAL(IRQ_HANDLED);
}
static int __init button_init(void) { int i; int err = 0; int ret = 0;
struct input_dev *input_dev;
input_dev = input_allocate_device(); if(!input_dev){ printk(KERN_ERR"Unable to alloc the input device!!\n"); }
button_devp = input_dev;
/*
button_devp->evbit[0] = BIT(EV_KEY) | BIT(EV_SYN); button_devp->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0) | BIT_MASK(BTN_1) | BIT_MASK(BTN_2) | BIT_MASK(BTN_3) | BIT_MASK(BTN_4) | BIT_MASK(BTN_5) | BIT_MASK(BTN_6) | BIT_MASK(BTN_7);
*/
button_devp->name = name; for(i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) { err = request_irq(button_irqs[i].irq, button_interrupt, IRQ_TYPE_EDGE_BOTH, button_irqs[i].name, (void *)&button_irqs[i]); if(err) { break; } }
if(err) { i--; for(; i >= 0; i--) { if(button_irqs[i].irq < 0) { continue; } disable_irq(button_irqs[i].irq); free_irq(button_irqs[i].irq, (void*)&button_irqs[i]); } return -EBUSY; }
set_bit(EV_KEY, button_devp->evbit); set_bit(BTN_0, button_devp->keybit); set_bit(BTN_1, button_devp->keybit); set_bit(BTN_2, button_devp->keybit); set_bit(BTN_3, button_devp->keybit); set_bit(BTN_4, button_devp->keybit); set_bit(BTN_5, button_devp->keybit); set_bit(BTN_6, button_devp->keybit); set_bit(BTN_7, button_devp->keybit); ret = input_register_device(button_devp); if(ret < 0){ printk("input_register_device(): failed !! \n"); }
return ret; }
static void __exit button_exit(void) { int i; for(i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) { disable_irq(button_irqs[i].irq); free_irq(button_irqs[i].irq, (void*)&button_irqs[i]); } input_unregister_device(button_devp); }
module_init(button_init); module_exit(button_exit);
测试函数:
#include <sys/ioctl.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/select.h> #include <sys/time.h> #include <errno.h> #include <linux/input.h>
int main(void) { struct input_event ievent; int fd = open("/dev/input/event1",O_RDWR ); if(fd < 0){ printf("Unable open /dev/input/event0\n"); return -1; } while(1){ if(read(fd, &ievent, sizeof(struct input_event)) < 0); return -1; if(ievent.type == EV_KEY){ switch(ievent.code){ case BTN_0: ievent.value ? printf("key1 is pressed!\n"):printf("key1 is released!!\n"); break; case BTN_1: ievent.value ? printf("key2 is pressed!\n"):printf("key2 is released!!\n"); break; case BTN_2: ievent.value ? printf("key3 is pressed!\n"):printf("key3 is released!!\n"); break; case BTN_3: ievent.value ? printf("key4 is pressed!\n"):printf("key4 is released!!\n"); break; case BTN_4: ievent.value ? printf("key5 is pressed!\n"):printf("key5 is released!!\n"); break; case BTN_5: ievent.value ? printf("key6 is pressed!\n"):printf("key6 is released!!\n"); break; case BTN_6: ievent.value ? printf("key7 is pressed!\n"):printf("key7 is released!!\n"); break; case BTN_7: ievent.value ? printf("key8 is pressed!\n"):printf("key8 is released!!\n"); break; } } } close(fd); return 0; } |