⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 keypad.c

📁 嵌入式linux系统下hi3510平台的osd开发源码
💻 C
字号:
/*  * extdrv/peripheral/keypad/keypad.c * * Copyright (c) 2006 Hisilicon Co., Ltd.  * * 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 * *  * History:  *      10-April-2006 create this file */#include <linux/config.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/sched.h>#include <linux/delay.h>#include <linux/string.h>#include <linux/poll.h>#include <linux/interrupt.h>#include <linux/timer.h>#include <linux/miscdevice.h>#include <asm/hardware.h>#include <asm/irq.h>#include <asm/uaccess.h>#include <asm/io.h>#include "keypad.h"#include "hi_gpio.h"static unsigned int 	  watch_dog = 0; 	static   DECLARE_WAIT_QUEUE_HEAD(keypad_wait);int             	  ready = 0;static int      	  key_value = 0; int             	  keypad_rx_buf[BUFSIZE];size_t          	  rx_buf_tail = 0;size_t                    rx_buf_head = 0;static struct   	  timer_list delay_timer;int    			  duration_beg,duration_end;static char 	    	  Col_Scan[3]={0xfd,0xfb,0xf7};/*  *	initalize gpio config */void gpio_init(void){    	unsigned int tmp;    	    	/* set gpio_0 dir: in 1~3 out 4~7 */    	gpio_dirgetbyte(KEY_L_PORT,&tmp);    	tmp |= 0x0e;    	tmp &= 0x0f;    	gpio_dirsetbyte(KEY_L_PORT,tmp);    	    	/* set gpio_0 interrupt mode */    	gpio_interruptset_byte(                              		KEY_L_PORT,                               		0xf0,                               		SENSE_BOTH,                               		SENSE_EDGE,                               		EVENT_FALLING_EDGE                               );                                       /* disable gpio_0_4~7 interrupt */                           	tmp = 0xf0;    	gpio_interruptdisable_byte(KEY_L_PORT,tmp);    	    	/* set gpio_0_1~3 low */    	writew(0xf1,(KEY_L_PORT_ADDR+0x038));        	    	/* clear the int_flags of gpio_0_4~7 */    	tmp = 0xf0;    	gpio_interruptclear_byte(KEY_L_PORT,tmp);    	    	/* enable interrupt gpio_0_4~7 */    	tmp = 0xf0;    	gpio_interruptenable_byte(KEY_L_PORT,tmp);}/* *	interrupt handle and start time_list *      Do not to modify the input parameter! */static irqreturn_t  keypad_irq_0(int irq, void *dev_id, struct pt_regs *reg){     	unsigned int  tmp;     	int handled = 0;    	tmp = 0xfe;    	gpio_interruptdisable_byte(KEY_L_PORT,tmp);        	delay_timer.expires = jiffies + margin;    	add_timer (&delay_timer);        	handled = 1;    	return IRQ_RETVAL(handled);}/* *	time_list handle */    static int delay_timer_handler(unsigned long data)    {    	key_info *key_table=NULL;     	static int key;    	unsigned int i;     	int found_irq = 0;     	int found_key = 0;     	unsigned char current_irq;    	unsigned int  up,tmp;     	/* get the int_flag */    	current_irq = readw(KEY_L_PORT_ADDR+GPIO_RIS);    	current_irq = current_irq & 0xf0;    	for (i = 0; i < sizeof key_info_tab / sizeof key_info_tab[1]; i++)        {    	    	key_table = (key_info *)(key_info_tab + i);    	    	if (key_table->irq_source == current_irq)            	{ 	        	found_irq = 1;     	        	break;	    	} 	} 	tmp = 0xf0;    	gpio_interruptclear_byte(KEY_L_PORT,tmp);    	if (!found_irq)       	{	             	gpio_init();            	return 0;	} 		/* identify the raising_edge int */    	up = readw(KEY_L_PORT_ADDR+0x3c0);    	up = up & current_irq;     	    	    	if (up && watch_dog == 1)            	duration_end = jiffies;    	else if(!up && watch_dog == 0)            	duration_beg = jiffies-margin;        else    	{            	gpio_init();            	watch_dog = 0;            	keypad_rx_buf[rx_buf_head] = -1;            	if (++rx_buf_head >= BUFSIZE)            		rx_buf_head -= BUFSIZE;            	            	ready = 1;	            	return 0;    	    	}            /* fix the position of key */        	for(i=0;i<(sizeof (Col_Scan) / sizeof(Col_Scan[1]));i++ )       	{            	writew(Col_Scan[i],(KEY_L_PORT_ADDR+0x038));            	tmp = readw(KEY_L_PORT_ADDR+0x3c0);	    	if(!(tmp&current_irq))              	{	          	key_value = key_table->keycode[i];                  	key_value = key_value ;                  	found_key = 1;                  	key = key_value;		  	break;              	}	}    	if (up && (key<0x5a))    	{       		key_value = key+0x20;          	found_key = 1;    	}    	if(found_key)     	{        	keypad_rx_buf[rx_buf_head] = key_value;            	if (++rx_buf_head >= BUFSIZE)            		rx_buf_head -= BUFSIZE;         }        	if(up)    	{    	    		tmp = duration_end - duration_beg;        	keypad_rx_buf[rx_buf_head] = tmp;        	if (++rx_buf_head >= BUFSIZE)            		rx_buf_head -= BUFSIZE;         	watch_dog = 0;   	    	}    	else        	watch_dog = 1;            	gpio_init();    	ready = 1;    	wake_up_interruptible(&keypad_wait);    	        return 0;}/* *	open device. init gpio and empty the key_value buf */static int hi_keypad_open(struct inode *inode ,struct file *file){    	gpio_init();    	rx_buf_tail = 0;    	rx_buf_head = 0;    	ready = 0;    	return 0;}/* *	Close device, Do nothing! */static int hi_keypad_close(struct inode *inode ,struct file *file){    return 0;}/* *	read key_value buf.  */static int hi_keypad_read(struct file * file, char * buffer, size_t count, loff_t *ppos) {     	int *user_buf = (int *)buffer;    	int *rx_key;retry:    	if (ready)    	{        	copy_to_user(user_buf,(int *)(&keypad_rx_buf[rx_buf_tail]),sizeof(*rx_key));        	if (++rx_buf_tail >= BUFSIZE)            		rx_buf_tail -= BUFSIZE;     	        	count = sizeof(char);        	if(rx_buf_tail == rx_buf_head)        		ready = 0;        	//printk("rx_buf_tail=%d   ,rx_buf_head=%d\n",rx_buf_tail,rx_buf_head);	        	return count;    	}    	else    	{        	if ((file->f_flags & O_NONBLOCK) == O_NONBLOCK)                    	return -EAGAIN;                	interruptible_sleep_on(&keypad_wait);        	goto retry;    	}	}/* select method. */static unsigned int hi_keypad_select( struct file *file, struct poll_table_struct *wait) {     	if((strlen((char *)&keypad_rx_buf)) == 0)    	       	ready = 0;        	if(ready)            	return 1;        	poll_wait(file, &keypad_wait, wait);    	return 0;}/* ioctl method,do thing. for future use */static int hi_keypad_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){     	switch(cmd)     	{         	default:             		return -EINVAL;     	} }    static struct file_operations hi_keypad_fops ={     	.owner =    THIS_MODULE,     	.open =    hi_keypad_open,    	.release=  hi_keypad_close,    	.ioctl=    hi_keypad_ioctl,     	.poll=     hi_keypad_select,     	.read=     hi_keypad_read, }; static struct miscdevice keypad_dev = {	MISC_DYNAMIC_MINOR,	"keypad",	&hi_keypad_fops,};   static int __init  hi_keypad_init(void){     	int ret;     	ret = misc_register(&keypad_dev);    	if(ret)    	{    		printk("could not register tlv320 devices. \n");    		return ret;    	}      	     	           	gpio_remap();   	  	              ret = request_irq(Irq_0,&keypad_irq_0,0,DEVICE_NAME,NULL);     	if (ret)     	{        	misc_deregister(&keypad_dev); 		      printk(DEVICE_NAME " can't request irq(%d)\n",Irq_0); 		      return ret;    	}	    	printk("Hi35**  Keypad Device Driver v1.0\n");    	init_waitqueue_head(&keypad_wait);    	init_timer(&delay_timer);    	delay_timer.function = (void *)delay_timer_handler;    	return 0; } static void __exit hi_keypad_exit(void) { 	    del_timer(&delay_timer);      misc_deregister(&keypad_dev);      free_irq(Irq_0,NULL);     	gpio_unmap();}module_init(hi_keypad_init);module_exit(hi_keypad_exit);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -