Пример #1
0
/* read one byte from the keyboard if it's allowed */
static int
ukbd_read(keyboard_t *kbd, int wait)
{
	ukbd_state_t *state;
	int usbcode;
#ifdef UKBD_EMULATE_ATSCANCODE
	int keycode;
	int scancode;
#endif

	state = (ukbd_state_t *)kbd->kb_data;
#ifdef UKBD_EMULATE_ATSCANCODE
	if (state->ks_buffered_char[0]) {
		scancode = state->ks_buffered_char[0];
		if (scancode & SCAN_PREFIX) {
			state->ks_buffered_char[0] = scancode & ~SCAN_PREFIX;
			return ((scancode & SCAN_PREFIX_E0) ? 0xe0 : 0xe1);
		} else {
			state->ks_buffered_char[0] = state->ks_buffered_char[1];
			state->ks_buffered_char[1] = 0;
			return scancode;
		}
	}
#endif /* UKBD_EMULATE_ATSCANCODE */

	usbcode = ukbd_getc(state, wait);
	if (!KBD_IS_ACTIVE(kbd) || (usbcode == -1)) {
		return -1;
	}
	++kbd->kb_count;
#ifdef UKBD_EMULATE_ATSCANCODE
	keycode = ukbd_trtab[KEY_INDEX(usbcode)];
	if (keycode == NN) {
		return -1;
	}

	scancode = keycode2scancode(keycode, state->ks_ndata.modifiers,
				    usbcode & KEY_RELEASE);
	if (scancode & SCAN_PREFIX) {
		if (scancode & SCAN_PREFIX_CTL) {
			state->ks_buffered_char[0] =
				0x1d | (scancode & SCAN_RELEASE); /* Ctrl */
			state->ks_buffered_char[1] = scancode & ~SCAN_PREFIX;
		} else if (scancode & SCAN_PREFIX_SHIFT) {
			state->ks_buffered_char[0] =
				0x2a | (scancode & SCAN_RELEASE); /* Shift */
			state->ks_buffered_char[1] =
				scancode & ~SCAN_PREFIX_SHIFT;
		} else {
			state->ks_buffered_char[0] = scancode & ~SCAN_PREFIX;
			state->ks_buffered_char[1] = 0;
		}
		return ((scancode & SCAN_PREFIX_E0) ? 0xe0 : 0xe1);
	}
	return scancode;
#else /* !UKBD_EMULATE_ATSCANCODE */
	return usbcode;
#endif /* UKBD_EMULATE_ATSCANCODE */
}
Пример #2
0
/* read char from the keyboard */
static u_int
ukbd_read_char(keyboard_t *kbd, int wait)
{
	ukbd_state_t *state;
	u_int action;
	int usbcode;
	int keycode;
#ifdef UKBD_EMULATE_ATSCANCODE
	int scancode;
#endif

	state = (ukbd_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;
	}

#ifdef UKBD_EMULATE_ATSCANCODE
	/* do we have a pending raw scan code? */
	if (state->ks_mode == K_RAW) {
		if (state->ks_buffered_char[0]) {
			scancode = state->ks_buffered_char[0];
			if (scancode & SCAN_PREFIX) {
				state->ks_buffered_char[0] =
					scancode & ~SCAN_PREFIX;
				return ((scancode & SCAN_PREFIX_E0) ? 0xe0 : 0xe1);
			} else {
				state->ks_buffered_char[0] =
					state->ks_buffered_char[1];
				state->ks_buffered_char[1] = 0;
				return scancode;
			}
		}
	}
#endif /* UKBD_EMULATE_ATSCANCODE */

	/* see if there is something in the keyboard port */
	/* XXX */
	usbcode = ukbd_getc(state, wait);
	if (usbcode == -1) {
		return NOKEY;
	}
	++kbd->kb_count;

#ifdef UKBD_EMULATE_ATSCANCODE
	/* USB key index -> key code -> AT scan code */
	keycode = ukbd_trtab[KEY_INDEX(usbcode)];
	if (keycode == NN) {
		return NOKEY;
	}

	/* return an AT scan code for the K_RAW mode */
	if (state->ks_mode == K_RAW) {
		scancode = keycode2scancode(keycode, state->ks_ndata.modifiers,
					    usbcode & KEY_RELEASE);
		if (scancode & SCAN_PREFIX) {
			if (scancode & SCAN_PREFIX_CTL) {
				state->ks_buffered_char[0] =
					0x1d | (scancode & SCAN_RELEASE);
				state->ks_buffered_char[1] =
					scancode & ~SCAN_PREFIX;
			} else if (scancode & SCAN_PREFIX_SHIFT) {
				state->ks_buffered_char[0] =
					0x2a | (scancode & SCAN_RELEASE);
				state->ks_buffered_char[1] =
					scancode & ~SCAN_PREFIX_SHIFT;
			} else {
				state->ks_buffered_char[0] =
					scancode & ~SCAN_PREFIX;
				state->ks_buffered_char[1] = 0;
			}
			return ((scancode & SCAN_PREFIX_E0) ? 0xe0 : 0xe1);
		}
		return scancode;
	}
#else /* !UKBD_EMULATE_ATSCANCODE */
	/* return the byte as is for the K_RAW mode */
	if (state->ks_mode == K_RAW) {
		return usbcode;
	}

	/* USB key index -> key code */
	keycode = ukbd_trtab[KEY_INDEX(usbcode)];
	if (keycode == NN) {
		return NOKEY;
	}
#endif /* UKBD_EMULATE_ATSCANCODE */

	switch (keycode) {
	case 0x38:	/* left alt (compose key) */
		if (usbcode & KEY_RELEASE) {
			if (state->ks_flags & COMPOSE) {
				state->ks_flags &= ~COMPOSE;
				if (state->ks_composed_char > UCHAR_MAX)
					state->ks_composed_char = 0;
			}
		} else {
			if (!(state->ks_flags & COMPOSE)) {
				state->ks_flags |= COMPOSE;
				state->ks_composed_char = 0;
			}
		}
		break;
	/* XXX: I don't like these... */
	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 (usbcode & KEY_RELEASE)
		keycode |= SCAN_RELEASE;
	if (state->ks_mode == K_CODE) {
		return keycode;
	}

	/* 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 SCAN_RELEASE | 0x47:
		case SCAN_RELEASE | 0x48:
		case SCAN_RELEASE | 0x49:		/* keypad 7,8,9 */
		case SCAN_RELEASE | 0x4B:
		case SCAN_RELEASE | 0x4C:
		case SCAN_RELEASE | 0x4D:		/* keypad 4,5,6 */
		case SCAN_RELEASE | 0x4F:
		case SCAN_RELEASE | 0x50:
		case SCAN_RELEASE | 0x51:		/* keypad 1,2,3 */
		case SCAN_RELEASE | 0x52:		/* 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, SCAN_CHAR(keycode),
				  keycode & SCAN_RELEASE, &state->ks_state,
				  &state->ks_accents);
	if (action == NOKEY) {
		goto next_code;
	} else {
		return action;
	}
	/* NOTREACHED */
}
Пример #3
0
static u_int
sunkbd_read_char(keyboard_t *kbd, int wait)
{
	struct sunkbd_softc *sc;
	int key, release, repeated, suncode;

	sc = (struct sunkbd_softc *)kbd;

#if defined(SUNKBD_EMULATE_ATKBD)
	if (sc->sc_mode == K_RAW && sc->sc_buffered_char[0]) {
		key = sc->sc_buffered_char[0];
		if (key & SCAN_PREFIX) {
			sc->sc_buffered_char[0] = key & ~SCAN_PREFIX;
			return ((key & SCAN_PREFIX_E0) ? 0xe0 : 0xe1);
		} else {
			sc->sc_buffered_char[0] = sc->sc_buffered_char[1];
			sc->sc_buffered_char[1] = 0;
			return (key);
		}
	}
#endif

	repeated = 0;
	if (sc->sc_repeating) {
		repeated = 1;
		sc->sc_repeating = 0;
		callout_reset(&sc->sc_repeat_callout, hz / 10,
		    sunkbd_repeat, sc);
		suncode = sc->sc_repeat_key;
		goto process_code;
	}

	for (;;) {
 next_code:
		if (!(sc->sc_flags & KPCOMPOSE) && (sc->sc_composed_char > 0)) {
			key = sc->sc_composed_char;
			sc->sc_composed_char = 0;
			if (key > UCHAR_MAX)
				return (ERRKEY);
			return (key);
		}

		if (sc->sc_uart != NULL && !uart_rx_empty(sc->sc_uart)) {
			suncode = uart_rx_get(sc->sc_uart);
		} else if (sc->sc_polling != 0 && sc->sc_sysdev != NULL) {
			if (wait)
				suncode = uart_getc(sc->sc_sysdev);
			else if ((suncode = uart_poll(sc->sc_sysdev)) == -1)
				return (NOKEY);
		} else {
			return (NOKEY);
		}

		switch (suncode) {
		case SKBD_RSP_IDLE:
			break;
		default:
 process_code:
			++kbd->kb_count;
			key = SKBD_KEY_CHAR(suncode);
			release = suncode & SKBD_KEY_RELEASE;
			if (!repeated) {
				if (release == 0) {
					callout_reset(&sc->sc_repeat_callout,
					    hz / 2, sunkbd_repeat, sc);
					sc->sc_repeat_key = suncode;
				} else if (sc->sc_repeat_key == key) {
					callout_stop(&sc->sc_repeat_callout);
					sc->sc_repeat_key = -1;
				}
			}

#if defined(SUNKBD_EMULATE_ATKBD)
			key = sunkbd_trtab[key];
			if (key == NOTR)
				return (NOKEY);

			if (!repeated) {
				switch (key) {
				case 0x1d:	/* ctrl */
					if (release != 0)
						sc->sc_flags &= ~CTLS;
					else
						sc->sc_flags |= CTLS;
					break;
				case 0x2a:	/* left shift */
				case 0x36:	/* right shift */
					if (release != 0)
						sc->sc_flags &= ~SHIFTS;
					else
						sc->sc_flags |= SHIFTS;
					break;
				case 0x38:	/* alt */
				case 0x5d:	/* altgr */
					if (release != 0)
						sc->sc_flags &= ~ALTS;
					else
						sc->sc_flags |= ALTS;
					break;
				}
			}
			if (sc->sc_mode == K_RAW) {
				key = keycode2scancode(key, sc->sc_flags,
				    release);
				if (key & SCAN_PREFIX) {
					if (key & SCAN_PREFIX_CTL) {
						sc->sc_buffered_char[0] =
						    0x1d | (key & SCAN_RELEASE);
						sc->sc_buffered_char[1] =
						    key & ~SCAN_PREFIX;
					} else if (key & SCAN_PREFIX_SHIFT) {
						sc->sc_buffered_char[0] =
						    0x2a | (key & SCAN_RELEASE);
						sc->sc_buffered_char[1] =
						    key & ~SCAN_PREFIX_SHIFT;
					} else {
						sc->sc_buffered_char[0] =
						    key & ~SCAN_PREFIX;
						sc->sc_buffered_char[1] = 0;
					}
					return ((key & SCAN_PREFIX_E0) ?
					    0xe0 : 0xe1);
				}
				return (key);
			}
			switch (key) {
			case 0x5c:	/* print screen */
				if (sc->sc_flags & ALTS)
					key = 0x54;	/* sysrq */
				break;
			case 0x68:	/* pause/break */
				if (sc->sc_flags & CTLS)
					key = 0x6c;	/* break */
				break;
			}

			if (sc->sc_mode == K_CODE)
				return (key | release);
#else
			if (sc->sc_mode == K_RAW || sc->sc_mode == K_CODE)
				return (suncode);
#endif

#if defined(SUNKBD_EMULATE_ATKBD)
			if (key == 0x38) {	/* left alt (KP compose key) */
#else
			if (key == 0x13) {	/* left alt (KP compose key) */
#endif
				if (release != 0) {
					if (sc->sc_flags & KPCOMPOSE) {
						sc->sc_flags &= ~KPCOMPOSE;
						if (sc->sc_composed_char >
						    UCHAR_MAX)
							sc->sc_composed_char =
							    0;
					}
				} else {
					if (!(sc->sc_flags & KPCOMPOSE)) {
						sc->sc_flags |= KPCOMPOSE;
						sc->sc_composed_char = 0;
					}
				}
			}
			if (sc->sc_flags & KPCOMPOSE) {
				switch (suncode) {
				case 0x44:			/* KP 7 */
				case 0x45:			/* KP 8 */
				case 0x46:			/* KP 9 */
					sc->sc_composed_char *= 10;
					sc->sc_composed_char += suncode - 0x3d;
					if (sc->sc_composed_char > UCHAR_MAX)
						return (ERRKEY);
					goto next_code;
				case 0x5b:			/* KP 4 */
				case 0x5c:			/* KP 5 */
				case 0x5d:			/* KP 6 */
					sc->sc_composed_char *= 10;
					sc->sc_composed_char += suncode - 0x58;
					if (sc->sc_composed_char > UCHAR_MAX)
						return (ERRKEY);
					goto next_code;
				case 0x70:			/* KP 1 */
				case 0x71:			/* KP 2 */
				case 0x72:			/* KP 3 */
					sc->sc_composed_char *= 10;
					sc->sc_composed_char += suncode - 0x6f;
					if (sc->sc_composed_char > UCHAR_MAX)
						return (ERRKEY);
					goto next_code;
				case 0x5e:			/* KP 0 */
					sc->sc_composed_char *= 10;
					if (sc->sc_composed_char > UCHAR_MAX)
						return (ERRKEY);
					goto next_code;

				case 0x44 | SKBD_KEY_RELEASE:	/* KP 7 */
				case 0x45 | SKBD_KEY_RELEASE:	/* KP 8 */
				case 0x46 | SKBD_KEY_RELEASE:	/* KP 9 */
				case 0x5b | SKBD_KEY_RELEASE:	/* KP 4 */
				case 0x5c | SKBD_KEY_RELEASE:	/* KP 5 */
				case 0x5d | SKBD_KEY_RELEASE:	/* KP 6 */
				case 0x70 | SKBD_KEY_RELEASE:	/* KP 1 */
				case 0x71 | SKBD_KEY_RELEASE:	/* KP 2 */
				case 0x72 | SKBD_KEY_RELEASE:	/* KP 3 */
				case 0x5e | SKBD_KEY_RELEASE:	/* KP 0 */
					goto next_code;
				default:
					if (sc->sc_composed_char > 0) {
						sc->sc_flags &= ~KPCOMPOSE;
						sc->sc_composed_char = 0;
						return (ERRKEY);
					}
				}
			}

			key = genkbd_keyaction(kbd, key, release,
			    &sc->sc_state, &sc->sc_accents);
			if (key != NOKEY || repeated)
				return (key);
		}
	}
	return (0);
}

static int
sunkbd_check_char(keyboard_t *kbd)
{
	struct sunkbd_softc *sc;

	if (!KBD_IS_ACTIVE(kbd))
		return (FALSE);

	sc = (struct sunkbd_softc *)kbd;
	if (!(sc->sc_flags & KPCOMPOSE) && (sc->sc_composed_char > 0))
		return (TRUE);

	return (sunkbd_check(kbd));
}

static int
sunkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t data)
{
	struct sunkbd_softc *sc;
	int c, error;
#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5)
	int ival;
#endif

	sc = (struct sunkbd_softc *)kbd;
	error = 0;
	switch (cmd) {
	case KDGKBMODE:
		*(int *)data = sc->sc_mode;
		break;
#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5)
	case _IO('K', 7):
		ival = IOCPARM_IVAL(data);
		data = (caddr_t)&ival;
		/* FALLTHROUGH */
#endif
	case KDSKBMODE:
		switch (*(int *)data) {
		case K_XLATE:
			if (sc->sc_mode != K_XLATE) {
				/* make lock key state and LED state match */
				sc->sc_state &= ~LOCK_MASK;
				sc->sc_state |= KBD_LED_VAL(kbd);
			}
			/* FALLTHROUGH */
		case K_RAW:
		case K_CODE:
			if (sc->sc_mode != *(int *)data) {
				sunkbd_clear_state(kbd);
				sc->sc_mode = *(int *)data;
			}
			break;
		default:
			error = EINVAL;
			break;
		}
		break;
	case KDGETLED:
		*(int *)data = KBD_LED_VAL(kbd);
		break;
#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5)
	case _IO('K', 66):
		ival = IOCPARM_IVAL(data);
		data = (caddr_t)&ival;
		/* FALLTHROUGH */
#endif
	case KDSETLED:
		if (*(int *)data & ~LOCK_MASK) {
			error = EINVAL;
			break;
		}
		if (sc->sc_sysdev == NULL)
			break;
		c = 0;
		if (*(int *)data & CLKED)
			c |= SKBD_LED_CAPSLOCK;
		if (*(int *)data & NLKED)
			c |= SKBD_LED_NUMLOCK;
		if (*(int *)data & SLKED)
			c |= SKBD_LED_SCROLLLOCK;
		uart_lock(sc->sc_sysdev->hwmtx);
		sc->sc_sysdev->ops->putc(&sc->sc_sysdev->bas, SKBD_CMD_SETLED);
		sc->sc_sysdev->ops->putc(&sc->sc_sysdev->bas, c);
		uart_unlock(sc->sc_sysdev->hwmtx);
		KBD_LED_VAL(kbd) = *(int *)data;
		break;
	case KDGKBSTATE:
		*(int *)data = sc->sc_state & LOCK_MASK;
		break;
#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5)
	case _IO('K', 20):
		ival = IOCPARM_IVAL(data);
		data = (caddr_t)&ival;
		/* FALLTHROUGH */
#endif
	case KDSKBSTATE:
		if (*(int *)data & ~LOCK_MASK) {
			error = EINVAL;
			break;
		}
		sc->sc_state &= ~LOCK_MASK;
		sc->sc_state |= *(int *)data;
		/* set LEDs and quit */
		return (sunkbd_ioctl(kbd, KDSETLED, data));
	case KDSETREPEAT:
	case KDSETRAD:
		break;
	case PIO_KEYMAP:
	case OPIO_KEYMAP:
	case PIO_KEYMAPENT:
	case PIO_DEADKEYMAP:
	default:
		return (genkbd_commonioctl(kbd, cmd, data));
	}
	return (error);
}

static int
sunkbd_lock(keyboard_t *kbd, int lock)
{

	TODO;
	return (0);
}
Пример #4
0
static u_int 
akbd_read_char(keyboard_t *kbd, int wait) 
{
	struct adb_kbd_softc *sc;
	uint16_t key;
	uint8_t adb_code;
	int i;

	sc = (struct adb_kbd_softc *)(kbd);

	mtx_lock(&sc->sc_mutex);

#if defined(AKBD_EMULATE_ATKBD)
	if (sc->sc_mode == K_RAW && sc->at_buffered_char[0]) {
		key = sc->at_buffered_char[0];
		if (key & SCAN_PREFIX) {
			sc->at_buffered_char[0] = key & ~SCAN_PREFIX;
			key = (key & SCAN_PREFIX_E0) ? 0xe0 : 0xe1;
		} else {
			sc->at_buffered_char[0] = sc->at_buffered_char[1];
			sc->at_buffered_char[1] = 0;
		}

		mtx_unlock(&sc->sc_mutex);

		return (key);
	}
#endif

	if (!sc->buffers && wait)
		cv_wait(&sc->sc_cv,&sc->sc_mutex);

	if (!sc->buffers) {
		mtx_unlock(&sc->sc_mutex);
		return (NOKEY);
	}

	adb_code = sc->buffer[0];

	for (i = 1; i < sc->buffers; i++)
		sc->buffer[i-1] = sc->buffer[i];

	sc->buffers--;

	#ifdef AKBD_EMULATE_ATKBD
		key = adb_to_at_scancode_map[adb_code & 0x7f];
		if (sc->sc_mode == K_CODE) {
			/* Add the key-release bit */
			key |= adb_code & 0x80;
		} else if (sc->sc_mode == K_RAW) {
			/*
			 * In the raw case, we have to emulate the gross
			 * variable-length AT keyboard thing. Since this code
			 * is copied from sunkbd, which is the same code
			 * as ukbd, it might be nice to have this centralized.
			 */

			key = keycode2scancode(key, 
			    0, adb_code & 0x80);

			if (key & SCAN_PREFIX) {
				if (key & SCAN_PREFIX_CTL) {
					sc->at_buffered_char[0] =
					    0x1d | (key & SCAN_RELEASE);
					sc->at_buffered_char[1] =
					    key & ~SCAN_PREFIX;
				} else if (key & SCAN_PREFIX_SHIFT) {
					sc->at_buffered_char[0] =
					    0x2a | (key & SCAN_RELEASE);
					sc->at_buffered_char[1] =
					    key & ~SCAN_PREFIX_SHIFT;
				} else {
					sc->at_buffered_char[0] =
					    key & ~SCAN_PREFIX;
					sc->at_buffered_char[1] = 0;
				}
	
				key = (key & SCAN_PREFIX_E0) ? 0xe0 : 0xe1;
			}
		}
	#else
		key = adb_code;
	#endif

	mtx_unlock(&sc->sc_mutex);

	return (key);
}