matrix6_kbd_m6x6.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:5k
- #include <linux/config.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/miscdevice.h>
- #include <linux/sched.h>
- #include <linux/delay.h>
- #include <linux/poll.h>
- #include <linux/spinlock.h>
- #include <linux/irq.h>
- #include <linux/delay.h>
- #include <asm/hardware.h>
- #define DEVICE_NAME "kbd_m6x6"
- #define BUTTON_MAJOR 233
- static int irq_col_tab[] = { IRQ_EINT16, IRQ_EINT19, IRQ_EINT14, IRQ_EINT15, IRQ_EINT11, IRQ_EINT13 };
- #define COL_NUM ( (sizeof irq_col_tab) / sizeof (irq_col_tab[0]) )
- static unsigned gpio_col_tab[] = {GPIO_G8, GPIO_G11, GPIO_G6, GPIO_G7, GPIO_G3, GPIO_G5};
- static unsigned gpio_row_tab[] = { GPIO_B1, GPIO_B0, GPIO_F4, GPIO_F0, GPIO_F6, GPIO_F5 };
- #define ROW_NUM ( sizeof gpio_row_tab / sizeof (gpio_row_tab[0]) )
- static int ready = 0;
- static int key_value = 0, last_value = 0;
- static DECLARE_WAIT_QUEUE_HEAD(buttons_wait);
- static int waitting_down_tab[] = {1, 1, 1, 1, 1, 1};
- static void buttons_irq(int irq, void *dev_id, struct pt_regs *reg)
- {
- int i;
- int col_no = -1, row_no = -1;
- unsigned long flags;
- local_irq_save(flags);
- for (i = 0; i < COL_NUM; i++) {
- if (irq_col_tab[i] == irq) {
- col_no = i;
- break;
- }
- }
- if (col_no < 0) {
- goto EXIT;
- }
- if (waitting_down_tab[col_no]) {
- for (i = 0; i < COL_NUM; i++) {
- set_gpio_ctrl(gpio_col_tab[i] | GPIO_PULLUP_DIS | GPIO_MODE_IN);
- }
- udelay(300);
- for (i = 0; i < ROW_NUM; i++) {
- int r;
- write_gpio_bit(gpio_row_tab[i], 1);
- udelay(300);
- r = read_gpio_bit(gpio_col_tab[col_no]);
- write_gpio_bit(gpio_row_tab[i], 0);
- if (r) { // found
- row_no = i;
- break;
- }
- }
- udelay(300);
- for (i = 0; i < COL_NUM; i++) {
- set_gpio_ctrl(gpio_col_tab[i] | GPIO_PULLUP_DIS | GPIO_MODE_ALT0);
- }
- if (col_no < 0 || row_no < 0) {
- goto EXIT;
- }
- key_value = row_no * 6 + col_no + 1;
- } else {
- key_value = last_value | 0x80;
- }
- waitting_down_tab[col_no] = !waitting_down_tab[col_no];
- set_external_irq(irq, waitting_down_tab[col_no]? EXT_LOWLEVEL: EXT_HIGHLEVEL, GPIO_PULLUP_DIS);
- udelay(300);
- ready = 1;
- wake_up_interruptible(&buttons_wait);
- EXIT:
- restore_flags(flags);
- }
- static void buttons_io_port_init(void)
- {
- int i;
- for (i = 0; i < ROW_NUM; i ++) {
- unsigned gpio = gpio_row_tab[i];
- set_gpio_ctrl(gpio | GPIO_PULLUP_DIS | GPIO_MODE_OUT);
- write_gpio_bit(gpio, 0);
- }
- }
- static int matrix4_buttons_read(struct file * file, char * buffer, size_t count, loff_t *ppos)
- {
- static int key;
- int repeat = key == key_value;
- key == key_value;
- if (!ready)
- return -EAGAIN;
- if (count != sizeof key_value)
- return -EINVAL;
- if (repeat) {
- return -EAGAIN;
- }
- copy_to_user(buffer, &key_value, sizeof key_value);
- last_value = key_value;
- ready = 0;
- return sizeof key_value;
- }
- static unsigned int matrix4_buttons_select(
- struct file *file,
- struct poll_table_struct *wait)
- {
- if (ready)
- return 1;
- poll_wait(file, &buttons_wait, wait);
- return 0;
- }
- static int matrix4_buttons_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
- {
- switch(cmd) {
- default:
- return -EINVAL;
- }
- }
- static struct file_operations matrix4_buttons_fops = {
- owner: THIS_MODULE,
- ioctl: matrix4_buttons_ioctl,
- poll: matrix4_buttons_select,
- read: matrix4_buttons_read,
- };
- static int request_irqs(void)
- {
- int i;
- for (i = 0; i < COL_NUM; i++) {
- int irq = irq_col_tab[i];
- int ret = request_irq(irq, &buttons_irq, SA_INTERRUPT, DEVICE_NAME, &buttons_irq);
- if (ret) {
- unregister_chrdev(BUTTON_MAJOR, DEVICE_NAME);
- printk(DEVICE_NAME " can't request irq %dn", irq);
- return ret;
- }
- }
- }
- static void free_irqs(void)
- {
- int i;
- for (i = 0; i < COL_NUM; i++) {
- int irq = irq_col_tab[i];
- free_irq(irq, buttons_irq);
- }
- }
- static devfs_handle_t devfs_handle;
- static int __init matrix4_buttons_init(void)
- {
- int ret;
- int i;
- ready = 0;
- ret = register_chrdev(BUTTON_MAJOR, DEVICE_NAME, &matrix4_buttons_fops);
- if (ret < 0) {
- printk(DEVICE_NAME " can't register major numbern");
- return ret;
- }
- buttons_io_port_init();
-
- for (i = 0; i < COL_NUM; i++) {
- int irq = irq_col_tab[i];
- set_external_irq(irq, EXT_LOWLEVEL, GPIO_PULLUP_DIS);
- }
- ret = request_irqs();
- if (ret) {
- return ret;
- }
- devfs_handle = devfs_register(NULL, DEVICE_NAME, DEVFS_FL_DEFAULT,
- BUTTON_MAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR, &matrix4_buttons_fops, NULL);
- return 0;
- }
- static void __exit matrix4_buttons_exit(void)
- {
- devfs_unregister(devfs_handle);
- free_irqs();
- unregister_chrdev(BUTTON_MAJOR, DEVICE_NAME);
- }
- module_init(matrix4_buttons_init);
- module_exit(matrix4_buttons_exit);
- MODULE_LICENSE("GPL");