2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2015 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
5 * Copyright (c) 2015 Nahanni Systems Inc.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
33 #include <sys/types.h>
41 #include <pthread_np.h>
46 /* keyboard device commands */
47 #define PS2KC_RESET_DEV 0xff
48 #define PS2KC_DISABLE 0xf5
49 #define PS2KC_ENABLE 0xf4
50 #define PS2KC_SET_TYPEMATIC 0xf3
51 #define PS2KC_SEND_DEV_ID 0xf2
52 #define PS2KC_SET_SCANCODE_SET 0xf0
53 #define PS2KC_ECHO 0xee
54 #define PS2KC_SET_LEDS 0xed
56 #define PS2KC_BAT_SUCCESS 0xaa
57 #define PS2KC_ACK 0xfa
59 #define PS2KBD_FIFOSZ 16
62 uint8_t buf[PS2KBD_FIFOSZ];
63 int rindex; /* index to read from */
64 int windex; /* index to write to */
65 int num; /* number of bytes in the fifo */
66 int size; /* size of the fifo */
70 struct atkbdc_softc *atkbdc_sc;
76 uint8_t curcmd; /* current command for next byte */
80 fifo_init(struct ps2kbd_softc *sc)
85 fifo->size = sizeof(((struct fifo *)0)->buf);
89 fifo_reset(struct ps2kbd_softc *sc)
94 bzero(fifo, sizeof(struct fifo));
95 fifo->size = sizeof(((struct fifo *)0)->buf);
99 fifo_put(struct ps2kbd_softc *sc, uint8_t val)
104 if (fifo->num < fifo->size) {
105 fifo->buf[fifo->windex] = val;
106 fifo->windex = (fifo->windex + 1) % fifo->size;
112 fifo_get(struct ps2kbd_softc *sc, uint8_t *val)
118 *val = fifo->buf[fifo->rindex];
119 fifo->rindex = (fifo->rindex + 1) % fifo->size;
128 ps2kbd_read(struct ps2kbd_softc *sc, uint8_t *val)
132 pthread_mutex_lock(&sc->mtx);
133 retval = fifo_get(sc, val);
134 pthread_mutex_unlock(&sc->mtx);
140 ps2kbd_write(struct ps2kbd_softc *sc, uint8_t val)
142 pthread_mutex_lock(&sc->mtx);
144 switch (sc->curcmd) {
145 case PS2KC_SET_TYPEMATIC:
146 fifo_put(sc, PS2KC_ACK);
148 case PS2KC_SET_SCANCODE_SET:
149 fifo_put(sc, PS2KC_ACK);
152 fifo_put(sc, PS2KC_ACK);
155 fprintf(stderr, "Unhandled ps2 keyboard current "
156 "command byte 0x%02x\n", val);
163 fifo_put(sc, PS2KC_ACK);
165 case PS2KC_RESET_DEV:
167 fifo_put(sc, PS2KC_ACK);
168 fifo_put(sc, PS2KC_BAT_SUCCESS);
172 fifo_put(sc, PS2KC_ACK);
177 fifo_put(sc, PS2KC_ACK);
179 case PS2KC_SET_TYPEMATIC:
181 fifo_put(sc, PS2KC_ACK);
183 case PS2KC_SEND_DEV_ID:
184 fifo_put(sc, PS2KC_ACK);
188 case PS2KC_SET_SCANCODE_SET:
190 fifo_put(sc, PS2KC_ACK);
193 fifo_put(sc, PS2KC_ECHO);
197 fifo_put(sc, PS2KC_ACK);
200 fprintf(stderr, "Unhandled ps2 keyboard command "
205 pthread_mutex_unlock(&sc->mtx);
209 * Translate keysym to type 2 scancode and insert into keyboard buffer.
212 ps2kbd_keysym_queue(struct ps2kbd_softc *sc,
213 int down, uint32_t keysym)
215 /* ASCII to type 2 scancode lookup table */
216 const uint8_t translation[128] = {
217 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
218 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
220 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
221 0x29, 0x16, 0x52, 0x26, 0x25, 0x2e, 0x3d, 0x52,
222 0x46, 0x45, 0x3e, 0x55, 0x41, 0x4e, 0x49, 0x4a,
223 0x45, 0x16, 0x1e, 0x26, 0x25, 0x2e, 0x36, 0x3d,
224 0x3e, 0x46, 0x4c, 0x4c, 0x41, 0x55, 0x49, 0x4a,
225 0x1e, 0x1c, 0x32, 0x21, 0x23, 0x24, 0x2b, 0x34,
226 0x33, 0x43, 0x3b, 0x42, 0x4b, 0x3a, 0x31, 0x44,
227 0x4d, 0x15, 0x2d, 0x1b, 0x2c, 0x3c, 0x2a, 0x1d,
228 0x22, 0x35, 0x1a, 0x54, 0x5d, 0x5b, 0x36, 0x4e,
229 0x0e, 0x1c, 0x32, 0x21, 0x23, 0x24, 0x2b, 0x34,
230 0x33, 0x43, 0x3b, 0x42, 0x4b, 0x3a, 0x31, 0x44,
231 0x4d, 0x15, 0x2d, 0x1b, 0x2c, 0x3c, 0x2a, 0x1d,
232 0x22, 0x35, 0x1a, 0x54, 0x5d, 0x5b, 0x0e, 0x00,
235 assert(pthread_mutex_isowned_np(&sc->mtx));
241 fifo_put(sc, translation[keysym]);
243 case 0xff08: /* Back space */
248 case 0xff09: /* Tab */
253 case 0xff0d: /* Return */
258 case 0xff1b: /* Escape */
263 case 0xff50: /* Home */
269 case 0xff51: /* Left arrow */
275 case 0xff52: /* Up arrow */
281 case 0xff53: /* Right arrow */
287 case 0xff54: /* Down arrow */
293 case 0xff55: /* PgUp */
299 case 0xff56: /* PgDwn */
305 case 0xff57: /* End */
311 case 0xff63: /* Ins */
317 case 0xff8d: /* Keypad Enter */
323 case 0xffe1: /* Left shift */
328 case 0xffe2: /* Right shift */
333 case 0xffe3: /* Left control */
338 case 0xffe4: /* Right control */
344 case 0xffe7: /* Left meta */
347 case 0xffe8: /* Right meta */
350 case 0xffe9: /* Left alt */
355 case 0xfe03: /* AltGr */
356 case 0xffea: /* Right alt */
362 case 0xffeb: /* Left Windows */
368 case 0xffec: /* Right Windows */
374 case 0xffbe: /* F1 */
379 case 0xffbf: /* F2 */
384 case 0xffc0: /* F3 */
389 case 0xffc1: /* F4 */
394 case 0xffc2: /* F5 */
399 case 0xffc3: /* F6 */
404 case 0xffc4: /* F7 */
409 case 0xffc5: /* F8 */
414 case 0xffc6: /* F9 */
419 case 0xffc7: /* F10 */
424 case 0xffc8: /* F11 */
429 case 0xffc9: /* F12 */
434 case 0xffff: /* Del */
441 fprintf(stderr, "Unhandled ps2 keyboard keysym 0x%x\n",
448 ps2kbd_event(int down, uint32_t keysym, void *arg)
450 struct ps2kbd_softc *sc = arg;
453 pthread_mutex_lock(&sc->mtx);
455 pthread_mutex_unlock(&sc->mtx);
458 fifo_full = sc->fifo.num == PS2KBD_FIFOSZ;
459 ps2kbd_keysym_queue(sc, down, keysym);
460 pthread_mutex_unlock(&sc->mtx);
463 atkbdc_event(sc->atkbdc_sc, 1);
466 struct ps2kbd_softc *
467 ps2kbd_init(struct atkbdc_softc *atkbdc_sc)
469 struct ps2kbd_softc *sc;
471 sc = calloc(1, sizeof (struct ps2kbd_softc));
472 pthread_mutex_init(&sc->mtx, NULL);
474 sc->atkbdc_sc = atkbdc_sc;
476 console_kbd_register(ps2kbd_event, sc, 1);