2 * Copyright (c) 2015 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
3 * Copyright (c) 2015 Nahanni Systems Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
31 #include <sys/types.h>
39 #include <pthread_np.h>
44 /* keyboard device commands */
45 #define PS2KC_RESET_DEV 0xff
46 #define PS2KC_DISABLE 0xf5
47 #define PS2KC_ENABLE 0xf4
48 #define PS2KC_SET_TYPEMATIC 0xf3
49 #define PS2KC_SEND_DEV_ID 0xf2
50 #define PS2KC_SET_SCANCODE_SET 0xf0
51 #define PS2KC_ECHO 0xee
52 #define PS2KC_SET_LEDS 0xed
54 #define PS2KC_BAT_SUCCESS 0xaa
55 #define PS2KC_ACK 0xfa
57 #define PS2KBD_FIFOSZ 16
60 uint8_t buf
[PS2KBD_FIFOSZ
];
61 int rindex
; /* index to read from */
62 int windex
; /* index to write to */
63 int num
; /* number of bytes in the fifo */
64 int size
; /* size of the fifo */
68 struct atkbdc_softc
*atkbdc_sc
;
74 uint8_t curcmd
; /* current command for next byte */
78 fifo_init(struct ps2kbd_softc
*sc
)
83 fifo
->size
= sizeof(((struct fifo
*)0)->buf
);
87 fifo_reset(struct ps2kbd_softc
*sc
)
92 bzero(fifo
, sizeof(struct fifo
));
93 fifo
->size
= sizeof(((struct fifo
*)0)->buf
);
97 fifo_put(struct ps2kbd_softc
*sc
, uint8_t val
)
102 if (fifo
->num
< fifo
->size
) {
103 fifo
->buf
[fifo
->windex
] = val
;
104 fifo
->windex
= (fifo
->windex
+ 1) % fifo
->size
;
110 fifo_get(struct ps2kbd_softc
*sc
, uint8_t *val
)
116 *val
= fifo
->buf
[fifo
->rindex
];
117 fifo
->rindex
= (fifo
->rindex
+ 1) % fifo
->size
;
126 ps2kbd_read(struct ps2kbd_softc
*sc
, uint8_t *val
)
130 pthread_mutex_lock(&sc
->mtx
);
131 retval
= fifo_get(sc
, val
);
132 pthread_mutex_unlock(&sc
->mtx
);
138 ps2kbd_write(struct ps2kbd_softc
*sc
, uint8_t val
)
140 pthread_mutex_lock(&sc
->mtx
);
142 switch (sc
->curcmd
) {
143 case PS2KC_SET_TYPEMATIC
:
144 fifo_put(sc
, PS2KC_ACK
);
146 case PS2KC_SET_SCANCODE_SET
:
147 fifo_put(sc
, PS2KC_ACK
);
150 fifo_put(sc
, PS2KC_ACK
);
153 fprintf(stderr
, "Unhandled ps2 keyboard current "
154 "command byte 0x%02x\n", val
);
161 fifo_put(sc
, PS2KC_ACK
);
163 case PS2KC_RESET_DEV
:
165 fifo_put(sc
, PS2KC_ACK
);
166 fifo_put(sc
, PS2KC_BAT_SUCCESS
);
170 fifo_put(sc
, PS2KC_ACK
);
175 fifo_put(sc
, PS2KC_ACK
);
177 case PS2KC_SET_TYPEMATIC
:
179 fifo_put(sc
, PS2KC_ACK
);
181 case PS2KC_SEND_DEV_ID
:
182 fifo_put(sc
, PS2KC_ACK
);
186 case PS2KC_SET_SCANCODE_SET
:
188 fifo_put(sc
, PS2KC_ACK
);
191 fifo_put(sc
, PS2KC_ECHO
);
195 fifo_put(sc
, PS2KC_ACK
);
198 fprintf(stderr
, "Unhandled ps2 keyboard command "
203 pthread_mutex_unlock(&sc
->mtx
);
207 * Translate keysym to type 2 scancode and insert into keyboard buffer.
210 ps2kbd_keysym_queue(struct ps2kbd_softc
*sc
,
211 int down
, uint32_t keysym
)
213 /* ASCII to type 2 scancode lookup table */
214 const uint8_t translation
[128] = {
215 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
216 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
217 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
218 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
219 0x29, 0x16, 0x52, 0x26, 0x25, 0x2e, 0x3d, 0x52,
220 0x46, 0x45, 0x3e, 0x55, 0x41, 0x4e, 0x49, 0x4a,
221 0x45, 0x16, 0x1e, 0x26, 0x25, 0x2e, 0x36, 0x3d,
222 0x3e, 0x46, 0x4c, 0x4c, 0x41, 0x55, 0x49, 0x4a,
223 0x1e, 0x1c, 0x32, 0x21, 0x23, 0x24, 0x2b, 0x34,
224 0x33, 0x43, 0x3b, 0x42, 0x4b, 0x3a, 0x31, 0x44,
225 0x4d, 0x15, 0x2d, 0x1b, 0x2c, 0x3c, 0x2a, 0x1d,
226 0x22, 0x35, 0x1a, 0x54, 0x5d, 0x5b, 0x36, 0x4e,
227 0x0e, 0x1c, 0x32, 0x21, 0x23, 0x24, 0x2b, 0x34,
228 0x33, 0x43, 0x3b, 0x42, 0x4b, 0x3a, 0x31, 0x44,
229 0x4d, 0x15, 0x2d, 0x1b, 0x2c, 0x3c, 0x2a, 0x1d,
230 0x22, 0x35, 0x1a, 0x54, 0x5d, 0x5b, 0x0e, 0x00,
233 assert(pthread_mutex_isowned_np(&sc
->mtx
));
239 fifo_put(sc
, translation
[keysym
]);
241 case 0xff08: /* Back space */
246 case 0xff09: /* Tab */
251 case 0xff0d: /* Return */
256 case 0xff1b: /* Escape */
261 case 0xff50: /* Home */
267 case 0xff51: /* Left arrow */
273 case 0xff52: /* Up arrow */
279 case 0xff53: /* Right arrow */
285 case 0xff54: /* Down arrow */
291 case 0xff55: /* PgUp */
297 case 0xff56: /* PgDwn */
303 case 0xff57: /* End */
309 case 0xff63: /* Ins */
315 case 0xff8d: /* Keypad Enter */
321 case 0xffe1: /* Left shift */
326 case 0xffe2: /* Right shift */
331 case 0xffe3: /* Left control */
336 case 0xffe4: /* Right control */
342 case 0xffe7: /* Left meta */
345 case 0xffe8: /* Right meta */
348 case 0xffe9: /* Left alt */
353 case 0xfe03: /* AltGr */
354 case 0xffea: /* Right alt */
360 case 0xffeb: /* Left Windows */
366 case 0xffec: /* Right Windows */
372 case 0xffbe: /* F1 */
377 case 0xffbf: /* F2 */
382 case 0xffc0: /* F3 */
387 case 0xffc1: /* F4 */
392 case 0xffc2: /* F5 */
397 case 0xffc3: /* F6 */
402 case 0xffc4: /* F7 */
407 case 0xffc5: /* F8 */
412 case 0xffc6: /* F9 */
417 case 0xffc7: /* F10 */
422 case 0xffc8: /* F11 */
427 case 0xffc9: /* F12 */
432 case 0xffff: /* Del */
439 fprintf(stderr
, "Unhandled ps2 keyboard keysym 0x%x\n",
446 ps2kbd_event(int down
, uint32_t keysym
, void *arg
)
448 struct ps2kbd_softc
*sc
= arg
;
451 pthread_mutex_lock(&sc
->mtx
);
453 pthread_mutex_unlock(&sc
->mtx
);
456 fifo_full
= sc
->fifo
.num
== PS2KBD_FIFOSZ
;
457 ps2kbd_keysym_queue(sc
, down
, keysym
);
458 pthread_mutex_unlock(&sc
->mtx
);
461 atkbdc_event(sc
->atkbdc_sc
, 1);
464 struct ps2kbd_softc
*
465 ps2kbd_init(struct atkbdc_softc
*atkbdc_sc
)
467 struct ps2kbd_softc
*sc
;
469 sc
= calloc(1, sizeof (struct ps2kbd_softc
));
470 pthread_mutex_init(&sc
->mtx
, NULL
);
472 sc
->atkbdc_sc
= atkbdc_sc
;
474 console_kbd_register(ps2kbd_event
, sc
, 1);