?? mykey.c
字號:
/************************************************************文檔類型: 原代碼 項目編號: 文檔編號: 修訂版本: v1.0生成日期: 2001.8.15文檔作者: 何雄倫審 核: ************************************************************相關文檔: ucdimm上的鍵盤連接 文檔編號 說明 ************************************************************修訂說明修訂版本 v1.1 修訂說明 重寫了select函數************************************************************/#include <linux/kernel.h>#include <asm/MC68VZ328.h>#include <asm/segment.h>#include <linux/types.h>#include <linux/fs.h>#include <linux/mm.h>#include <linux/errno.h>#include <linux/sched.h>#include <linux/tqueue.h>#include <linux/interrupt.h>#include "kbd.h"/*The size of keyboard input buffer.*/unsigned int kbd_major = 99;/*The keyboard input buffer.*/unsigned char kbd_buf[MAX_KEY_COUNT];/* The keyboard wait queque */struct wait_queque *kbd_wait;int key_count = 0;int kbd_head = 0;int kbd_end = 0;/************************************************************函數原型: static int kbd_read(struct inode*,struct file*,short*,int)功 能: Read one byte from keyboard driver's buffer,輸入參數: short *buf:The point of save the readed one byte data. int count:Not used.返 回 值: Sucess return 1,failed return 0.************************************************************/static int kbd_read(struct inode *node, struct file *fp, short *buf, int count){ if (verify_area(VERIFY_WRITE, buf, 1) == -EFAULT) return -1; if (key_count == 0) return 0; __put_user(kbd_buf[kbd_head],buf,1); key_count --; kbd_head ++; if (kbd_head == MAX_KEY_COUNT) kbd_head = 0; return 1;}/************************************************************函數原型: static int kbd_open(struct inode *,struct file*)功 能: Open the keyboard driver.輸入參數: struct inode *node:not used. struct file *file:not used.返 回 值: Always success so always return 0.************************************************************/static int kbd_open(struct inode *node, struct file *fp){ kbd_head = 0; kbd_end = 0; key_count = 0; return 0;}/************************************************************函數原型: static void kbd_close(struct inode *node,struct file *fp) 功 能: Close the keyboard driver.In here,it do nothing.輸入參數: struct inode *node:not used. struct file *fp:not used.返 回 值: no return value.************************************************************/static void kbd_close(struct inode *node, struct file *fp){}/************************************************************函數原型: kbd_write(struct inode *,struct file*,const char *,int)功 能: Write the data to keyboard driver.But in our driver, can not write to the keyboard,so it do nothing.輸入參數: All not used返 回 值: always return 0.************************************************************/int kbd_write(struct inode *node, struct file *fp, const char *buf, int count){ int i; if (verify_area(VERIFY_READ, buf, 1) == -EFAULT) return -1; if (key_count + count < MAX_KEY_COUNT) { for (i = 0;i < count;i ++) { kbd_buf[kbd_end] = buf[i]; kbd_end ++; key_count ++; if (kbd_end >= MAX_KEY_COUNT) kbd_end = 0; } wake_up(&kbd_wait); return count; } else return 0;}/************************************************************函數原型: static int kbd_select(struct inode *,struct file*,int,select_table *)功 能: If the keyboard driver's buffer have data to read,return 1,otherwise, return 0.輸入參數: All arguments are not used.返 回 值: If the keyboard driver's buffer have data to read,return 1,otherwise, return 0.************************************************************/static int kbd_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;}static unsigned int charcase = 0;static int kbd_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg){ int result; switch (cmd) { case 0: /* Set the low case */ charcase = 0; result = 2; break; case 1: /* Set the up case */ charcase = 1; result = 2; break; case 2: /* Get the char case */ result = charcase; break; } return result;}struct file_operations kbd_fops = { NULL, kbd_read, kbd_write, NULL, kbd_select, kbd_ioctl, NULL, kbd_open, kbd_close, NULL, NULL, NULL, NULL};/************************************************************函數原型: static unsigned short invert(unsigned short)功 能: Invert the input data.輸入參數: unsigned short data:the data witch want to invert.返 回 值: return the inverted data.************************************************************/static unsigned short invert(unsigned short data){ unsigned short tmp = 0; int i; for (i=0; i<11; i++) { if (data&(1<<i)) tmp |= (1<<(10-i)); } return tmp;}/************************************************************函數原型: static unsigned char check(unsigned short data)功 能: Check the input data(delete the start and stop bit,check the parity and delete the parity bit).輸入參數: unsigned short data:the data witch want to check.返 回 值: return the checked data.************************************************************/static unsigned char check(unsigned short data){ int i,par = 0; /*Check the end bit*/ if (!(data & 0x400)) return 255; /*Check the start bit*/ if (data & 0x1) return 255; /*Discard the start bit*/ data >>= 1; for (i=0; i<8; i++) { if (data & (1<<i)) par++; } if (data & 0x100) par++; /*Check the parity*/ if (par%2 == 0) return 255; return data;}static unsigned char nortable[132] = { /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ /*00...0f*/ 0x00,0x43,0x00,0x3f,0x3d,0x3b,0x3c,0x58,0x00,0x44,0x42,0x40,0x3e,0x0f,0x29,0x00, /*10...1f*/ 0x00,0x38,0x2a,0x00,0x1d,0x10,0x02,0x00,0x00,0x00,0x2c,0x1f,0x1e,0x11,0x03,0x00, /*20...2f*/ 0x00,0x2e,0x2d,0x20,0x12,0x05,0x04,0x00,0x00,0x39,0x2f,0x21,0x14,0x13,0x06,0x00, /*30...3f*/ 0x00,0x31,0x30,0x23,0x22,0x15,0x07,0x00,0x00,0x00,0x32,0x24,0x16,0x08,0x09,0x00, /*40...4f*/ 0x00,0x33,0x25,0x17,0x18,0x0b,0x0a,0x00,0x00,0x34,0x35,0x26,0x27,0x19,0x0c,0x00, /*50...5f*/ 0x00,0x00,0x28,0x00,0x1a,0x0d,0x00,0x00,0x3a,0x36,0x1c,0x1b,0x00,0x2b,0x00,0x00, /*60...6f*/ 0x00,0x56,0x00,0x00,0x00,0x00,0x0e,0x00,0x00,0x4f,0x00,0x4b,0x47,0x00,0x00,0x00, /*70...7f*/ 0x52,0x53,0x50,0x4c,0x4d,0x48,0x01,0x45,0x57,0x4e,0x51,0x4a,0x37,0x49,0x46,0x00, /*80...83*/ 0x00,0x00,0x00,0x41};static unsigned char exttable[14][2] = { {0x11,0x64}, {0x14,0x61}, {0x70,0x6e}, {0x71,0x6f}, {0x6b,0x69}, {0x6c,0x66}, {0x69,0x6b}, {0x75,0x67}, {0x72,0x6c}, {0x7d,0x68}, {0x7a,0x6d}, {0x74,0x6a}, {0x4a,0x62}, {0x5a,0x60},};/*The PrintScreen key's make scancode*/static unsigned char PrtScr[4] = {0xe0,0x12,0xe0,0x7c};/*The PrintScreen key's break scancode*/static unsigned char BreakPrt[5] = {0xf0,0x7c,0xe0,0xf0,0x12};/*The Pause/Break key's scancode*/static unsigned char Brk[8] = {0xe1,0x14,0x77,0xe1,0xf0,0x14,0xf0,0x77};static short flag_e0 = 0;static short flag_e1 = 0;static short flag_f0 = 0;/************************************************************函數原型: static unsigned char nortrans(unsigned char scancode)功 能: Translate the normal scancode from AT scancode to microwindows' scancode(include make and break scancode).輸入參數: unsigned char scancode:the data witch want to translate.返 回 值: return the corresponding microwindows' scancode.************************************************************/static unsigned char nortrans(unsigned char scancode){ unsigned char xtcode; if (flag_f0 == 0) { if (scancode == 0xf0) { flag_f0 = 1; return 0; } /*If the AT scancode is too lage then return*/ if (scancode > 131) return 0; xtcode = nortable[scancode]; /*If can't find the xt scancode then return*/ if (xtcode == 0) return 0; } else { /* translate the break scancode */ flag_f0 = 0; if (scancode > 131) return 0; xtcode = nortable[scancode]; if (xtcode == 0) return 0; xtcode |= 0x80; } /*Write the xt scancode to buffer*/ if (key_count < MAX_KEY_COUNT) { kbd_buf[kbd_end] = xtcode; kbd_end ++; key_count ++; if (kbd_end >= MAX_KEY_COUNT) kbd_end = 0; } return 1;}/************************************************************函數原型: unsigned char exttrans(unsigned char scancode)功 能: Translate the extend scancode.輸入參數: unsigned char scancode:the data witch want to translate.返 回 值: return the corresponding microwindows' scancode.************************************************************/unsigned char exttrans(unsigned char scancode){ unsigned char xtcode; int i; if (flag_f0 == 0) { /* process the make scancode */ if (scancode == PrtScr[flag_e0]) { flag_e0 ++; if (flag_e0 >= 4) { /*Write the xt scancode(PrtScr make) to buffer*/ if (key_count < MAX_KEY_COUNT) { kbd_buf[kbd_end] = 0x63; kbd_end ++; key_count ++; if (kbd_end >= MAX_KEY_COUNT) kbd_end = 0; } flag_e0 = 0; } return 0; } if (scancode == 0xf0) { flag_f0 = 1; return 0; } flag_e0 = 0; for (i = 0;i < 14;i ++) { if (exttable[i][0] == scancode) { xtcode = exttable[i][1]; break; } } if (i >= 14) return 0; } else { /* process the break scancode */ if (scancode == BreakPrt[flag_e0]) { flag_e0 ++; if (flag_e0 >= 5) { /*Write the xt scancode(PrtScr break) to buffer*/ if (key_count < MAX_KEY_COUNT) { kbd_buf[kbd_end] = 0xe3; kbd_end ++; key_count ++; if (kbd_end >= MAX_KEY_COUNT) kbd_end = 0; } flag_f0 = 0; flag_e0 = 0; } return 0; } flag_f0 = 0; flag_e0 = 0; for (i = 0;i < 14;i ++) { if (exttable[i][0] == scancode) { xtcode = exttable[i][1]; xtcode |= 0x80; break; } } if (i >= 14) return 0; } /*Write the xt scancode to buffer*/ if (key_count < MAX_KEY_COUNT) { kbd_buf[kbd_end] = xtcode; kbd_end ++; if (kbd_end >= MAX_KEY_COUNT) kbd_end = 0; } return 1;}/************************************************************函數原型: unsigned char translate(unsigned char scancode)功 能: The translate main function,include normal and extend key's scancode.輸入參數: unsigned char scancode:The data want to translate.返 回 值: return the translated scancode.************************************************************/unsigned char translate(unsigned char scancode){ if (flag_e0 == 0 && flag_e1 == 0) { /* process the normal AT scancode */ if (scancode == 0xe0) { flag_e0 = 1; return 0; } else if (scancode == 0xe1) { flag_e1 = 1; return 0; } return (nortrans(scancode)); } else if (flag_e1) { /* process the Pause/Break key's scancode */ if (scancode == Brk[flag_e1]) { flag_e1 ++; if (flag_e1 >= 8) { /*Write the xt scancode(PrtScr break) to buffer*/ if (key_count < MAX_KEY_COUNT) { kbd_buf[kbd_end] = 0x77; kbd_end ++; key_count ++; if (kbd_end >= MAX_KEY_COUNT) kbd_end = 0; } flag_e1 = 0; } } else flag_e1 = 0; return 0; } else { /* process the extend scancode */ return (exttrans(scancode)); }}/************************************************************函數原型: void irp_handler(int,void *,struct pt_regs)功 能: This is a interrupt handler function,it read the 11bits data from the SPI receive register.輸入參數: All arguments are not used.返 回 值: Have not return value.************************************************************/void irq_handler(int irq, void* dev_id, struct pt_regs* regs){ short tmp; unsigned char scancode = 0; unsigned char result;printk("keyboard irq hander\n"); cli(); tmp = SPI1RDATA; tmp = invert(tmp); scancode = check(tmp); if (scancode == 255) {// printk("scancode error!\n"); return; } result = translate(scancode); wake_up(&kbd_wait); sti();}/************************************************************函數原型: void initSPI()功 能: Initialize the SPI.輸入參數: Have not input arguments.返 回 值: Have not return value.************************************************************/void initSPI(){ //set pin selection PJSEL = (PJSEL&0xF2); //SET_PKSEL(0); //set SPI1 control/status register SPI1CONT = 0x021A;//0000,0010,00??,1010 //set SPI1 interrupt control/status register SPI1ICONT = 0x0800;}/************************************************************函數原型: void init_mykey()功 能: Do all the initialize work,include registe device, initialize the SPI,request interrupt.輸入參數: No input argument.返 回 值: No return value.************************************************************/void init_mykey(){ int result; result = register_chrdev(kbd_major, "keyboard", &kbd_fops); if (result<0) { printk("keyboard: can't get major number\n"); return; } /*Init SPI*/// initSPI(); //free_irq(12|0x10000000, NULL);// if (request_irq(21|0x10000000, irq_handler, SA_SHIRQ,// "test_keyboard_irq_handler", NULL))// printk("Cannot request irq\n"); kbd_wait = NULL;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -