/* 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 */ }
/* 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 */ }
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); }
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); }