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$ 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> 38230751Sjhibbits#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> 45230751Sjhibbits#include <dev/ofw/openfirm.h> 46230751Sjhibbits#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); 61230751Sjhibbitsstatic 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; 289230751Sjhibbits uint32_t fkeys; 290230751Sjhibbits 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 307262671Sjhibbits mtx_init(&sc->sc_mutex, KBD_DRIVER_NAME, NULL, MTX_DEF); 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 342230751Sjhibbits handle = OF_finddevice("mac-io/via-pmu/adb/keyboard"); 343230751Sjhibbits if (handle != -1 && OF_getprop(handle, "AAPL,has-embedded-fn-keys", 344230751Sjhibbits &fkeys, sizeof(fkeys)) != -1) { 345230751Sjhibbits static const char *key_names[] = {"F1", "F2", "F3", "F4", "F5", 346230751Sjhibbits "F6", "F7", "F8", "F9", "F10", "F11", "F12"}; 347230751Sjhibbits struct sysctl_ctx_list *ctx; 348230751Sjhibbits struct sysctl_oid *tree; 349230751Sjhibbits int i; 350230751Sjhibbits 351230751Sjhibbits if (bootverbose) 352230751Sjhibbits device_printf(dev, "Keyboard has embedded Fn keys\n"); 353230751Sjhibbits 354230751Sjhibbits for (i = 0; i < 12; i++) { 355230751Sjhibbits uint32_t keyval; 356230751Sjhibbits char buf[3]; 357230751Sjhibbits if (OF_getprop(handle, key_names[i], &keyval, 358230751Sjhibbits sizeof(keyval)) < 0) 359230751Sjhibbits continue; 360230751Sjhibbits buf[0] = 1; 361230751Sjhibbits buf[1] = i+1; 362230751Sjhibbits buf[2] = keyval; 363230751Sjhibbits adb_write_register(dev, 0, 3, buf); 364230751Sjhibbits } 365230751Sjhibbits adb_write_register(dev, 1, 2, &(uint16_t){0}); 366230751Sjhibbits 367230751Sjhibbits ctx = device_get_sysctl_ctx(dev); 368230751Sjhibbits tree = device_get_sysctl_tree(dev); 369230751Sjhibbits 370230751Sjhibbits SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 371230751Sjhibbits "fn_keys_function_as_primary", CTLTYPE_INT | CTLFLAG_RW, sc, 372230751Sjhibbits 0, adb_fn_keys, "I", 373230751Sjhibbits "Set the Fn keys to be their F-key type as default"); 374230751Sjhibbits } 375230751Sjhibbits 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); 426230751Sjhibbits /* 0x7f is always the power button */ 427230751Sjhibbits if (data[0] == 0x7f && devctl_process_running()) { 428230751Sjhibbits devctl_notify("PMU", "Button", "pressed", NULL); 429237773Sjhibbits mtx_unlock(&sc->sc_mutex); 430230751Sjhibbits return (0); 431230751Sjhibbits } else if (data[0] == 0xff) { 432237773Sjhibbits mtx_unlock(&sc->sc_mutex); 433230751Sjhibbits return (0); /* Ignore power button release. */ 434230751Sjhibbits } 435184299Snwhitehorn if ((data[0] & 0x7f) == 57 && sc->buffers < 7) { 436184299Snwhitehorn /* Fake the down/up cycle for caps lock */ 437184299Snwhitehorn sc->buffer[sc->buffers++] = data[0] & 0x7f; 438184299Snwhitehorn sc->buffer[sc->buffers++] = (data[0] & 0x7f) | (1 << 7); 439184299Snwhitehorn } else { 440184299Snwhitehorn sc->buffer[sc->buffers++] = data[0]; 441184299Snwhitehorn } 442184299Snwhitehorn if (sc->buffer[sc->buffers-1] < 0xff) 443184299Snwhitehorn sc->last_press = sc->buffer[sc->buffers-1]; 444184299Snwhitehorn 445184299Snwhitehorn if ((data[1] & 0x7f) == 57 && sc->buffers < 7) { 446184299Snwhitehorn /* Fake the down/up cycle for caps lock */ 447184299Snwhitehorn sc->buffer[sc->buffers++] = data[1] & 0x7f; 448184299Snwhitehorn sc->buffer[sc->buffers++] = (data[1] & 0x7f) | (1 << 7); 449184299Snwhitehorn } else { 450184299Snwhitehorn sc->buffer[sc->buffers++] = data[1]; 451184299Snwhitehorn } 452184299Snwhitehorn 453184299Snwhitehorn if (sc->buffer[sc->buffers-1] < 0xff) 454184299Snwhitehorn sc->last_press = sc->buffer[sc->buffers-1]; 455184299Snwhitehorn 456184299Snwhitehorn /* Stop any existing key repeating */ 457184299Snwhitehorn callout_stop(&sc->sc_repeater); 458184299Snwhitehorn 459184299Snwhitehorn /* Schedule a repeat callback on keydown */ 460184299Snwhitehorn if (!(sc->last_press & (1 << 7))) { 461184299Snwhitehorn callout_reset(&sc->sc_repeater, 462184299Snwhitehorn ms_to_ticks(sc->sc_kbd.kb_delay1), akbd_repeat, sc); 463184299Snwhitehorn } 464184299Snwhitehorn mtx_unlock(&sc->sc_mutex); 465184299Snwhitehorn 466184299Snwhitehorn cv_broadcast(&sc->sc_cv); 467184299Snwhitehorn 468184299Snwhitehorn if (KBD_IS_ACTIVE(&sc->sc_kbd) && KBD_IS_BUSY(&sc->sc_kbd)) { 469184299Snwhitehorn sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd, 470184299Snwhitehorn KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg); 471184299Snwhitehorn } 472184299Snwhitehorn 473184299Snwhitehorn return (0); 474184299Snwhitehorn} 475184299Snwhitehorn 476184299Snwhitehornstatic void 477184299Snwhitehornakbd_repeat(void *xsc) { 478184299Snwhitehorn struct adb_kbd_softc *sc = xsc; 479184299Snwhitehorn int notify_kbd = 0; 480184299Snwhitehorn 481184299Snwhitehorn /* Fake an up/down key repeat so long as we have the 482184299Snwhitehorn free buffers */ 483184299Snwhitehorn mtx_lock(&sc->sc_mutex); 484184299Snwhitehorn if (sc->buffers < 7) { 485184299Snwhitehorn sc->buffer[sc->buffers++] = sc->last_press | (1 << 7); 486184299Snwhitehorn sc->buffer[sc->buffers++] = sc->last_press; 487184299Snwhitehorn 488184299Snwhitehorn notify_kbd = 1; 489184299Snwhitehorn } 490184299Snwhitehorn mtx_unlock(&sc->sc_mutex); 491184299Snwhitehorn 492184299Snwhitehorn if (notify_kbd && KBD_IS_ACTIVE(&sc->sc_kbd) 493184299Snwhitehorn && KBD_IS_BUSY(&sc->sc_kbd)) { 494184299Snwhitehorn sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd, 495184299Snwhitehorn KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg); 496184299Snwhitehorn } 497184299Snwhitehorn 498184299Snwhitehorn /* Reschedule the callout */ 499184299Snwhitehorn callout_reset(&sc->sc_repeater, ms_to_ticks(sc->sc_kbd.kb_delay2), 500184299Snwhitehorn akbd_repeat, sc); 501184299Snwhitehorn} 502184299Snwhitehorn 503184299Snwhitehornstatic int 504184299Snwhitehornakbd_configure(int flags) 505184299Snwhitehorn{ 506184299Snwhitehorn return 0; 507184299Snwhitehorn} 508184299Snwhitehorn 509184299Snwhitehornstatic int 510184299Snwhitehornakbd_probe(int unit, void *arg, int flags) 511184299Snwhitehorn{ 512184299Snwhitehorn return 0; 513184299Snwhitehorn} 514184299Snwhitehorn 515184299Snwhitehornstatic int 516184299Snwhitehornakbd_init(int unit, keyboard_t **kbdp, void *arg, int flags) 517184299Snwhitehorn{ 518184299Snwhitehorn return 0; 519184299Snwhitehorn} 520184299Snwhitehorn 521184299Snwhitehornstatic int 522184299Snwhitehornakbd_term(keyboard_t *kbd) 523184299Snwhitehorn{ 524184299Snwhitehorn return 0; 525184299Snwhitehorn} 526184299Snwhitehorn 527184299Snwhitehornstatic int 528184299Snwhitehornakbd_interrupt(keyboard_t *kbd, void *arg) 529184299Snwhitehorn{ 530184299Snwhitehorn return 0; 531184299Snwhitehorn} 532184299Snwhitehorn 533184299Snwhitehornstatic int 534184299Snwhitehornakbd_test_if(keyboard_t *kbd) 535184299Snwhitehorn{ 536184299Snwhitehorn return 0; 537184299Snwhitehorn} 538184299Snwhitehorn 539184299Snwhitehornstatic int 540184299Snwhitehornakbd_enable(keyboard_t *kbd) 541184299Snwhitehorn{ 542184299Snwhitehorn KBD_ACTIVATE(kbd); 543184299Snwhitehorn return (0); 544184299Snwhitehorn} 545184299Snwhitehorn 546184299Snwhitehornstatic int 547184299Snwhitehornakbd_disable(keyboard_t *kbd) 548184299Snwhitehorn{ 549184299Snwhitehorn struct adb_kbd_softc *sc; 550184299Snwhitehorn sc = (struct adb_kbd_softc *)(kbd); 551184299Snwhitehorn 552184299Snwhitehorn callout_stop(&sc->sc_repeater); 553184299Snwhitehorn KBD_DEACTIVATE(kbd); 554184299Snwhitehorn return (0); 555184299Snwhitehorn} 556184299Snwhitehorn 557184299Snwhitehornstatic int 558184299Snwhitehornakbd_read(keyboard_t *kbd, int wait) 559184299Snwhitehorn{ 560184299Snwhitehorn return (0); 561184299Snwhitehorn} 562184299Snwhitehorn 563184299Snwhitehornstatic int 564184299Snwhitehornakbd_check(keyboard_t *kbd) 565184299Snwhitehorn{ 566184299Snwhitehorn struct adb_kbd_softc *sc; 567184299Snwhitehorn 568184299Snwhitehorn if (!KBD_IS_ACTIVE(kbd)) 569184299Snwhitehorn return (FALSE); 570184299Snwhitehorn 571184299Snwhitehorn sc = (struct adb_kbd_softc *)(kbd); 572184299Snwhitehorn 573184299Snwhitehorn mtx_lock(&sc->sc_mutex); 574186906Snwhitehorn#ifdef AKBD_EMULATE_ATKBD 575186906Snwhitehorn if (sc->at_buffered_char[0]) { 576186906Snwhitehorn mtx_unlock(&sc->sc_mutex); 577186906Snwhitehorn return (TRUE); 578186906Snwhitehorn } 579186906Snwhitehorn#endif 580186906Snwhitehorn 581184299Snwhitehorn if (sc->buffers > 0) { 582184299Snwhitehorn mtx_unlock(&sc->sc_mutex); 583184299Snwhitehorn return (TRUE); 584184299Snwhitehorn } 585184299Snwhitehorn mtx_unlock(&sc->sc_mutex); 586184299Snwhitehorn 587184299Snwhitehorn return (FALSE); 588184299Snwhitehorn} 589184299Snwhitehorn 590184299Snwhitehornstatic u_int 591184299Snwhitehornakbd_read_char(keyboard_t *kbd, int wait) 592184299Snwhitehorn{ 593184299Snwhitehorn struct adb_kbd_softc *sc; 594186906Snwhitehorn uint16_t key; 595186906Snwhitehorn uint8_t adb_code; 596184299Snwhitehorn int i; 597184299Snwhitehorn 598184299Snwhitehorn sc = (struct adb_kbd_softc *)(kbd); 599184299Snwhitehorn 600184299Snwhitehorn mtx_lock(&sc->sc_mutex); 601184299Snwhitehorn 602186906Snwhitehorn#if defined(AKBD_EMULATE_ATKBD) 603186906Snwhitehorn if (sc->sc_mode == K_RAW && sc->at_buffered_char[0]) { 604186906Snwhitehorn key = sc->at_buffered_char[0]; 605186906Snwhitehorn if (key & SCAN_PREFIX) { 606186906Snwhitehorn sc->at_buffered_char[0] = key & ~SCAN_PREFIX; 607186906Snwhitehorn key = (key & SCAN_PREFIX_E0) ? 0xe0 : 0xe1; 608186906Snwhitehorn } else { 609186906Snwhitehorn sc->at_buffered_char[0] = sc->at_buffered_char[1]; 610186906Snwhitehorn sc->at_buffered_char[1] = 0; 611184299Snwhitehorn } 612184299Snwhitehorn 613186906Snwhitehorn mtx_unlock(&sc->sc_mutex); 614184299Snwhitehorn 615186906Snwhitehorn return (key); 616186906Snwhitehorn } 617186906Snwhitehorn#endif 618184299Snwhitehorn 619186906Snwhitehorn if (!sc->buffers && wait) 620186906Snwhitehorn cv_wait(&sc->sc_cv,&sc->sc_mutex); 621184299Snwhitehorn 622186906Snwhitehorn if (!sc->buffers) { 623186906Snwhitehorn mtx_unlock(&sc->sc_mutex); 624186906Snwhitehorn return (0); 625186906Snwhitehorn } 626186906Snwhitehorn 627186906Snwhitehorn adb_code = sc->buffer[0]; 628186906Snwhitehorn 629186906Snwhitehorn for (i = 1; i < sc->buffers; i++) 630186906Snwhitehorn sc->buffer[i-1] = sc->buffer[i]; 631186906Snwhitehorn 632186906Snwhitehorn sc->buffers--; 633186906Snwhitehorn 634184299Snwhitehorn #ifdef AKBD_EMULATE_ATKBD 635186906Snwhitehorn key = adb_to_at_scancode_map[adb_code & 0x7f]; 636186906Snwhitehorn if (sc->sc_mode == K_CODE) { 637186906Snwhitehorn /* Add the key-release bit */ 638186906Snwhitehorn key |= adb_code & 0x80; 639186906Snwhitehorn } else if (sc->sc_mode == K_RAW) { 640186906Snwhitehorn /* 641186906Snwhitehorn * In the raw case, we have to emulate the gross 642186906Snwhitehorn * variable-length AT keyboard thing. Since this code 643186906Snwhitehorn * is copied from sunkbd, which is the same code 644186906Snwhitehorn * as ukbd, it might be nice to have this centralized. 645186906Snwhitehorn */ 646186906Snwhitehorn 647186906Snwhitehorn key = keycode2scancode(key, 648186906Snwhitehorn 0, adb_code & 0x80); 649186906Snwhitehorn 650186906Snwhitehorn if (key & SCAN_PREFIX) { 651186906Snwhitehorn if (key & SCAN_PREFIX_CTL) { 652186906Snwhitehorn sc->at_buffered_char[0] = 653186906Snwhitehorn 0x1d | (key & SCAN_RELEASE); 654186906Snwhitehorn sc->at_buffered_char[1] = 655186906Snwhitehorn key & ~SCAN_PREFIX; 656186906Snwhitehorn } else if (key & SCAN_PREFIX_SHIFT) { 657186906Snwhitehorn sc->at_buffered_char[0] = 658186906Snwhitehorn 0x2a | (key & SCAN_RELEASE); 659186906Snwhitehorn sc->at_buffered_char[1] = 660186906Snwhitehorn key & ~SCAN_PREFIX_SHIFT; 661186906Snwhitehorn } else { 662186906Snwhitehorn sc->at_buffered_char[0] = 663186906Snwhitehorn key & ~SCAN_PREFIX; 664186906Snwhitehorn sc->at_buffered_char[1] = 0; 665186906Snwhitehorn } 666186906Snwhitehorn 667186906Snwhitehorn key = (key & SCAN_PREFIX_E0) ? 0xe0 : 0xe1; 668186906Snwhitehorn } 669186906Snwhitehorn } 670184299Snwhitehorn #else 671186906Snwhitehorn key = adb_code; 672184299Snwhitehorn #endif 673184299Snwhitehorn 674186906Snwhitehorn mtx_unlock(&sc->sc_mutex); 675186906Snwhitehorn 676186906Snwhitehorn return (key); 677184299Snwhitehorn} 678184299Snwhitehorn 679184299Snwhitehornstatic int 680184299Snwhitehornakbd_check_char(keyboard_t *kbd) 681184299Snwhitehorn{ 682184299Snwhitehorn if (!KBD_IS_ACTIVE(kbd)) 683184299Snwhitehorn return (FALSE); 684184299Snwhitehorn 685184299Snwhitehorn return (akbd_check(kbd)); 686184299Snwhitehorn} 687184299Snwhitehorn 688184299Snwhitehornstatic int 689184299Snwhitehornset_typematic(keyboard_t *kbd, int code) 690184299Snwhitehorn{ 691184299Snwhitehorn /* These numbers are in microseconds, so convert to ticks */ 692184299Snwhitehorn 693184299Snwhitehorn static int delays[] = { 250, 500, 750, 1000 }; 694184299Snwhitehorn static int rates[] = { 34, 38, 42, 46, 50, 55, 59, 63, 695184299Snwhitehorn 68, 76, 84, 92, 100, 110, 118, 126, 696184299Snwhitehorn 136, 152, 168, 184, 200, 220, 236, 252, 697184299Snwhitehorn 272, 304, 336, 368, 400, 440, 472, 504 }; 698184299Snwhitehorn 699184299Snwhitehorn if (code & ~0x7f) 700184299Snwhitehorn return EINVAL; 701184299Snwhitehorn kbd->kb_delay1 = delays[(code >> 5) & 3]; 702184299Snwhitehorn kbd->kb_delay2 = rates[code & 0x1f]; 703184299Snwhitehorn return 0; 704184299Snwhitehorn} 705184299Snwhitehorn 706184299Snwhitehornstatic int akbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t data) 707184299Snwhitehorn{ 708184299Snwhitehorn struct adb_kbd_softc *sc; 709184299Snwhitehorn uint16_t r2; 710184299Snwhitehorn int error; 711184299Snwhitehorn 712184299Snwhitehorn sc = (struct adb_kbd_softc *)(kbd); 713184299Snwhitehorn error = 0; 714184299Snwhitehorn 715184299Snwhitehorn switch (cmd) { 716184299Snwhitehorn case KDGKBMODE: 717184299Snwhitehorn *(int *)data = sc->sc_mode; 718184299Snwhitehorn break; 719184299Snwhitehorn case KDSKBMODE: 720184299Snwhitehorn switch (*(int *)data) { 721184299Snwhitehorn case K_XLATE: 722184299Snwhitehorn if (sc->sc_mode != K_XLATE) { 723184299Snwhitehorn /* make lock key state and LED state match */ 724184299Snwhitehorn sc->sc_state &= ~LOCK_MASK; 725184299Snwhitehorn sc->sc_state |= KBD_LED_VAL(kbd); 726184299Snwhitehorn } 727184299Snwhitehorn /* FALLTHROUGH */ 728184299Snwhitehorn case K_RAW: 729184299Snwhitehorn case K_CODE: 730184299Snwhitehorn if (sc->sc_mode != *(int *)data) 731184299Snwhitehorn sc->sc_mode = *(int *)data; 732184299Snwhitehorn break; 733184299Snwhitehorn default: 734184299Snwhitehorn error = EINVAL; 735184299Snwhitehorn break; 736184299Snwhitehorn } 737184299Snwhitehorn 738184299Snwhitehorn break; 739184299Snwhitehorn 740184299Snwhitehorn case KDGETLED: 741184299Snwhitehorn *(int *)data = KBD_LED_VAL(kbd); 742184299Snwhitehorn break; 743184299Snwhitehorn 744184299Snwhitehorn case KDSKBSTATE: 745184299Snwhitehorn if (*(int *)data & ~LOCK_MASK) { 746184299Snwhitehorn error = EINVAL; 747184299Snwhitehorn break; 748184299Snwhitehorn } 749184299Snwhitehorn sc->sc_state &= ~LOCK_MASK; 750184299Snwhitehorn sc->sc_state |= *(int *)data; 751184299Snwhitehorn 752184299Snwhitehorn /* FALLTHROUGH */ 753184299Snwhitehorn 754184299Snwhitehorn case KDSETLED: 755184299Snwhitehorn KBD_LED_VAL(kbd) = *(int *)data; 756184299Snwhitehorn 757184299Snwhitehorn if (!sc->have_led_control) 758184299Snwhitehorn break; 759184299Snwhitehorn 760184299Snwhitehorn r2 = (~0 & 0x04) | 3; 761184299Snwhitehorn 762184299Snwhitehorn if (*(int *)data & NLKED) 763184299Snwhitehorn r2 &= ~1; 764184299Snwhitehorn if (*(int *)data & CLKED) 765184299Snwhitehorn r2 &= ~2; 766184299Snwhitehorn if (*(int *)data & SLKED) 767184299Snwhitehorn r2 &= ~4; 768184299Snwhitehorn 769184299Snwhitehorn adb_send_packet(sc->sc_dev,ADB_COMMAND_LISTEN,2, 770184299Snwhitehorn sizeof(uint16_t),(u_char *)&r2); 771184299Snwhitehorn 772184299Snwhitehorn break; 773184299Snwhitehorn 774184299Snwhitehorn case KDGKBSTATE: 775184299Snwhitehorn *(int *)data = sc->sc_state & LOCK_MASK; 776184299Snwhitehorn break; 777184299Snwhitehorn 778184299Snwhitehorn case KDSETREPEAT: 779184299Snwhitehorn if (!KBD_HAS_DEVICE(kbd)) 780184299Snwhitehorn return 0; 781184299Snwhitehorn if (((int *)data)[1] < 0) 782184299Snwhitehorn return EINVAL; 783184299Snwhitehorn if (((int *)data)[0] < 0) 784184299Snwhitehorn return EINVAL; 785184299Snwhitehorn else if (((int *)data)[0] == 0) /* fastest possible value */ 786184299Snwhitehorn kbd->kb_delay1 = 200; 787184299Snwhitehorn else 788184299Snwhitehorn kbd->kb_delay1 = ((int *)data)[0]; 789184299Snwhitehorn kbd->kb_delay2 = ((int *)data)[1]; 790184299Snwhitehorn 791184299Snwhitehorn break; 792184299Snwhitehorn 793184299Snwhitehorn case KDSETRAD: 794184299Snwhitehorn error = set_typematic(kbd, *(int *)data); 795184299Snwhitehorn break; 796184299Snwhitehorn 797184299Snwhitehorn case PIO_KEYMAP: 798224126Sed case OPIO_KEYMAP: 799184299Snwhitehorn case PIO_KEYMAPENT: 800184299Snwhitehorn case PIO_DEADKEYMAP: 801184299Snwhitehorn default: 802184299Snwhitehorn return (genkbd_commonioctl(kbd, cmd, data)); 803184299Snwhitehorn } 804184299Snwhitehorn 805184299Snwhitehorn return (error); 806184299Snwhitehorn} 807184299Snwhitehorn 808184299Snwhitehornstatic int akbd_lock(keyboard_t *kbd, int lock) 809184299Snwhitehorn{ 810184299Snwhitehorn return (0); 811184299Snwhitehorn} 812184299Snwhitehorn 813184299Snwhitehornstatic void akbd_clear_state(keyboard_t *kbd) 814184299Snwhitehorn{ 815186906Snwhitehorn struct adb_kbd_softc *sc; 816186906Snwhitehorn 817186906Snwhitehorn sc = (struct adb_kbd_softc *)(kbd); 818186906Snwhitehorn 819186906Snwhitehorn mtx_lock(&sc->sc_mutex); 820186906Snwhitehorn 821186906Snwhitehorn sc->buffers = 0; 822186906Snwhitehorn callout_stop(&sc->sc_repeater); 823186906Snwhitehorn 824186906Snwhitehorn#if defined(AKBD_EMULATE_ATKBD) 825186906Snwhitehorn sc->at_buffered_char[0] = 0; 826186906Snwhitehorn sc->at_buffered_char[1] = 0; 827186906Snwhitehorn#endif 828186906Snwhitehorn mtx_unlock(&sc->sc_mutex); 829184299Snwhitehorn} 830184299Snwhitehorn 831184299Snwhitehornstatic int akbd_get_state(keyboard_t *kbd, void *buf, size_t len) 832184299Snwhitehorn{ 833184299Snwhitehorn return (0); 834184299Snwhitehorn} 835184299Snwhitehorn 836184299Snwhitehornstatic int akbd_set_state(keyboard_t *kbd, void *buf, size_t len) 837184299Snwhitehorn{ 838184299Snwhitehorn return (0); 839184299Snwhitehorn} 840184299Snwhitehorn 841184299Snwhitehornstatic int akbd_poll(keyboard_t *kbd, int on) 842184299Snwhitehorn{ 843184299Snwhitehorn return (0); 844184299Snwhitehorn} 845184299Snwhitehorn 846184299Snwhitehornstatic int 847184299Snwhitehornakbd_modevent(module_t mod, int type, void *data) 848184299Snwhitehorn{ 849184299Snwhitehorn switch (type) { 850184299Snwhitehorn case MOD_LOAD: 851184299Snwhitehorn kbd_add_driver(&akbd_kbd_driver); 852184299Snwhitehorn break; 853184299Snwhitehorn 854184299Snwhitehorn case MOD_UNLOAD: 855184299Snwhitehorn kbd_delete_driver(&akbd_kbd_driver); 856184299Snwhitehorn break; 857184299Snwhitehorn 858184299Snwhitehorn default: 859184299Snwhitehorn return (EOPNOTSUPP); 860184299Snwhitehorn } 861184299Snwhitehorn 862184299Snwhitehorn return (0); 863184299Snwhitehorn} 864184299Snwhitehorn 865230751Sjhibbitsstatic int 866230751Sjhibbitsadb_fn_keys(SYSCTL_HANDLER_ARGS) 867230751Sjhibbits{ 868230751Sjhibbits struct adb_kbd_softc *sc = arg1; 869230751Sjhibbits int error; 870230751Sjhibbits uint16_t is_fn_enabled; 871230751Sjhibbits unsigned int is_fn_enabled_sysctl; 872230751Sjhibbits 873230751Sjhibbits adb_read_register(sc->sc_dev, 1, &is_fn_enabled); 874230751Sjhibbits is_fn_enabled &= 1; 875230751Sjhibbits is_fn_enabled_sysctl = is_fn_enabled; 876230751Sjhibbits error = sysctl_handle_int(oidp, &is_fn_enabled_sysctl, 0, req); 877230751Sjhibbits 878230751Sjhibbits if (error || !req->newptr) 879230751Sjhibbits return (error); 880230751Sjhibbits 881230751Sjhibbits is_fn_enabled = is_fn_enabled_sysctl; 882230751Sjhibbits if (is_fn_enabled != 1 && is_fn_enabled != 0) 883230751Sjhibbits return (EINVAL); 884230751Sjhibbits 885230751Sjhibbits adb_write_register(sc->sc_dev, 1, 2, &is_fn_enabled); 886230751Sjhibbits return (0); 887230751Sjhibbits} 888230751Sjhibbits 889184299SnwhitehornDEV_MODULE(akbd, akbd_modevent, NULL); 890184299Snwhitehorn 891