atkbd.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 1,423 行 · 第 1/3 页

C
1,423
字号
			if (state != NULL)				free(state, M_DEVBUF);			if (keymap != NULL)				free(keymap, M_DEVBUF);			if (accmap != NULL)				free(accmap, M_DEVBUF);			if (fkeymap != NULL)				free(fkeymap, M_DEVBUF);			free(kbd, M_DEVBUF);			return ENOMEM;		}		bzero(state, sizeof(*state));	} else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {		return 0;	} else {		kbd = *kbdp;		state = (atkbd_state_t *)kbd->kb_data;		bzero(state, sizeof(*state));		keymap = kbd->kb_keymap;		accmap = kbd->kb_accentmap;		fkeymap = kbd->kb_fkeytab;		fkeymap_size = kbd->kb_fkeytab_size;	}	if (!KBD_IS_PROBED(kbd)) {		state->kbdc = kbdc_open(data[0]);		if (state->kbdc == NULL)			return ENXIO;		kbd_init_struct(kbd, ATKBD_DRIVER_NAME, KB_OTHER, unit, flags,				data[0], IO_KBDSIZE);		bcopy(&key_map, keymap, sizeof(key_map));		bcopy(&accent_map, accmap, sizeof(accent_map));		bcopy(fkey_tab, fkeymap,		      imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));		kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);		kbd->kb_data = (void *)state;			if (probe_keyboard(state->kbdc, flags)) { /* shouldn't happen */			if (flags & KB_CONF_FAIL_IF_NO_KBD)				return ENXIO;		} else {			KBD_FOUND_DEVICE(kbd);		}		atkbd_clear_state(kbd);		state->ks_mode = K_XLATE;		/* 		 * FIXME: set the initial value for lock keys in ks_state		 * according to the BIOS data?		 */		KBD_PROBE_DONE(kbd);	}	if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {		if (KBD_HAS_DEVICE(kbd)	    	    && init_keyboard(state->kbdc, &kbd->kb_type, kbd->kb_config)	    	    && (kbd->kb_config & KB_CONF_FAIL_IF_NO_KBD))			return ENXIO;		atkbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);		KBD_INIT_DONE(kbd);	}	if (!KBD_IS_CONFIGURED(kbd)) {		if (kbd_register(kbd) < 0)			return ENXIO;		KBD_CONFIG_DONE(kbd);	}	return 0;}/* finish using this keyboard */static intatkbd_term(keyboard_t *kbd){	kbd_unregister(kbd);	return 0;}/* keyboard interrupt routine */static intatkbd_intr(keyboard_t *kbd, void *arg){	atkbd_state_t *state;	int c;	if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) {		/* let the callback function to process the input */		(*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT,					    kbd->kb_callback.kc_arg);	} else {		/* read and discard the input; no one is waiting for input */		do {			c = atkbd_read_char(kbd, FALSE);		} while (c != NOKEY);		if (!KBD_HAS_DEVICE(kbd)) {			/*			 * The keyboard was not detected before;			 * it must have been reconnected!			 */			state = (atkbd_state_t *)kbd->kb_data;			init_keyboard(state->kbdc, &kbd->kb_type,				      kbd->kb_config);			atkbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);			KBD_FOUND_DEVICE(kbd);		}	}	return 0;}/* test the interface to the device */static intatkbd_test_if(keyboard_t *kbd){	int error;	int s;	error = 0;	empty_both_buffers(((atkbd_state_t *)kbd->kb_data)->kbdc, 10);	s = spltty();	if (!test_controller(((atkbd_state_t *)kbd->kb_data)->kbdc))		error = EIO;	else if (test_kbd_port(((atkbd_state_t *)kbd->kb_data)->kbdc) != 0)		error = EIO;	splx(s);	return error;}/*  * Enable the access to the device; until this function is called, * the client cannot read from the keyboard. */static intatkbd_enable(keyboard_t *kbd){	int s;	s = spltty();	KBD_ACTIVATE(kbd);	splx(s);	return 0;}/* disallow the access to the device */static intatkbd_disable(keyboard_t *kbd){	int s;	s = spltty();	KBD_DEACTIVATE(kbd);	splx(s);	return 0;}/* read one byte from the keyboard if it's allowed */static intatkbd_read(keyboard_t *kbd, int wait){	int c;	if (wait)		c = read_kbd_data(((atkbd_state_t *)kbd->kb_data)->kbdc);	else		c = read_kbd_data_no_wait(((atkbd_state_t *)kbd->kb_data)->kbdc);	return (KBD_IS_ACTIVE(kbd) ? c : -1);}/* check if data is waiting */static intatkbd_check(keyboard_t *kbd){	if (!KBD_IS_ACTIVE(kbd))		return FALSE;	return kbdc_data_ready(((atkbd_state_t *)kbd->kb_data)->kbdc);}/* read char from the keyboard */static u_intatkbd_read_char(keyboard_t *kbd, int wait){	atkbd_state_t *state;	u_int action;	int scancode;	int keycode;	state = (atkbd_state_t *)kbd->kb_data;next_code:	/* do we have a composed char to return? */	if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {		action = state->ks_composed_char;		state->ks_composed_char = 0;		if (action > UCHAR_MAX)			return ERRKEY;		return action;	}	/* see if there is something in the keyboard port */	if (wait) {		do {			scancode = read_kbd_data(state->kbdc);		} while (scancode == -1);	} else {		scancode = read_kbd_data_no_wait(state->kbdc);		if (scancode == -1)			return NOKEY;	}	/* return the byte as is for the K_RAW mode */	if (state->ks_mode == K_RAW)		return scancode;	/* translate the scan code into a keycode */	keycode = scancode & 0x7F;	switch (state->ks_prefix) {	case 0x00:	/* normal scancode */		switch(scancode) {		case 0xB8:	/* left alt (compose key) released */			if (state->ks_flags & COMPOSE) {				state->ks_flags &= ~COMPOSE;				if (state->ks_composed_char > UCHAR_MAX)					state->ks_composed_char = 0;			}			break;		case 0x38:	/* left alt (compose key) pressed */			if (!(state->ks_flags & COMPOSE)) {				state->ks_flags |= COMPOSE;				state->ks_composed_char = 0;			}			break;		case 0xE0:		case 0xE1:			state->ks_prefix = scancode;			goto next_code;		}		break;	case 0xE0:      /* 0xE0 prefix */		state->ks_prefix = 0;		switch (keycode) {		case 0x1C:	/* right enter key */			keycode = 0x59;			break;		case 0x1D:	/* right ctrl key */			keycode = 0x5A;			break;		case 0x35:	/* keypad divide key */	    		keycode = 0x5B;	    		break;		case 0x37:	/* print scrn key */	    		keycode = 0x5C;	    		break;		case 0x38:	/* right alt key (alt gr) */	    		keycode = 0x5D;	    		break;		case 0x46:	/* ctrl-pause/break on AT 101 (see below) */			keycode = 0x68;	    		break;		case 0x47:	/* grey home key */	    		keycode = 0x5E;	    		break;		case 0x48:	/* grey up arrow key */	    		keycode = 0x5F;	    		break;		case 0x49:	/* grey page up key */	    		keycode = 0x60;	    		break;		case 0x4B:	/* grey left arrow key */	    		keycode = 0x61;	    		break;		case 0x4D:	/* grey right arrow key */	    		keycode = 0x62;	    		break;		case 0x4F:	/* grey end key */	    		keycode = 0x63;	    		break;		case 0x50:	/* grey down arrow key */	    		keycode = 0x64;	    		break;		case 0x51:	/* grey page down key */	    		keycode = 0x65;	    		break;		case 0x52:	/* grey insert key */	    		keycode = 0x66;	    		break;		case 0x53:	/* grey delete key */	    		keycode = 0x67;	    		break;		/* the following 3 are only used on the MS "Natural" keyboard */		case 0x5b:	/* left Window key */	    		keycode = 0x69;	    		break;		case 0x5c:	/* right Window key */	    		keycode = 0x6a;	    		break;		case 0x5d:	/* menu key */	    		keycode = 0x6b;	    		break;		default:	/* ignore everything else */	    		goto next_code;		}		break;    	case 0xE1:	/* 0xE1 prefix */		/* 		 * The pause/break key on the 101 keyboard produces:		 * E1-1D-45 E1-9D-C5		 * Ctrl-pause/break produces:		 * E0-46 E0-C6 (See above.)		 */		state->ks_prefix = 0;		if (keycode == 0x1D)	    		state->ks_prefix = 0x1D;		goto next_code;		/* NOT REACHED */    	case 0x1D:	/* pause / break */		state->ks_prefix = 0;		if (keycode != 0x45)			goto next_code;		keycode = 0x68;		break;	}	if (kbd->kb_type == KB_84) {		switch (keycode) {		case 0x37:	/* *(numpad)/print screen */			if (state->ks_flags & SHIFTS)	    			keycode = 0x5c;	/* print screen */			break;		case 0x45:	/* num lock/pause */			if (state->ks_flags & CTLS)				keycode = 0x68;	/* pause */			break;		case 0x46:	/* scroll lock/break */			if (state->ks_flags & CTLS)				keycode = 0x6c;	/* break */			break;		}	} else if (kbd->kb_type == KB_101) {		switch (keycode) {		case 0x5c:	/* print screen */			if (state->ks_flags & ALTS)				keycode = 0x54;	/* sysrq */			break;		case 0x68:	/* pause/break */			if (state->ks_flags & CTLS)				keycode = 0x6c;	/* break */			break;		}	}	/* return the key code in the K_CODE mode */	if (state->ks_mode == K_CODE)		return (keycode | (scancode & 0x80));	/* compose a character code */	if (state->ks_flags & COMPOSE) {		switch (keycode) {		/* key pressed, process it */		case 0x47: case 0x48: case 0x49:	/* keypad 7,8,9 */			state->ks_composed_char *= 10;			state->ks_composed_char += keycode - 0x40;			if (state->ks_composed_char > UCHAR_MAX)				return ERRKEY;			goto next_code;		case 0x4B: case 0x4C: case 0x4D:	/* keypad 4,5,6 */			state->ks_composed_char *= 10;			state->ks_composed_char += keycode - 0x47;			if (state->ks_composed_char > UCHAR_MAX)				return ERRKEY;			goto next_code;		case 0x4F: case 0x50: case 0x51:	/* keypad 1,2,3 */			state->ks_composed_char *= 10;			state->ks_composed_char += keycode - 0x4E;			if (state->ks_composed_char > UCHAR_MAX)				return ERRKEY;			goto next_code;		case 0x52:				/* keypad 0 */			state->ks_composed_char *= 10;			if (state->ks_composed_char > UCHAR_MAX)				return ERRKEY;			goto next_code;		/* key released, no interest here */		case 0xC7: case 0xC8: case 0xC9:	/* keypad 7,8,9 */		case 0xCB: case 0xCC: case 0xCD:	/* keypad 4,5,6 */		case 0xCF: case 0xD0: case 0xD1:	/* keypad 1,2,3 */		case 0xD2:				/* keypad 0 */			goto next_code;		case 0x38:				/* left alt key */			break;		default:			if (state->ks_composed_char > 0) {				state->ks_flags &= ~COMPOSE;				state->ks_composed_char = 0;				return ERRKEY;			}			break;		}	}	/* keycode to key action */	action = genkbd_keyaction(kbd, keycode, scancode & 0x80,				  &state->ks_state, &state->ks_accents);	if (action == NOKEY)		goto next_code;	else		return action;}/* check if char is waiting */static intatkbd_check_char(keyboard_t *kbd){	atkbd_state_t *state;	if (!KBD_IS_ACTIVE(kbd))		return FALSE;	state = (atkbd_state_t *)kbd->kb_data;	if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0))		return TRUE;	return kbdc_data_ready(state->kbdc);}/* some useful control functions */static intatkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg){	/* trasnlate LED_XXX bits into the device specific bits */	static u_char ledmap[8] = {		0, 4, 2, 6, 1, 5, 3, 7,	};	atkbd_state_t *state = kbd->kb_data;	int error;	int s;	int i;	s = spltty();	switch (cmd) {	case KDGKBMODE:		/* get keyboard mode */		*(int *)arg = state->ks_mode;		break;	case KDSKBMODE:		/* set keyboard mode */		switch (*(int *)arg) {		case K_XLATE:			if (state->ks_mode != K_XLATE) {				/* make lock key state and LED state match */				state->ks_state &= ~LOCK_MASK;				state->ks_state |= KBD_LED_VAL(kbd);			}			/* FALL THROUGH */		case K_RAW:		case K_CODE:			if (state->ks_mode != *(int *)arg) {				atkbd_clear_state(kbd);				state->ks_mode = *(int *)arg;			}			break;		default:			splx(s);			return EINVAL;		}		break;	case KDGETLED:		/* get keyboard LED */		*(int *)arg = KBD_LED_VAL(kbd);		break;	case KDSETLED:		/* set keyboard LED */		/* NOTE: lock key state in ks_state won't be changed */		if (*(int *)arg & ~LOCK_MASK) {			splx(s);			return EINVAL;		}		i = *(int *)arg;		/* replace CAPS LED with ALTGR LED for ALTGR keyboards */

⌨️ 快捷键说明

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