找回密码
 注册
关于网站域名变更的通知
查看: 298|回复: 2
打印 上一主题 下一主题

学习一下linux键盘驱动

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2019-9-18 13:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

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

该用户从未签到

2#
发表于 2019-9-18 17:31 | 只看该作者
看看linux键盘驱动。

该用户从未签到

3#
发表于 2019-9-25 18:45 | 只看该作者
学习一下linux键盘驱动。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-8-24 03:06 , Processed in 0.140625 second(s), 23 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表