亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? at91_key.c

?? 這是AT91RM200 在linux系統下的一個按鍵驅動
?? C
字號:
/*****************************************************************************
;Copyright (C) 2005  Hyesco Technology Co.,Ltd
;Institue of Automation, Chinese Academy of Sciences
;
;WebSite:				www.hyesco.com
;Description: 	Keyboard driver on Linux 
;Date:					2006-11-15		
;Author:				Hyesco			
;E_mail:				Lijg@hyesco.com
*****************************************************************************/

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/poll.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/irq.h> 				
#include <asm/arch/AT91RM9200_SYS.h>

#include <asm/arch/hardware.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/devfs_fs_kernel.h>

//全局變量,常量;
static int major=0;
static char s_name[]="key";

#define U8 unsigned char 
#define U16 unsigned short
#define U32 unsigned int

#define key_buffer_len	10 			//定義鍵盤緩沖區長度
#define KBD_JITTER			2 			//ms
#define QUERY_FREQ  		10 			//jiffer=10ms

struct kbd_info{
	U8 bKeyBuff[key_buffer_len]; 	//retunr key code
	U8 bCount; 										//Key count in buffer
	U8 bStart; 										//start location of key
	wait_queue_head_t key_wait;
	spinlock_t lock; 
};

//*********************************************************
//定義鍵值表,4X4矩陣鍵盤
//*********************************************************
static U8 keytable1[4][4] = {
	{0x11,0x12,0x13,0x14},
	{0x21,0x22,0x23,0x24},
	{0x31,0x32,0x33,0x34},
	{0x41,0x42,0x43,0x44},
};

//*********************************************************
//函數原型
//*********************************************************
void Init_Keyboard(void);
int key_open(struct inode * inode, struct file * filp);
int key_release(struct inode * inode, struct file * filp);
unsigned int key_poll(struct file * filp, struct poll_table_struct * wait);
ssize_t key_read(struct file * filp, char * buf, size_t count, loff_t * l);
void key_run_timer(void);


static struct kbd_info ownkbd_info;
static struct timer_list key_timer;

struct file_operations key_fops = {
		owner:		THIS_MODULE,
		open:			key_open,
		release: 	key_release,
		read:    	key_read,
		poll:    	key_poll,
};


//*********************************************************
//初始化模塊函數;
//*********************************************************
static devfs_handle_t devfs_handle;
int __init KEY1_at91_init(void)
{	
		//unsigned int result = 0;
		
		
		int ret;

		//初始化鍵盤端口;
		Init_Keyboard();
		//注冊模塊;
		if ((ret=devfs_register_chrdev(major,s_name,&key_fops)) < 0)
			{
			printk("\r\n<1>Keyboard Register Fail!\r\n");
			return ret;
			}
		
		//動態分配主設備號;
		if(major == 0)
			major = ret;
		
		//建立設備文件,文件名為:key;
		devfs_handle = devfs_register(NULL, "key",DEVFS_FL_DEFAULT,
			major, 0, S_IFCHR | S_IRUSR | S_IWUSR,&key_fops, NULL);
	
		init_waitqueue_head(&ownkbd_info.key_wait);
		ownkbd_info.bCount=0;
		ownkbd_info.bStart=0;
		
		spin_lock_init(&ownkbd_info.lock);
	
		key_run_timer();
		return 0;
}

//*********************************************************
//鍵盤模塊打開函數;
//*********************************************************
int key_open(struct inode * inode, struct file * filp)
{
		MOD_INC_USE_COUNT;
		return 0;
}

//*********************************************************
//鍵盤模塊釋放函數;
//*********************************************************
int key_release(struct inode * inode,struct file * filp)
{
		MOD_DEC_USE_COUNT;
		return 0;
}

//*********************************************************
//鍵值設置函數;
//*********************************************************
static int KEY_DATA(U8 x) 
{
		int status=-1;
		switch(x)
			{
			case 0:
				//第一行輸出高電平
			  status = AT91_SYS->PIOB_PDSR & (0x1 <<0);
		    break;
			case 1:
			  //第二行輸出高電平
			  status = AT91_SYS->PIOB_PDSR & (0x1 <<1);
		    break;
			case 2:
			 	//第三行輸出高電平
			  status = AT91_SYS->PIOB_PDSR & (0x1 <<2);
		  	break;
			case 3:
			  //第四行輸出高電平
			  status = AT91_SYS->PIOB_PDSR & (0x1 <<3);
		    break;
		    
			default:
				break;
	 		}
		return status;
}		

