adb_kbd.c revision 261068
1193323Sed/*- 2193323Sed * Copyright (C) 2008 Nathan Whitehorn 3193323Sed * All rights reserved. 4193323Sed * 5193323Sed * Redistribution and use in source and binary forms, with or without 6193323Sed * modification, are permitted provided that the following conditions 7193323Sed * are met: 8193323Sed * 1. Redistributions of source code must retain the above copyright 9193323Sed * notice, this list of conditions and the following disclaimer. 10193323Sed * 2. Redistributions in binary form must reproduce the above copyright 11193323Sed * notice, this list of conditions and the following disclaimer in the 12193323Sed * documentation and/or other materials provided with the distribution. 13193323Sed * 14193323Sed * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15193323Sed * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16193323Sed * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17193323Sed * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18193323Sed * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19193323Sed * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20193323Sed * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21193323Sed * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22193323Sed * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23193323Sed * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24193323Sed * 25193323Sed * $FreeBSD: head/sys/dev/adb/adb_kbd.c 261068 2014-01-23 01:09:33Z jhibbits $ 26193323Sed */ 27193323Sed 28193323Sed#include <sys/cdefs.h> 29193323Sed#include <sys/param.h> 30193323Sed#include <sys/systm.h> 31193323Sed#include <sys/module.h> 32193323Sed#include <sys/bus.h> 33193323Sed#include <sys/conf.h> 34193323Sed#include <sys/kbio.h> 35193323Sed#include <sys/condvar.h> 36193323Sed#include <sys/callout.h> 37193323Sed#include <sys/kernel.h> 38193323Sed#include <sys/sysctl.h> 39193323Sed 40193323Sed#include <machine/bus.h> 41193323Sed 42193323Sed#include "opt_kbd.h" 43193323Sed#include <dev/kbd/kbdreg.h> 44198090Srdivacky#include <dev/kbd/kbdtables.h> 45193323Sed#include <dev/ofw/openfirm.h> 46193323Sed#include <dev/ofw/ofw_bus.h> 47193323Sed 48193323Sed#include <vm/vm.h> 49193323Sed#include <vm/pmap.h> 50193323Sed 51193323Sed#include "adb.h" 52193323Sed 53193323Sed#define KBD_DRIVER_NAME "akbd" 54193323Sed 55193323Sed#define AKBD_EMULATE_ATKBD 1 56193323Sed 57193323Sedstatic int adb_kbd_probe(device_t dev); 58193323Sedstatic int adb_kbd_attach(device_t dev); 59193323Sedstatic int adb_kbd_detach(device_t dev); 60193323Sedstatic void akbd_repeat(void *xsc); 61193323Sedstatic int adb_fn_keys(SYSCTL_HANDLER_ARGS); 62198090Srdivacky 63198090Srdivackystatic u_int adb_kbd_receive_packet(device_t dev, u_char status, 64193323Sed u_char command, u_char reg, int len, u_char *data); 65193323Sed 66193323Sedstruct adb_kbd_softc { 67193323Sed keyboard_t sc_kbd; 68193323Sed 69193323Sed device_t sc_dev; 70193323Sed struct mtx sc_mutex; 71193323Sed struct cv sc_cv; 72193323Sed 73193323Sed int sc_mode; 74193323Sed int sc_state; 75193323Sed 76193323Sed int have_led_control; 77193323Sed 78193323Sed uint8_t buffer[8]; 79193323Sed#ifdef AKBD_EMULATE_ATKBD 80193323Sed uint8_t at_buffered_char[2]; 81193323Sed#endif 82193323Sed volatile int buffers; 83195340Sed 84193323Sed struct callout sc_repeater; 85198090Srdivacky int sc_repeatstart; 86198090Srdivacky int sc_repeatcontinue; 87198090Srdivacky uint8_t last_press; 88193323Sed}; 89193323Sed 90193323Sedstatic device_method_t adb_kbd_methods[] = { 91193323Sed /* Device interface */ 92193323Sed DEVMETHOD(device_probe, adb_kbd_probe), 93193323Sed DEVMETHOD(device_attach, adb_kbd_attach), 94195340Sed DEVMETHOD(device_detach, adb_kbd_detach), 95193323Sed DEVMETHOD(device_shutdown, bus_generic_shutdown), 96193323Sed DEVMETHOD(device_suspend, bus_generic_suspend), 97193323Sed DEVMETHOD(device_resume, bus_generic_resume), 98193323Sed 99193323Sed /* ADB interface */ 100193323Sed DEVMETHOD(adb_receive_packet, adb_kbd_receive_packet), 101193323Sed 102193323Sed { 0, 0 } 103193323Sed}; 104193323Sed 105193323Sedstatic driver_t adb_kbd_driver = { 106193323Sed "akbd", 107193323Sed adb_kbd_methods, 108193323Sed sizeof(struct adb_kbd_softc), 109193323Sed}; 110193323Sed 111193323Sedstatic devclass_t adb_kbd_devclass; 112193323Sed 113193323SedDRIVER_MODULE(akbd, adb, adb_kbd_driver, adb_kbd_devclass, 0, 0); 114193323Sed 115193323Sed#ifdef AKBD_EMULATE_ATKBD 116193323Sed 117193323Sed#define SCAN_PRESS 0x000 118193323Sed#define SCAN_RELEASE 0x080 119193323Sed#define SCAN_PREFIX_E0 0x100 120193323Sed#define SCAN_PREFIX_E1 0x200 121193323Sed#define SCAN_PREFIX_CTL 0x400 122193323Sed#define SCAN_PREFIX_SHIFT 0x800 123193323Sed#define SCAN_PREFIX (SCAN_PREFIX_E0 | SCAN_PREFIX_E1 | \ 124193323Sed SCAN_PREFIX_CTL | SCAN_PREFIX_SHIFT) 125193323Sed 126193323Sedstatic const uint8_t adb_to_at_scancode_map[128] = { 30, 31, 32, 33, 35, 34, 127193323Sed 44, 45, 46, 47, 0, 48, 16, 17, 18, 19, 21, 20, 2, 3, 4, 5, 7, 6, 13, 128193323Sed 10, 8, 12, 9, 11, 27, 24, 22, 26, 23, 25, 28, 38, 36, 40, 37, 39, 43, 129193323Sed 51, 53, 49, 50, 52, 15, 57, 41, 14, 0, 1, 29, 0, 42, 58, 56, 97, 98, 130193323Sed 100, 95, 0, 0, 83, 0, 55, 0, 78, 0, 69, 0, 0, 0, 91, 89, 0, 74, 13, 0, 131193323Sed 0, 82, 79, 80, 81, 75, 76, 77, 71, 0, 72, 73, 0, 0, 0, 63, 64, 65, 61, 132193323Sed 66, 67, 0, 87, 0, 105, 0, 70, 0, 68, 0, 88, 0, 107, 102, 94, 96, 103, 133193323Sed 62, 99, 60, 101, 59, 54, 93, 90, 0, 0 }; 134193323Sed 135193323Sedstatic int 136193323Sedkeycode2scancode(int keycode, int shift, int up) 137193323Sed{ 138193323Sed static const int scan[] = { 139193323Sed /* KP enter, right ctrl, KP divide */ 140193323Sed 0x1c , 0x1d , 0x35 , 141193323Sed /* print screen */ 142193323Sed 0x37 | SCAN_PREFIX_SHIFT, 143193323Sed /* right alt, home, up, page up, left, right, end */ 144193323Sed 0x38, 0x47, 0x48, 0x49, 0x4b, 0x4d, 0x4f, 145193323Sed /* down, page down, insert, delete */ 146193323Sed 0x50, 0x51, 0x52, 0x53, 147193323Sed /* pause/break (see also below) */ 148193323Sed 0x46, 149193323Sed /* 150193323Sed * MS: left window, right window, menu 151193323Sed * also Sun: left meta, right meta, compose 152193323Sed */ 153193323Sed 0x5b, 0x5c, 0x5d, 154193323Sed /* Sun type 6 USB */ 155193323Sed /* help, stop, again, props, undo, front, copy */ 156193323Sed 0x68, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 157198090Srdivacky /* open, paste, find, cut, audiomute, audiolower, audioraise */ 158198090Srdivacky 0x64, 0x65, 0x66, 0x67, 0x25, 0x1f, 0x1e, 159198090Srdivacky /* power */ 160198090Srdivacky 0x20 161198090Srdivacky }; 162198090Srdivacky int scancode; 163198090Srdivacky 164198090Srdivacky scancode = keycode; 165198090Srdivacky if ((keycode >= 89) && (keycode < 89 + sizeof(scan) / sizeof(scan[0]))) 166198090Srdivacky scancode = scan[keycode - 89] | SCAN_PREFIX_E0; 167198090Srdivacky /* pause/break */ 168198090Srdivacky if ((keycode == 104) && !(shift & CTLS)) 169198090Srdivacky scancode = 0x45 | SCAN_PREFIX_E1 | SCAN_PREFIX_CTL; 170198090Srdivacky if (shift & SHIFTS) 171198090Srdivacky scancode &= ~SCAN_PREFIX_SHIFT; 172198090Srdivacky return (scancode | (up ? SCAN_RELEASE : SCAN_PRESS)); 173193323Sed} 174193323Sed#endif 175193323Sed 176193323Sed/* keyboard driver declaration */ 177193323Sedstatic int akbd_configure(int flags); 178193323Sedstatic kbd_probe_t akbd_probe; 179193323Sedstatic kbd_init_t akbd_init; 180193323Sedstatic kbd_term_t akbd_term; 181193323Sedstatic kbd_intr_t akbd_interrupt; 182193323Sedstatic kbd_test_if_t akbd_test_if; 183193323Sedstatic kbd_enable_t akbd_enable; 184193323Sedstatic kbd_disable_t akbd_disable; 185193323Sedstatic kbd_read_t akbd_read; 186193323Sedstatic kbd_check_t akbd_check; 187193323Sedstatic kbd_read_char_t akbd_read_char; 188193323Sedstatic kbd_check_char_t akbd_check_char; 189193323Sedstatic kbd_ioctl_t akbd_ioctl; 190193323Sedstatic kbd_lock_t akbd_lock; 191193323Sedstatic kbd_clear_state_t akbd_clear_state; 192193323Sedstatic kbd_get_state_t akbd_get_state; 193193323Sedstatic kbd_set_state_t akbd_set_state; 194193323Sedstatic kbd_poll_mode_t akbd_poll; 195193323Sed 196193323Sedkeyboard_switch_t akbdsw = { 197193323Sed akbd_probe, 198193323Sed akbd_init, 199193323Sed akbd_term, 200193323Sed akbd_interrupt, 201193323Sed akbd_test_if, 202193323Sed akbd_enable, 203193323Sed akbd_disable, 204193323Sed akbd_read, 205193323Sed akbd_check, 206193323Sed akbd_read_char, 207193323Sed akbd_check_char, 208193323Sed akbd_ioctl, 209193323Sed akbd_lock, 210193323Sed akbd_clear_state, 211193323Sed akbd_get_state, 212193323Sed akbd_set_state, 213193323Sed genkbd_get_fkeystr, 214193323Sed akbd_poll, 215193323Sed genkbd_diag, 216193323Sed}; 217193323Sed 218193323SedKEYBOARD_DRIVER(akbd, akbdsw, akbd_configure); 219193323Sed 220193323Sedstatic int 221193323Sedadb_kbd_probe(device_t dev) 222193323Sed{ 223193323Sed uint8_t type; 224193323Sed 225193323Sed type = adb_get_device_type(dev); 226193323Sed 227193323Sed if (type != ADB_DEVICE_KEYBOARD) 228193323Sed return (ENXIO); 229193323Sed 230193323Sed switch(adb_get_device_handler(dev)) { 231193323Sed case 1: 232193323Sed device_set_desc(dev,"Apple Standard Keyboard"); 233193323Sed break; 234193323Sed case 2: 235193323Sed device_set_desc(dev,"Apple Extended Keyboard"); 236193323Sed break; 237198090Srdivacky case 4: 238193323Sed device_set_desc(dev,"Apple ISO Keyboard"); 239193323Sed break; 240193323Sed case 5: 241193323Sed device_set_desc(dev,"Apple Extended ISO Keyboard"); 242193323Sed break; 243193323Sed case 8: 244193323Sed device_set_desc(dev,"Apple Keyboard II"); 245193323Sed break; 246193323Sed case 9: 247193323Sed device_set_desc(dev,"Apple ISO Keyboard II"); 248193323Sed break; 249193323Sed case 12: 250193323Sed device_set_desc(dev,"PowerBook Keyboard"); 251193323Sed break; 252193323Sed case 13: 253193323Sed device_set_desc(dev,"PowerBook ISO Keyboard"); 254193323Sed break; 255193323Sed case 24: 256193323Sed device_set_desc(dev,"PowerBook Extended Keyboard"); 257193323Sed break; 258193323Sed case 27: 259193323Sed device_set_desc(dev,"Apple Design Keyboard"); 260193323Sed break; 261193323Sed case 195: 262193323Sed device_set_desc(dev,"PowerBook G3 Keyboard"); 263193323Sed break; 264193323Sed case 196: 265193323Sed device_set_desc(dev,"iBook Keyboard"); 266193323Sed break; 267193323Sed default: 268193323Sed device_set_desc(dev,"ADB Keyboard"); 269193323Sed break; 270193323Sed } 271193323Sed 272193323Sed return (0); 273193323Sed} 274193323Sed 275193323Sedstatic int 276193323Sedms_to_ticks(int ms) 277193323Sed{ 278193323Sed if (hz > 1000) 279193323Sed return ms*(hz/1000); 280193323Sed 281193323Sed return ms/(1000/hz); 282193323Sed} 283193323Sed 284193323Sedstatic int 285193323Sedadb_kbd_attach(device_t dev) 286193323Sed{ 287193323Sed struct adb_kbd_softc *sc; 288193323Sed keyboard_switch_t *sw; 289193323Sed uint32_t fkeys; 290193323Sed phandle_t handle; 291198090Srdivacky 292198090Srdivacky sw = kbd_get_switch(KBD_DRIVER_NAME); 293193323Sed if (sw == NULL) { 294193323Sed return ENXIO; 295193323Sed } 296193323Sed 297193323Sed sc = device_get_softc(dev); 298193323Sed sc->sc_dev = dev; 299193323Sed sc->sc_mode = K_RAW; 300193323Sed sc->sc_state = 0; 301193323Sed sc->have_led_control = 0; 302193323Sed sc->buffers = 0; 303198090Srdivacky 304193323Sed /* Try stepping forward to the extended keyboard protocol */ 305193323Sed adb_set_device_handler(dev,3); 306193323Sed 307193323Sed mtx_init(&sc->sc_mutex, KBD_DRIVER_NAME, NULL, MTX_DEF); 308193323Sed cv_init(&sc->sc_cv,KBD_DRIVER_NAME); 309193323Sed callout_init(&sc->sc_repeater, 0); 310193323Sed 311193323Sed#ifdef AKBD_EMULATE_ATKBD 312193323Sed kbd_init_struct(&sc->sc_kbd, KBD_DRIVER_NAME, KB_101, 0, 0, 0, 0); 313193323Sed kbd_set_maps(&sc->sc_kbd, &key_map, &accent_map, fkey_tab, 314193323Sed sizeof(fkey_tab) / sizeof(fkey_tab[0])); 315193323Sed#else 316193323Sed #error ADB raw mode not implemented 317193323Sed#endif 318193323Sed 319193323Sed KBD_FOUND_DEVICE(&sc->sc_kbd); 320193323Sed KBD_PROBE_DONE(&sc->sc_kbd); 321193323Sed KBD_INIT_DONE(&sc->sc_kbd); 322193323Sed KBD_CONFIG_DONE(&sc->sc_kbd); 323193323Sed 324193323Sed (*sw->enable)(&sc->sc_kbd); 325193323Sed 326193323Sed kbd_register(&sc->sc_kbd); 327193323Sed 328193323Sed#ifdef KBD_INSTALL_CDEV 329193323Sed if (kbd_attach(&sc->sc_kbd)) { 330193323Sed adb_kbd_detach(dev); 331193323Sed return ENXIO; 332193323Sed } 333198090Srdivacky#endif 334198090Srdivacky 335198090Srdivacky /* Check if we can read out the LED state from 336198090Srdivacky this keyboard by reading the key state register */ 337198090Srdivacky if (adb_read_register(dev, 2, NULL) == 2) 338198090Srdivacky sc->have_led_control = 1; 339193323Sed 340193323Sed adb_set_autopoll(dev,1); 341195340Sed 342198090Srdivacky handle = OF_finddevice("mac-io/via-pmu/adb/keyboard"); 343195340Sed if (handle != -1 && OF_getprop(handle, "AAPL,has-embedded-fn-keys", 344195340Sed &fkeys, sizeof(fkeys)) != -1) { 345193323Sed static const char *key_names[] = {"F1", "F2", "F3", "F4", "F5", 346195340Sed "F6", "F7", "F8", "F9", "F10", "F11", "F12"}; 347195340Sed struct sysctl_ctx_list *ctx; 348195340Sed struct sysctl_oid *tree; 349193323Sed int i; 350193323Sed 351193323Sed if (bootverbose) 352193323Sed device_printf(dev, "Keyboard has embedded Fn keys\n"); 353193323Sed 354193323Sed for (i = 0; i < 12; i++) { 355193323Sed uint32_t keyval; 356193323Sed char buf[3]; 357193323Sed if (OF_getprop(handle, key_names[i], &keyval, 358195340Sed sizeof(keyval)) < 0) 359193323Sed continue; 360193323Sed buf[0] = 1; 361193323Sed buf[1] = i+1; 362193323Sed buf[2] = keyval; 363193323Sed adb_write_register(dev, 0, 3, buf); 364193323Sed } 365193323Sed adb_write_register(dev, 1, 2, &(uint16_t){0}); 366193323Sed 367193323Sed ctx = device_get_sysctl_ctx(dev); 368193323Sed tree = device_get_sysctl_tree(dev); 369193323Sed 370193323Sed SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 371193323Sed "fn_keys_function_as_primary", CTLTYPE_INT | CTLFLAG_RW, sc, 372193323Sed 0, adb_fn_keys, "I", 373193323Sed "Set the Fn keys to be their F-key type as default"); 374193323Sed } 375193323Sed 376193323Sed return (0); 377193323Sed} 378193323Sed 379193323Sedstatic int 380193323Sedadb_kbd_detach(device_t dev) 381193574Sed{ 382193323Sed struct adb_kbd_softc *sc; 383193323Sed keyboard_t *kbd; 384193323Sed 385193323Sed sc = device_get_softc(dev); 386193323Sed 387193323Sed adb_set_autopoll(dev,0); 388193323Sed callout_stop(&sc->sc_repeater); 389193323Sed 390193323Sed mtx_lock(&sc->sc_mutex); 391193323Sed 392198090Srdivacky kbd = kbd_get_keyboard(kbd_find_keyboard(KBD_DRIVER_NAME, 393198090Srdivacky device_get_unit(dev))); 394198090Srdivacky 395198090Srdivacky kbdd_disable(kbd); 396198090Srdivacky 397198090Srdivacky#ifdef KBD_INSTALL_CDEV 398198090Srdivacky kbd_detach(kbd); 399198090Srdivacky#endif 400198090Srdivacky 401198090Srdivacky kbdd_term(kbd); 402198090Srdivacky 403198090Srdivacky mtx_unlock(&sc->sc_mutex); 404198090Srdivacky 405198090Srdivacky mtx_destroy(&sc->sc_mutex); 406198090Srdivacky cv_destroy(&sc->sc_cv); 407198090Srdivacky 408198090Srdivacky return (0); 409198090Srdivacky} 410198090Srdivacky 411198090Srdivackystatic u_int 412198090Srdivackyadb_kbd_receive_packet(device_t dev, u_char status, 413198090Srdivacky u_char command, u_char reg, int len, u_char *data) 414198090Srdivacky{ 415198090Srdivacky struct adb_kbd_softc *sc; 416198090Srdivacky 417198090Srdivacky sc = device_get_softc(dev); 418198090Srdivacky 419198090Srdivacky if (command != ADB_COMMAND_TALK) 420198090Srdivacky return 0; 421198090Srdivacky 422198090Srdivacky if (reg != 0 || len != 2) 423198090Srdivacky return (0); 424198090Srdivacky 425198090Srdivacky mtx_lock(&sc->sc_mutex); 426198090Srdivacky /* 0x7f is always the power button */ 427198090Srdivacky if (data[0] == 0x7f && devctl_process_running()) { 428198090Srdivacky devctl_notify("PMU", "Button", "pressed", NULL); 429198090Srdivacky mtx_unlock(&sc->sc_mutex); 430198090Srdivacky return (0); 431198090Srdivacky } else if (data[0] == 0xff) { 432198090Srdivacky mtx_unlock(&sc->sc_mutex); 433198090Srdivacky return (0); /* Ignore power button release. */ 434198090Srdivacky } 435198090Srdivacky if ((data[0] & 0x7f) == 57 && sc->buffers < 7) { 436198090Srdivacky /* Fake the down/up cycle for caps lock */ 437198090Srdivacky sc->buffer[sc->buffers++] = data[0] & 0x7f; 438198090Srdivacky sc->buffer[sc->buffers++] = (data[0] & 0x7f) | (1 << 7); 439198090Srdivacky } else { 440198090Srdivacky sc->buffer[sc->buffers++] = data[0]; 441198090Srdivacky } 442198090Srdivacky if (sc->buffer[sc->buffers-1] < 0xff) 443198090Srdivacky sc->last_press = sc->buffer[sc->buffers-1]; 444198090Srdivacky 445198090Srdivacky if ((data[1] & 0x7f) == 57 && sc->buffers < 7) { 446198090Srdivacky /* Fake the down/up cycle for caps lock */ 447198090Srdivacky sc->buffer[sc->buffers++] = data[1] & 0x7f; 448198090Srdivacky sc->buffer[sc->buffers++] = (data[1] & 0x7f) | (1 << 7); 449198090Srdivacky } else { 450198090Srdivacky sc->buffer[sc->buffers++] = data[1]; 451198090Srdivacky } 452198090Srdivacky 453198090Srdivacky if (sc->buffer[sc->buffers-1] < 0xff) 454198090Srdivacky sc->last_press = sc->buffer[sc->buffers-1]; 455198090Srdivacky 456198090Srdivacky /* Stop any existing key repeating */ 457193323Sed callout_stop(&sc->sc_repeater); 458193323Sed 459193323Sed /* Schedule a repeat callback on keydown */ 460193323Sed if (!(sc->last_press & (1 << 7))) { 461 callout_reset(&sc->sc_repeater, 462 ms_to_ticks(sc->sc_kbd.kb_delay1), akbd_repeat, sc); 463 } 464 mtx_unlock(&sc->sc_mutex); 465 466 cv_broadcast(&sc->sc_cv); 467 468 if (KBD_IS_ACTIVE(&sc->sc_kbd) && KBD_IS_BUSY(&sc->sc_kbd)) { 469 sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd, 470 KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg); 471 } 472 473 return (0); 474} 475 476static void 477akbd_repeat(void *xsc) { 478 struct adb_kbd_softc *sc = xsc; 479 int notify_kbd = 0; 480 481 /* Fake an up/down key repeat so long as we have the 482 free buffers */ 483 mtx_lock(&sc->sc_mutex); 484 if (sc->buffers < 7) { 485 sc->buffer[sc->buffers++] = sc->last_press | (1 << 7); 486 sc->buffer[sc->buffers++] = sc->last_press; 487 488 notify_kbd = 1; 489 } 490 mtx_unlock(&sc->sc_mutex); 491 492 if (notify_kbd && KBD_IS_ACTIVE(&sc->sc_kbd) 493 && KBD_IS_BUSY(&sc->sc_kbd)) { 494 sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd, 495 KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg); 496 } 497 498 /* Reschedule the callout */ 499 callout_reset(&sc->sc_repeater, ms_to_ticks(sc->sc_kbd.kb_delay2), 500 akbd_repeat, sc); 501} 502 503static int 504akbd_configure(int flags) 505{ 506 return 0; 507} 508 509static int 510akbd_probe(int unit, void *arg, int flags) 511{ 512 return 0; 513} 514 515static int 516akbd_init(int unit, keyboard_t **kbdp, void *arg, int flags) 517{ 518 return 0; 519} 520 521static int 522akbd_term(keyboard_t *kbd) 523{ 524 return 0; 525} 526 527static int 528akbd_interrupt(keyboard_t *kbd, void *arg) 529{ 530 return 0; 531} 532 533static int 534akbd_test_if(keyboard_t *kbd) 535{ 536 return 0; 537} 538 539static int 540akbd_enable(keyboard_t *kbd) 541{ 542 KBD_ACTIVATE(kbd); 543 return (0); 544} 545 546static int 547akbd_disable(keyboard_t *kbd) 548{ 549 struct adb_kbd_softc *sc; 550 sc = (struct adb_kbd_softc *)(kbd); 551 552 callout_stop(&sc->sc_repeater); 553 KBD_DEACTIVATE(kbd); 554 return (0); 555} 556 557static int 558akbd_read(keyboard_t *kbd, int wait) 559{ 560 return (0); 561} 562 563static int 564akbd_check(keyboard_t *kbd) 565{ 566 struct adb_kbd_softc *sc; 567 568 if (!KBD_IS_ACTIVE(kbd)) 569 return (FALSE); 570 571 sc = (struct adb_kbd_softc *)(kbd); 572 573 mtx_lock(&sc->sc_mutex); 574#ifdef AKBD_EMULATE_ATKBD 575 if (sc->at_buffered_char[0]) { 576 mtx_unlock(&sc->sc_mutex); 577 return (TRUE); 578 } 579#endif 580 581 if (sc->buffers > 0) { 582 mtx_unlock(&sc->sc_mutex); 583 return (TRUE); 584 } 585 mtx_unlock(&sc->sc_mutex); 586 587 return (FALSE); 588} 589 590static u_int 591akbd_read_char(keyboard_t *kbd, int wait) 592{ 593 struct adb_kbd_softc *sc; 594 uint16_t key; 595 uint8_t adb_code; 596 int i; 597 598 sc = (struct adb_kbd_softc *)(kbd); 599 600 mtx_lock(&sc->sc_mutex); 601 602#if defined(AKBD_EMULATE_ATKBD) 603 if (sc->sc_mode == K_RAW && sc->at_buffered_char[0]) { 604 key = sc->at_buffered_char[0]; 605 if (key & SCAN_PREFIX) { 606 sc->at_buffered_char[0] = key & ~SCAN_PREFIX; 607 key = (key & SCAN_PREFIX_E0) ? 0xe0 : 0xe1; 608 } else { 609 sc->at_buffered_char[0] = sc->at_buffered_char[1]; 610 sc->at_buffered_char[1] = 0; 611 } 612 613 mtx_unlock(&sc->sc_mutex); 614 615 return (key); 616 } 617#endif 618 619 if (!sc->buffers && wait) 620 cv_wait(&sc->sc_cv,&sc->sc_mutex); 621 622 if (!sc->buffers) { 623 mtx_unlock(&sc->sc_mutex); 624 return (NOKEY); 625 } 626 627 adb_code = sc->buffer[0]; 628 629 for (i = 1; i < sc->buffers; i++) 630 sc->buffer[i-1] = sc->buffer[i]; 631 632 sc->buffers--; 633 634 #ifdef AKBD_EMULATE_ATKBD 635 key = adb_to_at_scancode_map[adb_code & 0x7f]; 636 if (sc->sc_mode == K_CODE) { 637 /* Add the key-release bit */ 638 key |= adb_code & 0x80; 639 } else if (sc->sc_mode == K_RAW) { 640 /* 641 * In the raw case, we have to emulate the gross 642 * variable-length AT keyboard thing. Since this code 643 * is copied from sunkbd, which is the same code 644 * as ukbd, it might be nice to have this centralized. 645 */ 646 647 key = keycode2scancode(key, 648 0, adb_code & 0x80); 649 650 if (key & SCAN_PREFIX) { 651 if (key & SCAN_PREFIX_CTL) { 652 sc->at_buffered_char[0] = 653 0x1d | (key & SCAN_RELEASE); 654 sc->at_buffered_char[1] = 655 key & ~SCAN_PREFIX; 656 } else if (key & SCAN_PREFIX_SHIFT) { 657 sc->at_buffered_char[0] = 658 0x2a | (key & SCAN_RELEASE); 659 sc->at_buffered_char[1] = 660 key & ~SCAN_PREFIX_SHIFT; 661 } else { 662 sc->at_buffered_char[0] = 663 key & ~SCAN_PREFIX; 664 sc->at_buffered_char[1] = 0; 665 } 666 667 key = (key & SCAN_PREFIX_E0) ? 0xe0 : 0xe1; 668 } 669 } 670 #else 671 key = adb_code; 672 #endif 673 674 mtx_unlock(&sc->sc_mutex); 675 676 return (key); 677} 678 679static int 680akbd_check_char(keyboard_t *kbd) 681{ 682 if (!KBD_IS_ACTIVE(kbd)) 683 return (FALSE); 684 685 return (akbd_check(kbd)); 686} 687 688static int 689set_typematic(keyboard_t *kbd, int code) 690{ 691 /* These numbers are in microseconds, so convert to ticks */ 692 693 static int delays[] = { 250, 500, 750, 1000 }; 694 static int rates[] = { 34, 38, 42, 46, 50, 55, 59, 63, 695 68, 76, 84, 92, 100, 110, 118, 126, 696 136, 152, 168, 184, 200, 220, 236, 252, 697 272, 304, 336, 368, 400, 440, 472, 504 }; 698 699 if (code & ~0x7f) 700 return EINVAL; 701 kbd->kb_delay1 = delays[(code >> 5) & 3]; 702 kbd->kb_delay2 = rates[code & 0x1f]; 703 return 0; 704} 705 706static int akbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t data) 707{ 708 struct adb_kbd_softc *sc; 709 uint16_t r2; 710 int error; 711 712 sc = (struct adb_kbd_softc *)(kbd); 713 error = 0; 714 715 switch (cmd) { 716 case KDGKBMODE: 717 *(int *)data = sc->sc_mode; 718 break; 719 case KDSKBMODE: 720 switch (*(int *)data) { 721 case K_XLATE: 722 if (sc->sc_mode != K_XLATE) { 723 /* make lock key state and LED state match */ 724 sc->sc_state &= ~LOCK_MASK; 725 sc->sc_state |= KBD_LED_VAL(kbd); 726 } 727 /* FALLTHROUGH */ 728 case K_RAW: 729 case K_CODE: 730 if (sc->sc_mode != *(int *)data) 731 sc->sc_mode = *(int *)data; 732 break; 733 default: 734 error = EINVAL; 735 break; 736 } 737 738 break; 739 740 case KDGETLED: 741 *(int *)data = KBD_LED_VAL(kbd); 742 break; 743 744 case KDSKBSTATE: 745 if (*(int *)data & ~LOCK_MASK) { 746 error = EINVAL; 747 break; 748 } 749 sc->sc_state &= ~LOCK_MASK; 750 sc->sc_state |= *(int *)data; 751 752 /* FALLTHROUGH */ 753 754 case KDSETLED: 755 KBD_LED_VAL(kbd) = *(int *)data; 756 757 if (!sc->have_led_control) 758 break; 759 760 r2 = (~0 & 0x04) | 3; 761 762 if (*(int *)data & NLKED) 763 r2 &= ~1; 764 if (*(int *)data & CLKED) 765 r2 &= ~2; 766 if (*(int *)data & SLKED) 767 r2 &= ~4; 768 769 adb_send_packet(sc->sc_dev,ADB_COMMAND_LISTEN,2, 770 sizeof(uint16_t),(u_char *)&r2); 771 772 break; 773 774 case KDGKBSTATE: 775 *(int *)data = sc->sc_state & LOCK_MASK; 776 break; 777 778 case KDSETREPEAT: 779 if (!KBD_HAS_DEVICE(kbd)) 780 return 0; 781 if (((int *)data)[1] < 0) 782 return EINVAL; 783 if (((int *)data)[0] < 0) 784 return EINVAL; 785 else if (((int *)data)[0] == 0) /* fastest possible value */ 786 kbd->kb_delay1 = 200; 787 else 788 kbd->kb_delay1 = ((int *)data)[0]; 789 kbd->kb_delay2 = ((int *)data)[1]; 790 791 break; 792 793 case KDSETRAD: 794 error = set_typematic(kbd, *(int *)data); 795 break; 796 797 case PIO_KEYMAP: 798 case OPIO_KEYMAP: 799 case PIO_KEYMAPENT: 800 case PIO_DEADKEYMAP: 801 default: 802 return (genkbd_commonioctl(kbd, cmd, data)); 803 } 804 805 return (error); 806} 807 808static int akbd_lock(keyboard_t *kbd, int lock) 809{ 810 return (0); 811} 812 813static void akbd_clear_state(keyboard_t *kbd) 814{ 815 struct adb_kbd_softc *sc; 816 817 sc = (struct adb_kbd_softc *)(kbd); 818 819 mtx_lock(&sc->sc_mutex); 820 821 sc->buffers = 0; 822 callout_stop(&sc->sc_repeater); 823 824#if defined(AKBD_EMULATE_ATKBD) 825 sc->at_buffered_char[0] = 0; 826 sc->at_buffered_char[1] = 0; 827#endif 828 mtx_unlock(&sc->sc_mutex); 829} 830 831static int akbd_get_state(keyboard_t *kbd, void *buf, size_t len) 832{ 833 return (0); 834} 835 836static int akbd_set_state(keyboard_t *kbd, void *buf, size_t len) 837{ 838 return (0); 839} 840 841static int akbd_poll(keyboard_t *kbd, int on) 842{ 843 return (0); 844} 845 846static int 847akbd_modevent(module_t mod, int type, void *data) 848{ 849 switch (type) { 850 case MOD_LOAD: 851 kbd_add_driver(&akbd_kbd_driver); 852 break; 853 854 case MOD_UNLOAD: 855 kbd_delete_driver(&akbd_kbd_driver); 856 break; 857 858 default: 859 return (EOPNOTSUPP); 860 } 861 862 return (0); 863} 864 865static int 866adb_fn_keys(SYSCTL_HANDLER_ARGS) 867{ 868 struct adb_kbd_softc *sc = arg1; 869 int error; 870 uint16_t is_fn_enabled; 871 unsigned int is_fn_enabled_sysctl; 872 873 adb_read_register(sc->sc_dev, 1, &is_fn_enabled); 874 is_fn_enabled &= 1; 875 is_fn_enabled_sysctl = is_fn_enabled; 876 error = sysctl_handle_int(oidp, &is_fn_enabled_sysctl, 0, req); 877 878 if (error || !req->newptr) 879 return (error); 880 881 is_fn_enabled = is_fn_enabled_sysctl; 882 if (is_fn_enabled != 1 && is_fn_enabled != 0) 883 return (EINVAL); 884 885 adb_write_register(sc->sc_dev, 1, 2, &is_fn_enabled); 886 return (0); 887} 888 889DEV_MODULE(akbd, akbd_modevent, NULL); 890 891