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

📄 keyboard.c

📁 Minix3.11的源码。[MINIX 3是一个为高可靠性应用而设计的自由且简洁的类UNIX系统。]
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Keyboard driver for PC's and AT's. * * Changes:  *   Jul 13, 2004   processes can observe function keys  (Jorrit N. Herder) *   Jun 15, 2004   removed wreboot(), except panic dumps (Jorrit N. Herder) *   Feb 04, 1994   loadable keymaps  (Marcus Hampel) */#include "../drivers.h"#include <sys/time.h>#include <sys/select.h>#include <termios.h>#include <signal.h>#include <unistd.h>#include <minix/callnr.h>#include <minix/com.h>#include <minix/keymap.h>#include "tty.h"#include "keymaps/us-std.src"#include "../../kernel/const.h"#include "../../kernel/config.h"#include "../../kernel/type.h"#include "../../kernel/proc.h"int irq_hook_id = -1;/* Standard and AT keyboard.  (PS/2 MCA implies AT throughout.) */#define KEYBD		0x60	/* I/O port for keyboard data *//* AT keyboard. */#define KB_COMMAND	0x64	/* I/O port for commands on AT */#define KB_STATUS	0x64	/* I/O port for status on AT */#define KB_ACK		0xFA	/* keyboard ack response */#define KB_OUT_FULL	0x01	/* status bit set when keypress char pending */#define KB_IN_FULL	0x02	/* status bit set when not ready to receive */#define LED_CODE	0xED	/* command to keyboard to set LEDs */#define MAX_KB_ACK_RETRIES 0x1000	/* max #times to wait for kb ack */#define MAX_KB_BUSY_RETRIES 0x1000	/* max #times to loop while kb busy */#define KBIT		0x80	/* bit used to ack characters to keyboard *//* Miscellaneous. */#define ESC_SCAN	0x01	/* reboot key when panicking */#define SLASH_SCAN	0x35	/* to recognize numeric slash */#define RSHIFT_SCAN	0x36	/* to distinguish left and right shift */#define HOME_SCAN	0x47	/* first key on the numeric keypad */#define INS_SCAN	0x52	/* INS for use in CTRL-ALT-INS reboot */#define DEL_SCAN	0x53	/* DEL for use in CTRL-ALT-DEL reboot */#define CONSOLE		   0	/* line number for console */#define KB_IN_BYTES	  32	/* size of keyboard input buffer */PRIVATE char ibuf[KB_IN_BYTES];	/* input buffer */PRIVATE char *ihead = ibuf;	/* next free spot in input buffer */PRIVATE char *itail = ibuf;	/* scan code to return to TTY */PRIVATE int icount;		/* # codes in buffer */PRIVATE int esc;		/* escape scan code detected? */PRIVATE int alt_l;		/* left alt key state */PRIVATE int alt_r;		/* right alt key state */PRIVATE int alt;		/* either alt key */PRIVATE int ctrl_l;		/* left control key state */PRIVATE int ctrl_r;		/* right control key state */PRIVATE int ctrl;		/* either control key */PRIVATE int shift_l;		/* left shift key state */PRIVATE int shift_r;		/* right shift key state */PRIVATE int shift;		/* either shift key */PRIVATE int num_down;		/* num lock key depressed */PRIVATE int caps_down;		/* caps lock key depressed */PRIVATE int scroll_down;	/* scroll lock key depressed */PRIVATE int locks[NR_CONS];	/* per console lock keys state *//* Lock key active bits.  Chosen to be equal to the keyboard LED bits. */#define SCROLL_LOCK	0x01#define NUM_LOCK	0x02#define CAPS_LOCK	0x04PRIVATE char numpad_map[] =		{'H', 'Y', 'A', 'B', 'D', 'C', 'V', 'U', 'G', 'S', 'T', '@'};/* Variables and definition for observed function keys. */typedef struct observer { int proc_nr; int events; } obs_t;PRIVATE obs_t  fkey_obs[12];	/* observers for F1-F12 */PRIVATE obs_t sfkey_obs[12];	/* observers for SHIFT F1-F12 */FORWARD _PROTOTYPE( int kb_ack, (void) 					);FORWARD _PROTOTYPE( int kb_wait, (void)				 	);FORWARD _PROTOTYPE( int func_key, (int scode) 				);FORWARD _PROTOTYPE( int scan_keyboard, (void) 				);FORWARD _PROTOTYPE( unsigned make_break, (int scode) 			);FORWARD _PROTOTYPE( void set_leds, (void) 				);FORWARD _PROTOTYPE( void show_key_mappings, (void) 			);FORWARD _PROTOTYPE( int kb_read, (struct tty *tp, int try) 		);FORWARD _PROTOTYPE( unsigned map_key, (int scode) 			);/*===========================================================================* *				map_key0				     * *===========================================================================*//* Map a scan code to an ASCII code ignoring modifiers. */#define map_key0(scode)	 \	((unsigned) keymap[(scode) * MAP_COLS])/*===========================================================================* *				map_key					     * *===========================================================================*/PRIVATE unsigned map_key(scode)int scode;{/* Map a scan code to an ASCII code. */  int caps, column, lk;  u16_t *keyrow;  if (scode == SLASH_SCAN && esc) return '/';	/* don't map numeric slash */  keyrow = &keymap[scode * MAP_COLS];  caps = shift;  lk = locks[ccurrent];  if ((lk & NUM_LOCK) && HOME_SCAN <= scode && scode <= DEL_SCAN) caps = !caps;  if ((lk & CAPS_LOCK) && (keyrow[0] & HASCAPS)) caps = !caps;  if (alt) {	column = 2;	if (ctrl || alt_r) column = 3;	/* Ctrl + Alt == AltGr */	if (caps) column = 4;  } else {	column = 0;	if (caps) column = 1;	if (ctrl) column = 5;  }  return keyrow[column] & ~HASCAPS;}/*===========================================================================* *				kbd_interrupt				     * *===========================================================================*/PUBLIC void kbd_interrupt(m_ptr)message *m_ptr;{/* A keyboard interrupt has occurred.  Process it. */  int scode;  static timer_t timer;		/* timer must be static! */  /* Fetch the character from the keyboard hardware and acknowledge it. */  scode = scan_keyboard();  /* Store the scancode in memory so the task can get at it later. */  if (icount < KB_IN_BYTES) {	*ihead++ = scode;	if (ihead == ibuf + KB_IN_BYTES) ihead = ibuf;	icount++;	tty_table[ccurrent].tty_events = 1;	if (tty_table[ccurrent].tty_select_ops & SEL_RD) {		select_retry(&tty_table[ccurrent]);	}  }}/*===========================================================================* *				kb_read					     * *===========================================================================*/PRIVATE int kb_read(tp, try)tty_t *tp;int try;{/* Process characters from the circular keyboard buffer. */  char buf[3];  int scode;  unsigned ch;  tp = &tty_table[ccurrent];		/* always use the current console */  if (try) {  	if (icount > 0) return 1;  	return 0;  }  while (icount > 0) {	scode = *itail++;			/* take one key scan code */	if (itail == ibuf + KB_IN_BYTES) itail = ibuf;	icount--;	/* Function keys are being used for debug dumps. */	if (func_key(scode)) continue;	/* Perform make/break processing. */	ch = make_break(scode);	if (ch <= 0xFF) {		/* A normal character. */		buf[0] = ch;		(void) in_process(tp, buf, 1);	} else	if (HOME <= ch && ch <= INSRT) {		/* An ASCII escape sequence generated by the numeric pad. */		buf[0] = ESC;		buf[1] = '[';		buf[2] = numpad_map[ch - HOME];		(void) in_process(tp, buf, 3);	} else	if (ch == ALEFT) {		/* Choose lower numbered console as current console. */		select_console(ccurrent - 1);		set_leds();	} else	if (ch == ARIGHT) {		/* Choose higher numbered console as current console. */		select_console(ccurrent + 1);		set_leds();	} else	if (AF1 <= ch && ch <= AF12) {		/* Alt-F1 is console, Alt-F2 is ttyc1, etc. */		select_console(ch - AF1);		set_leds();	} else	if (CF1 <= ch && ch <= CF12) {	    switch(ch) {  		case CF1: show_key_mappings(); break;   		case CF3: toggle_scroll(); break; /* hardware <-> software */	  		case CF7: sigchar(&tty_table[CONSOLE], SIGQUIT); break;  		case CF8: sigchar(&tty_table[CONSOLE], SIGINT); break;  		case CF9: sigchar(&tty_table[CONSOLE], SIGKILL); break;  	    }	}  }  return 1;}/*===========================================================================* *				make_break				     * *===========================================================================*/PRIVATE unsigned make_break(scode)int scode;			/* scan code of key just struck or released */{/* This routine can handle keyboards that interrupt only on key depression, * as well as keyboards that interrupt on key depression and key release. * For efficiency, the interrupt routine filters out most key releases. */  int ch, make, escape;  static int CAD_count = 0;  /* Check for CTRL-ALT-DEL, and if found, halt the computer. This would   * be better done in keyboard() in case TTY is hung, except control and   * alt are set in the high level code.   */  if (ctrl && alt && (scode == DEL_SCAN || scode == INS_SCAN))  {	if (++CAD_count == 3) sys_abort(RBT_HALT);	sys_kill(INIT_PROC_NR, SIGABRT);	return -1;  }  /* High-order bit set on key release. */  make = (scode & KEY_RELEASE) == 0;		/* true if pressed */  ch = map_key(scode &= ASCII_MASK);		/* map to ASCII */  escape = esc;		/* Key is escaped?  (true if added since the XT) */  esc = 0;  switch (ch) {  	case CTRL:		/* Left or right control key */		*(escape ? &ctrl_r : &ctrl_l) = make;		ctrl = ctrl_l | ctrl_r;		break;  	case SHIFT:		/* Left or right shift key */		*(scode == RSHIFT_SCAN ? &shift_r : &shift_l) = make;		shift = shift_l | shift_r;		break;  	case ALT:		/* Left or right alt key */		*(escape ? &alt_r : &alt_l) = make;		alt = alt_l | alt_r;		break;  	case CALOCK:		/* Caps lock - toggle on 0 -> 1 transition */		if (caps_down < make) {			locks[ccurrent] ^= CAPS_LOCK;			set_leds();		}		caps_down = make;		break;  	case NLOCK:		/* Num lock */		if (num_down < make) {			locks[ccurrent] ^= NUM_LOCK;			set_leds();		}		num_down = make;		break;  	case SLOCK:		/* Scroll lock */		if (scroll_down < make) {			locks[ccurrent] ^= SCROLL_LOCK;			set_leds();		}		scroll_down = make;		break;  	case EXTKEY:		/* Escape keycode */		esc = 1;		/* Next key is escaped */		return(-1);  	default:		/* A normal key */		if (make) return(ch);  }  /* Key release, or a shift type key. */  return(-1);}/*===========================================================================* *				set_leds				     * *===========================================================================*/PRIVATE void set_leds(){/* Set the LEDs on the caps, num, and scroll lock keys */  int s;  if (! machine.pc_at) return;	/* PC/XT doesn't have LEDs */  kb_wait();			/* wait for buffer empty  */  if ((s=sys_outb(KEYBD, LED_CODE)) != OK)      printf("Warning, sys_outb couldn't prepare for LED values: %d\n", s);   				/* prepare keyboard to accept LED values */  kb_ack();			/* wait for ack response  */  kb_wait();			/* wait for buffer empty  */  if ((s=sys_outb(KEYBD, locks[ccurrent])) != OK)      printf("Warning, sys_outb couldn't give LED values: %d\n", s);				/* give keyboard LED values */  kb_ack();			/* wait for ack response  */}/*===========================================================================* *				kb_wait					     * *===========================================================================*/PRIVATE int kb_wait(){/* Wait until the controller is ready; return zero if this times out. */  int retries, status, temp;

⌨️ 快捷键说明

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