adb_kbd.c revision 226449
1184299Snwhitehorn/*- 2184299Snwhitehorn * Copyright (C) 2008 Nathan Whitehorn 3184299Snwhitehorn * All rights reserved. 4184299Snwhitehorn * 5184299Snwhitehorn * Redistribution and use in source and binary forms, with or without 6184299Snwhitehorn * modification, are permitted provided that the following conditions 7184299Snwhitehorn * are met: 8184299Snwhitehorn * 1. Redistributions of source code must retain the above copyright 9184299Snwhitehorn * notice, this list of conditions and the following disclaimer. 10184299Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright 11184299Snwhitehorn * notice, this list of conditions and the following disclaimer in the 12184299Snwhitehorn * documentation and/or other materials provided with the distribution. 13184299Snwhitehorn * 14184299Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15184299Snwhitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16184299Snwhitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17184299Snwhitehorn * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18184299Snwhitehorn * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19184299Snwhitehorn * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20184299Snwhitehorn * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21184299Snwhitehorn * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22184299Snwhitehorn * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23184299Snwhitehorn * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24184299Snwhitehorn * 25184299Snwhitehorn * $FreeBSD: head/sys/dev/adb/adb_kbd.c 226449 2011-10-16 21:01:42Z nwhitehorn $ 26184299Snwhitehorn */ 27184299Snwhitehorn 28184299Snwhitehorn#include <sys/cdefs.h> 29184299Snwhitehorn#include <sys/param.h> 30184299Snwhitehorn#include <sys/systm.h> 31184299Snwhitehorn#include <sys/module.h> 32184299Snwhitehorn#include <sys/bus.h> 33184299Snwhitehorn#include <sys/conf.h> 34184299Snwhitehorn#include <sys/kbio.h> 35184299Snwhitehorn#include <sys/condvar.h> 36184299Snwhitehorn#include <sys/callout.h> 37184299Snwhitehorn#include <sys/kernel.h> 38226449Snwhitehorn#include <sys/sysctl.h> 39184299Snwhitehorn 40184299Snwhitehorn#include <machine/bus.h> 41184299Snwhitehorn 42184299Snwhitehorn#include "opt_kbd.h" 43184299Snwhitehorn#include <dev/kbd/kbdreg.h> 44184299Snwhitehorn#include <dev/kbd/kbdtables.h> 45226449Snwhitehorn#include <dev/ofw/openfirm.h> 46226449Snwhitehorn#include <dev/ofw/ofw_bus.h> 47184299Snwhitehorn 48184299Snwhitehorn#include <vm/vm.h> 49184299Snwhitehorn#include <vm/pmap.h> 50184299Snwhitehorn 51184299Snwhitehorn#include "adb.h" 52184299Snwhitehorn 53184299Snwhitehorn#define KBD_DRIVER_NAME "akbd" 54184299Snwhitehorn 55184299Snwhitehorn#define AKBD_EMULATE_ATKBD 1 56184299Snwhitehorn 57184299Snwhitehornstatic int adb_kbd_probe(device_t dev); 58184299Snwhitehornstatic int adb_kbd_attach(device_t dev); 59184299Snwhitehornstatic int adb_kbd_detach(device_t dev); 60184299Snwhitehornstatic void akbd_repeat(void *xsc); 61226449Snwhitehornstatic int adb_fn_keys(SYSCTL_HANDLER_ARGS); 62184299Snwhitehorn 63184299Snwhitehornstatic u_int adb_kbd_receive_packet(device_t dev, u_char status, 64184299Snwhitehorn u_char command, u_char reg, int len, u_char *data); 65184299Snwhitehorn 66184299Snwhitehornstruct adb_kbd_softc { 67184299Snwhitehorn keyboard_t sc_kbd; 68184299Snwhitehorn 69184299Snwhitehorn device_t sc_dev; 70184299Snwhitehorn struct mtx sc_mutex; 71184299Snwhitehorn struct cv sc_cv; 72184299Snwhitehorn 73184299Snwhitehorn int sc_mode; 74184299Snwhitehorn int sc_state; 75184299Snwhitehorn 76184299Snwhitehorn int have_led_control; 77184299Snwhitehorn 78184299Snwhitehorn uint8_t buffer[8]; 79186906Snwhitehorn#ifdef AKBD_EMULATE_ATKBD 80186906Snwhitehorn uint8_t at_buffered_char[2]; 81186906Snwhitehorn#endif 82184299Snwhitehorn volatile int buffers; 83184299Snwhitehorn 84184299Snwhitehorn struct callout sc_repeater; 85184299Snwhitehorn int sc_repeatstart; 86184299Snwhitehorn int sc_repeatcontinue; 87184299Snwhitehorn uint8_t last_press; 88184299Snwhitehorn}; 89184299Snwhitehorn 90184299Snwhitehornstatic device_method_t adb_kbd_methods[] = { 91184299Snwhitehorn /* Device interface */ 92184299Snwhitehorn DEVMETHOD(device_probe, adb_kbd_probe), 93184299Snwhitehorn DEVMETHOD(device_attach, adb_kbd_attach), 94184299Snwhitehorn DEVMETHOD(device_detach, adb_kbd_detach), 95184299Snwhitehorn DEVMETHOD(device_shutdown, bus_generic_shutdown), 96184299Snwhitehorn DEVMETHOD(device_suspend, bus_generic_suspend), 97184299Snwhitehorn DEVMETHOD(device_resume, bus_generic_resume), 98184299Snwhitehorn 99184299Snwhitehorn /* ADB interface */ 100184299Snwhitehorn DEVMETHOD(adb_receive_packet, adb_kbd_receive_packet), 101184299Snwhitehorn 102184299Snwhitehorn { 0, 0 } 103184299Snwhitehorn}; 104184299Snwhitehorn 105184299Snwhitehornstatic driver_t adb_kbd_driver = { 106184299Snwhitehorn "akbd", 107184299Snwhitehorn adb_kbd_methods, 108184299Snwhitehorn sizeof(struct adb_kbd_softc), 109184299Snwhitehorn}; 110184299Snwhitehorn 111184299Snwhitehornstatic devclass_t adb_kbd_devclass; 112184299Snwhitehorn 113184299SnwhitehornDRIVER_MODULE(akbd, adb, adb_kbd_driver, adb_kbd_devclass, 0, 0); 114184299Snwhitehorn 115186906Snwhitehorn#ifdef AKBD_EMULATE_ATKBD 116186906Snwhitehorn 117186906Snwhitehorn#define SCAN_PRESS 0x000 118186906Snwhitehorn#define SCAN_RELEASE 0x080 119186906Snwhitehorn#define SCAN_PREFIX_E0 0x100 120186906Snwhitehorn#define SCAN_PREFIX_E1 0x200 121186906Snwhitehorn#define SCAN_PREFIX_CTL 0x400 122186906Snwhitehorn#define SCAN_PREFIX_SHIFT 0x800 123186906Snwhitehorn#define SCAN_PREFIX (SCAN_PREFIX_E0 | SCAN_PREFIX_E1 | \ 124186906Snwhitehorn SCAN_PREFIX_CTL | SCAN_PREFIX_SHIFT) 125186906Snwhitehorn 126184299Snwhitehornstatic const uint8_t adb_to_at_scancode_map[128] = { 30, 31, 32, 33, 35, 34, 127184299Snwhitehorn 44, 45, 46, 47, 0, 48, 16, 17, 18, 19, 21, 20, 2, 3, 4, 5, 7, 6, 13, 128184299Snwhitehorn 10, 8, 12, 9, 11, 27, 24, 22, 26, 23, 25, 28, 38, 36, 40, 37, 39, 43, 129184299Snwhitehorn 51, 53, 49, 50, 52, 15, 57, 41, 14, 0, 1, 29, 0, 42, 58, 56, 97, 98, 130184299Snwhitehorn 100, 95, 0, 0, 83, 0, 55, 0, 78, 0, 69, 0, 0, 0, 91, 89, 0, 74, 13, 0, 131184299Snwhitehorn 0, 82, 79, 80, 81, 75, 76, 77, 71, 0, 72, 73, 0, 0, 0, 63, 64, 65, 61, 132184299Snwhitehorn 66, 67, 0, 87, 0, 105, 0, 70, 0, 68, 0, 88, 0, 107, 102, 94, 96, 103, 133184299Snwhitehorn 62, 99, 60, 101, 59, 54, 93, 90, 0, 0 }; 134184299Snwhitehorn 135186906Snwhitehornstatic int 136186906Snwhitehornkeycode2scancode(int keycode, int shift, int up) 137186906Snwhitehorn{ 138186906Snwhitehorn static const int scan[] = { 139186906Snwhitehorn /* KP enter, right ctrl, KP divide */ 140186906Snwhitehorn 0x1c , 0x1d , 0x35 , 141186906Snwhitehorn /* print screen */ 142186906Snwhitehorn 0x37 | SCAN_PREFIX_SHIFT, 143186906Snwhitehorn /* right alt, home, up, page up, left, right, end */ 144186906Snwhitehorn 0x38, 0x47, 0x48, 0x49, 0x4b, 0x4d, 0x4f, 145186906Snwhitehorn /* down, page down, insert, delete */ 146186906Snwhitehorn 0x50, 0x51, 0x52, 0x53, 147186906Snwhitehorn /* pause/break (see also below) */ 148186906Snwhitehorn 0x46, 149186906Snwhitehorn /* 150186906Snwhitehorn * MS: left window, right window, menu 151186906Snwhitehorn * also Sun: left meta, right meta, compose 152186906Snwhitehorn */ 153186906Snwhitehorn 0x5b, 0x5c, 0x5d, 154186906Snwhitehorn /* Sun type 6 USB */ 155186906Snwhitehorn /* help, stop, again, props, undo, front, copy */ 156186906Snwhitehorn 0x68, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 157186906Snwhitehorn /* open, paste, find, cut, audiomute, audiolower, audioraise */ 158186906Snwhitehorn 0x64, 0x65, 0x66, 0x67, 0x25, 0x1f, 0x1e, 159186906Snwhitehorn /* power */ 160186906Snwhitehorn 0x20 161186906Snwhitehorn }; 162186906Snwhitehorn int scancode; 163186906Snwhitehorn 164186906Snwhitehorn scancode = keycode; 165186906Snwhitehorn if ((keycode >= 89) && (keycode < 89 + sizeof(scan) / sizeof(scan[0]))) 166186906Snwhitehorn scancode = scan[keycode - 89] | SCAN_PREFIX_E0; 167186906Snwhitehorn /* pause/break */ 168186906Snwhitehorn if ((keycode == 104) && !(shift & CTLS)) 169186906Snwhitehorn scancode = 0x45 | SCAN_PREFIX_E1 | SCAN_PREFIX_CTL; 170186906Snwhitehorn if (shift & SHIFTS) 171186906Snwhitehorn scancode &= ~SCAN_PREFIX_SHIFT; 172186906Snwhitehorn return (scancode | (up ? SCAN_RELEASE : SCAN_PRESS)); 173186906Snwhitehorn} 174186906Snwhitehorn#endif 175186906Snwhitehorn 176184299Snwhitehorn/* keyboard driver declaration */ 177184299Snwhitehornstatic int akbd_configure(int flags); 178184299Snwhitehornstatic kbd_probe_t akbd_probe; 179184299Snwhitehornstatic kbd_init_t akbd_init; 180184299Snwhitehornstatic kbd_term_t akbd_term; 181184299Snwhitehornstatic kbd_intr_t akbd_interrupt; 182184299Snwhitehornstatic kbd_test_if_t akbd_test_if; 183184299Snwhitehornstatic kbd_enable_t akbd_enable; 184184299Snwhitehornstatic kbd_disable_t akbd_disable; 185184299Snwhitehornstatic kbd_read_t akbd_read; 186184299Snwhitehornstatic kbd_check_t akbd_check; 187184299Snwhitehornstatic kbd_read_char_t akbd_read_char; 188184299Snwhitehornstatic kbd_check_char_t akbd_check_char; 189184299Snwhitehornstatic kbd_ioctl_t akbd_ioctl; 190184299Snwhitehornstatic kbd_lock_t akbd_lock; 191184299Snwhitehornstatic kbd_clear_state_t akbd_clear_state; 192184299Snwhitehornstatic kbd_get_state_t akbd_get_state; 193184299Snwhitehornstatic kbd_set_state_t akbd_set_state; 194184299Snwhitehornstatic kbd_poll_mode_t akbd_poll; 195184299Snwhitehorn 196184299Snwhitehornkeyboard_switch_t akbdsw = { 197184299Snwhitehorn akbd_probe, 198184299Snwhitehorn akbd_init, 199184299Snwhitehorn akbd_term, 200184299Snwhitehorn akbd_interrupt, 201184299Snwhitehorn akbd_test_if, 202184299Snwhitehorn akbd_enable, 203184299Snwhitehorn akbd_disable, 204184299Snwhitehorn akbd_read, 205184299Snwhitehorn akbd_check, 206184299Snwhitehorn akbd_read_char, 207184299Snwhitehorn akbd_check_char, 208184299Snwhitehorn akbd_ioctl, 209184299Snwhitehorn akbd_lock, 210184299Snwhitehorn akbd_clear_state, 211184299Snwhitehorn akbd_get_state, 212184299Snwhitehorn akbd_set_state, 213184299Snwhitehorn genkbd_get_fkeystr, 214184299Snwhitehorn akbd_poll, 215184299Snwhitehorn genkbd_diag, 216184299Snwhitehorn}; 217184299Snwhitehorn 218184299SnwhitehornKEYBOARD_DRIVER(akbd, akbdsw, akbd_configure); 219184299Snwhitehorn 220184299Snwhitehornstatic int 221184299Snwhitehornadb_kbd_probe(device_t dev) 222184299Snwhitehorn{ 223184299Snwhitehorn uint8_t type; 224184299Snwhitehorn 225184299Snwhitehorn type = adb_get_device_type(dev); 226184299Snwhitehorn 227184299Snwhitehorn if (type != ADB_DEVICE_KEYBOARD) 228184299Snwhitehorn return (ENXIO); 229184299Snwhitehorn 230184299Snwhitehorn switch(adb_get_device_handler(dev)) { 231184299Snwhitehorn case 1: 232184299Snwhitehorn device_set_desc(dev,"Apple Standard Keyboard"); 233184299Snwhitehorn break; 234184299Snwhitehorn case 2: 235184299Snwhitehorn device_set_desc(dev,"Apple Extended Keyboard"); 236184299Snwhitehorn break; 237184299Snwhitehorn case 4: 238184299Snwhitehorn device_set_desc(dev,"Apple ISO Keyboard"); 239184299Snwhitehorn break; 240184299Snwhitehorn case 5: 241184299Snwhitehorn device_set_desc(dev,"Apple Extended ISO Keyboard"); 242184299Snwhitehorn break; 243184299Snwhitehorn case 8: 244184299Snwhitehorn device_set_desc(dev,"Apple Keyboard II"); 245184299Snwhitehorn break; 246184299Snwhitehorn case 9: 247184299Snwhitehorn device_set_desc(dev,"Apple ISO Keyboard II"); 248184299Snwhitehorn break; 249184299Snwhitehorn case 12: 250184299Snwhitehorn device_set_desc(dev,"PowerBook Keyboard"); 251184299Snwhitehorn break; 252184299Snwhitehorn case 13: 253184299Snwhitehorn device_set_desc(dev,"PowerBook ISO Keyboard"); 254184299Snwhitehorn break; 255184299Snwhitehorn case 24: 256184299Snwhitehorn device_set_desc(dev,"PowerBook Extended Keyboard"); 257184299Snwhitehorn break; 258184299Snwhitehorn case 27: 259184299Snwhitehorn device_set_desc(dev,"Apple Design Keyboard"); 260184299Snwhitehorn break; 261184299Snwhitehorn case 195: 262184299Snwhitehorn device_set_desc(dev,"PowerBook G3 Keyboard"); 263184299Snwhitehorn break; 264184299Snwhitehorn case 196: 265184299Snwhitehorn device_set_desc(dev,"iBook Keyboard"); 266184299Snwhitehorn break; 267184299Snwhitehorn default: 268184299Snwhitehorn device_set_desc(dev,"ADB Keyboard"); 269184299Snwhitehorn break; 270184299Snwhitehorn } 271184299Snwhitehorn 272184299Snwhitehorn return (0); 273184299Snwhitehorn} 274184299Snwhitehorn 275184299Snwhitehornstatic int 276184299Snwhitehornms_to_ticks(int ms) 277184299Snwhitehorn{ 278184299Snwhitehorn if (hz > 1000) 279184299Snwhitehorn return ms*(hz/1000); 280184299Snwhitehorn 281184299Snwhitehorn return ms/(1000/hz); 282184299Snwhitehorn} 283184299Snwhitehorn 284184299Snwhitehornstatic int 285184299Snwhitehornadb_kbd_attach(device_t dev) 286184299Snwhitehorn{ 287184299Snwhitehorn struct adb_kbd_softc *sc; 288184299Snwhitehorn keyboard_switch_t *sw; 289226449Snwhitehorn uint32_t fkeys; 290226449Snwhitehorn phandle_t handle; 291184299Snwhitehorn 292184299Snwhitehorn sw = kbd_get_switch(KBD_DRIVER_NAME); 293184299Snwhitehorn if (sw == NULL) { 294184299Snwhitehorn return ENXIO; 295184299Snwhitehorn } 296184299Snwhitehorn 297184299Snwhitehorn sc = device_get_softc(dev); 298184299Snwhitehorn sc->sc_dev = dev; 299184299Snwhitehorn sc->sc_mode = K_RAW; 300184299Snwhitehorn sc->sc_state = 0; 301184299Snwhitehorn sc->have_led_control = 0; 302184299Snwhitehorn sc->buffers = 0; 303184299Snwhitehorn 304184299Snwhitehorn /* Try stepping forward to the extended keyboard protocol */ 305184299Snwhitehorn adb_set_device_handler(dev,3); 306184299Snwhitehorn 307184299Snwhitehorn mtx_init(&sc->sc_mutex,KBD_DRIVER_NAME,MTX_DEF,0); 308184299Snwhitehorn cv_init(&sc->sc_cv,KBD_DRIVER_NAME); 309184299Snwhitehorn callout_init(&sc->sc_repeater, 0); 310184299Snwhitehorn 311184299Snwhitehorn#ifdef AKBD_EMULATE_ATKBD 312184299Snwhitehorn kbd_init_struct(&sc->sc_kbd, KBD_DRIVER_NAME, KB_101, 0, 0, 0, 0); 313184299Snwhitehorn kbd_set_maps(&sc->sc_kbd, &key_map, &accent_map, fkey_tab, 314184299Snwhitehorn sizeof(fkey_tab) / sizeof(fkey_tab[0])); 315184299Snwhitehorn#else 316184299Snwhitehorn #error ADB raw mode not implemented 317184299Snwhitehorn#endif 318184299Snwhitehorn 319184299Snwhitehorn KBD_FOUND_DEVICE(&sc->sc_kbd); 320184299Snwhitehorn KBD_PROBE_DONE(&sc->sc_kbd); 321184299Snwhitehorn KBD_INIT_DONE(&sc->sc_kbd); 322184299Snwhitehorn KBD_CONFIG_DONE(&sc->sc_kbd); 323184299Snwhitehorn 324184299Snwhitehorn (*sw->enable)(&sc->sc_kbd); 325184299Snwhitehorn 326184299Snwhitehorn kbd_register(&sc->sc_kbd); 327184299Snwhitehorn 328184299Snwhitehorn#ifdef KBD_INSTALL_CDEV 329184299Snwhitehorn if (kbd_attach(&sc->sc_kbd)) { 330184299Snwhitehorn adb_kbd_detach(dev); 331184299Snwhitehorn return ENXIO; 332184299Snwhitehorn } 333184299Snwhitehorn#endif 334184299Snwhitehorn 335185724Snwhitehorn /* Check if we can read out the LED state from 336185724Snwhitehorn this keyboard by reading the key state register */ 337185724Snwhitehorn if (adb_read_register(dev, 2, NULL) == 2) 338185724Snwhitehorn sc->have_led_control = 1; 339185724Snwhitehorn 340184299Snwhitehorn adb_set_autopoll(dev,1); 341184299Snwhitehorn 342226449Snwhitehorn handle = OF_finddevice("mac-io/via-pmu/adb/keyboard"); 343226449Snwhitehorn if (handle != -1 && OF_getprop(handle, "AAPL,has-embedded-fn-keys", 344226449Snwhitehorn &fkeys, sizeof(fkeys)) != -1) { 345226449Snwhitehorn static const char *key_names[] = {"F1", "F2", "F3", "F4", "F5", 346226449Snwhitehorn "F6", "F7", "F8", "F9", "F10", "F11", "F12"}; 347226449Snwhitehorn struct sysctl_ctx_list *ctx; 348226449Snwhitehorn struct sysctl_oid *tree; 349226449Snwhitehorn int i; 350226449Snwhitehorn 351226449Snwhitehorn if (bootverbose) 352226449Snwhitehorn device_printf(dev, "Keyboard has embedded Fn keys\n"); 353226449Snwhitehorn 354226449Snwhitehorn for (i = 0; i < 12; i++) { 355226449Snwhitehorn uint32_t keyval; 356226449Snwhitehorn char buf[3]; 357226449Snwhitehorn if (OF_getprop(handle, key_names[i], &keyval, 358226449Snwhitehorn sizeof(keyval)) < 0) 359226449Snwhitehorn continue; 360226449Snwhitehorn buf[0] = 1; 361226449Snwhitehorn buf[1] = i+1; 362226449Snwhitehorn buf[2] = keyval; 363226449Snwhitehorn adb_write_register(dev, 0, 3, buf); 364226449Snwhitehorn } 365226449Snwhitehorn adb_write_register(dev, 1, 2, &(uint16_t){0}); 366226449Snwhitehorn 367226449Snwhitehorn ctx = device_get_sysctl_ctx(dev); 368226449Snwhitehorn tree = device_get_sysctl_tree(dev); 369226449Snwhitehorn 370226449Snwhitehorn SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 371226449Snwhitehorn "fn_keys_function_as_primary", CTLTYPE_INT | CTLFLAG_RW, sc, 372226449Snwhitehorn 0, adb_fn_keys, "I", 373226449Snwhitehorn "Set the Fn keys to be their F-key type as default"); 374226449Snwhitehorn } 375226449Snwhitehorn 376184299Snwhitehorn return (0); 377184299Snwhitehorn} 378184299Snwhitehorn 379184299Snwhitehornstatic int 380184299Snwhitehornadb_kbd_detach(device_t dev) 381184299Snwhitehorn{ 382184299Snwhitehorn struct adb_kbd_softc *sc; 383184299Snwhitehorn keyboard_t *kbd; 384184299Snwhitehorn 385184299Snwhitehorn sc = device_get_softc(dev); 386184299Snwhitehorn 387184299Snwhitehorn adb_set_autopoll(dev,0); 388184299Snwhitehorn callout_stop(&sc->sc_repeater); 389184299Snwhitehorn 390184299Snwhitehorn mtx_lock(&sc->sc_mutex); 391184299Snwhitehorn 392184299Snwhitehorn kbd = kbd_get_keyboard(kbd_find_keyboard(KBD_DRIVER_NAME, 393184299Snwhitehorn device_get_unit(dev))); 394184299Snwhitehorn 395184299Snwhitehorn kbdd_disable(kbd); 396184299Snwhitehorn 397184299Snwhitehorn#ifdef KBD_INSTALL_CDEV 398184299Snwhitehorn kbd_detach(kbd); 399184299Snwhitehorn#endif 400184299Snwhitehorn 401184299Snwhitehorn kbdd_term(kbd); 402184299Snwhitehorn 403184299Snwhitehorn mtx_unlock(&sc->sc_mutex); 404184299Snwhitehorn 405184299Snwhitehorn mtx_destroy(&sc->sc_mutex); 406184299Snwhitehorn cv_destroy(&sc->sc_cv); 407184299Snwhitehorn 408184299Snwhitehorn return (0); 409184299Snwhitehorn} 410184299Snwhitehorn 411184299Snwhitehornstatic u_int 412184299Snwhitehornadb_kbd_receive_packet(device_t dev, u_char status, 413184299Snwhitehorn u_char command, u_char reg, int len, u_char *data) 414184299Snwhitehorn{ 415184299Snwhitehorn struct adb_kbd_softc *sc; 416184299Snwhitehorn 417184299Snwhitehorn sc = device_get_softc(dev); 418184299Snwhitehorn 419184299Snwhitehorn if (command != ADB_COMMAND_TALK) 420184299Snwhitehorn return 0; 421184299Snwhitehorn 422184299Snwhitehorn if (reg != 0 || len != 2) 423184299Snwhitehorn return (0); 424184299Snwhitehorn 425184299Snwhitehorn mtx_lock(&sc->sc_mutex); 426226449Snwhitehorn /* 0x7f is always the power button */ 427226449Snwhitehorn if (data[0] == 0x7f && devctl_process_running()) { 428226449Snwhitehorn devctl_notify("PMU", "Button", "pressed", NULL); 429226449Snwhitehorn return (0); 430226449Snwhitehorn } else if (data[0] == 0xff) { 431226449Snwhitehorn return (0); /* Ignore power button release. */ 432226449Snwhitehorn } 433184299Snwhitehorn if ((data[0] & 0x7f) == 57 && sc->buffers < 7) { 434184299Snwhitehorn /* Fake the down/up cycle for caps lock */ 435184299Snwhitehorn sc->buffer[sc->buffers++] = data[0] & 0x7f; 436184299Snwhitehorn sc->buffer[sc->buffers++] = (data[0] & 0x7f) | (1 << 7); 437184299Snwhitehorn } else { 438184299Snwhitehorn sc->buffer[sc->buffers++] = data[0]; 439184299Snwhitehorn } 440184299Snwhitehorn if (sc->buffer[sc->buffers-1] < 0xff) 441184299Snwhitehorn sc->last_press = sc->buffer[sc->buffers-1]; 442184299Snwhitehorn 443184299Snwhitehorn if ((data[1] & 0x7f) == 57 && sc->buffers < 7) { 444184299Snwhitehorn /* Fake the down/up cycle for caps lock */ 445184299Snwhitehorn sc->buffer[sc->buffers++] = data[1] & 0x7f; 446184299Snwhitehorn sc->buffer[sc->buffers++] = (data[1] & 0x7f) | (1 << 7); 447184299Snwhitehorn } else { 448184299Snwhitehorn sc->buffer[sc->buffers++] = data[1]; 449184299Snwhitehorn } 450184299Snwhitehorn 451184299Snwhitehorn if (sc->buffer[sc->buffers-1] < 0xff) 452184299Snwhitehorn sc->last_press = sc->buffer[sc->buffers-1]; 453184299Snwhitehorn 454184299Snwhitehorn /* Stop any existing key repeating */ 455184299Snwhitehorn callout_stop(&sc->sc_repeater); 456184299Snwhitehorn 457184299Snwhitehorn /* Schedule a repeat callback on keydown */ 458184299Snwhitehorn if (!(sc->last_press & (1 << 7))) { 459184299Snwhitehorn callout_reset(&sc->sc_repeater, 460184299Snwhitehorn ms_to_ticks(sc->sc_kbd.kb_delay1), akbd_repeat, sc); 461184299Snwhitehorn } 462184299Snwhitehorn mtx_unlock(&sc->sc_mutex); 463184299Snwhitehorn 464184299Snwhitehorn cv_broadcast(&sc->sc_cv); 465184299Snwhitehorn 466184299Snwhitehorn if (KBD_IS_ACTIVE(&sc->sc_kbd) && KBD_IS_BUSY(&sc->sc_kbd)) { 467184299Snwhitehorn sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd, 468184299Snwhitehorn KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg); 469184299Snwhitehorn } 470184299Snwhitehorn 471184299Snwhitehorn return (0); 472184299Snwhitehorn} 473184299Snwhitehorn 474184299Snwhitehornstatic void 475184299Snwhitehornakbd_repeat(void *xsc) { 476184299Snwhitehorn struct adb_kbd_softc *sc = xsc; 477184299Snwhitehorn int notify_kbd = 0; 478184299Snwhitehorn 479184299Snwhitehorn /* Fake an up/down key repeat so long as we have the 480184299Snwhitehorn free buffers */ 481184299Snwhitehorn mtx_lock(&sc->sc_mutex); 482184299Snwhitehorn if (sc->buffers < 7) { 483184299Snwhitehorn sc->buffer[sc->buffers++] = sc->last_press | (1 << 7); 484184299Snwhitehorn sc->buffer[sc->buffers++] = sc->last_press; 485184299Snwhitehorn 486184299Snwhitehorn notify_kbd = 1; 487184299Snwhitehorn } 488184299Snwhitehorn mtx_unlock(&sc->sc_mutex); 489184299Snwhitehorn 490184299Snwhitehorn if (notify_kbd && KBD_IS_ACTIVE(&sc->sc_kbd) 491184299Snwhitehorn && KBD_IS_BUSY(&sc->sc_kbd)) { 492184299Snwhitehorn sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd, 493184299Snwhitehorn KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg); 494184299Snwhitehorn } 495184299Snwhitehorn 496184299Snwhitehorn /* Reschedule the callout */ 497184299Snwhitehorn callout_reset(&sc->sc_repeater, ms_to_ticks(sc->sc_kbd.kb_delay2), 498184299Snwhitehorn akbd_repeat, sc); 499184299Snwhitehorn} 500184299Snwhitehorn 501184299Snwhitehornstatic int 502184299Snwhitehornakbd_configure(int flags) 503184299Snwhitehorn{ 504184299Snwhitehorn return 0; 505184299Snwhitehorn} 506184299Snwhitehorn 507184299Snwhitehornstatic int 508184299Snwhitehornakbd_probe(int unit, void *arg, int flags) 509184299Snwhitehorn{ 510184299Snwhitehorn return 0; 511184299Snwhitehorn} 512184299Snwhitehorn 513184299Snwhitehornstatic int 514184299Snwhitehornakbd_init(int unit, keyboard_t **kbdp, void *arg, int flags) 515184299Snwhitehorn{ 516184299Snwhitehorn return 0; 517184299Snwhitehorn} 518184299Snwhitehorn 519184299Snwhitehornstatic int 520184299Snwhitehornakbd_term(keyboard_t *kbd) 521184299Snwhitehorn{ 522184299Snwhitehorn return 0; 523184299Snwhitehorn} 524184299Snwhitehorn 525184299Snwhitehornstatic int 526184299Snwhitehornakbd_interrupt(keyboard_t *kbd, void *arg) 527184299Snwhitehorn{ 528184299Snwhitehorn return 0; 529184299Snwhitehorn} 530184299Snwhitehorn 531184299Snwhitehornstatic int 532184299Snwhitehornakbd_test_if(keyboard_t *kbd) 533184299Snwhitehorn{ 534184299Snwhitehorn return 0; 535184299Snwhitehorn} 536184299Snwhitehorn 537184299Snwhitehornstatic int 538184299Snwhitehornakbd_enable(keyboard_t *kbd) 539184299Snwhitehorn{ 540184299Snwhitehorn KBD_ACTIVATE(kbd); 541184299Snwhitehorn return (0); 542184299Snwhitehorn} 543184299Snwhitehorn 544184299Snwhitehornstatic int 545184299Snwhitehornakbd_disable(keyboard_t *kbd) 546184299Snwhitehorn{ 547184299Snwhitehorn struct adb_kbd_softc *sc; 548184299Snwhitehorn sc = (struct adb_kbd_softc *)(kbd); 549184299Snwhitehorn 550184299Snwhitehorn callout_stop(&sc->sc_repeater); 551184299Snwhitehorn KBD_DEACTIVATE(kbd); 552184299Snwhitehorn return (0); 553184299Snwhitehorn} 554184299Snwhitehorn 555184299Snwhitehornstatic int 556184299Snwhitehornakbd_read(keyboard_t *kbd, int wait) 557184299Snwhitehorn{ 558184299Snwhitehorn return (0); 559184299Snwhitehorn} 560184299Snwhitehorn 561184299Snwhitehornstatic int 562184299Snwhitehornakbd_check(keyboard_t *kbd) 563184299Snwhitehorn{ 564184299Snwhitehorn struct adb_kbd_softc *sc; 565184299Snwhitehorn 566184299Snwhitehorn if (!KBD_IS_ACTIVE(kbd)) 567184299Snwhitehorn return (FALSE); 568184299Snwhitehorn 569184299Snwhitehorn sc = (struct adb_kbd_softc *)(kbd); 570184299Snwhitehorn 571184299Snwhitehorn mtx_lock(&sc->sc_mutex); 572186906Snwhitehorn#ifdef AKBD_EMULATE_ATKBD 573186906Snwhitehorn if (sc->at_buffered_char[0]) { 574186906Snwhitehorn mtx_unlock(&sc->sc_mutex); 575186906Snwhitehorn return (TRUE); 576186906Snwhitehorn } 577186906Snwhitehorn#endif 578186906Snwhitehorn 579184299Snwhitehorn if (sc->buffers > 0) { 580184299Snwhitehorn mtx_unlock(&sc->sc_mutex); 581184299Snwhitehorn return (TRUE); 582184299Snwhitehorn } 583184299Snwhitehorn mtx_unlock(&sc->sc_mutex); 584184299Snwhitehorn 585184299Snwhitehorn return (FALSE); 586184299Snwhitehorn} 587184299Snwhitehorn 588184299Snwhitehornstatic u_int 589184299Snwhitehornakbd_read_char(keyboard_t *kbd, int wait) 590184299Snwhitehorn{ 591184299Snwhitehorn struct adb_kbd_softc *sc; 592186906Snwhitehorn uint16_t key; 593186906Snwhitehorn uint8_t adb_code; 594184299Snwhitehorn int i; 595184299Snwhitehorn 596184299Snwhitehorn sc = (struct adb_kbd_softc *)(kbd); 597184299Snwhitehorn 598184299Snwhitehorn mtx_lock(&sc->sc_mutex); 599184299Snwhitehorn 600186906Snwhitehorn#if defined(AKBD_EMULATE_ATKBD) 601186906Snwhitehorn if (sc->sc_mode == K_RAW && sc->at_buffered_char[0]) { 602186906Snwhitehorn key = sc->at_buffered_char[0]; 603186906Snwhitehorn if (key & SCAN_PREFIX) { 604186906Snwhitehorn sc->at_buffered_char[0] = key & ~SCAN_PREFIX; 605186906Snwhitehorn key = (key & SCAN_PREFIX_E0) ? 0xe0 : 0xe1; 606186906Snwhitehorn } else { 607186906Snwhitehorn sc->at_buffered_char[0] = sc->at_buffered_char[1]; 608186906Snwhitehorn sc->at_buffered_char[1] = 0; 609184299Snwhitehorn } 610184299Snwhitehorn 611186906Snwhitehorn mtx_unlock(&sc->sc_mutex); 612184299Snwhitehorn 613186906Snwhitehorn return (key); 614186906Snwhitehorn } 615186906Snwhitehorn#endif 616184299Snwhitehorn 617186906Snwhitehorn if (!sc->buffers && wait) 618186906Snwhitehorn cv_wait(&sc->sc_cv,&sc->sc_mutex); 619184299Snwhitehorn 620186906Snwhitehorn if (!sc->buffers) { 621186906Snwhitehorn mtx_unlock(&sc->sc_mutex); 622186906Snwhitehorn return (0); 623186906Snwhitehorn } 624186906Snwhitehorn 625186906Snwhitehorn adb_code = sc->buffer[0]; 626186906Snwhitehorn 627186906Snwhitehorn for (i = 1; i < sc->buffers; i++) 628186906Snwhitehorn sc->buffer[i-1] = sc->buffer[i]; 629186906Snwhitehorn 630186906Snwhitehorn sc->buffers--; 631186906Snwhitehorn 632184299Snwhitehorn #ifdef AKBD_EMULATE_ATKBD 633186906Snwhitehorn key = adb_to_at_scancode_map[adb_code & 0x7f]; 634186906Snwhitehorn if (sc->sc_mode == K_CODE) { 635186906Snwhitehorn /* Add the key-release bit */ 636186906Snwhitehorn key |= adb_code & 0x80; 637186906Snwhitehorn } else if (sc->sc_mode == K_RAW) { 638186906Snwhitehorn /* 639186906Snwhitehorn * In the raw case, we have to emulate the gross 640186906Snwhitehorn * variable-length AT keyboard thing. Since this code 641186906Snwhitehorn * is copied from sunkbd, which is the same code 642186906Snwhitehorn * as ukbd, it might be nice to have this centralized. 643186906Snwhitehorn */ 644186906Snwhitehorn 645186906Snwhitehorn key = keycode2scancode(key, 646186906Snwhitehorn 0, adb_code & 0x80); 647186906Snwhitehorn 648186906Snwhitehorn if (key & SCAN_PREFIX) { 649186906Snwhitehorn if (key & SCAN_PREFIX_CTL) { 650186906Snwhitehorn sc->at_buffered_char[0] = 651186906Snwhitehorn 0x1d | (key & SCAN_RELEASE); 652186906Snwhitehorn sc->at_buffered_char[1] = 653186906Snwhitehorn key & ~SCAN_PREFIX; 654186906Snwhitehorn } else if (key & SCAN_PREFIX_SHIFT) { 655186906Snwhitehorn sc->at_buffered_char[0] = 656186906Snwhitehorn 0x2a | (key & SCAN_RELEASE); 657186906Snwhitehorn sc->at_buffered_char[1] = 658186906Snwhitehorn key & ~SCAN_PREFIX_SHIFT; 659186906Snwhitehorn } else { 660186906Snwhitehorn sc->at_buffered_char[0] = 661186906Snwhitehorn key & ~SCAN_PREFIX; 662186906Snwhitehorn sc->at_buffered_char[1] = 0; 663186906Snwhitehorn } 664186906Snwhitehorn 665186906Snwhitehorn key = (key & SCAN_PREFIX_E0) ? 0xe0 : 0xe1; 666186906Snwhitehorn } 667186906Snwhitehorn } 668184299Snwhitehorn #else 669186906Snwhitehorn key = adb_code; 670184299Snwhitehorn #endif 671184299Snwhitehorn 672186906Snwhitehorn mtx_unlock(&sc->sc_mutex); 673186906Snwhitehorn 674186906Snwhitehorn return (key); 675184299Snwhitehorn} 676184299Snwhitehorn 677184299Snwhitehornstatic int 678184299Snwhitehornakbd_check_char(keyboard_t *kbd) 679184299Snwhitehorn{ 680184299Snwhitehorn if (!KBD_IS_ACTIVE(kbd)) 681184299Snwhitehorn return (FALSE); 682184299Snwhitehorn 683184299Snwhitehorn return (akbd_check(kbd)); 684184299Snwhitehorn} 685184299Snwhitehorn 686184299Snwhitehornstatic int 687184299Snwhitehornset_typematic(keyboard_t *kbd, int code) 688184299Snwhitehorn{ 689184299Snwhitehorn /* These numbers are in microseconds, so convert to ticks */ 690184299Snwhitehorn 691184299Snwhitehorn static int delays[] = { 250, 500, 750, 1000 }; 692184299Snwhitehorn static int rates[] = { 34, 38, 42, 46, 50, 55, 59, 63, 693184299Snwhitehorn 68, 76, 84, 92, 100, 110, 118, 126, 694184299Snwhitehorn 136, 152, 168, 184, 200, 220, 236, 252, 695184299Snwhitehorn 272, 304, 336, 368, 400, 440, 472, 504 }; 696184299Snwhitehorn 697184299Snwhitehorn if (code & ~0x7f) 698184299Snwhitehorn return EINVAL; 699184299Snwhitehorn kbd->kb_delay1 = delays[(code >> 5) & 3]; 700184299Snwhitehorn kbd->kb_delay2 = rates[code & 0x1f]; 701184299Snwhitehorn return 0; 702184299Snwhitehorn} 703184299Snwhitehorn 704184299Snwhitehornstatic int akbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t data) 705184299Snwhitehorn{ 706184299Snwhitehorn struct adb_kbd_softc *sc; 707184299Snwhitehorn uint16_t r2; 708184299Snwhitehorn int error; 709184299Snwhitehorn 710184299Snwhitehorn sc = (struct adb_kbd_softc *)(kbd); 711184299Snwhitehorn error = 0; 712184299Snwhitehorn 713184299Snwhitehorn switch (cmd) { 714184299Snwhitehorn case KDGKBMODE: 715184299Snwhitehorn *(int *)data = sc->sc_mode; 716184299Snwhitehorn break; 717184299Snwhitehorn case KDSKBMODE: 718184299Snwhitehorn switch (*(int *)data) { 719184299Snwhitehorn case K_XLATE: 720184299Snwhitehorn if (sc->sc_mode != K_XLATE) { 721184299Snwhitehorn /* make lock key state and LED state match */ 722184299Snwhitehorn sc->sc_state &= ~LOCK_MASK; 723184299Snwhitehorn sc->sc_state |= KBD_LED_VAL(kbd); 724184299Snwhitehorn } 725184299Snwhitehorn /* FALLTHROUGH */ 726184299Snwhitehorn case K_RAW: 727184299Snwhitehorn case K_CODE: 728184299Snwhitehorn if (sc->sc_mode != *(int *)data) 729184299Snwhitehorn sc->sc_mode = *(int *)data; 730184299Snwhitehorn break; 731184299Snwhitehorn default: 732184299Snwhitehorn error = EINVAL; 733184299Snwhitehorn break; 734184299Snwhitehorn } 735184299Snwhitehorn 736184299Snwhitehorn break; 737184299Snwhitehorn 738184299Snwhitehorn case KDGETLED: 739184299Snwhitehorn *(int *)data = KBD_LED_VAL(kbd); 740184299Snwhitehorn break; 741184299Snwhitehorn 742184299Snwhitehorn case KDSKBSTATE: 743184299Snwhitehorn if (*(int *)data & ~LOCK_MASK) { 744184299Snwhitehorn error = EINVAL; 745184299Snwhitehorn break; 746184299Snwhitehorn } 747184299Snwhitehorn sc->sc_state &= ~LOCK_MASK; 748184299Snwhitehorn sc->sc_state |= *(int *)data; 749184299Snwhitehorn 750184299Snwhitehorn /* FALLTHROUGH */ 751184299Snwhitehorn 752184299Snwhitehorn case KDSETLED: 753184299Snwhitehorn KBD_LED_VAL(kbd) = *(int *)data; 754184299Snwhitehorn 755184299Snwhitehorn if (!sc->have_led_control) 756184299Snwhitehorn break; 757184299Snwhitehorn 758184299Snwhitehorn r2 = (~0 & 0x04) | 3; 759184299Snwhitehorn 760184299Snwhitehorn if (*(int *)data & NLKED) 761184299Snwhitehorn r2 &= ~1; 762184299Snwhitehorn if (*(int *)data & CLKED) 763184299Snwhitehorn r2 &= ~2; 764184299Snwhitehorn if (*(int *)data & SLKED) 765184299Snwhitehorn r2 &= ~4; 766184299Snwhitehorn 767184299Snwhitehorn adb_send_packet(sc->sc_dev,ADB_COMMAND_LISTEN,2, 768184299Snwhitehorn sizeof(uint16_t),(u_char *)&r2); 769184299Snwhitehorn 770184299Snwhitehorn break; 771184299Snwhitehorn 772184299Snwhitehorn case KDGKBSTATE: 773184299Snwhitehorn *(int *)data = sc->sc_state & LOCK_MASK; 774184299Snwhitehorn break; 775184299Snwhitehorn 776184299Snwhitehorn case KDSETREPEAT: 777184299Snwhitehorn if (!KBD_HAS_DEVICE(kbd)) 778184299Snwhitehorn return 0; 779184299Snwhitehorn if (((int *)data)[1] < 0) 780184299Snwhitehorn return EINVAL; 781184299Snwhitehorn if (((int *)data)[0] < 0) 782184299Snwhitehorn return EINVAL; 783184299Snwhitehorn else if (((int *)data)[0] == 0) /* fastest possible value */ 784184299Snwhitehorn kbd->kb_delay1 = 200; 785184299Snwhitehorn else 786184299Snwhitehorn kbd->kb_delay1 = ((int *)data)[0]; 787184299Snwhitehorn kbd->kb_delay2 = ((int *)data)[1]; 788184299Snwhitehorn 789184299Snwhitehorn break; 790184299Snwhitehorn 791184299Snwhitehorn case KDSETRAD: 792184299Snwhitehorn error = set_typematic(kbd, *(int *)data); 793184299Snwhitehorn break; 794184299Snwhitehorn 795184299Snwhitehorn case PIO_KEYMAP: 796224126Sed case OPIO_KEYMAP: 797184299Snwhitehorn case PIO_KEYMAPENT: 798184299Snwhitehorn case PIO_DEADKEYMAP: 799184299Snwhitehorn default: 800184299Snwhitehorn return (genkbd_commonioctl(kbd, cmd, data)); 801184299Snwhitehorn } 802184299Snwhitehorn 803184299Snwhitehorn return (error); 804184299Snwhitehorn} 805184299Snwhitehorn 806184299Snwhitehornstatic int akbd_lock(keyboard_t *kbd, int lock) 807184299Snwhitehorn{ 808184299Snwhitehorn return (0); 809184299Snwhitehorn} 810184299Snwhitehorn 811184299Snwhitehornstatic void akbd_clear_state(keyboard_t *kbd) 812184299Snwhitehorn{ 813186906Snwhitehorn struct adb_kbd_softc *sc; 814186906Snwhitehorn 815186906Snwhitehorn sc = (struct adb_kbd_softc *)(kbd); 816186906Snwhitehorn 817186906Snwhitehorn mtx_lock(&sc->sc_mutex); 818186906Snwhitehorn 819186906Snwhitehorn sc->buffers = 0; 820186906Snwhitehorn callout_stop(&sc->sc_repeater); 821186906Snwhitehorn 822186906Snwhitehorn#if defined(AKBD_EMULATE_ATKBD) 823186906Snwhitehorn sc->at_buffered_char[0] = 0; 824186906Snwhitehorn sc->at_buffered_char[1] = 0; 825186906Snwhitehorn#endif 826186906Snwhitehorn mtx_unlock(&sc->sc_mutex); 827184299Snwhitehorn} 828184299Snwhitehorn 829184299Snwhitehornstatic int akbd_get_state(keyboard_t *kbd, void *buf, size_t len) 830184299Snwhitehorn{ 831184299Snwhitehorn return (0); 832184299Snwhitehorn} 833184299Snwhitehorn 834184299Snwhitehornstatic int akbd_set_state(keyboard_t *kbd, void *buf, size_t len) 835184299Snwhitehorn{ 836184299Snwhitehorn return (0); 837184299Snwhitehorn} 838184299Snwhitehorn 839184299Snwhitehornstatic int akbd_poll(keyboard_t *kbd, int on) 840184299Snwhitehorn{ 841184299Snwhitehorn return (0); 842184299Snwhitehorn} 843184299Snwhitehorn 844184299Snwhitehornstatic int 845184299Snwhitehornakbd_modevent(module_t mod, int type, void *data) 846184299Snwhitehorn{ 847184299Snwhitehorn switch (type) { 848184299Snwhitehorn case MOD_LOAD: 849184299Snwhitehorn kbd_add_driver(&akbd_kbd_driver); 850184299Snwhitehorn break; 851184299Snwhitehorn 852184299Snwhitehorn case MOD_UNLOAD: 853184299Snwhitehorn kbd_delete_driver(&akbd_kbd_driver); 854184299Snwhitehorn break; 855184299Snwhitehorn 856184299Snwhitehorn default: 857184299Snwhitehorn return (EOPNOTSUPP); 858184299Snwhitehorn } 859184299Snwhitehorn 860184299Snwhitehorn return (0); 861184299Snwhitehorn} 862184299Snwhitehorn 863226449Snwhitehornstatic int 864226449Snwhitehornadb_fn_keys(SYSCTL_HANDLER_ARGS) 865226449Snwhitehorn{ 866226449Snwhitehorn struct adb_kbd_softc *sc = arg1; 867226449Snwhitehorn int error; 868226449Snwhitehorn uint16_t is_fn_enabled; 869226449Snwhitehorn unsigned int is_fn_enabled_sysctl; 870226449Snwhitehorn 871226449Snwhitehorn adb_read_register(sc->sc_dev, 1, &is_fn_enabled); 872226449Snwhitehorn is_fn_enabled &= 1; 873226449Snwhitehorn is_fn_enabled_sysctl = is_fn_enabled; 874226449Snwhitehorn error = sysctl_handle_int(oidp, &is_fn_enabled_sysctl, 0, req); 875226449Snwhitehorn 876226449Snwhitehorn if (error || !req->newptr) 877226449Snwhitehorn return (error); 878226449Snwhitehorn 879226449Snwhitehorn is_fn_enabled = is_fn_enabled_sysctl; 880226449Snwhitehorn if (is_fn_enabled != 1 && is_fn_enabled != 0) 881226449Snwhitehorn return (EINVAL); 882226449Snwhitehorn 883226449Snwhitehorn adb_write_register(sc->sc_dev, 1, 2, &is_fn_enabled); 884226449Snwhitehorn return (0); 885226449Snwhitehorn} 886226449Snwhitehorn 887184299SnwhitehornDEV_MODULE(akbd, akbd_modevent, NULL); 888184299Snwhitehorn 889