The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/adb/adb_kbd.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 8c06713452c839024e9daa91ffc93e82


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.