//*********************************************************
//讀鍵函數;
//*********************************************************
ssize_t key_read(struct file * filp, char * buf, size_t count, loff_t * l)
{
		//Get count keys from keyboard
		U8 bTrueCount=0;
		U8 bTmp=0;
		if ((buf!=NULL) && (count>0) && (ownkbd_info.bCount>0))
				{
				spin_lock(&ownkbd_info.lock);

				bTrueCount=(count>ownkbd_info.bCount) ? ownkbd_info.bCount : count;
				bTmp=ownkbd_info.bStart+bTrueCount;
				if (bTmp<=key_buffer_len)
						copy_to_user(buf, ownkbd_info.bKeyBuff+ownkbd_info.bStart, bTrueCount);
				else
						{
						copy_to_user(buf, ownkbd_info.bKeyBuff+ownkbd_info.bStart, key_buffer_len-ownkbd_info.bStart);
						copy_to_user(buf+key_buffer_len-ownkbd_info.bStart, ownkbd_info.bKeyBuff, bTmp-key_buffer_len);
						}
				ownkbd_info.bCount-=bTrueCount;
				ownkbd_info.bStart+=bTrueCount;
				ownkbd_info.bStart=(ownkbd_info.bStart<key_buffer_len)?ownkbd_info.bStart : (ownkbd_info.bStart-key_buffer_len);

				spin_unlock(&ownkbd_info.lock);
				return bTrueCount;
				}
		return -1;
}

//*********************************************************
//  鍵盤輪詢函數;
//*********************************************************
unsigned int key_poll(struct file * filp, struct poll_table_struct * wait)
{
		//Support select/poll 
		spin_lock(&ownkbd_info.lock);
		poll_wait(filp,&ownkbd_info.key_wait,wait);
		if (ownkbd_info.bCount>0)
				{
				spin_unlock(&ownkbd_info.lock);
				return POLLIN |POLLRDNORM;
				}
		else
				{
				spin_unlock(&ownkbd_info.lock);
				return 0;
				}
}

//*********************************************************
//  鍵掃描函數;
//*********************************************************
int Scan_Keyboard(void)
{
		//keyboard scan main function
		//scan key board to detect if a key down or up
		//the result is stored in ownkbd_info
		unsigned char row=0,col=0;
		unsigned int iScanCode1=0,iScanCode2=0;
		U8 bKeyLocation=0;
		int i;

		spin_lock(&ownkbd_info.lock);
		
		if (ownkbd_info.bCount<key_buffer_len)
			{
			//There are remains in Key buffer, so we continue scaning
			//get the location of the key buffer if a key down/up
			bKeyLocation= ownkbd_info.bStart+ownkbd_info.bCount;
			bKeyLocation=(bKeyLocation<key_buffer_len) ? bKeyLocation : (bKeyLocation-key_buffer_len);
			
			//check key down
			if (KEY_DATA(0)==0)
		  	row=0x0;
			else if (KEY_DATA(1)==0)
				row=0x1;
			else if (KEY_DATA(2)==0)
				row=0x2;
			else if (KEY_DATA(3)==0)
				row=0x3;
			else
				goto end;
		
			//列線全送高電平
    	AT91_SYS->PIOB_SODR |= 0xf0;		//0xfc0;
	
			for(i=0;i<4;i++)	
				{
			 	//PB4~PB7依次送出低電平
			 	AT91_SYS->PIOB_CODR |= (0x10 << i);
			 	if (KEY_DATA(row) == 0)
			 		{
			 		//列值在行值的基礎上加10,便于區別;
					col = i+0xa;				
					iScanCode1 = row | (col<<4) ;
					break ;
			 		}
			 	else if(i == 3)
			 		goto end ;
			 	else
        	AT91_SYS->PIOB_SODR |= (0x10 << i);                                
   			}
		
			mdelay(KBD_JITTER);
			AT91_SYS->PIOB_CODR |=0xf0; 

			//check key down again
			if (KEY_DATA(0)==0)
		  	row=0;
			else if (KEY_DATA(1)==0)
				row=1;
			else if (KEY_DATA(2)==0)
				row=2;
			else if (KEY_DATA(3)==0)
				row=3;
			else
					goto end;	  
	  

      AT91_SYS->PIOB_SODR |= 0xf0;

			for(i=0;i<4;i++)	
			{
			 	//AT91_SYS->PIOB_SODR |= (0x1 << i);
			 	AT91_SYS->PIOB_CODR |= (0x10 << i);
			 	if (KEY_DATA(row) == 0)
			 		{
					col = i+0xa;
					iScanCode2 = row | (col<<4) ;
					break ;
					}
			 	else if(i == 3)
			 		goto end ;
			  else
			 		AT91_SYS->PIOB_CODR |= (0x10 << i);
   		}
		
	   	//鍵確認	
	   	if(iScanCode1 != iScanCode2)
	   	goto end;
	 		
	 		//AT91_SYS->PIOB_CODR |= 0xf;
			AT91_SYS->PIOB_CODR |= 0xf0;
	 
	   	//鍵up
	   	while(KEY_DATA(row)==0);
	 
	   	*(ownkbd_info.bKeyBuff+bKeyLocation)=keytable1[row][col-0xa];
			ownkbd_info.bCount++;
                        
      //DPRINTK("Key up %d\n", *(ownkbd_info.bKeyBuff+bKeyLocation));
		
		}

end:
		spin_unlock(&ownkbd_info.lock);
		AT91_SYS->PIOB_CODR |= 0xf0;
		return 0;
}/*end of scan*/


void key_timeout(unsigned long ptr)
{
    Scan_Keyboard();
	  key_run_timer();
}

void key_run_timer(void)
{
    init_timer(&key_timer);
    key_timer.function = key_timeout;
    key_timer.data = (unsigned long)0;
    key_timer.expires = jiffies + QUERY_FREQ;
    add_timer(&key_timer);
}

//*********************************************************
//  鍵盤端口初始化函數;
//*********************************************************
void Init_Keyboard(void)
{
		//PB7~PB0用作鍵盤端口,PB0~PB3作為行,PB4~PB7作為列;
		
		//使能PB7~PB0的GPIO功能
		//	PB7		PB6		PB5		PB4		PB3		PB2		PB1		PB0
		//	1			1			1			1			1			1			1			1		
		AT91_SYS->PIOB_PER |=0xff; 
		
		
		// PB0~PB3 輸入功能設置;
		// PB0~PB3 enable input;
		AT91_SYS->PIOB_ODR |=0xf; 
		
		// PB0~PB3 enable input filter;
		AT91_SYS->PIOB_IFER |=0xf;
		
		// PB0~PB3 enable Pull up;
		AT91_SYS->PIOB_PPUER |=0xf;	
		
		
		// PB4~PB7 輸出功能設置;
  	// PB4~PB7 enable output;
  	AT91_SYS->PIOB_OER |=0xf0; 
  	
		/* set PB4-7 are 0 */  
  	AT91_SYS->PIOB_CODR |=0xf0;  
  
		/* enable piob clock */
  	AT91_SYS->PMC_PCER =0x1<< AT91C_ID_PIOB;
  	
}

//*********************************************************
//注銷模塊函數;
//*********************************************************
void __exit KEY1_at91_cleanup(void)
{
		int retv;
		del_timer_sync(&key_timer);
		
		//注銷模塊;
		retv=devfs_unregister_chrdev(major,s_name);
		return;
}

module_init(KEY1_at91_init);
module_exit(KEY1_at91_cleanup);

MODULE_AUTHOR("www.hyesco.com");
MODULE_DESCRIPTION("AT91 KEY Driver (AT91_KEY)");
MODULE_LICENSE("GPL");

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
eeuss鲁片一区二区三区 | 亚洲日本在线天堂| www.色综合.com| 亚洲欧美激情一区二区| 欧美日韩国产一二三| 国产主播一区二区三区| 亚洲欧美色图小说| 91麻豆精品国产91久久久| 成人午夜电影久久影院| 天天影视色香欲综合网老头| 精品国产乱码久久| 高清av一区二区| 日本免费在线视频不卡一不卡二 | 亚洲婷婷综合久久一本伊一区| 欧美日韩一区小说| 国产一区二区三区免费看| 午夜精品一区二区三区电影天堂 | 久久午夜免费电影| 色综合天天综合在线视频| 国产一区二区三区在线观看免费| 亚洲一二三专区| 亚洲欧美视频在线观看| 久久精品日产第一区二区三区高清版| 91国偷自产一区二区开放时间 | 天天综合网天天综合色| 亚洲三级在线免费| 国产亚洲短视频| 欧美一区二区三区啪啪| 欧美性videosxxxxx| 不卡一区在线观看| 国产高清成人在线| 久久99最新地址| 久久婷婷久久一区二区三区| 欧美不卡一区二区三区| 欧美日韩精品免费| 欧美日本一区二区| 91搞黄在线观看| 在线观看日韩精品| 在线观看免费视频综合| 99re热视频精品| 一本到三区不卡视频| 成人午夜视频网站| av中文字幕在线不卡| 成人黄色片在线观看| 国产精品亚洲人在线观看| 国产揄拍国内精品对白| 久久精品国产精品亚洲精品 | 激情av综合网| 日本三级亚洲精品| 美女脱光内衣内裤视频久久网站| 亚洲aaa精品| 午夜一区二区三区视频| 日韩中文字幕区一区有砖一区 | 久久综合九色综合欧美就去吻| 欧美精品v日韩精品v韩国精品v| 欧美日韩成人在线| 欧美精品第一页| 91官网在线免费观看| 欧美三级一区二区| 欧美午夜理伦三级在线观看| 欧美性三三影院| 欧美精品久久天天躁| 久久综合丝袜日本网| 久久亚洲综合av| 亚洲色图第一区| 亚洲一卡二卡三卡四卡无卡久久 | 国产精品亚洲午夜一区二区三区| 国产成人精品亚洲午夜麻豆| 972aa.com艺术欧美| 91久久精品一区二区二区| 色94色欧美sute亚洲线路一ni| 91久久国产最好的精华液| 欧美精品久久久久久久久老牛影院| 日韩精品一区二区三区老鸭窝 | 韩国v欧美v日本v亚洲v| 国产麻豆视频一区| 国产一区激情在线| 91极品美女在线| 91超碰这里只有精品国产| 久久这里只有精品视频网| 国产欧美日韩激情| 国产精品久久久久aaaa樱花| 亚洲自拍偷拍综合| 免费一区二区视频| 色哟哟国产精品免费观看| 欧美日韩国产另类不卡| 国产欧美在线观看一区| 亚洲一区在线播放| 久久精品国产秦先生| 9人人澡人人爽人人精品| 欧美三级日本三级少妇99| 欧美一区二区三区白人 | 一区二区三区不卡视频| 婷婷中文字幕综合| 国产精品一区二区你懂的| 99视频精品免费视频| 欧美日本乱大交xxxxx| 2019国产精品| 亚洲福利一区二区| 国产91丝袜在线观看| 欧美在线三级电影| 久久久久99精品国产片| 亚洲精品免费视频| 亚洲午夜三级在线| 国产精品123区| 欧美日韩免费电影| 精品日韩99亚洲| 亚洲男同性恋视频| 美美哒免费高清在线观看视频一区二区 | 亚洲欧美在线视频观看| 免费欧美在线视频| 色呦呦日韩精品| 久久久国产午夜精品| 亚洲成人免费视| 成人在线综合网站| 欧美午夜影院一区| 中文一区二区在线观看| 麻豆精品视频在线观看| 色菇凉天天综合网| 精品欧美一区二区三区精品久久| 亚洲欧美日韩在线| 国产乱码精品一区二区三区忘忧草| 在线视频一区二区三| 欧美mv日韩mv国产| 亚洲成人免费观看| 91女人视频在线观看| 久久精品亚洲一区二区三区浴池| 午夜激情一区二区三区| 91亚洲精品乱码久久久久久蜜桃| 精品久久久久久亚洲综合网| 天天色天天爱天天射综合| 色综合天天做天天爱| 欧美高清在线一区| 午夜精品aaa| 欧美最新大片在线看 | 亚洲成人你懂的| 色噜噜夜夜夜综合网| 国产精品国产三级国产aⅴ中文 | 欧美刺激午夜性久久久久久久| 亚洲夂夂婷婷色拍ww47| 99视频一区二区三区| 国产亚洲欧美激情| 国产在线一区二区综合免费视频| 色乱码一区二区三区88| 亚洲日本青草视频在线怡红院| 国产美女精品人人做人人爽| 欧美肥胖老妇做爰| 亚洲精品v日韩精品| 91蜜桃免费观看视频| 国产精品青草久久| 成人一区在线观看| 国产精品第一页第二页第三页| 国产成人av一区二区三区在线| 精品国产91洋老外米糕| 麻豆成人久久精品二区三区红 | 麻豆91免费看| 精品福利一区二区三区免费视频| 久久精品国产澳门| 精品少妇一区二区三区视频免付费| 免播放器亚洲一区| 欧美videos中文字幕| 韩国v欧美v日本v亚洲v| 日韩无一区二区| 免费观看一级欧美片| 91精选在线观看| 久久精品国产77777蜜臀| 精品少妇一区二区三区日产乱码| 激情综合色播五月| 久久久久成人黄色影片| 不卡一区二区三区四区| 欧美国产日韩精品免费观看| 99久久久无码国产精品| 亚洲一区二区精品视频| 成人av免费观看| 亚洲bt欧美bt精品| 久久久天堂av| 欧美亚洲国产一区在线观看网站| 日韩精品电影在线| 国产精品毛片久久久久久| 欧美日韩久久不卡| 国产黄人亚洲片| 亚洲gay无套男同| 日本一区二区三区国色天香| 欧美日韩一级视频| 国产成人在线网站| 亚洲免费观看高清完整版在线观看熊 | 日韩影院在线观看| 日本一区二区三区高清不卡| 欧美三级韩国三级日本三斤 | 欧美日韩美少妇| 成人美女视频在线观看| 日韩高清在线不卡| 亚洲日本一区二区三区| 久久婷婷国产综合精品青草| 欧美性xxxxxxxx| 成人h精品动漫一区二区三区| 日韩成人免费电影| 亚洲精品福利视频网站| 国产欧美一区二区精品性 | 一区二区三区中文在线观看|