Esempio n. 1
0
static int 
akbd_check(keyboard_t *kbd) 
{
	struct adb_kbd_softc *sc;

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

	sc = (struct adb_kbd_softc *)(kbd);

	mtx_lock(&sc->sc_mutex);
#ifdef AKBD_EMULATE_ATKBD
		if (sc->at_buffered_char[0]) {
			mtx_unlock(&sc->sc_mutex);
			return (TRUE);
		}
#endif

		if (sc->buffers > 0) {
			mtx_unlock(&sc->sc_mutex);
			return (TRUE); 
		}
	mtx_unlock(&sc->sc_mutex);

	return (FALSE);
}
Esempio n. 2
0
static void
akbd_repeat(void *xsc) {
	struct adb_kbd_softc *sc = xsc;
	int notify_kbd = 0;

	/* Fake an up/down key repeat so long as we have the
	   free buffers */
	mtx_lock(&sc->sc_mutex);
		if (sc->buffers < 7) {
			sc->buffer[sc->buffers++] = sc->last_press | (1 << 7);
			sc->buffer[sc->buffers++] = sc->last_press;

			notify_kbd = 1;
		}
	mtx_unlock(&sc->sc_mutex);

	if (notify_kbd && KBD_IS_ACTIVE(&sc->sc_kbd) 
	    && KBD_IS_BUSY(&sc->sc_kbd)) {
		sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd,
		    KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg);
	}

	/* Reschedule the callout */
	callout_reset(&sc->sc_repeater, ms_to_ticks(sc->sc_kbd.kb_delay2),
	    akbd_repeat, sc);
}
Esempio n. 3
0
/* check if data is waiting */
static int
pckbd_check(keyboard_t *kbd)
{
	if (!KBD_IS_ACTIVE(kbd))
		return FALSE;
	return kbdc_data_ready(((pckbd_state_t *)kbd->kb_data)->kbdc);
}
Esempio n. 4
0
/* check if data is waiting */
static int
ukbd_check(keyboard_t *kbd)
{
	ukbd_state_t *state;

	if (!KBD_IS_ACTIVE(kbd)) {
		return FALSE;
	}
	state = (ukbd_state_t *)kbd->kb_data;
	if (state->ks_polling) {
		crit_enter();
		usbd_dopoll(state->ks_iface);
		crit_exit();
	}
#ifdef UKBD_EMULATE_ATSCANCODE
	if (((ukbd_state_t *)kbd->kb_data)->ks_buffered_char[0]) {
		return TRUE;
	}
#endif
	if (((ukbd_state_t *)kbd->kb_data)->ks_inputs > 0) {
		return TRUE;
	}

	return FALSE;
}
Esempio n. 5
0
/* check if data is waiting */
static int
ckb_check(keyboard_t *kbd)
{
	struct ckb_softc *sc;
	int i;

	sc = kbd->kb_data;

	CKB_CTX_LOCK_ASSERT();

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

	if (sc->sc_flags & CKB_FLAG_POLLING) {
		return (1);
	};

	for (i = 0; i < sc->cols; i++)
		if (sc->scan_local[i] != sc->scan[i]) {
			return (1);
		};

	if (sc->sc_repeating)
		return (1);

	return (0);
}
Esempio n. 6
0
static int
sunkbd_check(keyboard_t *kbd)
{
	struct sunkbd_softc *sc;

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

	sc = (struct sunkbd_softc *)kbd;

#if defined(SUNKBD_EMULATE_ATKBD)
	if (sc->sc_buffered_char[0])
		return (TRUE);
#endif

	if (sc->sc_repeating)
		return (TRUE);

	if (sc->sc_uart != NULL && !uart_rx_empty(sc->sc_uart))
		return (TRUE);

	if (sc->sc_polling != 0 && sc->sc_sysdev != NULL &&
	    uart_rxready(sc->sc_sysdev))
		return (TRUE);

	return (FALSE);
}
Esempio n. 7
0
File: atkbd.c Progetto: MarginC/kame
/* keyboard interrupt routine */
static int
atkbd_intr(keyboard_t *kbd, void *arg)
{
	atkbd_state_t *state;
	int delay[2];
	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);
			get_typematic(kbd);
			delay[0] = kbd->kb_delay1;
			delay[1] = kbd->kb_delay2;
			atkbd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
			KBD_FOUND_DEVICE(kbd);
		}
	}
	return 0;
}
Esempio n. 8
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 */
}
Esempio n. 9
0
static int 
akbd_check_char(keyboard_t *kbd) 
{
	if (!KBD_IS_ACTIVE(kbd))
		return (FALSE);

	return (akbd_check(kbd));
}
Esempio n. 10
0
/* check if char is waiting */
static int
kmi_check_char_locked(keyboard_t *kbd)
{
	KMI_CTX_LOCK_ASSERT();

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

	return (kmi_check(kbd));
}
Esempio n. 11
0
/* check if char is waiting */
static int
ckb_check_char_locked(keyboard_t *kbd)
{
	CKB_CTX_LOCK_ASSERT();

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

	return (ckb_check(kbd));
}
Esempio n. 12
0
/* Currently unused. */
static int
ckb_read(keyboard_t *kbd, int wait)
{
	CKB_CTX_LOCK_ASSERT();

	if (!KBD_IS_ACTIVE(kbd))
		return (-1);

	printf("Implement ME: %s\n", __func__);
	return (0);
}
Esempio n. 13
0
/* read one byte from the keyboard if it's allowed */
static int
pckbd_read(keyboard_t *kbd, int wait)
{
	int c;

	if (wait)
		c = read_kbd_data(((pckbd_state_t *)kbd->kb_data)->kbdc);
	else
		c = read_kbd_data_no_wait(((pckbd_state_t *)kbd->kb_data)->kbdc);
	return (KBD_IS_ACTIVE(kbd) ? c : -1);
}
Esempio n. 14
0
/* check if char is waiting */
static int
pckbd_check_char(keyboard_t *kbd)
{
	pckbd_state_t *state;

	if (!KBD_IS_ACTIVE(kbd))
		return FALSE;
	state = (pckbd_state_t *)kbd->kb_data;
	if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0))
		return TRUE;
	return kbdc_data_ready(state->kbdc);
}
Esempio n. 15
0
/* check if data is waiting */
static int
atkbd_check(keyboard_t *kbd)
{
	int ret;

	if (!KBD_IS_ACTIVE(kbd)) {
		return FALSE;
	}
	ret = kbdc_data_ready(((atkbd_state_t *)kbd->kb_data)->kbdc);

	return ret;
}
Esempio n. 16
0
/* Currently unused. */
static int
kmi_read(keyboard_t *kbd, int wait)
{
	KMI_CTX_LOCK_ASSERT();

	if (!KBD_IS_ACTIVE(kbd))
		return (-1);

	++(kbd->kb_count);
	printf("Implement ME: %s\n", __func__);
	return (0);
}
Esempio n. 17
0
/* check if data is waiting */
static int
ukbd_check(keyboard_t *kbd)
{
	if (!KBD_IS_ACTIVE(kbd))
		return FALSE;
#ifdef UKBD_EMULATE_ATSCANCODE
	if (((ukbd_state_t *)kbd->kb_data)->ks_buffered_char[0])
		return TRUE;
#endif
	if (((ukbd_state_t *)kbd->kb_data)->ks_inputs > 0)
		return TRUE;
	return FALSE;
}
Esempio n. 18
0
static void
sunkbd_repeat(void *v)
{
	struct sunkbd_softc *sc = v;

	if (KBD_IS_ACTIVE(&sc->sc_kbd) && KBD_IS_BUSY(&sc->sc_kbd)) {
		if (sc->sc_repeat_key != -1) {
			sc->sc_repeating = 1;
			sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd,
			    KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg);
		}
	}
}
Esempio n. 19
0
/* check if char is waiting */
static int
ukbd_check_char(keyboard_t *kbd)
{
	ukbd_state_t *state;

	if (!KBD_IS_ACTIVE(kbd))
		return FALSE;
	state = (ukbd_state_t *)kbd->kb_data;
	if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0))
		return TRUE;
	if (state->ks_inputs > 0)
		return TRUE;
	return FALSE;
}
Esempio n. 20
0
/* check if data is waiting */
static int
kmi_check(keyboard_t *kbd)
{
	struct kmi_softc *sc = kbd->kb_data;
	uint32_t reg;

	KMI_CTX_LOCK_ASSERT();

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

	reg = pl050_kmi_read_4(sc, KMIIR);
	return (reg & KMIIR_RXINTR);
}
Esempio n. 21
0
/* read one byte from the keyboard if it's allowed */
static int
atkbd_read(keyboard_t *kbd, int wait)
{
	int c, ret;

	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);
	if (c != -1)
		++kbd->kb_count;

	ret = (KBD_IS_ACTIVE(kbd) ? c : -1);

	return ret;
}
Esempio n. 22
0
/* check if char is waiting */
static int
atkbd_check_char(keyboard_t *kbd)
{
	atkbd_state_t *state;
	int ret;

	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;
	}
	ret = kbdc_data_ready(state->kbdc);
	return ret;
}
Esempio n. 23
0
/* keyboard interrupt routine */
static int
pckbd_intr(keyboard_t *kbd, void *arg)
{
	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 = pckbd_read_char(kbd, FALSE);
		} while (c != NOKEY);
	}
	return 0;
}
Esempio n. 24
0
static void
sunkbd_uart_intr(void *arg)
{
	struct sunkbd_softc *sc = arg;
	int pend;

	if (sc->sc_uart->sc_leaving)
		return;

	pend = atomic_readandclear_32(&sc->sc_uart->sc_ttypend);
	if (!(pend & SER_INT_MASK))
		return;

	if (pend & SER_INT_RXREADY) {
		if (KBD_IS_ACTIVE(&sc->sc_kbd) && KBD_IS_BUSY(&sc->sc_kbd)) {
			sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd,
			    KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg);
		}
	}
}
Esempio n. 25
0
/* read char from the keyboard */
static uint32_t
kmi_read_char_locked(keyboard_t *kbd, int wait)
{
	struct kmi_softc *sc = kbd->kb_data;
	uint32_t reg, data;

	KMI_CTX_LOCK_ASSERT();

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

	reg = pl050_kmi_read_4(sc, KMIIR);
	if (reg & KMIIR_RXINTR) {
		data = pl050_kmi_read_4(sc, KMIDATA);
		return (data);
	}

	++kbd->kb_count;
	return (NOKEY);
}
Esempio n. 26
0
static void
pl050_kmi_intr(void *arg)
{
	struct kmi_softc *sc = arg;
	uint32_t c;

	KMI_CTX_LOCK_ASSERT();

	if ((sc->sc_flags & KMI_FLAG_POLLING) != 0)
		return;

	if (KBD_IS_ACTIVE(&sc->sc_kbd) &&
	    KBD_IS_BUSY(&sc->sc_kbd)) {
		/* let the callback function process the input */
		(sc->sc_kbd.kb_callback.kc_func) (&sc->sc_kbd, KBDIO_KEYINPUT,
		    sc->sc_kbd.kb_callback.kc_arg);
	} else {
		/* read and discard the input, no one is waiting for it */
		do {
			c = kmi_read_char_locked(&sc->sc_kbd, 0);
		} while (c != NOKEY);
	}

}
Esempio n. 27
0
/* read char from the keyboard */
static uint32_t
ckb_read_char_locked(keyboard_t *kbd, int wait)
{
	struct ckb_softc *sc;
	int i,j;
	uint16_t key;
	int oldbit;
	int newbit;
	int status;

	sc = kbd->kb_data;

	CKB_CTX_LOCK_ASSERT();

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

	if (sc->sc_repeating) {
		sc->sc_repeating = 0;
		callout_reset(&sc->sc_repeat_callout, hz / 10,
                    ckb_repeat, sc);
		return (sc->sc_repeat_key);
	};

	if (sc->sc_flags & CKB_FLAG_POLLING) {
		for (;;) {
			GPIO_PIN_GET(sc->gpio_dev, sc->gpio, &status);
			if (status == 0) {
				if (ec_command(EC_CMD_MKBP_STATE, sc->scan,
					sc->cols,
				    sc->scan, sc->cols)) {
					return (NOKEY);
				}
				break;
			}
			if (!wait) {
				return (NOKEY);
			}
			DELAY(1000);
		}
	};

	for (i = 0; i < sc->cols; i++) {
		for (j = 0; j < sc->rows; j++) {
			oldbit = (sc->scan_local[i] & (1 << j));
			newbit = (sc->scan[i] & (1 << j));

			if (oldbit == newbit)
				continue;

			key = keymap_read(sc, i, j);
			if (key == 0) {
				continue;
			};

			if (newbit > 0) {
				/* key pressed */
				sc->scan_local[i] |= (1 << j);

				/* setup repeating */
				sc->sc_repeat_key = key;
				callout_reset(&sc->sc_repeat_callout,
				    hz / 2, ckb_repeat, sc);

			} else {
				/* key released */
				sc->scan_local[i] &= ~(1 << j);

				/* release flag */
				key |= 0x80;

				/* unsetup repeating */
				sc->sc_repeat_key = -1;
				callout_stop(&sc->sc_repeat_callout);
			}

			return (key);
		}
	}

	return (NOKEY);
}
Esempio n. 28
0
static int
ukbd_interrupt(keyboard_t *kbd, void *arg)
{
	usbd_status status = (usbd_status)arg;
	ukbd_state_t *state;
	struct ukbd_data *ud;
	struct timeval tv;
	u_long now;
	int mod, omod;
	int key, c;
	int i, j;

	DPRINTFN(5, ("ukbd_intr: status=%d\n", status));
	if (status == USBD_CANCELLED)
		return 0;

	state = (ukbd_state_t *)kbd->kb_data;
	ud = &state->ks_ndata;

	if (status != USBD_NORMAL_COMPLETION) {
		DPRINTF(("ukbd_intr: status=%d\n", status));
		if (status == USBD_STALLED)
		    usbd_clear_endpoint_stall_async(state->ks_intrpipe);
		return 0;
	}

	if (ud->keycode[0] == KEY_ERROR) {
		return 0;		/* ignore  */
	}

	getmicrouptime(&tv);
	now = (u_long)tv.tv_sec*1000 + (u_long)tv.tv_usec/1000;

#define ADDKEY1(c) 		\
	if (state->ks_inputs < INPUTBUFSIZE) {				\
		state->ks_input[state->ks_inputtail] = (c);		\
		++state->ks_inputs;					\
		state->ks_inputtail = (state->ks_inputtail + 1)%INPUTBUFSIZE; \
	}

	mod = ud->modifiers;
	omod = state->ks_odata.modifiers;
	if (mod != omod) {
		for (i = 0; i < NMOD; i++)
			if (( mod & ukbd_mods[i].mask) !=
			    (omod & ukbd_mods[i].mask))
				ADDKEY1(ukbd_mods[i].key |
				       (mod & ukbd_mods[i].mask
					  ? KEY_PRESS : KEY_RELEASE));
	}

	/* Check for released keys. */
	for (i = 0; i < NKEYCODE; i++) {
		key = state->ks_odata.keycode[i];
		if (key == 0)
			continue;
		for (j = 0; j < NKEYCODE; j++) {
			if (ud->keycode[j] == 0)
				continue;
			if (key == ud->keycode[j])
				goto rfound;
		}
		ADDKEY1(key | KEY_RELEASE);
	rfound:
		;
	}

	/* Check for pressed keys. */
	for (i = 0; i < NKEYCODE; i++) {
		key = ud->keycode[i];
		if (key == 0)
			continue;
		state->ks_ntime[i] = now + kbd->kb_delay1;
		for (j = 0; j < NKEYCODE; j++) {
			if (state->ks_odata.keycode[j] == 0)
				continue;
			if (key == state->ks_odata.keycode[j]) {
				state->ks_ntime[i] = state->ks_otime[j];
				if (state->ks_otime[j] > now)
					goto pfound;
				state->ks_ntime[i] = now + kbd->kb_delay2;
				break;
			}
		}
		ADDKEY1(key | KEY_PRESS);
		/*
		 * If any other key is presently down, force its repeat to be
		 * well in the future (100s).  This makes the last key to be
		 * pressed do the autorepeat.
		 */
		for (j = 0; j < NKEYCODE; j++) {
			if (j != i)
				state->ks_ntime[j] = now + 100 * 1000;
		}
	pfound:
		;
	}

	state->ks_odata = *ud;
	bcopy(state->ks_ntime, state->ks_otime, sizeof(state->ks_ntime));
	if (state->ks_inputs <= 0) {
		return 0;
	}

#ifdef USB_DEBUG
	for (i = state->ks_inputhead, j = 0; j < state->ks_inputs; ++j,
		i = (i + 1)%INPUTBUFSIZE) {
		c = state->ks_input[i];
		DPRINTF(("0x%x (%d) %s\n", c, c,
			(c & KEY_RELEASE) ? "released":"pressed"));
	}
	if (ud->modifiers)
		DPRINTF(("mod:0x%04x ", ud->modifiers));
        for (i = 0; i < NKEYCODE; i++) {
		if (ud->keycode[i])
			DPRINTF(("%d ", ud->keycode[i]));
	}
	DPRINTF(("\n"));
#endif /* USB_DEBUG */

	if (state->ks_polling) {
		return 0;
	}

	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 it */
		do {
			c = ukbd_read_char(kbd, FALSE);
		} while (c != NOKEY);
	}

	return 0;
}
Esempio n. 29
0
/* read char from the keyboard */
static uint32_t
ckb_read_char_locked(keyboard_t *kbd, int wait)
{
	struct ckb_softc *sc;
	int i,j;
	uint16_t key;
	int oldbit;
	int newbit;

	sc = kbd->kb_data;

	CKB_CTX_LOCK_ASSERT();

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

	if (sc->sc_repeating) {
		sc->sc_repeating = 0;
		callout_reset(&sc->sc_repeat_callout, hz / 10,
                    ckb_repeat, sc);
		return (sc->sc_repeat_key);
	};

	if (sc->sc_flags & CKB_FLAG_POLLING) {
		/* TODO */
	};

	for (i = 0; i < sc->cols; i++) {
		for (j = 0; j < sc->rows; j++) {
			oldbit = (sc->scan_local[i] & (1 << j));
			newbit = (sc->scan[i] & (1 << j));

			if (oldbit == newbit)
				continue;

			key = scantokey(i,j);
			if (key == 0) {
				continue;
			};

			if (newbit > 0) {
				/* key pressed */
				sc->scan_local[i] |= (1 << j);

				/* setup repeating */
				sc->sc_repeat_key = key;
				callout_reset(&sc->sc_repeat_callout,
				    hz / 2, ckb_repeat, sc);

			} else {
				/* key released */
				sc->scan_local[i] &= ~(1 << j);

				/* release flag */
				key |= 0x80;

				/* unsetup repeating */
				sc->sc_repeat_key = -1;
				callout_stop(&sc->sc_repeat_callout);
			}

			return (key);
		}
	}

	return (NOKEY);
}
Esempio n. 30
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);
}