1b4dbc599SNathan Whitehorn /*- 2b4dbc599SNathan Whitehorn * Copyright (C) 2008 Nathan Whitehorn 3b4dbc599SNathan Whitehorn * All rights reserved. 4b4dbc599SNathan Whitehorn * 5b4dbc599SNathan Whitehorn * Redistribution and use in source and binary forms, with or without 6b4dbc599SNathan Whitehorn * modification, are permitted provided that the following conditions 7b4dbc599SNathan Whitehorn * are met: 8b4dbc599SNathan Whitehorn * 1. Redistributions of source code must retain the above copyright 9b4dbc599SNathan Whitehorn * notice, this list of conditions and the following disclaimer. 10b4dbc599SNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright 11b4dbc599SNathan Whitehorn * notice, this list of conditions and the following disclaimer in the 12b4dbc599SNathan Whitehorn * documentation and/or other materials provided with the distribution. 13b4dbc599SNathan Whitehorn * 14b4dbc599SNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15b4dbc599SNathan Whitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16b4dbc599SNathan Whitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17b4dbc599SNathan Whitehorn * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18b4dbc599SNathan Whitehorn * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19b4dbc599SNathan Whitehorn * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20b4dbc599SNathan Whitehorn * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21b4dbc599SNathan Whitehorn * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22b4dbc599SNathan Whitehorn * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23b4dbc599SNathan Whitehorn * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24b4dbc599SNathan Whitehorn * 25b4dbc599SNathan Whitehorn * $FreeBSD$ 26b4dbc599SNathan Whitehorn */ 27b4dbc599SNathan Whitehorn 28b4dbc599SNathan Whitehorn #include <sys/cdefs.h> 29b4dbc599SNathan Whitehorn #include <sys/param.h> 30b4dbc599SNathan Whitehorn #include <sys/systm.h> 31b4dbc599SNathan Whitehorn #include <sys/module.h> 32b4dbc599SNathan Whitehorn #include <sys/bus.h> 33b4dbc599SNathan Whitehorn #include <sys/conf.h> 34b4dbc599SNathan Whitehorn #include <sys/kbio.h> 35b4dbc599SNathan Whitehorn #include <sys/condvar.h> 36b4dbc599SNathan Whitehorn #include <sys/callout.h> 37b4dbc599SNathan Whitehorn #include <sys/kernel.h> 38b6faf3cfSNathan Whitehorn #include <sys/sysctl.h> 39b4dbc599SNathan Whitehorn 40b4dbc599SNathan Whitehorn #include <machine/bus.h> 41b4dbc599SNathan Whitehorn 42b4dbc599SNathan Whitehorn #include "opt_kbd.h" 43b4dbc599SNathan Whitehorn #include <dev/kbd/kbdreg.h> 44b4dbc599SNathan Whitehorn #include <dev/kbd/kbdtables.h> 45b6faf3cfSNathan Whitehorn #include <dev/ofw/openfirm.h> 46b6faf3cfSNathan Whitehorn #include <dev/ofw/ofw_bus.h> 47b4dbc599SNathan Whitehorn 48b4dbc599SNathan Whitehorn #include <vm/vm.h> 49b4dbc599SNathan Whitehorn #include <vm/pmap.h> 50b4dbc599SNathan Whitehorn 51b4dbc599SNathan Whitehorn #include "adb.h" 52b4dbc599SNathan Whitehorn 53b4dbc599SNathan Whitehorn #define KBD_DRIVER_NAME "akbd" 54b4dbc599SNathan Whitehorn 55b4dbc599SNathan Whitehorn #define AKBD_EMULATE_ATKBD 1 56b4dbc599SNathan Whitehorn 57b4dbc599SNathan Whitehorn static int adb_kbd_probe(device_t dev); 58b4dbc599SNathan Whitehorn static int adb_kbd_attach(device_t dev); 59b4dbc599SNathan Whitehorn static int adb_kbd_detach(device_t dev); 60b4dbc599SNathan Whitehorn static void akbd_repeat(void *xsc); 61b6faf3cfSNathan Whitehorn static int adb_fn_keys(SYSCTL_HANDLER_ARGS); 62b4dbc599SNathan Whitehorn 63b4dbc599SNathan Whitehorn static u_int adb_kbd_receive_packet(device_t dev, u_char status, 64b4dbc599SNathan Whitehorn u_char command, u_char reg, int len, u_char *data); 65b4dbc599SNathan Whitehorn 66b4dbc599SNathan Whitehorn struct adb_kbd_softc { 67b4dbc599SNathan Whitehorn keyboard_t sc_kbd; 68b4dbc599SNathan Whitehorn 69b4dbc599SNathan Whitehorn device_t sc_dev; 70b4dbc599SNathan Whitehorn struct mtx sc_mutex; 71b4dbc599SNathan Whitehorn struct cv sc_cv; 72b4dbc599SNathan Whitehorn 73b4dbc599SNathan Whitehorn int sc_mode; 74b4dbc599SNathan Whitehorn int sc_state; 75b4dbc599SNathan Whitehorn 76b4dbc599SNathan Whitehorn int have_led_control; 77b4dbc599SNathan Whitehorn 78b4dbc599SNathan Whitehorn uint8_t buffer[8]; 794fb52093SNathan Whitehorn #ifdef AKBD_EMULATE_ATKBD 804fb52093SNathan Whitehorn uint8_t at_buffered_char[2]; 814fb52093SNathan Whitehorn #endif 82b4dbc599SNathan Whitehorn volatile int buffers; 83b4dbc599SNathan Whitehorn 84b4dbc599SNathan Whitehorn struct callout sc_repeater; 85b4dbc599SNathan Whitehorn int sc_repeatstart; 86b4dbc599SNathan Whitehorn int sc_repeatcontinue; 87b4dbc599SNathan Whitehorn uint8_t last_press; 88b4dbc599SNathan Whitehorn }; 89b4dbc599SNathan Whitehorn 90b4dbc599SNathan Whitehorn static device_method_t adb_kbd_methods[] = { 91b4dbc599SNathan Whitehorn /* Device interface */ 92b4dbc599SNathan Whitehorn DEVMETHOD(device_probe, adb_kbd_probe), 93b4dbc599SNathan Whitehorn DEVMETHOD(device_attach, adb_kbd_attach), 94b4dbc599SNathan Whitehorn DEVMETHOD(device_detach, adb_kbd_detach), 95b4dbc599SNathan Whitehorn DEVMETHOD(device_shutdown, bus_generic_shutdown), 96b4dbc599SNathan Whitehorn DEVMETHOD(device_suspend, bus_generic_suspend), 97b4dbc599SNathan Whitehorn DEVMETHOD(device_resume, bus_generic_resume), 98b4dbc599SNathan Whitehorn 99b4dbc599SNathan Whitehorn /* ADB interface */ 100b4dbc599SNathan Whitehorn DEVMETHOD(adb_receive_packet, adb_kbd_receive_packet), 101b4dbc599SNathan Whitehorn 102b4dbc599SNathan Whitehorn { 0, 0 } 103b4dbc599SNathan Whitehorn }; 104b4dbc599SNathan Whitehorn 105b4dbc599SNathan Whitehorn static driver_t adb_kbd_driver = { 106b4dbc599SNathan Whitehorn "akbd", 107b4dbc599SNathan Whitehorn adb_kbd_methods, 108b4dbc599SNathan Whitehorn sizeof(struct adb_kbd_softc), 109b4dbc599SNathan Whitehorn }; 110b4dbc599SNathan Whitehorn 111b4dbc599SNathan Whitehorn static devclass_t adb_kbd_devclass; 112b4dbc599SNathan Whitehorn 113b4dbc599SNathan Whitehorn DRIVER_MODULE(akbd, adb, adb_kbd_driver, adb_kbd_devclass, 0, 0); 114b4dbc599SNathan Whitehorn 1154fb52093SNathan Whitehorn #ifdef AKBD_EMULATE_ATKBD 1164fb52093SNathan Whitehorn 1174fb52093SNathan Whitehorn #define SCAN_PRESS 0x000 1184fb52093SNathan Whitehorn #define SCAN_RELEASE 0x080 1194fb52093SNathan Whitehorn #define SCAN_PREFIX_E0 0x100 1204fb52093SNathan Whitehorn #define SCAN_PREFIX_E1 0x200 1214fb52093SNathan Whitehorn #define SCAN_PREFIX_CTL 0x400 1224fb52093SNathan Whitehorn #define SCAN_PREFIX_SHIFT 0x800 1234fb52093SNathan Whitehorn #define SCAN_PREFIX (SCAN_PREFIX_E0 | SCAN_PREFIX_E1 | \ 1244fb52093SNathan Whitehorn SCAN_PREFIX_CTL | SCAN_PREFIX_SHIFT) 1254fb52093SNathan Whitehorn 126b4dbc599SNathan Whitehorn static const uint8_t adb_to_at_scancode_map[128] = { 30, 31, 32, 33, 35, 34, 127b4dbc599SNathan Whitehorn 44, 45, 46, 47, 0, 48, 16, 17, 18, 19, 21, 20, 2, 3, 4, 5, 7, 6, 13, 128b4dbc599SNathan Whitehorn 10, 8, 12, 9, 11, 27, 24, 22, 26, 23, 25, 28, 38, 36, 40, 37, 39, 43, 129b4dbc599SNathan Whitehorn 51, 53, 49, 50, 52, 15, 57, 41, 14, 0, 1, 29, 0, 42, 58, 56, 97, 98, 130b4dbc599SNathan Whitehorn 100, 95, 0, 0, 83, 0, 55, 0, 78, 0, 69, 0, 0, 0, 91, 89, 0, 74, 13, 0, 131b4dbc599SNathan Whitehorn 0, 82, 79, 80, 81, 75, 76, 77, 71, 0, 72, 73, 0, 0, 0, 63, 64, 65, 61, 132b4dbc599SNathan Whitehorn 66, 67, 0, 87, 0, 105, 0, 70, 0, 68, 0, 88, 0, 107, 102, 94, 96, 103, 133b4dbc599SNathan Whitehorn 62, 99, 60, 101, 59, 54, 93, 90, 0, 0 }; 134b4dbc599SNathan Whitehorn 1354fb52093SNathan Whitehorn static int 1364fb52093SNathan Whitehorn keycode2scancode(int keycode, int shift, int up) 1374fb52093SNathan Whitehorn { 1384fb52093SNathan Whitehorn static const int scan[] = { 1394fb52093SNathan Whitehorn /* KP enter, right ctrl, KP divide */ 1404fb52093SNathan Whitehorn 0x1c , 0x1d , 0x35 , 1414fb52093SNathan Whitehorn /* print screen */ 1424fb52093SNathan Whitehorn 0x37 | SCAN_PREFIX_SHIFT, 1434fb52093SNathan Whitehorn /* right alt, home, up, page up, left, right, end */ 1444fb52093SNathan Whitehorn 0x38, 0x47, 0x48, 0x49, 0x4b, 0x4d, 0x4f, 1454fb52093SNathan Whitehorn /* down, page down, insert, delete */ 1464fb52093SNathan Whitehorn 0x50, 0x51, 0x52, 0x53, 1474fb52093SNathan Whitehorn /* pause/break (see also below) */ 1484fb52093SNathan Whitehorn 0x46, 1494fb52093SNathan Whitehorn /* 1504fb52093SNathan Whitehorn * MS: left window, right window, menu 1514fb52093SNathan Whitehorn * also Sun: left meta, right meta, compose 1524fb52093SNathan Whitehorn */ 1534fb52093SNathan Whitehorn 0x5b, 0x5c, 0x5d, 1544fb52093SNathan Whitehorn /* Sun type 6 USB */ 1554fb52093SNathan Whitehorn /* help, stop, again, props, undo, front, copy */ 1564fb52093SNathan Whitehorn 0x68, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 1574fb52093SNathan Whitehorn /* open, paste, find, cut, audiomute, audiolower, audioraise */ 1584fb52093SNathan Whitehorn 0x64, 0x65, 0x66, 0x67, 0x25, 0x1f, 0x1e, 1594fb52093SNathan Whitehorn /* power */ 1604fb52093SNathan Whitehorn 0x20 1614fb52093SNathan Whitehorn }; 1624fb52093SNathan Whitehorn int scancode; 1634fb52093SNathan Whitehorn 1644fb52093SNathan Whitehorn scancode = keycode; 165*73a1170aSPedro F. Giffuni if ((keycode >= 89) && (keycode < 89 + nitems(scan))) 1664fb52093SNathan Whitehorn scancode = scan[keycode - 89] | SCAN_PREFIX_E0; 1674fb52093SNathan Whitehorn /* pause/break */ 1684fb52093SNathan Whitehorn if ((keycode == 104) && !(shift & CTLS)) 1694fb52093SNathan Whitehorn scancode = 0x45 | SCAN_PREFIX_E1 | SCAN_PREFIX_CTL; 1704fb52093SNathan Whitehorn if (shift & SHIFTS) 1714fb52093SNathan Whitehorn scancode &= ~SCAN_PREFIX_SHIFT; 1724fb52093SNathan Whitehorn return (scancode | (up ? SCAN_RELEASE : SCAN_PRESS)); 1734fb52093SNathan Whitehorn } 1744fb52093SNathan Whitehorn #endif 1754fb52093SNathan Whitehorn 176b4dbc599SNathan Whitehorn /* keyboard driver declaration */ 177b4dbc599SNathan Whitehorn static int akbd_configure(int flags); 178b4dbc599SNathan Whitehorn static kbd_probe_t akbd_probe; 179b4dbc599SNathan Whitehorn static kbd_init_t akbd_init; 180b4dbc599SNathan Whitehorn static kbd_term_t akbd_term; 181b4dbc599SNathan Whitehorn static kbd_intr_t akbd_interrupt; 182b4dbc599SNathan Whitehorn static kbd_test_if_t akbd_test_if; 183b4dbc599SNathan Whitehorn static kbd_enable_t akbd_enable; 184b4dbc599SNathan Whitehorn static kbd_disable_t akbd_disable; 185b4dbc599SNathan Whitehorn static kbd_read_t akbd_read; 186b4dbc599SNathan Whitehorn static kbd_check_t akbd_check; 187b4dbc599SNathan Whitehorn static kbd_read_char_t akbd_read_char; 188b4dbc599SNathan Whitehorn static kbd_check_char_t akbd_check_char; 189b4dbc599SNathan Whitehorn static kbd_ioctl_t akbd_ioctl; 190b4dbc599SNathan Whitehorn static kbd_lock_t akbd_lock; 191b4dbc599SNathan Whitehorn static kbd_clear_state_t akbd_clear_state; 192b4dbc599SNathan Whitehorn static kbd_get_state_t akbd_get_state; 193b4dbc599SNathan Whitehorn static kbd_set_state_t akbd_set_state; 194b4dbc599SNathan Whitehorn static kbd_poll_mode_t akbd_poll; 195b4dbc599SNathan Whitehorn 196b4dbc599SNathan Whitehorn keyboard_switch_t akbdsw = { 197b4dbc599SNathan Whitehorn akbd_probe, 198b4dbc599SNathan Whitehorn akbd_init, 199b4dbc599SNathan Whitehorn akbd_term, 200b4dbc599SNathan Whitehorn akbd_interrupt, 201b4dbc599SNathan Whitehorn akbd_test_if, 202b4dbc599SNathan Whitehorn akbd_enable, 203b4dbc599SNathan Whitehorn akbd_disable, 204b4dbc599SNathan Whitehorn akbd_read, 205b4dbc599SNathan Whitehorn akbd_check, 206b4dbc599SNathan Whitehorn akbd_read_char, 207b4dbc599SNathan Whitehorn akbd_check_char, 208b4dbc599SNathan Whitehorn akbd_ioctl, 209b4dbc599SNathan Whitehorn akbd_lock, 210b4dbc599SNathan Whitehorn akbd_clear_state, 211b4dbc599SNathan Whitehorn akbd_get_state, 212b4dbc599SNathan Whitehorn akbd_set_state, 213b4dbc599SNathan Whitehorn genkbd_get_fkeystr, 214b4dbc599SNathan Whitehorn akbd_poll, 215b4dbc599SNathan Whitehorn genkbd_diag, 216b4dbc599SNathan Whitehorn }; 217b4dbc599SNathan Whitehorn 218b4dbc599SNathan Whitehorn KEYBOARD_DRIVER(akbd, akbdsw, akbd_configure); 219b4dbc599SNathan Whitehorn 220b4dbc599SNathan Whitehorn static int 221b4dbc599SNathan Whitehorn adb_kbd_probe(device_t dev) 222b4dbc599SNathan Whitehorn { 223b4dbc599SNathan Whitehorn uint8_t type; 224b4dbc599SNathan Whitehorn 225b4dbc599SNathan Whitehorn type = adb_get_device_type(dev); 226b4dbc599SNathan Whitehorn 227b4dbc599SNathan Whitehorn if (type != ADB_DEVICE_KEYBOARD) 228b4dbc599SNathan Whitehorn return (ENXIO); 229b4dbc599SNathan Whitehorn 230b4dbc599SNathan Whitehorn switch(adb_get_device_handler(dev)) { 231b4dbc599SNathan Whitehorn case 1: 232b4dbc599SNathan Whitehorn device_set_desc(dev,"Apple Standard Keyboard"); 233b4dbc599SNathan Whitehorn break; 234b4dbc599SNathan Whitehorn case 2: 235b4dbc599SNathan Whitehorn device_set_desc(dev,"Apple Extended Keyboard"); 236b4dbc599SNathan Whitehorn break; 237b4dbc599SNathan Whitehorn case 4: 238b4dbc599SNathan Whitehorn device_set_desc(dev,"Apple ISO Keyboard"); 239b4dbc599SNathan Whitehorn break; 240b4dbc599SNathan Whitehorn case 5: 241b4dbc599SNathan Whitehorn device_set_desc(dev,"Apple Extended ISO Keyboard"); 242b4dbc599SNathan Whitehorn break; 243b4dbc599SNathan Whitehorn case 8: 244b4dbc599SNathan Whitehorn device_set_desc(dev,"Apple Keyboard II"); 245b4dbc599SNathan Whitehorn break; 246b4dbc599SNathan Whitehorn case 9: 247b4dbc599SNathan Whitehorn device_set_desc(dev,"Apple ISO Keyboard II"); 248b4dbc599SNathan Whitehorn break; 249b4dbc599SNathan Whitehorn case 12: 250b4dbc599SNathan Whitehorn device_set_desc(dev,"PowerBook Keyboard"); 251b4dbc599SNathan Whitehorn break; 252b4dbc599SNathan Whitehorn case 13: 253b4dbc599SNathan Whitehorn device_set_desc(dev,"PowerBook ISO Keyboard"); 254b4dbc599SNathan Whitehorn break; 255b4dbc599SNathan Whitehorn case 24: 256b4dbc599SNathan Whitehorn device_set_desc(dev,"PowerBook Extended Keyboard"); 257b4dbc599SNathan Whitehorn break; 258b4dbc599SNathan Whitehorn case 27: 259b4dbc599SNathan Whitehorn device_set_desc(dev,"Apple Design Keyboard"); 260b4dbc599SNathan Whitehorn break; 261b4dbc599SNathan Whitehorn case 195: 262b4dbc599SNathan Whitehorn device_set_desc(dev,"PowerBook G3 Keyboard"); 263b4dbc599SNathan Whitehorn break; 264b4dbc599SNathan Whitehorn case 196: 265b4dbc599SNathan Whitehorn device_set_desc(dev,"iBook Keyboard"); 266b4dbc599SNathan Whitehorn break; 267b4dbc599SNathan Whitehorn default: 268b4dbc599SNathan Whitehorn device_set_desc(dev,"ADB Keyboard"); 269b4dbc599SNathan Whitehorn break; 270b4dbc599SNathan Whitehorn } 271b4dbc599SNathan Whitehorn 272b4dbc599SNathan Whitehorn return (0); 273b4dbc599SNathan Whitehorn } 274b4dbc599SNathan Whitehorn 275b4dbc599SNathan Whitehorn static int 276b4dbc599SNathan Whitehorn ms_to_ticks(int ms) 277b4dbc599SNathan Whitehorn { 278b4dbc599SNathan Whitehorn if (hz > 1000) 279b4dbc599SNathan Whitehorn return ms*(hz/1000); 280b4dbc599SNathan Whitehorn 281b4dbc599SNathan Whitehorn return ms/(1000/hz); 282b4dbc599SNathan Whitehorn } 283b4dbc599SNathan Whitehorn 284b4dbc599SNathan Whitehorn static int 285b4dbc599SNathan Whitehorn adb_kbd_attach(device_t dev) 286b4dbc599SNathan Whitehorn { 287b4dbc599SNathan Whitehorn struct adb_kbd_softc *sc; 288b4dbc599SNathan Whitehorn keyboard_switch_t *sw; 289b6faf3cfSNathan Whitehorn uint32_t fkeys; 290b6faf3cfSNathan Whitehorn phandle_t handle; 291b4dbc599SNathan Whitehorn 292b4dbc599SNathan Whitehorn sw = kbd_get_switch(KBD_DRIVER_NAME); 293b4dbc599SNathan Whitehorn if (sw == NULL) { 294b4dbc599SNathan Whitehorn return ENXIO; 295b4dbc599SNathan Whitehorn } 296b4dbc599SNathan Whitehorn 297b4dbc599SNathan Whitehorn sc = device_get_softc(dev); 298b4dbc599SNathan Whitehorn sc->sc_dev = dev; 299b4dbc599SNathan Whitehorn sc->sc_mode = K_RAW; 300b4dbc599SNathan Whitehorn sc->sc_state = 0; 301b4dbc599SNathan Whitehorn sc->have_led_control = 0; 302b4dbc599SNathan Whitehorn sc->buffers = 0; 303b4dbc599SNathan Whitehorn 304b4dbc599SNathan Whitehorn /* Try stepping forward to the extended keyboard protocol */ 305b4dbc599SNathan Whitehorn adb_set_device_handler(dev,3); 306b4dbc599SNathan Whitehorn 307c821b482SJustin Hibbits mtx_init(&sc->sc_mutex, KBD_DRIVER_NAME, NULL, MTX_DEF); 308b4dbc599SNathan Whitehorn cv_init(&sc->sc_cv,KBD_DRIVER_NAME); 309b4dbc599SNathan Whitehorn callout_init(&sc->sc_repeater, 0); 310b4dbc599SNathan Whitehorn 311b4dbc599SNathan Whitehorn #ifdef AKBD_EMULATE_ATKBD 312b4dbc599SNathan Whitehorn kbd_init_struct(&sc->sc_kbd, KBD_DRIVER_NAME, KB_101, 0, 0, 0, 0); 313b4dbc599SNathan Whitehorn kbd_set_maps(&sc->sc_kbd, &key_map, &accent_map, fkey_tab, 314b4dbc599SNathan Whitehorn sizeof(fkey_tab) / sizeof(fkey_tab[0])); 315b4dbc599SNathan Whitehorn #else 316b4dbc599SNathan Whitehorn #error ADB raw mode not implemented 317b4dbc599SNathan Whitehorn #endif 318b4dbc599SNathan Whitehorn 319b4dbc599SNathan Whitehorn KBD_FOUND_DEVICE(&sc->sc_kbd); 320b4dbc599SNathan Whitehorn KBD_PROBE_DONE(&sc->sc_kbd); 321b4dbc599SNathan Whitehorn KBD_INIT_DONE(&sc->sc_kbd); 322b4dbc599SNathan Whitehorn KBD_CONFIG_DONE(&sc->sc_kbd); 323b4dbc599SNathan Whitehorn 324b4dbc599SNathan Whitehorn (*sw->enable)(&sc->sc_kbd); 325b4dbc599SNathan Whitehorn 326b4dbc599SNathan Whitehorn kbd_register(&sc->sc_kbd); 327b4dbc599SNathan Whitehorn 328b4dbc599SNathan Whitehorn #ifdef KBD_INSTALL_CDEV 329b4dbc599SNathan Whitehorn if (kbd_attach(&sc->sc_kbd)) { 330b4dbc599SNathan Whitehorn adb_kbd_detach(dev); 331b4dbc599SNathan Whitehorn return ENXIO; 332b4dbc599SNathan Whitehorn } 333b4dbc599SNathan Whitehorn #endif 334b4dbc599SNathan Whitehorn 335582434bdSNathan Whitehorn /* Check if we can read out the LED state from 336b4dbc599SNathan Whitehorn this keyboard by reading the key state register */ 337582434bdSNathan Whitehorn if (adb_read_register(dev, 2, NULL) == 2) 338582434bdSNathan Whitehorn sc->have_led_control = 1; 339582434bdSNathan Whitehorn 340582434bdSNathan Whitehorn adb_set_autopoll(dev,1); 341b4dbc599SNathan Whitehorn 342b6faf3cfSNathan Whitehorn handle = OF_finddevice("mac-io/via-pmu/adb/keyboard"); 343b6faf3cfSNathan Whitehorn if (handle != -1 && OF_getprop(handle, "AAPL,has-embedded-fn-keys", 344b6faf3cfSNathan Whitehorn &fkeys, sizeof(fkeys)) != -1) { 345b6faf3cfSNathan Whitehorn static const char *key_names[] = {"F1", "F2", "F3", "F4", "F5", 346b6faf3cfSNathan Whitehorn "F6", "F7", "F8", "F9", "F10", "F11", "F12"}; 347b6faf3cfSNathan Whitehorn struct sysctl_ctx_list *ctx; 348b6faf3cfSNathan Whitehorn struct sysctl_oid *tree; 349b6faf3cfSNathan Whitehorn int i; 350b6faf3cfSNathan Whitehorn 351b6faf3cfSNathan Whitehorn if (bootverbose) 352b6faf3cfSNathan Whitehorn device_printf(dev, "Keyboard has embedded Fn keys\n"); 353b6faf3cfSNathan Whitehorn 354b6faf3cfSNathan Whitehorn for (i = 0; i < 12; i++) { 355b6faf3cfSNathan Whitehorn uint32_t keyval; 356b6faf3cfSNathan Whitehorn char buf[3]; 357b6faf3cfSNathan Whitehorn if (OF_getprop(handle, key_names[i], &keyval, 358b6faf3cfSNathan Whitehorn sizeof(keyval)) < 0) 359b6faf3cfSNathan Whitehorn continue; 360b6faf3cfSNathan Whitehorn buf[0] = 1; 361b6faf3cfSNathan Whitehorn buf[1] = i+1; 362b6faf3cfSNathan Whitehorn buf[2] = keyval; 363b6faf3cfSNathan Whitehorn adb_write_register(dev, 0, 3, buf); 364b6faf3cfSNathan Whitehorn } 365b6faf3cfSNathan Whitehorn adb_write_register(dev, 1, 2, &(uint16_t){0}); 366b6faf3cfSNathan Whitehorn 367b6faf3cfSNathan Whitehorn ctx = device_get_sysctl_ctx(dev); 368b6faf3cfSNathan Whitehorn tree = device_get_sysctl_tree(dev); 369b6faf3cfSNathan Whitehorn 370b6faf3cfSNathan Whitehorn SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 371b6faf3cfSNathan Whitehorn "fn_keys_function_as_primary", CTLTYPE_INT | CTLFLAG_RW, sc, 372b6faf3cfSNathan Whitehorn 0, adb_fn_keys, "I", 373b6faf3cfSNathan Whitehorn "Set the Fn keys to be their F-key type as default"); 374b6faf3cfSNathan Whitehorn } 375b6faf3cfSNathan Whitehorn 376b4dbc599SNathan Whitehorn return (0); 377b4dbc599SNathan Whitehorn } 378b4dbc599SNathan Whitehorn 379b4dbc599SNathan Whitehorn static int 380b4dbc599SNathan Whitehorn adb_kbd_detach(device_t dev) 381b4dbc599SNathan Whitehorn { 382b4dbc599SNathan Whitehorn struct adb_kbd_softc *sc; 383b4dbc599SNathan Whitehorn keyboard_t *kbd; 384b4dbc599SNathan Whitehorn 385b4dbc599SNathan Whitehorn sc = device_get_softc(dev); 386b4dbc599SNathan Whitehorn 387b4dbc599SNathan Whitehorn adb_set_autopoll(dev,0); 388b4dbc599SNathan Whitehorn callout_stop(&sc->sc_repeater); 389b4dbc599SNathan Whitehorn 390b4dbc599SNathan Whitehorn mtx_lock(&sc->sc_mutex); 391b4dbc599SNathan Whitehorn 392b4dbc599SNathan Whitehorn kbd = kbd_get_keyboard(kbd_find_keyboard(KBD_DRIVER_NAME, 393b4dbc599SNathan Whitehorn device_get_unit(dev))); 394b4dbc599SNathan Whitehorn 395b4dbc599SNathan Whitehorn kbdd_disable(kbd); 396b4dbc599SNathan Whitehorn 397b4dbc599SNathan Whitehorn #ifdef KBD_INSTALL_CDEV 398b4dbc599SNathan Whitehorn kbd_detach(kbd); 399b4dbc599SNathan Whitehorn #endif 400b4dbc599SNathan Whitehorn 401b4dbc599SNathan Whitehorn kbdd_term(kbd); 402b4dbc599SNathan Whitehorn 403b4dbc599SNathan Whitehorn mtx_unlock(&sc->sc_mutex); 404b4dbc599SNathan Whitehorn 405b4dbc599SNathan Whitehorn mtx_destroy(&sc->sc_mutex); 406b4dbc599SNathan Whitehorn cv_destroy(&sc->sc_cv); 407b4dbc599SNathan Whitehorn 408b4dbc599SNathan Whitehorn return (0); 409b4dbc599SNathan Whitehorn } 410b4dbc599SNathan Whitehorn 411b4dbc599SNathan Whitehorn static u_int 412b4dbc599SNathan Whitehorn adb_kbd_receive_packet(device_t dev, u_char status, 413b4dbc599SNathan Whitehorn u_char command, u_char reg, int len, u_char *data) 414b4dbc599SNathan Whitehorn { 415b4dbc599SNathan Whitehorn struct adb_kbd_softc *sc; 416b4dbc599SNathan Whitehorn 417b4dbc599SNathan Whitehorn sc = device_get_softc(dev); 418b4dbc599SNathan Whitehorn 419b4dbc599SNathan Whitehorn if (command != ADB_COMMAND_TALK) 420b4dbc599SNathan Whitehorn return 0; 421b4dbc599SNathan Whitehorn 422b4dbc599SNathan Whitehorn if (reg != 0 || len != 2) 423b4dbc599SNathan Whitehorn return (0); 424b4dbc599SNathan Whitehorn 425b4dbc599SNathan Whitehorn mtx_lock(&sc->sc_mutex); 426b6faf3cfSNathan Whitehorn /* 0x7f is always the power button */ 4270b3a30a6SJustin Hibbits if (data[0] == 0x7f) { 428b6faf3cfSNathan Whitehorn devctl_notify("PMU", "Button", "pressed", NULL); 429ff1b355cSJustin Hibbits mtx_unlock(&sc->sc_mutex); 430b6faf3cfSNathan Whitehorn return (0); 431b6faf3cfSNathan Whitehorn } else if (data[0] == 0xff) { 432ff1b355cSJustin Hibbits mtx_unlock(&sc->sc_mutex); 433b6faf3cfSNathan Whitehorn return (0); /* Ignore power button release. */ 434b6faf3cfSNathan Whitehorn } 435b4dbc599SNathan Whitehorn if ((data[0] & 0x7f) == 57 && sc->buffers < 7) { 436b4dbc599SNathan Whitehorn /* Fake the down/up cycle for caps lock */ 437b4dbc599SNathan Whitehorn sc->buffer[sc->buffers++] = data[0] & 0x7f; 438b4dbc599SNathan Whitehorn sc->buffer[sc->buffers++] = (data[0] & 0x7f) | (1 << 7); 439b4dbc599SNathan Whitehorn } else { 440b4dbc599SNathan Whitehorn sc->buffer[sc->buffers++] = data[0]; 441b4dbc599SNathan Whitehorn } 442b4dbc599SNathan Whitehorn if (sc->buffer[sc->buffers-1] < 0xff) 443b4dbc599SNathan Whitehorn sc->last_press = sc->buffer[sc->buffers-1]; 444b4dbc599SNathan Whitehorn 445b4dbc599SNathan Whitehorn if ((data[1] & 0x7f) == 57 && sc->buffers < 7) { 446b4dbc599SNathan Whitehorn /* Fake the down/up cycle for caps lock */ 447b4dbc599SNathan Whitehorn sc->buffer[sc->buffers++] = data[1] & 0x7f; 448b4dbc599SNathan Whitehorn sc->buffer[sc->buffers++] = (data[1] & 0x7f) | (1 << 7); 449b4dbc599SNathan Whitehorn } else { 450b4dbc599SNathan Whitehorn sc->buffer[sc->buffers++] = data[1]; 451b4dbc599SNathan Whitehorn } 452b4dbc599SNathan Whitehorn 453b4dbc599SNathan Whitehorn if (sc->buffer[sc->buffers-1] < 0xff) 454b4dbc599SNathan Whitehorn sc->last_press = sc->buffer[sc->buffers-1]; 455b4dbc599SNathan Whitehorn 456b4dbc599SNathan Whitehorn /* Stop any existing key repeating */ 457b4dbc599SNathan Whitehorn callout_stop(&sc->sc_repeater); 458b4dbc599SNathan Whitehorn 459b4dbc599SNathan Whitehorn /* Schedule a repeat callback on keydown */ 460b4dbc599SNathan Whitehorn if (!(sc->last_press & (1 << 7))) { 461b4dbc599SNathan Whitehorn callout_reset(&sc->sc_repeater, 462b4dbc599SNathan Whitehorn ms_to_ticks(sc->sc_kbd.kb_delay1), akbd_repeat, sc); 463b4dbc599SNathan Whitehorn } 464b4dbc599SNathan Whitehorn mtx_unlock(&sc->sc_mutex); 465b4dbc599SNathan Whitehorn 466b4dbc599SNathan Whitehorn cv_broadcast(&sc->sc_cv); 467b4dbc599SNathan Whitehorn 468b4dbc599SNathan Whitehorn if (KBD_IS_ACTIVE(&sc->sc_kbd) && KBD_IS_BUSY(&sc->sc_kbd)) { 469b4dbc599SNathan Whitehorn sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd, 470b4dbc599SNathan Whitehorn KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg); 471b4dbc599SNathan Whitehorn } 472b4dbc599SNathan Whitehorn 473b4dbc599SNathan Whitehorn return (0); 474b4dbc599SNathan Whitehorn } 475b4dbc599SNathan Whitehorn 476b4dbc599SNathan Whitehorn static void 477b4dbc599SNathan Whitehorn akbd_repeat(void *xsc) { 478b4dbc599SNathan Whitehorn struct adb_kbd_softc *sc = xsc; 479b4dbc599SNathan Whitehorn int notify_kbd = 0; 480b4dbc599SNathan Whitehorn 481b4dbc599SNathan Whitehorn /* Fake an up/down key repeat so long as we have the 482b4dbc599SNathan Whitehorn free buffers */ 483b4dbc599SNathan Whitehorn mtx_lock(&sc->sc_mutex); 484b4dbc599SNathan Whitehorn if (sc->buffers < 7) { 485b4dbc599SNathan Whitehorn sc->buffer[sc->buffers++] = sc->last_press | (1 << 7); 486b4dbc599SNathan Whitehorn sc->buffer[sc->buffers++] = sc->last_press; 487b4dbc599SNathan Whitehorn 488b4dbc599SNathan Whitehorn notify_kbd = 1; 489b4dbc599SNathan Whitehorn } 490b4dbc599SNathan Whitehorn mtx_unlock(&sc->sc_mutex); 491b4dbc599SNathan Whitehorn 492b4dbc599SNathan Whitehorn if (notify_kbd && KBD_IS_ACTIVE(&sc->sc_kbd) 493b4dbc599SNathan Whitehorn && KBD_IS_BUSY(&sc->sc_kbd)) { 494b4dbc599SNathan Whitehorn sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd, 495b4dbc599SNathan Whitehorn KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg); 496b4dbc599SNathan Whitehorn } 497b4dbc599SNathan Whitehorn 498b4dbc599SNathan Whitehorn /* Reschedule the callout */ 499b4dbc599SNathan Whitehorn callout_reset(&sc->sc_repeater, ms_to_ticks(sc->sc_kbd.kb_delay2), 500b4dbc599SNathan Whitehorn akbd_repeat, sc); 501b4dbc599SNathan Whitehorn } 502b4dbc599SNathan Whitehorn 503b4dbc599SNathan Whitehorn static int 504b4dbc599SNathan Whitehorn akbd_configure(int flags) 505b4dbc599SNathan Whitehorn { 506b4dbc599SNathan Whitehorn return 0; 507b4dbc599SNathan Whitehorn } 508b4dbc599SNathan Whitehorn 509b4dbc599SNathan Whitehorn static int 510b4dbc599SNathan Whitehorn akbd_probe(int unit, void *arg, int flags) 511b4dbc599SNathan Whitehorn { 512b4dbc599SNathan Whitehorn return 0; 513b4dbc599SNathan Whitehorn } 514b4dbc599SNathan Whitehorn 515b4dbc599SNathan Whitehorn static int 516b4dbc599SNathan Whitehorn akbd_init(int unit, keyboard_t **kbdp, void *arg, int flags) 517b4dbc599SNathan Whitehorn { 518b4dbc599SNathan Whitehorn return 0; 519b4dbc599SNathan Whitehorn } 520b4dbc599SNathan Whitehorn 521b4dbc599SNathan Whitehorn static int 522b4dbc599SNathan Whitehorn akbd_term(keyboard_t *kbd) 523b4dbc599SNathan Whitehorn { 524b4dbc599SNathan Whitehorn return 0; 525b4dbc599SNathan Whitehorn } 526b4dbc599SNathan Whitehorn 527b4dbc599SNathan Whitehorn static int 528b4dbc599SNathan Whitehorn akbd_interrupt(keyboard_t *kbd, void *arg) 529b4dbc599SNathan Whitehorn { 530b4dbc599SNathan Whitehorn return 0; 531b4dbc599SNathan Whitehorn } 532b4dbc599SNathan Whitehorn 533b4dbc599SNathan Whitehorn static int 534b4dbc599SNathan Whitehorn akbd_test_if(keyboard_t *kbd) 535b4dbc599SNathan Whitehorn { 536b4dbc599SNathan Whitehorn return 0; 537b4dbc599SNathan Whitehorn } 538b4dbc599SNathan Whitehorn 539b4dbc599SNathan Whitehorn static int 540b4dbc599SNathan Whitehorn akbd_enable(keyboard_t *kbd) 541b4dbc599SNathan Whitehorn { 542b4dbc599SNathan Whitehorn KBD_ACTIVATE(kbd); 543b4dbc599SNathan Whitehorn return (0); 544b4dbc599SNathan Whitehorn } 545b4dbc599SNathan Whitehorn 546b4dbc599SNathan Whitehorn static int 547b4dbc599SNathan Whitehorn akbd_disable(keyboard_t *kbd) 548b4dbc599SNathan Whitehorn { 549b4dbc599SNathan Whitehorn struct adb_kbd_softc *sc; 550b4dbc599SNathan Whitehorn sc = (struct adb_kbd_softc *)(kbd); 551b4dbc599SNathan Whitehorn 552b4dbc599SNathan Whitehorn callout_stop(&sc->sc_repeater); 553b4dbc599SNathan Whitehorn KBD_DEACTIVATE(kbd); 554b4dbc599SNathan Whitehorn return (0); 555b4dbc599SNathan Whitehorn } 556b4dbc599SNathan Whitehorn 557b4dbc599SNathan Whitehorn static int 558b4dbc599SNathan Whitehorn akbd_read(keyboard_t *kbd, int wait) 559b4dbc599SNathan Whitehorn { 560b4dbc599SNathan Whitehorn return (0); 561b4dbc599SNathan Whitehorn } 562b4dbc599SNathan Whitehorn 563b4dbc599SNathan Whitehorn static int 564b4dbc599SNathan Whitehorn akbd_check(keyboard_t *kbd) 565b4dbc599SNathan Whitehorn { 566b4dbc599SNathan Whitehorn struct adb_kbd_softc *sc; 567b4dbc599SNathan Whitehorn 568b4dbc599SNathan Whitehorn if (!KBD_IS_ACTIVE(kbd)) 569b4dbc599SNathan Whitehorn return (FALSE); 570b4dbc599SNathan Whitehorn 571b4dbc599SNathan Whitehorn sc = (struct adb_kbd_softc *)(kbd); 572b4dbc599SNathan Whitehorn 573b4dbc599SNathan Whitehorn mtx_lock(&sc->sc_mutex); 5744fb52093SNathan Whitehorn #ifdef AKBD_EMULATE_ATKBD 5754fb52093SNathan Whitehorn if (sc->at_buffered_char[0]) { 5764fb52093SNathan Whitehorn mtx_unlock(&sc->sc_mutex); 5774fb52093SNathan Whitehorn return (TRUE); 5784fb52093SNathan Whitehorn } 5794fb52093SNathan Whitehorn #endif 5804fb52093SNathan Whitehorn 581b4dbc599SNathan Whitehorn if (sc->buffers > 0) { 582b4dbc599SNathan Whitehorn mtx_unlock(&sc->sc_mutex); 583b4dbc599SNathan Whitehorn return (TRUE); 584b4dbc599SNathan Whitehorn } 585b4dbc599SNathan Whitehorn mtx_unlock(&sc->sc_mutex); 586b4dbc599SNathan Whitehorn 587b4dbc599SNathan Whitehorn return (FALSE); 588b4dbc599SNathan Whitehorn } 589b4dbc599SNathan Whitehorn 590b4dbc599SNathan Whitehorn static u_int 591b4dbc599SNathan Whitehorn akbd_read_char(keyboard_t *kbd, int wait) 592b4dbc599SNathan Whitehorn { 593b4dbc599SNathan Whitehorn struct adb_kbd_softc *sc; 5944fb52093SNathan Whitehorn uint16_t key; 5954fb52093SNathan Whitehorn uint8_t adb_code; 596b4dbc599SNathan Whitehorn int i; 597b4dbc599SNathan Whitehorn 598b4dbc599SNathan Whitehorn sc = (struct adb_kbd_softc *)(kbd); 599b4dbc599SNathan Whitehorn 600b4dbc599SNathan Whitehorn mtx_lock(&sc->sc_mutex); 6014fb52093SNathan Whitehorn 6024fb52093SNathan Whitehorn #if defined(AKBD_EMULATE_ATKBD) 6034fb52093SNathan Whitehorn if (sc->sc_mode == K_RAW && sc->at_buffered_char[0]) { 6044fb52093SNathan Whitehorn key = sc->at_buffered_char[0]; 6054fb52093SNathan Whitehorn if (key & SCAN_PREFIX) { 6064fb52093SNathan Whitehorn sc->at_buffered_char[0] = key & ~SCAN_PREFIX; 6074fb52093SNathan Whitehorn key = (key & SCAN_PREFIX_E0) ? 0xe0 : 0xe1; 6084fb52093SNathan Whitehorn } else { 6094fb52093SNathan Whitehorn sc->at_buffered_char[0] = sc->at_buffered_char[1]; 6104fb52093SNathan Whitehorn sc->at_buffered_char[1] = 0; 6114fb52093SNathan Whitehorn } 6124fb52093SNathan Whitehorn 6134fb52093SNathan Whitehorn mtx_unlock(&sc->sc_mutex); 6144fb52093SNathan Whitehorn 6154fb52093SNathan Whitehorn return (key); 6164fb52093SNathan Whitehorn } 6174fb52093SNathan Whitehorn #endif 6184fb52093SNathan Whitehorn 619b4dbc599SNathan Whitehorn if (!sc->buffers && wait) 620b4dbc599SNathan Whitehorn cv_wait(&sc->sc_cv,&sc->sc_mutex); 621b4dbc599SNathan Whitehorn 622b4dbc599SNathan Whitehorn if (!sc->buffers) { 623b4dbc599SNathan Whitehorn mtx_unlock(&sc->sc_mutex); 624f7d6cb20SNathan Whitehorn return (NOKEY); 625b4dbc599SNathan Whitehorn } 626b4dbc599SNathan Whitehorn 627b4dbc599SNathan Whitehorn adb_code = sc->buffer[0]; 628b4dbc599SNathan Whitehorn 629b4dbc599SNathan Whitehorn for (i = 1; i < sc->buffers; i++) 630b4dbc599SNathan Whitehorn sc->buffer[i-1] = sc->buffer[i]; 631b4dbc599SNathan Whitehorn 632b4dbc599SNathan Whitehorn sc->buffers--; 633b4dbc599SNathan Whitehorn 634b4dbc599SNathan Whitehorn #ifdef AKBD_EMULATE_ATKBD 6354fb52093SNathan Whitehorn key = adb_to_at_scancode_map[adb_code & 0x7f]; 6364fb52093SNathan Whitehorn if (sc->sc_mode == K_CODE) { 6374fb52093SNathan Whitehorn /* Add the key-release bit */ 6384fb52093SNathan Whitehorn key |= adb_code & 0x80; 6394fb52093SNathan Whitehorn } else if (sc->sc_mode == K_RAW) { 6404fb52093SNathan Whitehorn /* 6414fb52093SNathan Whitehorn * In the raw case, we have to emulate the gross 6424fb52093SNathan Whitehorn * variable-length AT keyboard thing. Since this code 6434fb52093SNathan Whitehorn * is copied from sunkbd, which is the same code 6444fb52093SNathan Whitehorn * as ukbd, it might be nice to have this centralized. 6454fb52093SNathan Whitehorn */ 6464fb52093SNathan Whitehorn 6474fb52093SNathan Whitehorn key = keycode2scancode(key, 6484fb52093SNathan Whitehorn 0, adb_code & 0x80); 6494fb52093SNathan Whitehorn 6504fb52093SNathan Whitehorn if (key & SCAN_PREFIX) { 6514fb52093SNathan Whitehorn if (key & SCAN_PREFIX_CTL) { 6524fb52093SNathan Whitehorn sc->at_buffered_char[0] = 6534fb52093SNathan Whitehorn 0x1d | (key & SCAN_RELEASE); 6544fb52093SNathan Whitehorn sc->at_buffered_char[1] = 6554fb52093SNathan Whitehorn key & ~SCAN_PREFIX; 6564fb52093SNathan Whitehorn } else if (key & SCAN_PREFIX_SHIFT) { 6574fb52093SNathan Whitehorn sc->at_buffered_char[0] = 6584fb52093SNathan Whitehorn 0x2a | (key & SCAN_RELEASE); 6594fb52093SNathan Whitehorn sc->at_buffered_char[1] = 6604fb52093SNathan Whitehorn key & ~SCAN_PREFIX_SHIFT; 6614fb52093SNathan Whitehorn } else { 6624fb52093SNathan Whitehorn sc->at_buffered_char[0] = 6634fb52093SNathan Whitehorn key & ~SCAN_PREFIX; 6644fb52093SNathan Whitehorn sc->at_buffered_char[1] = 0; 6654fb52093SNathan Whitehorn } 6664fb52093SNathan Whitehorn 6674fb52093SNathan Whitehorn key = (key & SCAN_PREFIX_E0) ? 0xe0 : 0xe1; 6684fb52093SNathan Whitehorn } 6694fb52093SNathan Whitehorn } 670b4dbc599SNathan Whitehorn #else 6714fb52093SNathan Whitehorn key = adb_code; 672b4dbc599SNathan Whitehorn #endif 673b4dbc599SNathan Whitehorn 6744fb52093SNathan Whitehorn mtx_unlock(&sc->sc_mutex); 6754fb52093SNathan Whitehorn 6764fb52093SNathan Whitehorn return (key); 677b4dbc599SNathan Whitehorn } 678b4dbc599SNathan Whitehorn 679b4dbc599SNathan Whitehorn static int 680b4dbc599SNathan Whitehorn akbd_check_char(keyboard_t *kbd) 681b4dbc599SNathan Whitehorn { 682b4dbc599SNathan Whitehorn if (!KBD_IS_ACTIVE(kbd)) 683b4dbc599SNathan Whitehorn return (FALSE); 684b4dbc599SNathan Whitehorn 685b4dbc599SNathan Whitehorn return (akbd_check(kbd)); 686b4dbc599SNathan Whitehorn } 687b4dbc599SNathan Whitehorn 688b4dbc599SNathan Whitehorn static int 689b4dbc599SNathan Whitehorn set_typematic(keyboard_t *kbd, int code) 690b4dbc599SNathan Whitehorn { 691b4dbc599SNathan Whitehorn /* These numbers are in microseconds, so convert to ticks */ 692b4dbc599SNathan Whitehorn 693b4dbc599SNathan Whitehorn static int delays[] = { 250, 500, 750, 1000 }; 694b4dbc599SNathan Whitehorn static int rates[] = { 34, 38, 42, 46, 50, 55, 59, 63, 695b4dbc599SNathan Whitehorn 68, 76, 84, 92, 100, 110, 118, 126, 696b4dbc599SNathan Whitehorn 136, 152, 168, 184, 200, 220, 236, 252, 697b4dbc599SNathan Whitehorn 272, 304, 336, 368, 400, 440, 472, 504 }; 698b4dbc599SNathan Whitehorn 699b4dbc599SNathan Whitehorn if (code & ~0x7f) 700b4dbc599SNathan Whitehorn return EINVAL; 701b4dbc599SNathan Whitehorn kbd->kb_delay1 = delays[(code >> 5) & 3]; 702b4dbc599SNathan Whitehorn kbd->kb_delay2 = rates[code & 0x1f]; 703b4dbc599SNathan Whitehorn return 0; 704b4dbc599SNathan Whitehorn } 705b4dbc599SNathan Whitehorn 706b4dbc599SNathan Whitehorn static int akbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t data) 707b4dbc599SNathan Whitehorn { 708b4dbc599SNathan Whitehorn struct adb_kbd_softc *sc; 709b4dbc599SNathan Whitehorn uint16_t r2; 710b4dbc599SNathan Whitehorn int error; 711b4dbc599SNathan Whitehorn 712b4dbc599SNathan Whitehorn sc = (struct adb_kbd_softc *)(kbd); 713b4dbc599SNathan Whitehorn error = 0; 714b4dbc599SNathan Whitehorn 715b4dbc599SNathan Whitehorn switch (cmd) { 716b4dbc599SNathan Whitehorn case KDGKBMODE: 717b4dbc599SNathan Whitehorn *(int *)data = sc->sc_mode; 718b4dbc599SNathan Whitehorn break; 719b4dbc599SNathan Whitehorn case KDSKBMODE: 720b4dbc599SNathan Whitehorn switch (*(int *)data) { 721b4dbc599SNathan Whitehorn case K_XLATE: 722b4dbc599SNathan Whitehorn if (sc->sc_mode != K_XLATE) { 723b4dbc599SNathan Whitehorn /* make lock key state and LED state match */ 724b4dbc599SNathan Whitehorn sc->sc_state &= ~LOCK_MASK; 725b4dbc599SNathan Whitehorn sc->sc_state |= KBD_LED_VAL(kbd); 726b4dbc599SNathan Whitehorn } 727b4dbc599SNathan Whitehorn /* FALLTHROUGH */ 728b4dbc599SNathan Whitehorn case K_RAW: 729b4dbc599SNathan Whitehorn case K_CODE: 730b4dbc599SNathan Whitehorn if (sc->sc_mode != *(int *)data) 731b4dbc599SNathan Whitehorn sc->sc_mode = *(int *)data; 732b4dbc599SNathan Whitehorn break; 733b4dbc599SNathan Whitehorn default: 734b4dbc599SNathan Whitehorn error = EINVAL; 735b4dbc599SNathan Whitehorn break; 736b4dbc599SNathan Whitehorn } 737b4dbc599SNathan Whitehorn 738b4dbc599SNathan Whitehorn break; 739b4dbc599SNathan Whitehorn 740b4dbc599SNathan Whitehorn case KDGETLED: 741b4dbc599SNathan Whitehorn *(int *)data = KBD_LED_VAL(kbd); 742b4dbc599SNathan Whitehorn break; 743b4dbc599SNathan Whitehorn 744b4dbc599SNathan Whitehorn case KDSKBSTATE: 745b4dbc599SNathan Whitehorn if (*(int *)data & ~LOCK_MASK) { 746b4dbc599SNathan Whitehorn error = EINVAL; 747b4dbc599SNathan Whitehorn break; 748b4dbc599SNathan Whitehorn } 749b4dbc599SNathan Whitehorn sc->sc_state &= ~LOCK_MASK; 750b4dbc599SNathan Whitehorn sc->sc_state |= *(int *)data; 751b4dbc599SNathan Whitehorn 752b4dbc599SNathan Whitehorn /* FALLTHROUGH */ 753b4dbc599SNathan Whitehorn 754b4dbc599SNathan Whitehorn case KDSETLED: 755b4dbc599SNathan Whitehorn KBD_LED_VAL(kbd) = *(int *)data; 756b4dbc599SNathan Whitehorn 757b4dbc599SNathan Whitehorn if (!sc->have_led_control) 758b4dbc599SNathan Whitehorn break; 759b4dbc599SNathan Whitehorn 760b4dbc599SNathan Whitehorn r2 = (~0 & 0x04) | 3; 761b4dbc599SNathan Whitehorn 762b4dbc599SNathan Whitehorn if (*(int *)data & NLKED) 763b4dbc599SNathan Whitehorn r2 &= ~1; 764b4dbc599SNathan Whitehorn if (*(int *)data & CLKED) 765b4dbc599SNathan Whitehorn r2 &= ~2; 766b4dbc599SNathan Whitehorn if (*(int *)data & SLKED) 767b4dbc599SNathan Whitehorn r2 &= ~4; 768b4dbc599SNathan Whitehorn 769b4dbc599SNathan Whitehorn adb_send_packet(sc->sc_dev,ADB_COMMAND_LISTEN,2, 770b4dbc599SNathan Whitehorn sizeof(uint16_t),(u_char *)&r2); 771b4dbc599SNathan Whitehorn 772b4dbc599SNathan Whitehorn break; 773b4dbc599SNathan Whitehorn 774b4dbc599SNathan Whitehorn case KDGKBSTATE: 775b4dbc599SNathan Whitehorn *(int *)data = sc->sc_state & LOCK_MASK; 776b4dbc599SNathan Whitehorn break; 777b4dbc599SNathan Whitehorn 778b4dbc599SNathan Whitehorn case KDSETREPEAT: 779b4dbc599SNathan Whitehorn if (!KBD_HAS_DEVICE(kbd)) 780b4dbc599SNathan Whitehorn return 0; 781b4dbc599SNathan Whitehorn if (((int *)data)[1] < 0) 782b4dbc599SNathan Whitehorn return EINVAL; 783b4dbc599SNathan Whitehorn if (((int *)data)[0] < 0) 784b4dbc599SNathan Whitehorn return EINVAL; 785b4dbc599SNathan Whitehorn else if (((int *)data)[0] == 0) /* fastest possible value */ 786b4dbc599SNathan Whitehorn kbd->kb_delay1 = 200; 787b4dbc599SNathan Whitehorn else 788b4dbc599SNathan Whitehorn kbd->kb_delay1 = ((int *)data)[0]; 789b4dbc599SNathan Whitehorn kbd->kb_delay2 = ((int *)data)[1]; 790b4dbc599SNathan Whitehorn 791b4dbc599SNathan Whitehorn break; 792b4dbc599SNathan Whitehorn 793b4dbc599SNathan Whitehorn case KDSETRAD: 794b4dbc599SNathan Whitehorn error = set_typematic(kbd, *(int *)data); 795b4dbc599SNathan Whitehorn break; 796b4dbc599SNathan Whitehorn 797b4dbc599SNathan Whitehorn case PIO_KEYMAP: 79878d4d8eeSEd Schouten case OPIO_KEYMAP: 799b4dbc599SNathan Whitehorn case PIO_KEYMAPENT: 800b4dbc599SNathan Whitehorn case PIO_DEADKEYMAP: 801b4dbc599SNathan Whitehorn default: 802b4dbc599SNathan Whitehorn return (genkbd_commonioctl(kbd, cmd, data)); 803b4dbc599SNathan Whitehorn } 804b4dbc599SNathan Whitehorn 805b4dbc599SNathan Whitehorn return (error); 806b4dbc599SNathan Whitehorn } 807b4dbc599SNathan Whitehorn 808b4dbc599SNathan Whitehorn static int akbd_lock(keyboard_t *kbd, int lock) 809b4dbc599SNathan Whitehorn { 810b4dbc599SNathan Whitehorn return (0); 811b4dbc599SNathan Whitehorn } 812b4dbc599SNathan Whitehorn 813b4dbc599SNathan Whitehorn static void akbd_clear_state(keyboard_t *kbd) 814b4dbc599SNathan Whitehorn { 8154fb52093SNathan Whitehorn struct adb_kbd_softc *sc; 8164fb52093SNathan Whitehorn 8174fb52093SNathan Whitehorn sc = (struct adb_kbd_softc *)(kbd); 8184fb52093SNathan Whitehorn 8194fb52093SNathan Whitehorn mtx_lock(&sc->sc_mutex); 8204fb52093SNathan Whitehorn 8214fb52093SNathan Whitehorn sc->buffers = 0; 8224fb52093SNathan Whitehorn callout_stop(&sc->sc_repeater); 8234fb52093SNathan Whitehorn 8244fb52093SNathan Whitehorn #if defined(AKBD_EMULATE_ATKBD) 8254fb52093SNathan Whitehorn sc->at_buffered_char[0] = 0; 8264fb52093SNathan Whitehorn sc->at_buffered_char[1] = 0; 8274fb52093SNathan Whitehorn #endif 8284fb52093SNathan Whitehorn mtx_unlock(&sc->sc_mutex); 829b4dbc599SNathan Whitehorn } 830b4dbc599SNathan Whitehorn 831b4dbc599SNathan Whitehorn static int akbd_get_state(keyboard_t *kbd, void *buf, size_t len) 832b4dbc599SNathan Whitehorn { 833b4dbc599SNathan Whitehorn return (0); 834b4dbc599SNathan Whitehorn } 835b4dbc599SNathan Whitehorn 836b4dbc599SNathan Whitehorn static int akbd_set_state(keyboard_t *kbd, void *buf, size_t len) 837b4dbc599SNathan Whitehorn { 838b4dbc599SNathan Whitehorn return (0); 839b4dbc599SNathan Whitehorn } 840b4dbc599SNathan Whitehorn 841b4dbc599SNathan Whitehorn static int akbd_poll(keyboard_t *kbd, int on) 842b4dbc599SNathan Whitehorn { 843b4dbc599SNathan Whitehorn return (0); 844b4dbc599SNathan Whitehorn } 845b4dbc599SNathan Whitehorn 846b4dbc599SNathan Whitehorn static int 847b4dbc599SNathan Whitehorn akbd_modevent(module_t mod, int type, void *data) 848b4dbc599SNathan Whitehorn { 849b4dbc599SNathan Whitehorn switch (type) { 850b4dbc599SNathan Whitehorn case MOD_LOAD: 851b4dbc599SNathan Whitehorn kbd_add_driver(&akbd_kbd_driver); 852b4dbc599SNathan Whitehorn break; 853b4dbc599SNathan Whitehorn 854b4dbc599SNathan Whitehorn case MOD_UNLOAD: 855b4dbc599SNathan Whitehorn kbd_delete_driver(&akbd_kbd_driver); 856b4dbc599SNathan Whitehorn break; 857b4dbc599SNathan Whitehorn 858b4dbc599SNathan Whitehorn default: 859b4dbc599SNathan Whitehorn return (EOPNOTSUPP); 860b4dbc599SNathan Whitehorn } 861b4dbc599SNathan Whitehorn 862b4dbc599SNathan Whitehorn return (0); 863b4dbc599SNathan Whitehorn } 864b4dbc599SNathan Whitehorn 865b6faf3cfSNathan Whitehorn static int 866b6faf3cfSNathan Whitehorn adb_fn_keys(SYSCTL_HANDLER_ARGS) 867b6faf3cfSNathan Whitehorn { 868b6faf3cfSNathan Whitehorn struct adb_kbd_softc *sc = arg1; 869b6faf3cfSNathan Whitehorn int error; 870b6faf3cfSNathan Whitehorn uint16_t is_fn_enabled; 871b6faf3cfSNathan Whitehorn unsigned int is_fn_enabled_sysctl; 872b6faf3cfSNathan Whitehorn 873b6faf3cfSNathan Whitehorn adb_read_register(sc->sc_dev, 1, &is_fn_enabled); 874b6faf3cfSNathan Whitehorn is_fn_enabled &= 1; 875b6faf3cfSNathan Whitehorn is_fn_enabled_sysctl = is_fn_enabled; 876b6faf3cfSNathan Whitehorn error = sysctl_handle_int(oidp, &is_fn_enabled_sysctl, 0, req); 877b6faf3cfSNathan Whitehorn 878b6faf3cfSNathan Whitehorn if (error || !req->newptr) 879b6faf3cfSNathan Whitehorn return (error); 880b6faf3cfSNathan Whitehorn 881b6faf3cfSNathan Whitehorn is_fn_enabled = is_fn_enabled_sysctl; 882b6faf3cfSNathan Whitehorn if (is_fn_enabled != 1 && is_fn_enabled != 0) 883b6faf3cfSNathan Whitehorn return (EINVAL); 884b6faf3cfSNathan Whitehorn 885b6faf3cfSNathan Whitehorn adb_write_register(sc->sc_dev, 1, 2, &is_fn_enabled); 886b6faf3cfSNathan Whitehorn return (0); 887b6faf3cfSNathan Whitehorn } 888b6faf3cfSNathan Whitehorn 889b4dbc599SNathan Whitehorn DEV_MODULE(akbd, akbd_modevent, NULL); 890b4dbc599SNathan Whitehorn 891