⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 keyb.c.org

📁 键盘设备驱动,只需修改代码里的功能码和系统码即可使用
💻 ORG
📖 第 1 页 / 共 2 页
字号:
			/* sets the "release_key" bit when a key is 			   released. HP keyboard send f0 followed by 			   the keycode while AT keyboard send the keycode			   with this bit set. */			brk = 0x80;			return;		case KBD_ESCAPEE0 :			/* 2chars sequence, commonly used to differenciate 			   the two ALT keys and the two ENTER keys and so 			   on... */			esc0 = 2;	/* e0-xx are 2 chars */			scancode = keyval;			break;		case KBD_ESCAPEE1 :  			/* 3chars sequence, only used by the Pause key. */			esc1 = 3;	/* e1-xx-xx are 3 chars */			scancode = keyval;			break;		case 0x14 : 			/* translate e1-14-77-e1-f0-14-f0-77 to 			   e1-1d-45-e1-9d-c5 (the Pause key) */			if (esc1==2) scancode = brk | 0x1d;			break;		case 0x77 :			if (esc1==1) scancode = brk | 0x45;			break;		case 0x12 :			/* an extended key is e0-12-e0-xx e0-f0-xx-e0-f0-12			   on HP, while it is e0-2a-e0-xx e0-(xx|80)-f0-aa 			   on AT. */			if (esc0==1) scancode = brk | 0x2a;			break;	}		/* translates HP scancodes to AT scancodes */	if (!scancode) scancode = brk | keycode_translate[keyval];	if (!scancode) printk(KERN_INFO "keyboard: unexpected key code %02x\n",keyval);	/* now behave like an AT keyboard */		handle_keyboard(scancode);	if (esc0) esc0--;	if (esc1) esc1--;	/* release key bit must be unset for the next key */	brk = 0;}int kbd_translate(unsigned char scancode, unsigned char *keycode,		    char raw_mode){	static int prev_scancode;	/* special prefix scancodes.. */	if (scancode == 0xe0 || scancode == 0xe1) {		prev_scancode = scancode;		return 0;	}	/* 0xFF is sent by a few keyboards, ignore it. 0x00 is error */	if (scancode == 0x00 || scancode == 0xff) {		prev_scancode = 0;		return 0;	}	scancode &= 0x7f;	if (prev_scancode) {	  /*	   * usually it will be 0xe0, but a Pause key generates	   * e1 1d 45 e1 9d c5 when pressed, and nothing when released	   */	  if (prev_scancode != 0xe0) 	  {	      if (prev_scancode == 0xe1 && scancode == 0x1d) 	      {		   prev_scancode = 0x100;		   return 0;	      } 	      else if (prev_scancode == 0x100 && scancode == 0x45) 	      {		   *keycode = E1_PAUSE;		   prev_scancode = 0;	      } 	      else 	       {#ifdef KBD_REPORT_UNKN		  	if (!raw_mode)		    	printk(KERN_INFO "keyboard: unknown e1 escape sequence\n");#endif		  	prev_scancode = 0;		  	return 0;	      }	  } 	  else 	  {	      prev_scancode = 0;	      /*	       *  The keyboard maintains its own internal caps lock and	       *  num lock statuses. In caps lock mode E0 AA precedes make	       *  code and E0 2A follows break code. In num lock mode,	       *  E0 2A precedes make code and E0 AA follows break code.	       *  We do our own book-keeping, so we will just ignore these.	       */	      /*	       *  For my keyboard there is no caps lock mode, but there are	       *  both Shift-L and Shift-R modes. The former mode generates	       *  E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs.	       *  So, we should also ignore the latter. - aeb@cwi.nl	       */	      if (scancode == 0x2a || scancode == 0x36)		return 0;	      if (e0_keys[scancode])			*keycode = e0_keys[scancode];	      else 	       {#ifdef KBD_REPORT_UNKN		  if (!raw_mode)		    printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n",			   scancode);#endif		    return 0;	      }	  }	} else if (scancode >= SC_LIM) {	    /* This happens with the FOCUS 9000 keyboard	       Its keys PF1..PF12 are reported to generate	       55 73 77 78 79 7a 7b 7c 74 7e 6d 6f	       Moreover, unless repeated, they do not generate	       key-down events, so we have to zero up_flag below */	    /* Also, Japanese 86/106 keyboards are reported to	       generate 0x73 and 0x7d for \ - and \ | respectively. */	    /* Also, some Brazilian keyboard is reported to produce	       0x73 and 0x7e for \ ? and KP-dot, respectively. */	  *keycode = high_keys[scancode - SC_LIM];	  if (!*keycode) {	      if (!raw_mode) {#ifdef KBD_REPORT_UNKN		  printk(KERN_INFO "keyboard: unrecognized scancode (%02x)"			 " - ignored\n", scancode);#endif	      }	      return 0;	  } 	} else	  *keycode = scancode;	  	handle_keyboard(*keycode);  //yhwang add	 	return 1;}void command(unsigned char cmd){	int key;	outportb(PORT_PSDAT,cmd);	while((inportb(PORT_PSTAT)&0x2)==0);	key = inportb(PORT_PSTAT);	outportb(PORT_PSCON,0x80);}void pscon(unsigned char cmd){	outportb(PORT_PSCON,cmd);}void delay(int i){	do {		int j =1000;	// ori		do {			asm volatile ("nop");		} while (--j>=0);	} while (--i>=0);}void init_kbd(void);void init_kbd(){	pscon(0x6c);	command(0xff);}void pollingKeyboard(void){	int i;	int stat;	for(i=0;i<10;i++) {		stat = inportb(PORT_PSTAT);		if ((stat&0x0a)==0x0a) {			int in_key;			in_key = inportb(PORT_PSDAT);			handle_at_scancode(in_key);			if(debug>0)				printk("kbd(%d)[%x] ",i,in_key);			outportb(PORT_PSCON,0x80);		}	}}#ifdef SUPPORT_IRextern int read_ir(void);extern void init_ir(void);void polling_ir(void){	int i;	int data;	int keyb;	for(i=0;i<1;i++) {		data = read_ir();		if(data>=0) {			keyb= ir_map[data];			if(debug>0)				printk("ir(%d)[%x]->[%x] ",i,data, keyb);			switch(keyb) {			case R_UP:			case R_DOWN:			case R_LEFT:			case R_RGHT:/*				handle_at_scancode(0xe0);				handle_at_scancode(keyb);*/				handle_at_scancode(0xe0);				handle_at_scancode(0xf0);				handle_at_scancode(keyb);			default:				handle_at_scancode(keyb);				handle_at_scancode(0xf0);				handle_at_scancode(keyb);				break;			}		}	}}#endif //SUPPORT_IRstruct timer_list keyboard_timer;  static void dvd_keyboard_timeup(unsigned long data){	if(use_keyb)		pollingKeyboard();#ifdef SUPPORT_IR	if(use_ir)		polling_ir();#endif	mod_timer(&keyboard_timer, jiffies + SCANHZ);   }                                        static void  dvd_keyboard_starttimer(void){	printk("dvd_keyboard_starttimer\n");	init_timer(&keyboard_timer);	keyboard_timer.function = dvd_keyboard_timeup;	keyboard_timer.data = 0;	keyboard_timer.expires = jiffies + SCANHZ;	add_timer(&keyboard_timer);}/* *	PS/2 Auxiliary Device */static spinlock_t controller_lock = SPIN_LOCK_UNLOCKED; static struct aux_queue *queue;	/* Mouse data buffer. */static int aux_count;static inline void handle_keyboard(unsigned char scancode){	static unsigned char prev_code;	int head;	prev_code = scancode;	add_mouse_randomness(scancode);	if (aux_count) {		head = queue->head;		queue->buf[head] = scancode;		head = (head + 1) & (AUX_BUF_SIZE-1);		if (head != queue->tail) {			queue->head = head;			kill_fasync(&queue->fasync, SIGIO, POLL_IN);			wake_up_interruptible(&queue->proc_list);		}	}}static unsigned char get_from_queue(void){	unsigned char result;	unsigned long flags;	spin_lock_irqsave(&controller_lock, flags);	result = queue->buf[queue->tail];	queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);	spin_unlock_irqrestore(&controller_lock, flags);	return result;}static inline int queue_empty(void){	return queue->head == queue->tail;}static int fasync_aux(int fd, struct file *filp, int on){	int retval;	retval = fasync_helper(fd, filp, on, &queue->fasync);	if (retval < 0)		return retval;	return 0;}/* * Random magic cookie for the aux device */#define AUX_DEV ((void *)queue)static int release_aux(struct inode * inode, struct file * file){	lock_kernel();	fasync_aux(-1, file, 0);	if (--aux_count) {		unlock_kernel();		return 0;	}	del_timer(&keyboard_timer);	unlock_kernel();	return 0;}/* * Install interrupt handler. * Enable auxiliary device. */static int open_aux(struct inode * inode, struct file * file){	if (aux_count++) {		return 0;	}	queue->head = queue->tail = 0;		/* Flush input queue */	dvd_keyboard_starttimer();	return 0;}/* * Put bytes from input queue to buffer. */static ssize_t read_aux(struct file * file, char * buffer,			size_t count, loff_t *ppos){	DECLARE_WAITQUEUE(wait, current);	ssize_t i = count;	unsigned char c;	if (queue_empty()) {		if (file->f_flags & O_NONBLOCK)			return -EAGAIN;		add_wait_queue(&queue->proc_list, &wait);repeat:		set_current_state(TASK_INTERRUPTIBLE);		if (queue_empty() && !signal_pending(current)) {			schedule();			goto repeat;		}		current->state = TASK_RUNNING;		remove_wait_queue(&queue->proc_list, &wait);	}	while (i > 0 && !queue_empty()) {		c = get_from_queue();		put_user(c, buffer++);		i--;	}	if (count-i) {		file->f_dentry->d_inode->i_atime = CURRENT_TIME;		return count-i;	}	if (signal_pending(current))		return -ERESTARTSYS;	return 0;}/* * Write to the aux device. */#if 0static ssize_t write_aux(struct file * file, const char * buffer,			 size_t count, loff_t *ppos){	ssize_t retval = 0;	if (count) {		ssize_t written = 0;		if (count > 32)			count = 32; /* Limit to 32 bytes. */		do {			char c;			get_user(c, buffer++);			aux_write_dev(c);			written++;		} while (--count);		retval = -EIO;		if (written) {			retval = written;			file->f_dentry->d_inode->i_mtime = CURRENT_TIME;		}	}	return retval;}#endifstatic int set_ir_map(int keymap){	switch(keymap) {		case 1:			ir_map = ir_map_coship;			printk("INFO: sp_keyb: ir_map = ir_map_coship\n");			break;		default:			ir_map = ir_map_sunplus;			printk("INFO: sp_keyb: ir_map = ir_map_sunplus\n");			break;	}	return 0;}/* No kernel lock held - fine */static unsigned int aux_poll(struct file *file, poll_table * wait){	poll_wait(file, &queue->proc_list, wait);	if (!queue_empty())		return POLLIN | POLLRDNORM;	return 0;}struct file_operations psaux_fops = {	read:		read_aux,//	write:		write_aux,	poll:		aux_poll,	open:		open_aux,	release:	release_aux,	fasync:		fasync_aux,};/* * Initialize driver. */static struct miscdevice psaux_mouse = {	/*PSMOUSE_MINOR*/2, "psaux1", &psaux_fops};int __init psaux_init(void){	int retval;	printk("Sunplus DVD PS/2 Keyboard Driver Initial\n");//	printk("INFO: sp_keyb v0.1c(2003.11.28)\n");//	printk("INFO: sp_keyb v0.1d(2003.12.30)[SUNPLUS IR]\n");//	printk("INFO: sp_keyb v0.1d(2004.01.02)[SUNPLUS IR]\n");//	printk("INFO: sp_keyb v0.1e(2004.01.02)[debug, ir_type]\n");	if ((retval = misc_register(&psaux_mouse)))		return retval;	queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);	if (queue == NULL) {		printk(KERN_ERR "psaux_init(): out of memory\n");		misc_deregister(&psaux_mouse);		return -ENOMEM;	}	memset(queue, 0, sizeof(*queue));	queue->head = queue->tail = 0;	init_waitqueue_head(&queue->proc_list);	set_ir_map(ir_type);	init_kbd();#ifdef SUPPORT_IR	init_ir();#endif	return 0;}#ifdef CONFIG_PROC_FS#include <linux/proc_fs.h>#define	DRVNAME	"sp_keyb"#define	PROCNAME "driver/" DRVNAME//char sp_keyb_version[]="sp_keyb: v0.1(2004.01.19)";char sp_keyb_version[]="sp_keyb: v0.2a(2004.02.23) use_keyb use_ir time_tick";static int sp_keyb_read_proc(char *buf, char **start, off_t offset,			   int len, int *eof, void *private){	int clen=0;	clen += sprintf(buf + clen, "%s\n", sp_keyb_version);	*start = buf + offset;	if (clen > offset)		clen -= offset;	else		clen = 0;	return clen < len ? clen : len;}#endif	//CONFIG_PROC_FSstatic int init_module(void){#ifdef CONFIG_PROC_FS	create_proc_read_entry(PROCNAME, 0, 0, sp_keyb_read_proc, NULL);#endif	return psaux_init();	}static void cleanup_module(void){	#ifdef CONFIG_PROC_FS	remove_proc_entry(PROCNAME, NULL);#endif	del_timer(&keyboard_timer); //yhwang for testing 	misc_deregister(&psaux_mouse);	printk("cleanup_module\n");	return;}MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -