📄 key_dev.c
字号:
/*----------------------------------------------------------- * key_dev.c * micro keyboard driver with interrupt mode * copyright(C) jilin huafeng * up_key : port GPB0 * down_key : port GPB1 * left_key : port GPB9 * right_key : port GPB10 * confirm_key : port GPF1 * cancel_key : port GPF2 * key_press_interrupt : EINT5 *-----------------------------------------------------------*/#include <linux/module.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/timer.h>#include <linux/interrupt.h>#include <asm/irq.h>#include <asm/hardware.h>#include <asm/uaccess.h>#include <asm/arch/irqs.h>#include <asm/io.h>#include <asm/semaphore.h> #include <linux/major.h>#include <linux/vmalloc.h>#include <linux/fs.h>#include <linux/poll.h>static DECLARE_WAIT_QUEUE_HEAD( keys_wait );#define MICRO_KEY_MAJOR 138 //key_dat : x x x x x right left x x x x x cancel confirm down up// 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0#define NOKEY 0#define RIGHT_KEY 0x04000#define LEFT_KEY 0x02000#define UP_KEY 0x00001#define DOWN_KEY 0x00002#define CONFIRM_KEY 0x00004#define CANCEL_KEY 0x00008static struct semaphore key_sem;static char key = NOKEY;unsigned long gpfdat, gpfup, gpfcon;unsigned long gpbdat, gpbup, gpbcon;devfs_handle_t devfs_microkey;static void microkey_clearirq( void ){ /*respond to EINT5*/ SRCPND &= ( ~0x00000010 ); //bit4 INTPND = INTPND; EINTPEND &= ( ~0x00000020 ); //bit5}void delay(){ int i, j; for( i = 0; i < 10000; i++ ) { for( j = 0; j < 100; j++ ); }}static void microkey_irq_isr( int irq, void *dev_id, struct pt_regs *regs ){ unsigned long f_dat, b_dat, k_dat; printk( "key pressed\n" ); f_dat = ( *( volatile unsigned long * )gpfdat ); b_dat = ( *( volatile unsigned long * )gpbdat ); k_dat = ( f_dat << 1 ) | b_dat; k_dat = ~k_dat; k_dat &= 0x060f; switch( k_dat ) { case 0x0400: key = RIGHT_KEY;printk("right key\n"); break; case 0x0200: key = LEFT_KEY;printk("left key\n"); break; case 0x0008: key = CANCEL_KEY;printk("cancel key\n"); break; case 0x0004: key = CONFIRM_KEY;printk("confirm key\n"); break; case 0x0002: key = DOWN_KEY;printk("down key\n"); break; case 0x0001: key = UP_KEY;printk("up key\n"); break; default: key = NOKEY; break; } microkey_clearirq(); up( &key_sem );}static ssize_t microkey_read( struct inode *inode, char *buf, unsigned long count ){ if( key != NOKEY ) { down_interruptible( &key_sem ); put_user( key, buf ); key = NOKEY; return 1; } else { return 0; }}int microkey_open( struct inode *inode, struct file *file ){ sema_init( &key_sem, 0 ); return 0;}void microkey_release( struct inode *inode, struct file *filp ){ printk( "release ok!\n" ); return;}static unsigned int microkey_poll( struct file *file, poll_table *wait ){ //always ready return POLLIN | POLLRDNORM;}struct file_operations microkey_fops ={ read : microkey_read, open : microkey_open, release : microkey_release, poll : microkey_poll,};static int __init microkey_init(void){ static int rc; set_external_irq( IRQ_EINT5, EXT_FALLING_EDGE, GPIO_PULLUP_DIS ); //map port f config register address gpfcon = ioremap( 0x56000050, 4 ); //set port f io status: gpf1/2 : input(00), gpf5:10(EINT5) ( *( volatile unsigned long * )gpfcon ) &= 0xfbc3; //bit1,2 = 00, bit5 = 10 //map port f data register address gpfdat = ioremap( 0x56000054, 4 ); //map port b config register address gpbcon = ioremap( 0x56000010, 4 ); //set port b io status: gpb0/1/9/10 : input(00) ( *( volatile unsigned long * )gpbcon ) &= 0xffc3fff0; //bit0/1/9/10 = 00 //map port b data register address gpbdat = ioremap( 0x56000014, 4 ); disable_irq( IRQ_EINT5 ); enable_irq( IRQ_EINT5 ); rc = request_irq( IRQ_EINT5, microkey_irq_isr, SA_INTERRUPT, "microkey", NULL ); if( rc ) { printk( "<1>microkey irq 5 irq not registered. Error: %d\n", rc ); } printk("*********key_dev init ok!***********\n"); /* Register myirq as character device */ devfs_microkey = devfs_register( NULL, "microkey", DEVFS_FL_DEFAULT, MICRO_KEY_MAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, µkey_fops, NULL ); return 0;}static void __exit microkey_exit(void){ disable_irq( IRQ_EINT5 ); free_irq( IRQ_EINT5, microkey_irq_isr ); devfs_unregister( devfs_microkey );}module_init( microkey_init );module_exit( microkey_exit );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -