1bf21cd93STycho Nightingale /*- 24c87aefeSPatrick Mooney * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 34c87aefeSPatrick Mooney * 4bf21cd93STycho Nightingale * Copyright (c) 2015 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com> 5bf21cd93STycho Nightingale * Copyright (c) 2015 Nahanni Systems Inc. 6bf21cd93STycho Nightingale * All rights reserved. 7bf21cd93STycho Nightingale * 8bf21cd93STycho Nightingale * Redistribution and use in source and binary forms, with or without 9bf21cd93STycho Nightingale * modification, are permitted provided that the following conditions 10bf21cd93STycho Nightingale * are met: 11bf21cd93STycho Nightingale * 1. Redistributions of source code must retain the above copyright 12bf21cd93STycho Nightingale * notice, this list of conditions and the following disclaimer. 13bf21cd93STycho Nightingale * 2. Redistributions in binary form must reproduce the above copyright 14bf21cd93STycho Nightingale * notice, this list of conditions and the following disclaimer in the 15bf21cd93STycho Nightingale * documentation and/or other materials provided with the distribution. 16bf21cd93STycho Nightingale * 17bf21cd93STycho Nightingale * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 18bf21cd93STycho Nightingale * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19bf21cd93STycho Nightingale * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20bf21cd93STycho Nightingale * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21bf21cd93STycho Nightingale * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22bf21cd93STycho Nightingale * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23bf21cd93STycho Nightingale * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24bf21cd93STycho Nightingale * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25bf21cd93STycho Nightingale * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26bf21cd93STycho Nightingale * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27bf21cd93STycho Nightingale * SUCH DAMAGE. 28bf21cd93STycho Nightingale */ 29bf21cd93STycho Nightingale 30bf21cd93STycho Nightingale #include <sys/cdefs.h> 31bf21cd93STycho Nightingale __FBSDID("$FreeBSD$"); 32bf21cd93STycho Nightingale 33bf21cd93STycho Nightingale #include <sys/types.h> 34bf21cd93STycho Nightingale 35bf21cd93STycho Nightingale #include <assert.h> 36bf21cd93STycho Nightingale #include <stdbool.h> 37bf21cd93STycho Nightingale #include <stdio.h> 38bf21cd93STycho Nightingale #include <stdlib.h> 39bf21cd93STycho Nightingale #include <strings.h> 40bf21cd93STycho Nightingale #include <pthread.h> 41bf21cd93STycho Nightingale #include <pthread_np.h> 42bf21cd93STycho Nightingale 43bf21cd93STycho Nightingale #include "atkbdc.h" 44154972afSPatrick Mooney #include "debug.h" 45bf21cd93STycho Nightingale #include "console.h" 46bf21cd93STycho Nightingale 47bf21cd93STycho Nightingale /* keyboard device commands */ 48bf21cd93STycho Nightingale #define PS2KC_RESET_DEV 0xff 49bf21cd93STycho Nightingale #define PS2KC_DISABLE 0xf5 50bf21cd93STycho Nightingale #define PS2KC_ENABLE 0xf4 51bf21cd93STycho Nightingale #define PS2KC_SET_TYPEMATIC 0xf3 52bf21cd93STycho Nightingale #define PS2KC_SEND_DEV_ID 0xf2 53bf21cd93STycho Nightingale #define PS2KC_SET_SCANCODE_SET 0xf0 54bf21cd93STycho Nightingale #define PS2KC_ECHO 0xee 55bf21cd93STycho Nightingale #define PS2KC_SET_LEDS 0xed 56bf21cd93STycho Nightingale 57bf21cd93STycho Nightingale #define PS2KC_BAT_SUCCESS 0xaa 58bf21cd93STycho Nightingale #define PS2KC_ACK 0xfa 59bf21cd93STycho Nightingale 60bf21cd93STycho Nightingale #define PS2KBD_FIFOSZ 16 61bf21cd93STycho Nightingale 62bf21cd93STycho Nightingale struct fifo { 63bf21cd93STycho Nightingale uint8_t buf[PS2KBD_FIFOSZ]; 64bf21cd93STycho Nightingale int rindex; /* index to read from */ 65bf21cd93STycho Nightingale int windex; /* index to write to */ 66bf21cd93STycho Nightingale int num; /* number of bytes in the fifo */ 67bf21cd93STycho Nightingale int size; /* size of the fifo */ 68bf21cd93STycho Nightingale }; 69bf21cd93STycho Nightingale 70bf21cd93STycho Nightingale struct ps2kbd_softc { 71bf21cd93STycho Nightingale struct atkbdc_softc *atkbdc_sc; 72bf21cd93STycho Nightingale pthread_mutex_t mtx; 73bf21cd93STycho Nightingale 74bf21cd93STycho Nightingale bool enabled; 75bf21cd93STycho Nightingale struct fifo fifo; 76bf21cd93STycho Nightingale 77bf21cd93STycho Nightingale uint8_t curcmd; /* current command for next byte */ 78bf21cd93STycho Nightingale }; 79bf21cd93STycho Nightingale 804c87aefeSPatrick Mooney #define SCANCODE_E0_PREFIX 1 814c87aefeSPatrick Mooney struct extended_translation { 824c87aefeSPatrick Mooney uint32_t keysym; 834c87aefeSPatrick Mooney uint8_t scancode; 844c87aefeSPatrick Mooney int flags; 854c87aefeSPatrick Mooney }; 864c87aefeSPatrick Mooney 874c87aefeSPatrick Mooney /* 884c87aefeSPatrick Mooney * FIXME: Pause/break and Print Screen/SysRq require special handling. 894c87aefeSPatrick Mooney */ 904c87aefeSPatrick Mooney static const struct extended_translation extended_translations[] = { 914c87aefeSPatrick Mooney {0xff08, 0x66}, /* Back space */ 924c87aefeSPatrick Mooney {0xff09, 0x0d}, /* Tab */ 934c87aefeSPatrick Mooney {0xff0d, 0x5a}, /* Return */ 944c87aefeSPatrick Mooney {0xff1b, 0x76}, /* Escape */ 954c87aefeSPatrick Mooney {0xff50, 0x6c, SCANCODE_E0_PREFIX}, /* Home */ 964c87aefeSPatrick Mooney {0xff51, 0x6b, SCANCODE_E0_PREFIX}, /* Left arrow */ 974c87aefeSPatrick Mooney {0xff52, 0x75, SCANCODE_E0_PREFIX}, /* Up arrow */ 984c87aefeSPatrick Mooney {0xff53, 0x74, SCANCODE_E0_PREFIX}, /* Right arrow */ 994c87aefeSPatrick Mooney {0xff54, 0x72, SCANCODE_E0_PREFIX}, /* Down arrow */ 1004c87aefeSPatrick Mooney {0xff55, 0x7d, SCANCODE_E0_PREFIX}, /* PgUp */ 1014c87aefeSPatrick Mooney {0xff56, 0x7a, SCANCODE_E0_PREFIX}, /* PgDown */ 1024c87aefeSPatrick Mooney {0xff57, 0x69, SCANCODE_E0_PREFIX}, /* End */ 1034c87aefeSPatrick Mooney {0xff63, 0x70, SCANCODE_E0_PREFIX}, /* Ins */ 1044c87aefeSPatrick Mooney {0xff8d, 0x5a, SCANCODE_E0_PREFIX}, /* Keypad Enter */ 1054c87aefeSPatrick Mooney {0xffe1, 0x12}, /* Left shift */ 1064c87aefeSPatrick Mooney {0xffe2, 0x59}, /* Right shift */ 1074c87aefeSPatrick Mooney {0xffe3, 0x14}, /* Left control */ 1084c87aefeSPatrick Mooney {0xffe4, 0x14, SCANCODE_E0_PREFIX}, /* Right control */ 1094c87aefeSPatrick Mooney /* {0xffe7, XXX}, Left meta */ 1104c87aefeSPatrick Mooney /* {0xffe8, XXX}, Right meta */ 1114c87aefeSPatrick Mooney {0xffe9, 0x11}, /* Left alt */ 1124c87aefeSPatrick Mooney {0xfe03, 0x11, SCANCODE_E0_PREFIX}, /* AltGr */ 1134c87aefeSPatrick Mooney {0xffea, 0x11, SCANCODE_E0_PREFIX}, /* Right alt */ 1144c87aefeSPatrick Mooney {0xffeb, 0x1f, SCANCODE_E0_PREFIX}, /* Left Windows */ 1154c87aefeSPatrick Mooney {0xffec, 0x27, SCANCODE_E0_PREFIX}, /* Right Windows */ 1164c87aefeSPatrick Mooney {0xffbe, 0x05}, /* F1 */ 1174c87aefeSPatrick Mooney {0xffbf, 0x06}, /* F2 */ 1184c87aefeSPatrick Mooney {0xffc0, 0x04}, /* F3 */ 1194c87aefeSPatrick Mooney {0xffc1, 0x0c}, /* F4 */ 1204c87aefeSPatrick Mooney {0xffc2, 0x03}, /* F5 */ 1214c87aefeSPatrick Mooney {0xffc3, 0x0b}, /* F6 */ 1224c87aefeSPatrick Mooney {0xffc4, 0x83}, /* F7 */ 1234c87aefeSPatrick Mooney {0xffc5, 0x0a}, /* F8 */ 1244c87aefeSPatrick Mooney {0xffc6, 0x01}, /* F9 */ 1254c87aefeSPatrick Mooney {0xffc7, 0x09}, /* F10 */ 1264c87aefeSPatrick Mooney {0xffc8, 0x78}, /* F11 */ 1274c87aefeSPatrick Mooney {0xffc9, 0x07}, /* F12 */ 1284c87aefeSPatrick Mooney {0xffff, 0x71, SCANCODE_E0_PREFIX}, /* Del */ 1294c87aefeSPatrick Mooney {0xff14, 0x7e}, /* ScrollLock */ 1304c87aefeSPatrick Mooney /* NumLock and Keypads*/ 1314c87aefeSPatrick Mooney {0xff7f, 0x77}, /* NumLock */ 1324c87aefeSPatrick Mooney {0xffaf, 0x4a, SCANCODE_E0_PREFIX}, /* Keypad slash */ 1334c87aefeSPatrick Mooney {0xffaa, 0x7c}, /* Keypad asterisk */ 1344c87aefeSPatrick Mooney {0xffad, 0x7b}, /* Keypad minus */ 1354c87aefeSPatrick Mooney {0xffab, 0x79}, /* Keypad plus */ 1364c87aefeSPatrick Mooney {0xffb7, 0x6c}, /* Keypad 7 */ 1374c87aefeSPatrick Mooney {0xff95, 0x6c}, /* Keypad home */ 1384c87aefeSPatrick Mooney {0xffb8, 0x75}, /* Keypad 8 */ 1394c87aefeSPatrick Mooney {0xff97, 0x75}, /* Keypad up arrow */ 1404c87aefeSPatrick Mooney {0xffb9, 0x7d}, /* Keypad 9 */ 1414c87aefeSPatrick Mooney {0xff9a, 0x7d}, /* Keypad PgUp */ 1424c87aefeSPatrick Mooney {0xffb4, 0x6b}, /* Keypad 4 */ 1434c87aefeSPatrick Mooney {0xff96, 0x6b}, /* Keypad left arrow */ 1444c87aefeSPatrick Mooney {0xffb5, 0x73}, /* Keypad 5 */ 1454c87aefeSPatrick Mooney {0xff9d, 0x73}, /* Keypad empty */ 1464c87aefeSPatrick Mooney {0xffb6, 0x74}, /* Keypad 6 */ 1474c87aefeSPatrick Mooney {0xff98, 0x74}, /* Keypad right arrow */ 1484c87aefeSPatrick Mooney {0xffb1, 0x69}, /* Keypad 1 */ 1494c87aefeSPatrick Mooney {0xff9c, 0x69}, /* Keypad end */ 1504c87aefeSPatrick Mooney {0xffb2, 0x72}, /* Keypad 2 */ 1514c87aefeSPatrick Mooney {0xff99, 0x72}, /* Keypad down arrow */ 1524c87aefeSPatrick Mooney {0xffb3, 0x7a}, /* Keypad 3 */ 1534c87aefeSPatrick Mooney {0xff9b, 0x7a}, /* Keypad PgDown */ 1544c87aefeSPatrick Mooney {0xffb0, 0x70}, /* Keypad 0 */ 1554c87aefeSPatrick Mooney {0xff9e, 0x70}, /* Keypad ins */ 1564c87aefeSPatrick Mooney {0xffae, 0x71}, /* Keypad . */ 1574c87aefeSPatrick Mooney {0xff9f, 0x71}, /* Keypad del */ 1584c87aefeSPatrick Mooney {0, 0, 0} /* Terminator */ 1594c87aefeSPatrick Mooney }; 1604c87aefeSPatrick Mooney 1614c87aefeSPatrick Mooney /* ASCII to type 2 scancode lookup table */ 1624c87aefeSPatrick Mooney static const uint8_t ascii_translations[128] = { 1634c87aefeSPatrick Mooney 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1644c87aefeSPatrick Mooney 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1654c87aefeSPatrick Mooney 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1664c87aefeSPatrick Mooney 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1674c87aefeSPatrick Mooney 0x29, 0x16, 0x52, 0x26, 0x25, 0x2e, 0x3d, 0x52, 1684c87aefeSPatrick Mooney 0x46, 0x45, 0x3e, 0x55, 0x41, 0x4e, 0x49, 0x4a, 1694c87aefeSPatrick Mooney 0x45, 0x16, 0x1e, 0x26, 0x25, 0x2e, 0x36, 0x3d, 1704c87aefeSPatrick Mooney 0x3e, 0x46, 0x4c, 0x4c, 0x41, 0x55, 0x49, 0x4a, 1714c87aefeSPatrick Mooney 0x1e, 0x1c, 0x32, 0x21, 0x23, 0x24, 0x2b, 0x34, 1724c87aefeSPatrick Mooney 0x33, 0x43, 0x3b, 0x42, 0x4b, 0x3a, 0x31, 0x44, 1734c87aefeSPatrick Mooney 0x4d, 0x15, 0x2d, 0x1b, 0x2c, 0x3c, 0x2a, 0x1d, 1744c87aefeSPatrick Mooney 0x22, 0x35, 0x1a, 0x54, 0x5d, 0x5b, 0x36, 0x4e, 1754c87aefeSPatrick Mooney 0x0e, 0x1c, 0x32, 0x21, 0x23, 0x24, 0x2b, 0x34, 1764c87aefeSPatrick Mooney 0x33, 0x43, 0x3b, 0x42, 0x4b, 0x3a, 0x31, 0x44, 1774c87aefeSPatrick Mooney 0x4d, 0x15, 0x2d, 0x1b, 0x2c, 0x3c, 0x2a, 0x1d, 1784c87aefeSPatrick Mooney 0x22, 0x35, 0x1a, 0x54, 0x5d, 0x5b, 0x0e, 0x00, 1794c87aefeSPatrick Mooney }; 1804c87aefeSPatrick Mooney 181*b0de25cbSAndy Fiddaman /* ScanCode set1 to set2 lookup table */ 182*b0de25cbSAndy Fiddaman const uint8_t keyset1to2_translations[128] = { 183*b0de25cbSAndy Fiddaman 0, 0x76, 0x16, 0x1E, 0x26, 0x25, 0x2e, 0x36, 184*b0de25cbSAndy Fiddaman 0x3d, 0x3e, 0x46, 0x45, 0x4e, 0x55, 0x66, 0x0d, 185*b0de25cbSAndy Fiddaman 0x15, 0x1d, 0x24, 0x2d, 0x2c, 0x35, 0x3c, 0x43, 186*b0de25cbSAndy Fiddaman 0x44, 0x4d, 0x54, 0x5b, 0x5a, 0x14, 0x1c, 0x1b, 187*b0de25cbSAndy Fiddaman 0x23, 0x2b, 0x34, 0x33, 0x3b, 0x42, 0x4b, 0x4c, 188*b0de25cbSAndy Fiddaman 0x52, 0x0e, 0x12, 0x5d, 0x1a, 0x22, 0x21, 0x2a, 189*b0de25cbSAndy Fiddaman 0x32, 0x31, 0x3a, 0x41, 0x49, 0x4a, 0x59, 0x7c, 190*b0de25cbSAndy Fiddaman 0x11, 0x29, 0x58, 0x05, 0x06, 0x04, 0x0c, 0x03, 191*b0de25cbSAndy Fiddaman 0x0b, 0x83, 0x0a, 0x01, 0x09, 0x77, 0x7e, 0x6c, 192*b0de25cbSAndy Fiddaman 0x75, 0x7d, 0x7b, 0x6b, 0x73, 0x74, 0x79, 0x69, 193*b0de25cbSAndy Fiddaman 0x72, 0x7a, 0x70, 0x71, 0x84, 0x60, 0x61, 0x78, 194*b0de25cbSAndy Fiddaman 0x07, 0x0f, 0x17, 0x1f, 0x27, 0x2f, 0x37, 0x3f, 195*b0de25cbSAndy Fiddaman 0x47, 0x4f, 0x56, 0x5e, 0x08, 0x10, 0x18, 0x20, 196*b0de25cbSAndy Fiddaman 0x28, 0x30, 0x38, 0x40, 0x48, 0x50, 0x57, 0x6f, 197*b0de25cbSAndy Fiddaman 0x13, 0x19, 0x39, 0x51, 0x53, 0x5c, 0x5f, 0x62, 198*b0de25cbSAndy Fiddaman 0x63, 0x64, 0x65, 0x67, 0x68, 0x6a, 0x6d, 0x6e, 199*b0de25cbSAndy Fiddaman }; 200*b0de25cbSAndy Fiddaman 201bf21cd93STycho Nightingale static void 202bf21cd93STycho Nightingale fifo_init(struct ps2kbd_softc *sc) 203bf21cd93STycho Nightingale { 204bf21cd93STycho Nightingale struct fifo *fifo; 205bf21cd93STycho Nightingale 206bf21cd93STycho Nightingale fifo = &sc->fifo; 207bf21cd93STycho Nightingale fifo->size = sizeof(((struct fifo *)0)->buf); 208bf21cd93STycho Nightingale } 209bf21cd93STycho Nightingale 210bf21cd93STycho Nightingale static void 211bf21cd93STycho Nightingale fifo_reset(struct ps2kbd_softc *sc) 212bf21cd93STycho Nightingale { 213bf21cd93STycho Nightingale struct fifo *fifo; 214bf21cd93STycho Nightingale 215bf21cd93STycho Nightingale fifo = &sc->fifo; 216bf21cd93STycho Nightingale bzero(fifo, sizeof(struct fifo)); 217bf21cd93STycho Nightingale fifo->size = sizeof(((struct fifo *)0)->buf); 218bf21cd93STycho Nightingale } 219bf21cd93STycho Nightingale 220bf21cd93STycho Nightingale static void 221bf21cd93STycho Nightingale fifo_put(struct ps2kbd_softc *sc, uint8_t val) 222bf21cd93STycho Nightingale { 223bf21cd93STycho Nightingale struct fifo *fifo; 224bf21cd93STycho Nightingale 225bf21cd93STycho Nightingale fifo = &sc->fifo; 226bf21cd93STycho Nightingale if (fifo->num < fifo->size) { 227bf21cd93STycho Nightingale fifo->buf[fifo->windex] = val; 228bf21cd93STycho Nightingale fifo->windex = (fifo->windex + 1) % fifo->size; 229bf21cd93STycho Nightingale fifo->num++; 230bf21cd93STycho Nightingale } 231bf21cd93STycho Nightingale } 232bf21cd93STycho Nightingale 233bf21cd93STycho Nightingale static int 234bf21cd93STycho Nightingale fifo_get(struct ps2kbd_softc *sc, uint8_t *val) 235bf21cd93STycho Nightingale { 236bf21cd93STycho Nightingale struct fifo *fifo; 237bf21cd93STycho Nightingale 238bf21cd93STycho Nightingale fifo = &sc->fifo; 239bf21cd93STycho Nightingale if (fifo->num > 0) { 240bf21cd93STycho Nightingale *val = fifo->buf[fifo->rindex]; 241bf21cd93STycho Nightingale fifo->rindex = (fifo->rindex + 1) % fifo->size; 242bf21cd93STycho Nightingale fifo->num--; 243bf21cd93STycho Nightingale return (0); 244bf21cd93STycho Nightingale } 245bf21cd93STycho Nightingale 246bf21cd93STycho Nightingale return (-1); 247bf21cd93STycho Nightingale } 248bf21cd93STycho Nightingale 249bf21cd93STycho Nightingale int 250bf21cd93STycho Nightingale ps2kbd_read(struct ps2kbd_softc *sc, uint8_t *val) 251bf21cd93STycho Nightingale { 252bf21cd93STycho Nightingale int retval; 253bf21cd93STycho Nightingale 254bf21cd93STycho Nightingale pthread_mutex_lock(&sc->mtx); 255bf21cd93STycho Nightingale retval = fifo_get(sc, val); 256bf21cd93STycho Nightingale pthread_mutex_unlock(&sc->mtx); 257bf21cd93STycho Nightingale 258bf21cd93STycho Nightingale return (retval); 259bf21cd93STycho Nightingale } 260bf21cd93STycho Nightingale 261bf21cd93STycho Nightingale void 262bf21cd93STycho Nightingale ps2kbd_write(struct ps2kbd_softc *sc, uint8_t val) 263bf21cd93STycho Nightingale { 264bf21cd93STycho Nightingale pthread_mutex_lock(&sc->mtx); 265bf21cd93STycho Nightingale if (sc->curcmd) { 266bf21cd93STycho Nightingale switch (sc->curcmd) { 267bf21cd93STycho Nightingale case PS2KC_SET_TYPEMATIC: 268bf21cd93STycho Nightingale fifo_put(sc, PS2KC_ACK); 269bf21cd93STycho Nightingale break; 270bf21cd93STycho Nightingale case PS2KC_SET_SCANCODE_SET: 271bf21cd93STycho Nightingale fifo_put(sc, PS2KC_ACK); 272bf21cd93STycho Nightingale break; 273bf21cd93STycho Nightingale case PS2KC_SET_LEDS: 274bf21cd93STycho Nightingale fifo_put(sc, PS2KC_ACK); 275bf21cd93STycho Nightingale break; 276bf21cd93STycho Nightingale default: 277154972afSPatrick Mooney EPRINTLN("Unhandled ps2 keyboard current " 278154972afSPatrick Mooney "command byte 0x%02x", val); 279bf21cd93STycho Nightingale break; 280bf21cd93STycho Nightingale } 281bf21cd93STycho Nightingale sc->curcmd = 0; 282bf21cd93STycho Nightingale } else { 283bf21cd93STycho Nightingale switch (val) { 2844c87aefeSPatrick Mooney case 0x00: 2854c87aefeSPatrick Mooney fifo_put(sc, PS2KC_ACK); 2864c87aefeSPatrick Mooney break; 287bf21cd93STycho Nightingale case PS2KC_RESET_DEV: 288bf21cd93STycho Nightingale fifo_reset(sc); 289bf21cd93STycho Nightingale fifo_put(sc, PS2KC_ACK); 290bf21cd93STycho Nightingale fifo_put(sc, PS2KC_BAT_SUCCESS); 291bf21cd93STycho Nightingale break; 292bf21cd93STycho Nightingale case PS2KC_DISABLE: 293bf21cd93STycho Nightingale sc->enabled = false; 294bf21cd93STycho Nightingale fifo_put(sc, PS2KC_ACK); 295bf21cd93STycho Nightingale break; 296bf21cd93STycho Nightingale case PS2KC_ENABLE: 297bf21cd93STycho Nightingale sc->enabled = true; 298bf21cd93STycho Nightingale fifo_reset(sc); 299bf21cd93STycho Nightingale fifo_put(sc, PS2KC_ACK); 300bf21cd93STycho Nightingale break; 301bf21cd93STycho Nightingale case PS2KC_SET_TYPEMATIC: 302bf21cd93STycho Nightingale sc->curcmd = val; 303bf21cd93STycho Nightingale fifo_put(sc, PS2KC_ACK); 304bf21cd93STycho Nightingale break; 305bf21cd93STycho Nightingale case PS2KC_SEND_DEV_ID: 306bf21cd93STycho Nightingale fifo_put(sc, PS2KC_ACK); 307bf21cd93STycho Nightingale fifo_put(sc, 0xab); 308bf21cd93STycho Nightingale fifo_put(sc, 0x83); 309bf21cd93STycho Nightingale break; 310bf21cd93STycho Nightingale case PS2KC_SET_SCANCODE_SET: 311bf21cd93STycho Nightingale sc->curcmd = val; 312bf21cd93STycho Nightingale fifo_put(sc, PS2KC_ACK); 313bf21cd93STycho Nightingale break; 314bf21cd93STycho Nightingale case PS2KC_ECHO: 315bf21cd93STycho Nightingale fifo_put(sc, PS2KC_ECHO); 316bf21cd93STycho Nightingale break; 317bf21cd93STycho Nightingale case PS2KC_SET_LEDS: 318bf21cd93STycho Nightingale sc->curcmd = val; 319bf21cd93STycho Nightingale fifo_put(sc, PS2KC_ACK); 320bf21cd93STycho Nightingale break; 321bf21cd93STycho Nightingale default: 322154972afSPatrick Mooney EPRINTLN("Unhandled ps2 keyboard command " 323154972afSPatrick Mooney "0x%02x", val); 324bf21cd93STycho Nightingale break; 325bf21cd93STycho Nightingale } 326bf21cd93STycho Nightingale } 327bf21cd93STycho Nightingale pthread_mutex_unlock(&sc->mtx); 328bf21cd93STycho Nightingale } 329bf21cd93STycho Nightingale 330bf21cd93STycho Nightingale /* 331bf21cd93STycho Nightingale * Translate keysym to type 2 scancode and insert into keyboard buffer. 332bf21cd93STycho Nightingale */ 333bf21cd93STycho Nightingale static void 334bf21cd93STycho Nightingale ps2kbd_keysym_queue(struct ps2kbd_softc *sc, 335*b0de25cbSAndy Fiddaman int down, uint32_t keysym, uint32_t keycode) 336bf21cd93STycho Nightingale { 337bf21cd93STycho Nightingale assert(pthread_mutex_isowned_np(&sc->mtx)); 3384c87aefeSPatrick Mooney int e0_prefix, found; 3394c87aefeSPatrick Mooney uint8_t code; 3404c87aefeSPatrick Mooney const struct extended_translation *trans; 3414c87aefeSPatrick Mooney 342*b0de25cbSAndy Fiddaman if (keycode) { 343*b0de25cbSAndy Fiddaman code = keyset1to2_translations[(uint8_t)(keycode & 0x7f)]; 344*b0de25cbSAndy Fiddaman e0_prefix = ((keycode & 0x80) ? SCANCODE_E0_PREFIX : 0); 3454c87aefeSPatrick Mooney found = 1; 3464c87aefeSPatrick Mooney } else { 347*b0de25cbSAndy Fiddaman found = 0; 348*b0de25cbSAndy Fiddaman if (keysym < 0x80) { 349*b0de25cbSAndy Fiddaman code = ascii_translations[keysym]; 350*b0de25cbSAndy Fiddaman e0_prefix = 0; 351*b0de25cbSAndy Fiddaman found = 1; 352*b0de25cbSAndy Fiddaman } else { 353*b0de25cbSAndy Fiddaman for (trans = &(extended_translations[0]); trans->keysym != 0; 354*b0de25cbSAndy Fiddaman trans++) { 355*b0de25cbSAndy Fiddaman if (keysym == trans->keysym) { 356*b0de25cbSAndy Fiddaman code = trans->scancode; 357*b0de25cbSAndy Fiddaman e0_prefix = trans->flags & SCANCODE_E0_PREFIX; 358*b0de25cbSAndy Fiddaman found = 1; 359*b0de25cbSAndy Fiddaman break; 360*b0de25cbSAndy Fiddaman } 3614c87aefeSPatrick Mooney } 3624c87aefeSPatrick Mooney } 3634c87aefeSPatrick Mooney } 364bf21cd93STycho Nightingale 3654c87aefeSPatrick Mooney if (!found) { 366154972afSPatrick Mooney EPRINTLN("Unhandled ps2 keyboard keysym 0x%x", keysym); 3674c87aefeSPatrick Mooney return; 368bf21cd93STycho Nightingale } 3694c87aefeSPatrick Mooney 3704c87aefeSPatrick Mooney if (e0_prefix) 3714c87aefeSPatrick Mooney fifo_put(sc, 0xe0); 3724c87aefeSPatrick Mooney if (!down) 3734c87aefeSPatrick Mooney fifo_put(sc, 0xf0); 3744c87aefeSPatrick Mooney fifo_put(sc, code); 375bf21cd93STycho Nightingale } 376bf21cd93STycho Nightingale 377bf21cd93STycho Nightingale static void 378*b0de25cbSAndy Fiddaman ps2kbd_event(int down, uint32_t keysym, uint32_t keycode, void *arg) 379bf21cd93STycho Nightingale { 380bf21cd93STycho Nightingale struct ps2kbd_softc *sc = arg; 3814c87aefeSPatrick Mooney int fifo_full; 382bf21cd93STycho Nightingale 383bf21cd93STycho Nightingale pthread_mutex_lock(&sc->mtx); 384bf21cd93STycho Nightingale if (!sc->enabled) { 385bf21cd93STycho Nightingale pthread_mutex_unlock(&sc->mtx); 386bf21cd93STycho Nightingale return; 387bf21cd93STycho Nightingale } 3884c87aefeSPatrick Mooney fifo_full = sc->fifo.num == PS2KBD_FIFOSZ; 389*b0de25cbSAndy Fiddaman ps2kbd_keysym_queue(sc, down, keysym, keycode); 390bf21cd93STycho Nightingale pthread_mutex_unlock(&sc->mtx); 391bf21cd93STycho Nightingale 3924c87aefeSPatrick Mooney if (!fifo_full) 3934c87aefeSPatrick Mooney atkbdc_event(sc->atkbdc_sc, 1); 394bf21cd93STycho Nightingale } 395bf21cd93STycho Nightingale 396bf21cd93STycho Nightingale struct ps2kbd_softc * 397bf21cd93STycho Nightingale ps2kbd_init(struct atkbdc_softc *atkbdc_sc) 398bf21cd93STycho Nightingale { 399bf21cd93STycho Nightingale struct ps2kbd_softc *sc; 400bf21cd93STycho Nightingale 401bf21cd93STycho Nightingale sc = calloc(1, sizeof (struct ps2kbd_softc)); 402bf21cd93STycho Nightingale pthread_mutex_init(&sc->mtx, NULL); 403bf21cd93STycho Nightingale fifo_init(sc); 404bf21cd93STycho Nightingale sc->atkbdc_sc = atkbdc_sc; 405bf21cd93STycho Nightingale 4064c87aefeSPatrick Mooney console_kbd_register(ps2kbd_event, sc, 1); 407bf21cd93STycho Nightingale 408bf21cd93STycho Nightingale return (sc); 409bf21cd93STycho Nightingale } 4104c87aefeSPatrick Mooney 411