📄 s3c2410_kbd_m6x6.c
字号:
#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 233static 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 %d\n", 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 number\n"); 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");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -