📄 smallkbd.c
字号:
/***********************************************************Document Type : source codeItem number : Document number:Version : v1.0Date : 2002.4.22Author :zhou ze mingAuditing : ************************************************************Correlation Document: Document number :Explain :************************************************************Edit explain :Edit version :************************************************************/#include <linux/kernel.h>#include <asm/MC68VZ328.h>#include <linux/fs.h>#include <linux/param.h>#include <linux/errno.h>#include <linux/sched.h>#include <linux/timer.h>#include <linux/mm.h>#include <linux/delay.h>#include "kbd.h"extern unsigned char kbd_buf[MAX_KEY_COUNT]; // keyboard bufferextern int key_count; // key number in keyboard bufferextern int kbd_head; // head pointer of keyboard bufferextern int kbd_end; // tail pointer of keyboard bufferextern struct wait_queue *kbd_wait; // keyboard wait queuestatic unsigned int _nMajor = SMALLKBD_MAJOR; // major devide idstruct timer_list _tmlist;static int _nDelayTime = SMALLKBD_DELAY*HZ/1000;// s1 ~ s9 key default value//static unsigned char _s[SMALLKBD_KEYNUM] = {LEFT,RIGHT,UP,DOWN,PAGEUP,PAGEDOWN,HOME,END,UNDEFINE};static unsigned char _s[SMALLKBD_KEYNUM] = {UNDEFINE,UP,RIGHT,LEFT,DOWN,PAGEUP,PAGEDOWN,UNDEFINE,UNDEFINE};// enable/disable small keyboardstatic int _smallkbd_enable = SMALLKBD_ENABLE; // 0,disable;otherwise,enable/************************************************************Prototype: static int smallkbd_read(struct inode*,struct file*,short*,int)Function : Read one byte from keyboard driver's buffer,Parameter: short *buf : The point of save the readed one byte data. int count : byte number which is user required readingReturn : Sucess return non-zero,failed return 0.************************************************************/static int smallkbd_read(struct inode *node, struct file *fp,char *buf, int count){ int i = 0; if (-EFAULT == verify_area(VERIFY_WRITE,buf,count)) return -1; if (0 >= key_count) { sleep_on(&kbd_wait); return 0; } while ((i < count) && (0 < key_count)) { __put_user(kbd_buf[kbd_head],buf+i,1); key_count--; kbd_head++; if (MAX_KEY_COUNT <= kbd_head) kbd_head = 0; i++; } return i;}/************************************************************Prototype: static int smallkbd_open(struct inode *,struct file*)Function : Open the keyboard driver.Parameter: struct inode *node : not used. struct file *file : not used.Return : Always success so always return 0.************************************************************/static int smallkbd_open(struct inode *node, struct file *fp){ return 0;}/************************************************************Prototype: static void smallkbd_close(struct inode *node,struct file *fp) Function : Close the keyboard driver.In here,it do nothing.Parameter: struct inode *node : not used. struct file *fp : not used.Return : no************************************************************/static void smallkbd_release(struct inode *node, struct file *fp){}/************************************************************Prototype: smallkbd_write(struct inode *,struct file*,const char *,int)Function : Write the data to keyboard driver.But in our driver, can not write to the keyboard,so it do nothing.Parameter: All not usedReturn : always return 0.************************************************************/static int smallkbd_write(struct inode *node, struct file *fp, const char *buf, int count){ int i = 0; if (-EFAULT == verify_area(VERIFY_READ,buf,count)) return -1; while ((i < count) && (key_count < MAX_KEY_COUNT)) { kbd_buf[kbd_end++] = (unsigned char)(*(buf+i)); i++; if (MAX_KEY_COUNT <= kbd_end) kbd_end = 0; key_count++; } if (0 < i) wake_up(&kbd_wait); return i;}/************************************************************Prototype: static int smallkbd_select(struct inode *,struct file*,int,select_table *)Function : If the keyboard driver's buffer have data to read,return 1,otherwise,return 0Parameter: All arguments are not used.Return : If the keyboard driver's buffer have data to read,return 1,otherwise,return 0************************************************************/static int smallkbd_select(struct inode *inode,struct file *file,int mode,select_table *table){ if (mode == SEL_IN) { if (key_count) return 1; select_wait(&kbd_wait,table); } return 0;}/************************************************************Prototype: static int smallkbd_ioctl(struct inode *,struct file*,unsigned int,unsigned long)Function : redefine key s1~s9Parameter: cmd = which key,1=s1,2=s2,...,9=s9 arg = key valueReturn : 0,success,-EFAULT failure.************************************************************/static int smallkbd_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg){ switch(cmd) { case SMALLKBD_EN_DIS: if (arg) _smallkbd_enable = SMALLKBD_ENABLE; // enable small keyboard else _smallkbd_enable = SMALLKBD_DISABLE; // disable small keyboard break; case SMALLKBD_KEY1: case SMALLKBD_KEY2: case SMALLKBD_KEY3: case SMALLKBD_KEY4: case SMALLKBD_KEY5: case SMALLKBD_KEY6: case SMALLKBD_KEY7: case SMALLKBD_KEY8: case SMALLKBD_KEY9: _s[cmd-1] = (unsigned char)arg; break; default: return -EFAULT; break; } return 0;}struct file_operations smallkbd_fops ={ NULL, smallkbd_read, smallkbd_write, NULL, smallkbd_select, smallkbd_ioctl, NULL, smallkbd_open, smallkbd_release,};/*********************************************************Prototype: unsigned int read_scancode(unsigned int nScanCode)Function : receive input-scancode,output output-scancodeParameter: nScanCode,input-scancodeReturn : output-scancode*********************************************************/unsigned char read_scancode(const unsigned char nScanCode){ unsigned char nTemp; nTemp = nScanCode & 0x03; PGDATA &= 0xfc; // write scan code to PG0~PG1 PGDATA |= nTemp; nTemp = (PKDATA & 0x0c) >> 2; // read scan code from PM5,PK3,PK2 nTemp |= (PMDATA & 0x20) >> 3; return nTemp;}//extern int kbd_write(struct inode *node,struct file *fp,const char *buf,int count);/**************************************************Prototype: void AddKeytoBuf(const unsigned char keycode)Function : Add key code to keyboard bufferParameter: keycode -- key codeReturn : no**************************************************/void AddKeytoBuf(unsigned char keycode){ if (MAX_KEY_COUNT <= key_count) return; kbd_buf[kbd_end] = keycode;// printk("key value=%d\n",kbd_buf[kbd_end]); kbd_end++; key_count++; if (MAX_KEY_COUNT <= kbd_end) kbd_end = 0; wake_up(&kbd_wait);// kbd_write(NULL,NULL,&keycode,1);}/*********************************************************Prototype: void scan_smallkbd(void)Function : scan small keyboard,rejoin self to kernel timer list,wait for another run.Parameter: noReturn : no*********************************************************/static unsigned char _byOldScanCode1 = 0x00,_byOldScanCode2 = 0x00;//,_byOldScanCode3 = 0x00;static short _bKeyDownFlag1 = 0,_bKeyDownFlag2 = 0;//,_bKeyDownFlag3 = 0;void scan_smallkbd(void){ unsigned char byScanCode1,byScanCode2,byScanCode3; if (!_smallkbd_enable) { // disable small keyboard init_timer(&_tmlist); _tmlist.expires = jiffies + _nDelayTime; _tmlist.function = (void*)scan_smallkbd; add_timer(&_tmlist); return; } byScanCode1 = read_scancode(0x02); if ((_byOldScanCode1 == byScanCode1) && (0 == _bKeyDownFlag1)) { _bKeyDownFlag1 = 1; switch (byScanCode1) { case 0x06: // s7 key is pressed if (UNDEFINE != _s[1]) AddKeytoBuf(_s[1]); printk("s1 is pressed\n"); break; case 0x05: // s8 key is pressed if (UNDEFINE != _s[2]) AddKeytoBuf(_s[2]); printk("s2 is pressed\n"); break; case 0x03: // s9 key is pressed if (UNDEFINE != _s[3]) AddKeytoBuf(_s[3]); printk("s3 is pressed\n"); break; case 0x01: // both s8,s9 are pressed printk("s8 & s9 is pressed\n"); break; case 0x02: // both s7,s9 are pressed printk("s7 & s9 is pressed\n"); break; case 0x04: // both s7,s8 are pressed printk("s7 & s8 is pressed\n"); break; case 0x00: // s7,s8,s9 are pressed printk("s7 & s8 & s9 is pressed\n"); break; case 0x07: // no key is pressed break; default: // error break;printk("scan code1 %d\n",byScanCode1); } } else if (_byOldScanCode1 != byScanCode1) { _bKeyDownFlag1 = 0; _byOldScanCode1 = byScanCode1; } byScanCode2 = read_scancode(0x01); if ((_byOldScanCode2 == byScanCode2) && (0 == _bKeyDownFlag2)) { _bKeyDownFlag2 = 1; switch (byScanCode2) { case 0x06: // s6 key is pressed if (UNDEFINE != _s[4]) AddKeytoBuf(_s[4]); printk("s4 is pressed\n"); break; case 0x05: // s5 key is pressed if (UNDEFINE != _s[5]) AddKeytoBuf(_s[5]); printk("s5 is pressed\n"); break; case 0x03: // s4 key is pressed if (UNDEFINE != _s[6]) AddKeytoBuf(_s[6]); printk("s6 is pressed\n"); break; case 0x01: // both s5,s6 are pressed printk("s5 & s6 is pressed\n"); break; case 0x02: // both s4,s6 are pressed printk("s4 & s6 is pressed\n"); break; case 0x04: // both s4,s5 are pressed printk("s4 & s5 is pressed\n"); break; case 0x00: // s4,s5,s6 are pressed printk("s4 & s5 & s6 is pressed\n"); break; case 0x07: // no key is pressed break; default: // error break;printk("scan code2 %d\n",byScanCode2); } } else if (_byOldScanCode2 != byScanCode2) { _bKeyDownFlag2 = 0; _byOldScanCode2 = byScanCode2; } /*byScanCode3 = read_scancode(0x06); if ((_byOldScanCode3 == byScanCode3) && (0 == _bKeyDownFlag3)) { _bKeyDownFlag3 = 1; switch (byScanCode3) { case 0x03: // s3 key is pressed if (UNDEFINE != _s[2]) AddKeytoBuf(_s[2]); printk("s3 is pressed\n"); break; case 0x05: // s2 key is pressed if (UNDEFINE != _s[1]) AddKeytoBuf(_s[1]); printk("s2 is pressed\n"); break; case 0x06: // s1 key is pressed if (UNDEFINE != _s[0]) AddKeytoBuf(_s[0]); printk("s1 is pressed\n"); break; case 0x01: // both s2,s3 are pressed printk("s2 & s3 is pressed\n"); break; case 0x02: // both s1,s3 are pressed printk("s1 & s3 is pressed\n"); break; case 0x04: // both s1,s2 are pressed printk("s1 & s2 is pressed\n"); break; case 0x00: // s1,s2,s3 are pressed printk("s1 & s2 & s3 is pressed\n"); break; case 0x07: // no key is pressed break; default: // error break; } } else if (_byOldScanCode3 != byScanCode3) { _bKeyDownFlag3 = 0; _byOldScanCode3 = byScanCode3; } */ if ( (0 == byScanCode1) && (0 == byScanCode2) /*&& (0 == byScanCode3)*/ ) _byOldScanCode1 = _byOldScanCode2 /*= _byOldScanCode3*/ = 0x00; init_timer(&_tmlist); _tmlist.expires = jiffies + _nDelayTime; _tmlist.function = (void*)scan_smallkbd; add_timer(&_tmlist);}/************************************************************Prototype: void init_smallkbd(void)Function : Do all the initialize work.Parameter: No input argument.Return : No return value.************************************************************/void init_smallkbd(void){ int nResult; // register device nResult = register_chrdev(_nMajor, "smallkbd", &smallkbd_fops); if (nResult<0) { printk("smallkbd: can't get small keyboard major device number\n"); return; } // initial wait queue// init_waitqueue(&kbd_wait); // init PG0 ~ PG2,PK2,PK3,PM5 PKSEL |= 0x0c; //PK2,PK3 as I/O port(set to 1) PMSEL |= 0x20; //PM5 as I/O port(set to 1) PGSEL |= 0x03; //PG0 ~ PG1 as I/O port(set to 1) PKDIR &= 0xf3; //PK2,PK3 as input pin(set to 0) PMDIR &= 0xdf; //PM5 as input pin(set to 0) PGDIR |= 0x03; //PG0 ~ PG1 set to output pin(set to 1) PGPUEN |= 0x03; //PG0 ~ PG1 pull-up enable // initial timer list init_timer(&_tmlist); _tmlist.expires = _nDelayTime; _tmlist.function = (void*)scan_smallkbd; add_timer(&_tmlist); printk("Init smallkbd module success.\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -