📄 kdriver.c
字号:
/* * $Id: khello-driver.c,v 0.01 2008/10/01 $ * * Copyright (c) 2005-2008 69zsx * * Based on the work of: * vojtech Exp *//* * scan keyboard driver for Linux/arm/at91rm9200 *//* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */#include <linux/kernel.h>#include <linux/init.h>#include <linux/module.h>#include <linux/input.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <linux/timer.h>#include <linux/wait.h>#include <asm/irq.h>//#include <asm/arch/AT91RM9200_SYS.h>#include <asm/arch-at91rm9200/hardware.h>#include <asm/delay.h>#include <asm/uaccess.h>#define KB_ROWS 4#define KB_COLS 5#define KB_ROWMASK(r) (1 << (r))#define SCANCODE(r,c) ( ((r)<<2) + (c) + r )#define NR_SCANCODES 20#define SCAN_INTERVAL (HZ/10)#define SCAN_KBD_PRESSED 1MODULE_DESCRIPTION("at91rm9200 keyboard module");MODULE_AUTHOR("69zsx");MODULE_LICENSE("GPL");static unsigned long kbd_status = 0;/*static unsigned char scan_kbd_keycode[20] = { [0] = KEY_DOWN, [1] = KEY_UP, [2] = KEY_3, [3] = KEY_6, [4] = KEY_9, [5] = 0, [6] = KEY_0, [7] = KEY_2, [8] = KEY_5, [9] = KEY_8, [10] = 0, [11] = 0, [12] = KEY_1, [13] = KEY_4, [14] = KEY_7, [15] = 0, [16] = KEY_BACKSPACE, [17] = KEY_ESC, [18] = KEY_ENTER, [19] = KEY_DOT,};*//*static unsigned char scan_kbd_keycode[20] = { 0,KEY_1,KEY_2,KEY_ESC,KEY_ENTER, KEY_DOWN,KEY_UP,KEY_9,KEY_6,KEY_3, 0,KEY_0,KEY_8,KEY_5,KEY_2, 0,0,KEY_7,KEY_4,KEY_1,};*///转换后的键码CHANGE: 1 PRINT: 2static unsigned char scan_kbd_keycode[20] = { [0] = 0, [1] = KEY_TAB, [2] = KEY_TAB, [3] = KEY_ESC, [4] = KEY_ENTER, [5] = KEY_DOWN, [6] = KEY_UP, [7] = KEY_9, [8] = KEY_6, [9] = KEY_3, [10] = 0, [11] = KEY_0, [12] = KEY_8, [13] = KEY_5, [14] = KEY_2, [15] = 0, [16] = 0, [17] = KEY_7, [18] = KEY_4, [19] = KEY_1,};struct scankbd { unsigned char keycode[20]; struct input_dev scan_kbd_dev; char phys[32]; unsigned char state[20]; spinlock_t lock; struct timer_list scan_timer; };struct scankbd *scankbd_dev;static void handle_scancode(unsigned int pressed,unsigned int scancode, struct scankbd *scankbd_data){//pressed = 0 if (pressed && !(scankbd_data->state[scancode] & SCAN_KBD_PRESSED)) { scankbd_data->state[scancode] |= SCAN_KBD_PRESSED;//1 input_report_key(&scankbd_data->scan_kbd_dev, scankbd_data->keycode[scancode], 1); printk(KERN_ALERT "keycode %i\n", scankbd_data->keycode[scancode]); } else if (!pressed && scankbd_data->state[scancode] & SCAN_KBD_PRESSED) { scankbd_data->state[scancode] &= ~SCAN_KBD_PRESSED;// //input_report_key(&scankbd_data->scan_kbd_dev, scankbd_data->keycode[scancode], 0); printk(KERN_ALERT "keycode %i\n", scankbd_data->keycode[scancode]); }}static char *scan_kbd_name = "scan 4*5 keyboard";static char *scan_kbd_phys = "scankbd";unsigned int readr;/* Helper functions for reading the keyboard matrix * Note: We should really be using pxa_gpio_mode to alter GPDR but it * requires a function call per GPIO bit which is excessive * when we need to access 12 bits at once multiple times. * These functions must be called within local_irq_save()/local_irq_restore() * or similar. */void KBD_CLOSE_INT(void){//interrupt enable register IER/interrupt disable register IDR AT91_SYS->PIOB_IER &= ~( AT91C_PIO_PB9 | AT91C_PIO_PB10 | AT91C_PIO_PB11 | AT91C_PIO_PB12 );// AT91_SYS->PIOB_IDR |= ( AT91C_PIO_PB9 | AT91C_PIO_PB10 | AT91C_PIO_PB11 | AT91C_PIO_PB12 );} unsigned char ISKBD_DOWN(void){ unsigned int status = AT91C_PIO_PB9 | AT91C_PIO_PB10 | AT91C_PIO_PB11 | AT91C_PIO_PB12; if( (AT91_SYS->PIOB_PDSR & status) != status)//pin data status register return 1; else return 0;} void KBD_OPEN_INT(void){ AT91_SYS->PIOB_IER |= ( AT91C_PIO_PB9 | AT91C_PIO_PB10 | AT91C_PIO_PB11 | AT91C_PIO_PB12 ); AT91_SYS->PIOB_IDR &= ~( AT91C_PIO_PB9 | AT91C_PIO_PB10 | AT91C_PIO_PB11 | AT91C_PIO_PB12 );}void scan_kbd_discharge_all(void){//all set high// at91_set_gpio_value(AT91_PIN_PB1,0);// at91_set_gpio_value(AT91_PIN_PB2,0);// at91_set_gpio_value(AT91_PIN_PB6,0);// at91_set_gpio_value(AT91_PIN_PA24,0); at91_set_gpio_value(AT91_PIN_PB7,0); at91_set_gpio_value(AT91_PIN_PB8,0); at91_set_gpio_value(AT91_PIN_PB15,0); at91_set_gpio_value(AT91_PIN_PB16,0); at91_set_gpio_value(AT91_PIN_PB17,0);}static inline void scan_kbd_activate_all(void){// at91_set_gpio_value(AT91_PIN_PB1,1);// at91_set_gpio_value(AT91_PIN_PB2,1);// at91_set_gpio_value(AT91_PIN_PB6,1);// at91_set_gpio_value(AT91_PIN_PA24,1); at91_set_gpio_value(AT91_PIN_PB7,1); at91_set_gpio_value(AT91_PIN_PB8,1); at91_set_gpio_value(AT91_PIN_PB15,1); at91_set_gpio_value(AT91_PIN_PB16,1); at91_set_gpio_value(AT91_PIN_PB17,1);}static inline int GET_ROWS_STATUS(int col){//read all rows'status /* int rd=0; int rd_t=0; rd = at91_get_gpio_value(AT91_PIN_PB1); rd_t |= !rd; rd = at91_get_gpio_value(AT91_PIN_PB2); rd_t |= (!rd)<<1; rd = at91_get_gpio_value(AT91_PIN_PB6); rd_t |= (!rd)<<2; rd = at91_get_gpio_value(AT91_PIN_PA24); rd_t |= (!rd)<<3; //printk(KERN_ALERT "rd %i\n", rd_t);*/ //udelay(10); unsigned int rd=0xf; unsigned int rd_t=0; rd_t |= rd & at91_get_gpio_value(AT91_PIN_PA24); rd_t |= rd & (at91_get_gpio_value(AT91_PIN_PB1)<<1); rd_t |= rd & (at91_get_gpio_value(AT91_PIN_PB2)<<2); rd_t |= rd & (at91_get_gpio_value(AT91_PIN_PB6)<<3); rd_t = ~rd_t & 0xf; //printk(KERN_ALERT "rd %i\n", rd_t); return rd_t;}static inline void scan_kbd_activate_col(int col){//Set one col is 0 switch(col) { case 0: at91_set_gpio_value(AT91_PIN_PB7,1); break; case 1: at91_set_gpio_value(AT91_PIN_PB8,1); break; case 2: at91_set_gpio_value(AT91_PIN_PB15,1); break; case 3: at91_set_gpio_value(AT91_PIN_PB16,1); break; case 4: at91_set_gpio_value(AT91_PIN_PB17,1); break; }}static inline void scan_kbd_reset_col(int col){//reset cols 1 switch(col) { case 0: at91_set_gpio_value(AT91_PIN_PB7,0); break; case 1: at91_set_gpio_value(AT91_PIN_PB8,0); break; case 2:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -