|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
- /*****************************************************************************
- ;Copyright (C) 2005 Hyesco Technology Co.,Ltd
- ;Institue of Automation, Chinese Academy of Sciences
- ;
- ;WebSite:
- ;Description: Keyboard driver on Linux
- ;Date:
- ;Author: Hyesco
- ;E_mail:
- *****************************************************************************/
-
- #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"); ' [5 w1 B8 A: V9 y; w
+ r0 P4 ~/ W8 G1 o
+ Y8 C9 R6 A( Y4 R( c
- /*****************************************************************************
- ;Copyright (C) 2005 Hyesco Technology Co.,Ltd
- ;Institue of Automation, Chinese Academy of Sciences
- ;
- ;WebSite:
- ;Description: Keyboard test on Linux
- ;Date:
- ;Author: Hyesco
- ;E_mail:
- *****************************************************************************/
-
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <sys/time.h>
- #include <sys/types.h>
- #include <unistd.h>
-
- int main(int argc,char **argv)
- {
- fd_set RFds;
- int retval;
- int fd;
-
- unsigned char number=0;
- struct timeval tv;
-
- fd = open("/dev/key",O_RDONLY);
- if (fd <0)
- {
- printf("open device key error!\n");
- return 0;
- }
-
- tv.tv_sec=1;
- tv.tv_usec=0;
-
- while(1)
- {
- FD_ZERO(&rfds);
- FD_SET(fd,&rfds);
- if (select(1+fd,&rfds,NULL,NULL,&tv)>0)
- {
- if(FD_ISSET(fd,&rfds))
- {
- retval=read(fd, &number, 1);
- if (retval> 0)
- printf("key %x stroke\n", number);
- }
- }
- }
-
- close(fd);
- return 0;
- }
# i5 _6 W1 d+ O+ `4 | * L/ ^4 x2 l# ]
( B7 K' m' _ m6 [9 B9 a& W5 s
$ Y/ ^6 q! V4 g0 d
* n" j1 v& h# E9 z4 j' F& {! G, G/ }2 ~3 x8 w
5 }" H4 b5 q5 ?
, K! N8 E3 d! z5 ?/ ^9 j5 H7 d |
|