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/gpio/gpiokeys.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  * Copyright (c) 2015-2016 Oleksandr Tymoshenko <gonzo@freebsd.org>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD$");
   29 
   30 #include "opt_platform.h"
   31 #include "opt_kbd.h"
   32 #include "opt_evdev.h"
   33 
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/bus.h>
   37 #include <sys/gpio.h>
   38 #include <sys/kernel.h>
   39 #include <sys/lock.h>
   40 #include <sys/malloc.h>
   41 #include <sys/module.h>
   42 #include <sys/mutex.h>
   43 #include <sys/proc.h>
   44 #include <sys/kdb.h>
   45 
   46 #include <sys/ioccom.h>
   47 #include <sys/filio.h>
   48 #include <sys/kbio.h>
   49 
   50 #include <dev/kbd/kbdreg.h>
   51 #include <dev/kbd/kbdtables.h>
   52 
   53 #include <dev/fdt/fdt_common.h>
   54 #include <dev/ofw/ofw_bus.h>
   55 #include <dev/ofw/ofw_bus_subr.h>
   56 
   57 #include <dev/gpio/gpiobusvar.h>
   58 #include <dev/gpio/gpiokeys.h>
   59 
   60 #ifdef EVDEV_SUPPORT
   61 #include <dev/evdev/evdev.h>
   62 #include <dev/evdev/input.h>
   63 #endif
   64 
   65 #define KBD_DRIVER_NAME "gpiokeys"
   66 
   67 #define GPIOKEYS_LOCK(_sc)              mtx_lock(&(_sc)->sc_mtx)
   68 #define GPIOKEYS_UNLOCK(_sc)            mtx_unlock(&(_sc)->sc_mtx)
   69 #define GPIOKEYS_LOCK_INIT(_sc) \
   70         mtx_init(&_sc->sc_mtx, device_get_nameunit((_sc)->sc_dev), \
   71             "gpiokeys", MTX_DEF)
   72 #define GPIOKEYS_LOCK_DESTROY(_sc)      mtx_destroy(&(_sc)->sc_mtx);
   73 #define GPIOKEYS_ASSERT_LOCKED(_sc)     mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
   74 
   75 #define GPIOKEY_LOCK(_key)              mtx_lock(&(_key)->mtx)
   76 #define GPIOKEY_UNLOCK(_key)            mtx_unlock(&(_key)->mtx)
   77 #define GPIOKEY_LOCK_INIT(_key) \
   78         mtx_init(&(_key)->mtx, "gpiokey", "gpiokey", MTX_DEF)
   79 #define GPIOKEY_LOCK_DESTROY(_key)      mtx_destroy(&(_key)->mtx);
   80 
   81 #define KEY_PRESS         0
   82 #define KEY_RELEASE       0x80
   83 
   84 #define SCAN_PRESS        0
   85 #define SCAN_RELEASE      0x80
   86 #define SCAN_CHAR(c)    ((c) & 0x7f)
   87 
   88 #define GPIOKEYS_GLOBAL_NMOD                     8      /* units */
   89 #define GPIOKEYS_GLOBAL_NKEYCODE                 6      /* units */
   90 #define GPIOKEYS_GLOBAL_IN_BUF_SIZE  (2*(GPIOKEYS_GLOBAL_NMOD + (2*GPIOKEYS_GLOBAL_NKEYCODE)))  /* bytes */
   91 #define GPIOKEYS_GLOBAL_IN_BUF_FULL  (GPIOKEYS_GLOBAL_IN_BUF_SIZE / 2)  /* bytes */
   92 #define GPIOKEYS_GLOBAL_NFKEY        (sizeof(fkey_tab)/sizeof(fkey_tab[0]))     /* units */
   93 #define GPIOKEYS_GLOBAL_BUFFER_SIZE           64        /* bytes */
   94 
   95 #define AUTOREPEAT_DELAY        250
   96 #define AUTOREPEAT_REPEAT       34
   97 
   98 struct gpiokeys_softc;
   99 
  100 struct gpiokey
  101 {
  102         struct gpiokeys_softc   *parent_sc;
  103         gpio_pin_t              pin;
  104         int                     irq_rid;
  105         struct resource         *irq_res;
  106         void                    *intr_hl;
  107         struct mtx              mtx;
  108 #ifdef EVDEV_SUPPORT
  109         uint32_t                evcode;
  110 #endif
  111         uint32_t                keycode;
  112         int                     autorepeat;
  113         struct callout          debounce_callout;
  114         struct callout          repeat_callout;
  115         int                     repeat_delay;
  116         int                     repeat;
  117         int                     debounce_interval;
  118 };
  119 
  120 struct gpiokeys_softc
  121 {
  122         device_t        sc_dev;
  123         struct mtx      sc_mtx;
  124         struct gpiokey  *sc_keys;
  125         int             sc_total_keys;
  126 
  127 #ifdef EVDEV_SUPPORT
  128         struct evdev_dev        *sc_evdev;
  129 #endif
  130         keyboard_t      sc_kbd;
  131         keymap_t        sc_keymap;
  132         accentmap_t     sc_accmap;
  133         fkeytab_t       sc_fkeymap[GPIOKEYS_GLOBAL_NFKEY];
  134 
  135         uint32_t        sc_input[GPIOKEYS_GLOBAL_IN_BUF_SIZE];  /* input buffer */
  136         uint32_t        sc_time_ms;
  137 #define GPIOKEYS_GLOBAL_FLAG_POLLING    0x00000002
  138 
  139         uint32_t        sc_flags;               /* flags */
  140 
  141         int             sc_mode;                /* input mode (K_XLATE,K_RAW,K_CODE) */
  142         int             sc_state;               /* shift/lock key state */
  143         int             sc_accents;             /* accent key index (> 0) */
  144         int             sc_kbd_size;
  145 
  146         uint16_t        sc_inputs;
  147         uint16_t        sc_inputhead;
  148         uint16_t        sc_inputtail;
  149 
  150         uint8_t         sc_kbd_id;
  151 };
  152 
  153 /* gpio-keys device */
  154 static int gpiokeys_probe(device_t);
  155 static int gpiokeys_attach(device_t);
  156 static int gpiokeys_detach(device_t);
  157 
  158 /* kbd methods prototypes */
  159 static int      gpiokeys_set_typematic(keyboard_t *, int);
  160 static uint32_t gpiokeys_read_char(keyboard_t *, int);
  161 static void     gpiokeys_clear_state(keyboard_t *);
  162 static int      gpiokeys_ioctl(keyboard_t *, u_long, caddr_t);
  163 static int      gpiokeys_enable(keyboard_t *);
  164 static int      gpiokeys_disable(keyboard_t *);
  165 static void     gpiokeys_event_keyinput(struct gpiokeys_softc *);
  166 
  167 static void
  168 gpiokeys_put_key(struct gpiokeys_softc *sc, uint32_t key)
  169 {
  170 
  171         GPIOKEYS_ASSERT_LOCKED(sc);
  172 
  173         if (sc->sc_inputs < GPIOKEYS_GLOBAL_IN_BUF_SIZE) {
  174                 sc->sc_input[sc->sc_inputtail] = key;
  175                 ++(sc->sc_inputs);
  176                 ++(sc->sc_inputtail);
  177                 if (sc->sc_inputtail >= GPIOKEYS_GLOBAL_IN_BUF_SIZE) {
  178                         sc->sc_inputtail = 0;
  179                 }
  180         } else {
  181                 device_printf(sc->sc_dev, "input buffer is full\n");
  182         }
  183 }
  184 
  185 static void
  186 gpiokeys_key_event(struct gpiokeys_softc *sc, struct gpiokey *key, int pressed)
  187 {
  188         uint32_t code;
  189 
  190         GPIOKEYS_LOCK(sc);
  191 #ifdef EVDEV_SUPPORT
  192         if (key->evcode != GPIOKEY_NONE &&
  193             (evdev_rcpt_mask & EVDEV_RCPT_HW_KBD) != 0) {
  194                 evdev_push_key(sc->sc_evdev, key->evcode, pressed);
  195                 evdev_sync(sc->sc_evdev);
  196         }
  197         if (evdev_is_grabbed(sc->sc_evdev)) {
  198                 GPIOKEYS_UNLOCK(sc);
  199                 return;
  200         }
  201 #endif
  202         if (key->keycode != GPIOKEY_NONE) {
  203                 code = key->keycode & SCAN_KEYCODE_MASK;
  204                 if (!pressed)
  205                         code |= KEY_RELEASE;
  206 
  207                 if (key->keycode & SCAN_PREFIX_E0)
  208                         gpiokeys_put_key(sc, 0xe0);
  209                 else if (key->keycode & SCAN_PREFIX_E1)
  210                         gpiokeys_put_key(sc, 0xe1);
  211 
  212                 gpiokeys_put_key(sc, code);
  213         }
  214         GPIOKEYS_UNLOCK(sc);
  215 
  216         if (key->keycode != GPIOKEY_NONE)
  217                 gpiokeys_event_keyinput(sc);
  218 }
  219 
  220 static void
  221 gpiokey_autorepeat(void *arg)
  222 {
  223         struct gpiokey *key;
  224 
  225         key = arg;
  226 
  227         gpiokeys_key_event(key->parent_sc, key, 1);
  228 
  229         callout_reset(&key->repeat_callout, key->repeat,
  230                     gpiokey_autorepeat, key);
  231 }
  232 
  233 static void
  234 gpiokey_debounced_intr(void *arg)
  235 {
  236         struct gpiokey *key;
  237         bool active;
  238 
  239         key = arg;
  240 
  241         gpio_pin_is_active(key->pin, &active);
  242         if (active) {
  243                 gpiokeys_key_event(key->parent_sc, key, 1);
  244                 if (key->autorepeat) {
  245                         callout_reset(&key->repeat_callout, key->repeat_delay,
  246                             gpiokey_autorepeat, key);
  247                 }
  248         }
  249         else {
  250                 if (key->autorepeat &&
  251                     callout_pending(&key->repeat_callout))
  252                         callout_stop(&key->repeat_callout);
  253                 gpiokeys_key_event(key->parent_sc, key, 0);
  254         }
  255 }
  256 
  257 static void
  258 gpiokey_intr(void *arg)
  259 {
  260         struct gpiokey *key;
  261         int debounce_ticks;
  262 
  263         key = arg;
  264 
  265         GPIOKEY_LOCK(key);
  266         debounce_ticks = (hz * key->debounce_interval) / 1000;
  267         if (debounce_ticks == 0)
  268                 debounce_ticks = 1;
  269         if (!callout_pending(&key->debounce_callout))
  270                 callout_reset(&key->debounce_callout, debounce_ticks,
  271                     gpiokey_debounced_intr, key);
  272         GPIOKEY_UNLOCK(key);
  273 }
  274 
  275 static void
  276 gpiokeys_attach_key(struct gpiokeys_softc *sc, phandle_t node,
  277     struct gpiokey *key)
  278 {
  279         pcell_t prop;
  280         char *name;
  281         uint32_t code;
  282         int err;
  283         const char *key_name;
  284 
  285         GPIOKEY_LOCK_INIT(key);
  286         key->parent_sc = sc;
  287         callout_init_mtx(&key->debounce_callout, &key->mtx, 0);
  288         callout_init_mtx(&key->repeat_callout, &key->mtx, 0);
  289 
  290         name = NULL;
  291         if (OF_getprop_alloc(node, "label", (void **)&name) == -1)
  292                 OF_getprop_alloc(node, "name", (void **)&name);
  293 
  294         if (name != NULL)
  295                 key_name = name;
  296         else
  297                 key_name = "unknown";
  298 
  299         key->autorepeat = OF_hasprop(node, "autorepeat");
  300 
  301         key->repeat_delay = (hz * AUTOREPEAT_DELAY) / 1000;
  302         if (key->repeat_delay == 0)
  303                 key->repeat_delay = 1;
  304 
  305         key->repeat = (hz * AUTOREPEAT_REPEAT) / 1000;
  306         if (key->repeat == 0)
  307                 key->repeat = 1;
  308 
  309         if ((OF_getprop(node, "debounce-interval", &prop, sizeof(prop))) > 0)
  310                 key->debounce_interval = fdt32_to_cpu(prop);
  311         else
  312                 key->debounce_interval = 5;
  313 
  314         if ((OF_getprop(node, "freebsd,code", &prop, sizeof(prop))) > 0)
  315                 key->keycode = fdt32_to_cpu(prop);
  316         else if ((OF_getprop(node, "linux,code", &prop, sizeof(prop))) > 0) {
  317                 code = fdt32_to_cpu(prop);
  318                 key->keycode = gpiokey_map_linux_code(code);
  319                 if (key->keycode == GPIOKEY_NONE)
  320                         device_printf(sc->sc_dev, "<%s> failed to map linux,code value 0x%x\n",
  321                             key_name, code);
  322 #ifdef EVDEV_SUPPORT
  323                 key->evcode = code;
  324                 evdev_support_key(sc->sc_evdev, code);
  325 #endif
  326         }
  327         else
  328                 device_printf(sc->sc_dev, "<%s> no linux,code or freebsd,code property\n",
  329                     key_name);
  330 
  331         err = gpio_pin_get_by_ofw_idx(sc->sc_dev, node, 0, &key->pin);
  332         if (err) {
  333                 device_printf(sc->sc_dev, "<%s> failed to map pin\n", key_name);
  334                 if (name)
  335                         OF_prop_free(name);
  336                 return;
  337         }
  338 
  339         key->irq_res = gpio_alloc_intr_resource(sc->sc_dev, &key->irq_rid,
  340             RF_ACTIVE, key->pin, GPIO_INTR_EDGE_BOTH);
  341         if (!key->irq_res) {
  342                 device_printf(sc->sc_dev, "<%s> cannot allocate interrupt\n", key_name);
  343                 gpio_pin_release(key->pin);
  344                 key->pin = NULL;
  345                 if (name)
  346                         OF_prop_free(name);
  347                 return;
  348         }
  349 
  350         if (bus_setup_intr(sc->sc_dev, key->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
  351                         NULL, gpiokey_intr, key,
  352                         &key->intr_hl) != 0) {
  353                 device_printf(sc->sc_dev, "<%s> unable to setup the irq handler\n", key_name);
  354                 bus_release_resource(sc->sc_dev, SYS_RES_IRQ, key->irq_rid,
  355                     key->irq_res);
  356                 gpio_pin_release(key->pin);
  357                 key->pin = NULL;
  358                 key->irq_res = NULL;
  359                 if (name)
  360                         OF_prop_free(name);
  361                 return;
  362         }
  363 
  364         if (bootverbose)
  365                 device_printf(sc->sc_dev, "<%s> code=%08x, autorepeat=%d, "\
  366                     "repeat=%d, repeat_delay=%d\n", key_name, key->keycode,
  367                     key->autorepeat, key->repeat, key->repeat_delay);
  368 
  369         if (name)
  370                 OF_prop_free(name);
  371 }
  372 
  373 static void
  374 gpiokeys_detach_key(struct gpiokeys_softc *sc, struct gpiokey *key)
  375 {
  376 
  377         GPIOKEY_LOCK(key);
  378         if (key->intr_hl)
  379                 bus_teardown_intr(sc->sc_dev, key->irq_res, key->intr_hl);
  380         if (key->irq_res)
  381                 bus_release_resource(sc->sc_dev, SYS_RES_IRQ,
  382                     key->irq_rid, key->irq_res);
  383         if (callout_pending(&key->repeat_callout))
  384                 callout_drain(&key->repeat_callout);
  385         if (callout_pending(&key->debounce_callout))
  386                 callout_drain(&key->debounce_callout);
  387         if (key->pin)
  388                 gpio_pin_release(key->pin);
  389         GPIOKEY_UNLOCK(key);
  390         GPIOKEY_LOCK_DESTROY(key);
  391 }
  392 
  393 static int
  394 gpiokeys_probe(device_t dev)
  395 {
  396         if (!ofw_bus_is_compatible(dev, "gpio-keys"))
  397                 return (ENXIO);
  398 
  399         device_set_desc(dev, "GPIO keyboard");
  400 
  401         return (0);
  402 }
  403 
  404 static int
  405 gpiokeys_attach(device_t dev)
  406 {
  407         struct gpiokeys_softc *sc;
  408         keyboard_t *kbd;
  409 #ifdef EVDEV_SUPPORT
  410         char *name;
  411 #endif
  412         phandle_t keys, child;
  413         int total_keys;
  414         int unit;
  415 
  416         if ((keys = ofw_bus_get_node(dev)) == -1)
  417                 return (ENXIO);
  418 
  419         sc = device_get_softc(dev);
  420         sc->sc_dev = dev;
  421         kbd = &sc->sc_kbd;
  422 
  423         GPIOKEYS_LOCK_INIT(sc);
  424         unit = device_get_unit(dev);
  425         kbd_init_struct(kbd, KBD_DRIVER_NAME, KB_OTHER, unit, 0, 0, 0);
  426 
  427         kbd->kb_data = (void *)sc;
  428         sc->sc_mode = K_XLATE;
  429 
  430         sc->sc_keymap = key_map;
  431         sc->sc_accmap = accent_map;
  432 
  433         kbd_set_maps(kbd, &sc->sc_keymap, &sc->sc_accmap,
  434             sc->sc_fkeymap, GPIOKEYS_GLOBAL_NFKEY);
  435 
  436         KBD_FOUND_DEVICE(kbd);
  437 
  438         gpiokeys_clear_state(kbd);
  439 
  440         KBD_PROBE_DONE(kbd);
  441 
  442         KBD_INIT_DONE(kbd);
  443 
  444         if (kbd_register(kbd) < 0) {
  445                 goto detach;
  446         }
  447 
  448         KBD_CONFIG_DONE(kbd);
  449 
  450         gpiokeys_enable(kbd);
  451 
  452 #ifdef KBD_INSTALL_CDEV
  453         if (kbd_attach(kbd)) {
  454                 goto detach;
  455         }
  456 #endif
  457 
  458         if (bootverbose) {
  459                 kbdd_diag(kbd, 1);
  460         }
  461 
  462 #ifdef EVDEV_SUPPORT
  463         sc->sc_evdev = evdev_alloc();
  464         evdev_set_name(sc->sc_evdev, device_get_desc(dev));
  465 
  466         OF_getprop_alloc(keys, "name", (void **)&name);
  467         evdev_set_phys(sc->sc_evdev, name != NULL ? name : "unknown");
  468         OF_prop_free(name);
  469 
  470         evdev_set_id(sc->sc_evdev, BUS_VIRTUAL, 0, 0, 0);
  471         evdev_support_event(sc->sc_evdev, EV_SYN);
  472         evdev_support_event(sc->sc_evdev, EV_KEY);
  473 #endif
  474 
  475         total_keys = 0;
  476 
  477         /* Traverse the 'gpio-keys' node and count keys */
  478         for (child = OF_child(keys); child != 0; child = OF_peer(child)) {
  479                 if (!OF_hasprop(child, "gpios"))
  480                         continue;
  481                 total_keys++;
  482         }
  483 
  484         if (total_keys) {
  485                 sc->sc_keys =  malloc(sizeof(struct gpiokey) * total_keys,
  486                     M_DEVBUF, M_WAITOK | M_ZERO);
  487 
  488                 sc->sc_total_keys = 0;
  489                 /* Traverse the 'gpio-keys' node and count keys */
  490                 for (child = OF_child(keys); child != 0; child = OF_peer(child)) {
  491                         if (!OF_hasprop(child, "gpios"))
  492                                 continue;
  493                         gpiokeys_attach_key(sc, child ,&sc->sc_keys[sc->sc_total_keys]);
  494                         sc->sc_total_keys++;
  495                 }
  496         }
  497 
  498 #ifdef EVDEV_SUPPORT
  499         if (evdev_register_mtx(sc->sc_evdev, &sc->sc_mtx) != 0) {
  500                 device_printf(dev, "failed to register evdev device\n");
  501                 goto detach;
  502         }
  503 #endif
  504 
  505         return (0);
  506 
  507 detach:
  508         gpiokeys_detach(dev);
  509         return (ENXIO);
  510 }
  511 
  512 static int
  513 gpiokeys_detach(device_t dev)
  514 {
  515         struct gpiokeys_softc *sc;
  516         keyboard_t *kbd;
  517         int i;
  518 
  519         sc = device_get_softc(dev);
  520 
  521         for (i = 0; i < sc->sc_total_keys; i++)
  522                 gpiokeys_detach_key(sc, &sc->sc_keys[i]);
  523 
  524         kbd = kbd_get_keyboard(kbd_find_keyboard(KBD_DRIVER_NAME,
  525             device_get_unit(dev)));
  526 
  527 #ifdef KBD_INSTALL_CDEV
  528         kbd_detach(kbd);
  529 #endif
  530         kbd_unregister(kbd);
  531 
  532 #ifdef EVDEV_SUPPORT
  533         evdev_free(sc->sc_evdev);
  534 #endif
  535 
  536         GPIOKEYS_LOCK_DESTROY(sc);
  537         if (sc->sc_keys)
  538                 free(sc->sc_keys, M_DEVBUF);
  539 
  540         return (0);
  541 }
  542 
  543 /* early keyboard probe, not supported */
  544 static int
  545 gpiokeys_configure(int flags)
  546 {
  547         return (0);
  548 }
  549 
  550 /* detect a keyboard, not used */
  551 static int
  552 gpiokeys__probe(int unit, void *arg, int flags)
  553 {
  554         return (ENXIO);
  555 }
  556 
  557 /* reset and initialize the device, not used */
  558 static int
  559 gpiokeys_init(int unit, keyboard_t **kbdp, void *arg, int flags)
  560 {
  561         return (ENXIO);
  562 }
  563 
  564 /* test the interface to the device, not used */
  565 static int
  566 gpiokeys_test_if(keyboard_t *kbd)
  567 {
  568         return (0);
  569 }
  570 
  571 /* finish using this keyboard, not used */
  572 static int
  573 gpiokeys_term(keyboard_t *kbd)
  574 {
  575         return (ENXIO);
  576 }
  577 
  578 /* keyboard interrupt routine, not used */
  579 static int
  580 gpiokeys_intr(keyboard_t *kbd, void *arg)
  581 {
  582         return (0);
  583 }
  584 
  585 /* lock the access to the keyboard, not used */
  586 static int
  587 gpiokeys_lock(keyboard_t *kbd, int lock)
  588 {
  589         return (1);
  590 }
  591 
  592 /*
  593  * Enable the access to the device; until this function is called,
  594  * the client cannot read from the keyboard.
  595  */
  596 static int
  597 gpiokeys_enable(keyboard_t *kbd)
  598 {
  599         struct gpiokeys_softc *sc;
  600 
  601         sc = kbd->kb_data;
  602         GPIOKEYS_LOCK(sc);
  603         KBD_ACTIVATE(kbd);
  604         GPIOKEYS_UNLOCK(sc);
  605 
  606         return (0);
  607 }
  608 
  609 /* disallow the access to the device */
  610 static int
  611 gpiokeys_disable(keyboard_t *kbd)
  612 {
  613         struct gpiokeys_softc *sc;
  614 
  615         sc = kbd->kb_data;
  616         GPIOKEYS_LOCK(sc);
  617         KBD_DEACTIVATE(kbd);
  618         GPIOKEYS_UNLOCK(sc);
  619 
  620         return (0);
  621 }
  622 
  623 static void
  624 gpiokeys_do_poll(struct gpiokeys_softc *sc, uint8_t wait)
  625 {
  626 
  627         KASSERT((sc->sc_flags & GPIOKEYS_GLOBAL_FLAG_POLLING) != 0,
  628             ("gpiokeys_do_poll called when not polling\n"));
  629 
  630         GPIOKEYS_ASSERT_LOCKED(sc);
  631 
  632         if (!kdb_active && !SCHEDULER_STOPPED()) {
  633                 while (sc->sc_inputs == 0) {
  634                         kern_yield(PRI_UNCHANGED);
  635                         if (!wait)
  636                                 break;
  637                 }
  638                 return;
  639         }
  640 
  641         while ((sc->sc_inputs == 0) && wait) {
  642                 printf("POLL!\n");
  643         }
  644 }
  645 
  646 /* check if data is waiting */
  647 static int
  648 gpiokeys_check(keyboard_t *kbd)
  649 {
  650         struct gpiokeys_softc *sc = kbd->kb_data;
  651 
  652         GPIOKEYS_ASSERT_LOCKED(sc);
  653 
  654         if (!KBD_IS_ACTIVE(kbd))
  655                 return (0);
  656 
  657         if (sc->sc_flags & GPIOKEYS_GLOBAL_FLAG_POLLING)
  658                 gpiokeys_do_poll(sc, 0);
  659 
  660         if (sc->sc_inputs > 0) {
  661                 return (1);
  662         }
  663         return (0);
  664 }
  665 
  666 /* check if char is waiting */
  667 static int
  668 gpiokeys_check_char_locked(keyboard_t *kbd)
  669 {
  670         if (!KBD_IS_ACTIVE(kbd))
  671                 return (0);
  672 
  673         return (gpiokeys_check(kbd));
  674 }
  675 
  676 static int
  677 gpiokeys_check_char(keyboard_t *kbd)
  678 {
  679         int result;
  680         struct gpiokeys_softc *sc = kbd->kb_data;
  681 
  682         GPIOKEYS_LOCK(sc);
  683         result = gpiokeys_check_char_locked(kbd);
  684         GPIOKEYS_UNLOCK(sc);
  685 
  686         return (result);
  687 }
  688 
  689 static int32_t
  690 gpiokeys_get_key(struct gpiokeys_softc *sc, uint8_t wait)
  691 {
  692         int32_t c;
  693 
  694         KASSERT((!kdb_active && !SCHEDULER_STOPPED())
  695             || (sc->sc_flags & GPIOKEYS_GLOBAL_FLAG_POLLING) != 0,
  696             ("not polling in kdb or panic\n"));
  697 
  698         GPIOKEYS_ASSERT_LOCKED(sc);
  699 
  700         if (sc->sc_flags & GPIOKEYS_GLOBAL_FLAG_POLLING)
  701                 gpiokeys_do_poll(sc, wait);
  702 
  703         if (sc->sc_inputs == 0) {
  704                 c = -1;
  705         } else {
  706                 c = sc->sc_input[sc->sc_inputhead];
  707                 --(sc->sc_inputs);
  708                 ++(sc->sc_inputhead);
  709                 if (sc->sc_inputhead >= GPIOKEYS_GLOBAL_IN_BUF_SIZE) {
  710                         sc->sc_inputhead = 0;
  711                 }
  712         }
  713 
  714         return (c);
  715 }
  716 
  717 /* read one byte from the keyboard if it's allowed */
  718 static int
  719 gpiokeys_read(keyboard_t *kbd, int wait)
  720 {
  721         struct gpiokeys_softc *sc = kbd->kb_data;
  722         int32_t keycode;
  723 
  724         if (!KBD_IS_ACTIVE(kbd))
  725                 return (-1);
  726 
  727         /* XXX */
  728         keycode = gpiokeys_get_key(sc, (wait == FALSE) ? 0 : 1);
  729         if (!KBD_IS_ACTIVE(kbd) || (keycode == -1))
  730                 return (-1);
  731 
  732         ++(kbd->kb_count);
  733 
  734         return (keycode);
  735 }
  736 
  737 /* read char from the keyboard */
  738 static uint32_t
  739 gpiokeys_read_char_locked(keyboard_t *kbd, int wait)
  740 {
  741         struct gpiokeys_softc *sc = kbd->kb_data;
  742         uint32_t action;
  743         uint32_t keycode;
  744 
  745         if (!KBD_IS_ACTIVE(kbd))
  746                 return (NOKEY);
  747 
  748 next_code:
  749 
  750         /* see if there is something in the keyboard port */
  751         /* XXX */
  752         keycode = gpiokeys_get_key(sc, (wait == FALSE) ? 0 : 1);
  753         ++kbd->kb_count;
  754 
  755         /* return the byte as is for the K_RAW mode */
  756         if (sc->sc_mode == K_RAW) {
  757                 return (keycode);
  758         }
  759 
  760         /* return the key code in the K_CODE mode */
  761         /* XXX: keycode |= SCAN_RELEASE; */
  762 
  763         if (sc->sc_mode == K_CODE) {
  764                 return (keycode);
  765         }
  766 
  767         /* keycode to key action */
  768         action = genkbd_keyaction(kbd, SCAN_CHAR(keycode),
  769             (keycode & SCAN_RELEASE),
  770             &sc->sc_state, &sc->sc_accents);
  771         if (action == NOKEY) {
  772                 goto next_code;
  773         }
  774 
  775         return (action);
  776 }
  777 
  778 /* Currently wait is always false. */
  779 static uint32_t
  780 gpiokeys_read_char(keyboard_t *kbd, int wait)
  781 {
  782         uint32_t keycode;
  783         struct gpiokeys_softc *sc = kbd->kb_data;
  784 
  785         GPIOKEYS_LOCK(sc);
  786         keycode = gpiokeys_read_char_locked(kbd, wait);
  787         GPIOKEYS_UNLOCK(sc);
  788 
  789         return (keycode);
  790 }
  791 
  792 /* some useful control functions */
  793 static int
  794 gpiokeys_ioctl_locked(keyboard_t *kbd, u_long cmd, caddr_t arg)
  795 {
  796         struct gpiokeys_softc *sc = kbd->kb_data;
  797 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
  798     defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
  799         int ival;
  800 
  801 #endif
  802 
  803         switch (cmd) {
  804         case KDGKBMODE:         /* get keyboard mode */
  805                 *(int *)arg = sc->sc_mode;
  806                 break;
  807 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
  808     defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
  809         case _IO('K', 7):
  810                 ival = IOCPARM_IVAL(arg);
  811                 arg = (caddr_t)&ival;
  812                 /* FALLTHROUGH */
  813 #endif
  814         case KDSKBMODE:         /* set keyboard mode */
  815                 switch (*(int *)arg) {
  816                 case K_XLATE:
  817                         if (sc->sc_mode != K_XLATE) {
  818                                 /* make lock key state and LED state match */
  819                                 sc->sc_state &= ~LOCK_MASK;
  820                                 sc->sc_state |= KBD_LED_VAL(kbd);
  821                         }
  822                         /* FALLTHROUGH */
  823                 case K_RAW:
  824                 case K_CODE:
  825                         if (sc->sc_mode != *(int *)arg) {
  826                                 if ((sc->sc_flags & GPIOKEYS_GLOBAL_FLAG_POLLING) == 0)
  827                                         gpiokeys_clear_state(kbd);
  828                                 sc->sc_mode = *(int *)arg;
  829                         }
  830                         break;
  831                 default:
  832                         return (EINVAL);
  833                 }
  834                 break;
  835 
  836         case KDGETLED:                  /* get keyboard LED */
  837                 *(int *)arg = KBD_LED_VAL(kbd);
  838                 break;
  839 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
  840     defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
  841         case _IO('K', 66):
  842                 ival = IOCPARM_IVAL(arg);
  843                 arg = (caddr_t)&ival;
  844                 /* FALLTHROUGH */
  845 #endif
  846         case KDSETLED:                  /* set keyboard LED */
  847                 KBD_LED_VAL(kbd) = *(int *)arg;
  848                 break;
  849         case KDGKBSTATE:                /* get lock key state */
  850                 *(int *)arg = sc->sc_state & LOCK_MASK;
  851                 break;
  852 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
  853     defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
  854         case _IO('K', 20):
  855                 ival = IOCPARM_IVAL(arg);
  856                 arg = (caddr_t)&ival;
  857                 /* FALLTHROUGH */
  858 #endif
  859         case KDSKBSTATE:                /* set lock key state */
  860                 if (*(int *)arg & ~LOCK_MASK) {
  861                         return (EINVAL);
  862                 }
  863                 sc->sc_state &= ~LOCK_MASK;
  864                 sc->sc_state |= *(int *)arg;
  865                 return (0);
  866 
  867         case KDSETREPEAT:               /* set keyboard repeat rate (new
  868                                          * interface) */
  869                 if (!KBD_HAS_DEVICE(kbd)) {
  870                         return (0);
  871                 }
  872                 if (((int *)arg)[1] < 0) {
  873                         return (EINVAL);
  874                 }
  875                 if (((int *)arg)[0] < 0) {
  876                         return (EINVAL);
  877                 }
  878                 if (((int *)arg)[0] < 200)      /* fastest possible value */
  879                         kbd->kb_delay1 = 200;
  880                 else
  881                         kbd->kb_delay1 = ((int *)arg)[0];
  882                 kbd->kb_delay2 = ((int *)arg)[1];
  883                 return (0);
  884 
  885 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
  886     defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
  887         case _IO('K', 67):
  888                 ival = IOCPARM_IVAL(arg);
  889                 arg = (caddr_t)&ival;
  890                 /* FALLTHROUGH */
  891 #endif
  892         case KDSETRAD:                  /* set keyboard repeat rate (old
  893                                          * interface) */
  894                 return (gpiokeys_set_typematic(kbd, *(int *)arg));
  895 
  896         case PIO_KEYMAP:                /* set keyboard translation table */
  897         case OPIO_KEYMAP:               /* set keyboard translation table
  898                                          * (compat) */
  899         case PIO_KEYMAPENT:             /* set keyboard translation table
  900                                          * entry */
  901         case PIO_DEADKEYMAP:            /* set accent key translation table */
  902                 sc->sc_accents = 0;
  903                 /* FALLTHROUGH */
  904         default:
  905                 return (genkbd_commonioctl(kbd, cmd, arg));
  906         }
  907 
  908         return (0);
  909 }
  910 
  911 static int
  912 gpiokeys_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
  913 {
  914         int result;
  915         struct gpiokeys_softc *sc;
  916 
  917         sc = kbd->kb_data;
  918         /*
  919          * XXX Check if someone is calling us from a critical section:
  920          */
  921         if (curthread->td_critnest != 0)
  922                 return (EDEADLK);
  923 
  924         GPIOKEYS_LOCK(sc);
  925         result = gpiokeys_ioctl_locked(kbd, cmd, arg);
  926         GPIOKEYS_UNLOCK(sc);
  927 
  928         return (result);
  929 }
  930 
  931 /* clear the internal state of the keyboard */
  932 static void
  933 gpiokeys_clear_state(keyboard_t *kbd)
  934 {
  935         struct gpiokeys_softc *sc = kbd->kb_data;
  936 
  937         sc->sc_flags &= ~(GPIOKEYS_GLOBAL_FLAG_POLLING);
  938         sc->sc_state &= LOCK_MASK;      /* preserve locking key state */
  939         sc->sc_accents = 0;
  940 }
  941 
  942 /* get the internal state, not used */
  943 static int
  944 gpiokeys_get_state(keyboard_t *kbd, void *buf, size_t len)
  945 {
  946         return (len == 0) ? 1 : -1;
  947 }
  948 
  949 /* set the internal state, not used */
  950 static int
  951 gpiokeys_set_state(keyboard_t *kbd, void *buf, size_t len)
  952 {
  953         return (EINVAL);
  954 }
  955 
  956 static int
  957 gpiokeys_poll(keyboard_t *kbd, int on)
  958 {
  959         struct gpiokeys_softc *sc = kbd->kb_data;
  960 
  961         GPIOKEYS_LOCK(sc);
  962         if (on)
  963                 sc->sc_flags |= GPIOKEYS_GLOBAL_FLAG_POLLING;
  964         else
  965                 sc->sc_flags &= ~GPIOKEYS_GLOBAL_FLAG_POLLING;
  966         GPIOKEYS_UNLOCK(sc);
  967 
  968         return (0);
  969 }
  970 
  971 static int
  972 gpiokeys_set_typematic(keyboard_t *kbd, int code)
  973 {
  974         static const int delays[] = {250, 500, 750, 1000};
  975         static const int rates[] = {34, 38, 42, 46, 50, 55, 59, 63,
  976                 68, 76, 84, 92, 100, 110, 118, 126,
  977                 136, 152, 168, 184, 200, 220, 236, 252,
  978         272, 304, 336, 368, 400, 440, 472, 504};
  979 
  980         if (code & ~0x7f) {
  981                 return (EINVAL);
  982         }
  983         kbd->kb_delay1 = delays[(code >> 5) & 3];
  984         kbd->kb_delay2 = rates[code & 0x1f];
  985         return (0);
  986 }
  987 
  988 static void
  989 gpiokeys_event_keyinput(struct gpiokeys_softc *sc)
  990 {
  991         int c;
  992 
  993         if ((sc->sc_flags & GPIOKEYS_GLOBAL_FLAG_POLLING) != 0)
  994                 return;
  995 
  996         if (KBD_IS_ACTIVE(&sc->sc_kbd) &&
  997             KBD_IS_BUSY(&sc->sc_kbd)) {
  998                 /* let the callback function process the input */
  999                 (sc->sc_kbd.kb_callback.kc_func) (&sc->sc_kbd, KBDIO_KEYINPUT,
 1000                     sc->sc_kbd.kb_callback.kc_arg);
 1001         } else {
 1002                 /* read and discard the input, no one is waiting for it */
 1003                 do {
 1004                         c = gpiokeys_read_char(&sc->sc_kbd, 0);
 1005                 } while (c != NOKEY);
 1006         }
 1007 }
 1008 
 1009 static keyboard_switch_t gpiokeyssw = {
 1010         .probe = &gpiokeys__probe,
 1011         .init = &gpiokeys_init,
 1012         .term = &gpiokeys_term,
 1013         .intr = &gpiokeys_intr,
 1014         .test_if = &gpiokeys_test_if,
 1015         .enable = &gpiokeys_enable,
 1016         .disable = &gpiokeys_disable,
 1017         .read = &gpiokeys_read,
 1018         .check = &gpiokeys_check,
 1019         .read_char = &gpiokeys_read_char,
 1020         .check_char = &gpiokeys_check_char,
 1021         .ioctl = &gpiokeys_ioctl,
 1022         .lock = &gpiokeys_lock,
 1023         .clear_state = &gpiokeys_clear_state,
 1024         .get_state = &gpiokeys_get_state,
 1025         .set_state = &gpiokeys_set_state,
 1026         .poll = &gpiokeys_poll,
 1027 };
 1028 
 1029 KEYBOARD_DRIVER(gpiokeys, gpiokeyssw, gpiokeys_configure);
 1030 
 1031 static int
 1032 gpiokeys_driver_load(module_t mod, int what, void *arg)
 1033 {
 1034         switch (what) {
 1035         case MOD_LOAD:
 1036                 kbd_add_driver(&gpiokeys_kbd_driver);
 1037                 break;
 1038         case MOD_UNLOAD:
 1039                 kbd_delete_driver(&gpiokeys_kbd_driver);
 1040                 break;
 1041         }
 1042         return (0);
 1043 }
 1044 
 1045 static device_method_t gpiokeys_methods[] = {
 1046         DEVMETHOD(device_probe,         gpiokeys_probe),
 1047         DEVMETHOD(device_attach,        gpiokeys_attach),
 1048         DEVMETHOD(device_detach,        gpiokeys_detach),
 1049 
 1050         DEVMETHOD_END
 1051 };
 1052 
 1053 static driver_t gpiokeys_driver = {
 1054         "gpiokeys",
 1055         gpiokeys_methods,
 1056         sizeof(struct gpiokeys_softc),
 1057 };
 1058 
 1059 DRIVER_MODULE(gpiokeys, simplebus, gpiokeys_driver, gpiokeys_driver_load, NULL);
 1060 MODULE_VERSION(gpiokeys, 1);

Cache object: e9576beb35496f99297df0a7bf846a2f


[ 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.