LCOV - code coverage report
Current view: top level - dev/usb - ukbd.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 189 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 19 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: ukbd.c,v 1.78 2017/05/12 09:16:55 mpi Exp $   */
       2             : /*      $NetBSD: ukbd.c,v 1.85 2003/03/11 16:44:00 augustss Exp $        */
       3             : 
       4             : /*
       5             :  * Copyright (c) 2010 Miodrag Vallat.
       6             :  *
       7             :  * Permission to use, copy, modify, and distribute this software for any
       8             :  * purpose with or without fee is hereby granted, provided that the above
       9             :  * copyright notice and this permission notice appear in all copies.
      10             :  *
      11             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      12             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      13             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      14             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      15             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      16             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      17             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      18             :  */
      19             : /*
      20             :  * Copyright (c) 1998 The NetBSD Foundation, Inc.
      21             :  * All rights reserved.
      22             :  *
      23             :  * This code is derived from software contributed to The NetBSD Foundation
      24             :  * by Lennart Augustsson (lennart@augustsson.net) at
      25             :  * Carlstedt Research & Technology.
      26             :  *
      27             :  * Redistribution and use in source and binary forms, with or without
      28             :  * modification, are permitted provided that the following conditions
      29             :  * are met:
      30             :  * 1. Redistributions of source code must retain the above copyright
      31             :  *    notice, this list of conditions and the following disclaimer.
      32             :  * 2. Redistributions in binary form must reproduce the above copyright
      33             :  *    notice, this list of conditions and the following disclaimer in the
      34             :  *    documentation and/or other materials provided with the distribution.
      35             :  *
      36             :  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
      37             :  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
      38             :  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
      39             :  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
      40             :  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      41             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      42             :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      43             :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      44             :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      45             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46             :  * POSSIBILITY OF SUCH DAMAGE.
      47             :  */
      48             : 
      49             : /*
      50             :  * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf
      51             :  */
      52             : 
      53             : #include <sys/param.h>
      54             : #include <sys/systm.h>
      55             : #include <sys/timeout.h>
      56             : #include <sys/kernel.h>
      57             : #include <sys/device.h>
      58             : #include <sys/ioctl.h>
      59             : 
      60             : #include <machine/bus.h>
      61             : 
      62             : #include <dev/usb/usb.h>
      63             : #include <dev/usb/usbhid.h>
      64             : 
      65             : #include <dev/usb/usbdi.h>
      66             : #include <dev/usb/usbdivar.h> /* needs_reattach() */
      67             : #include <dev/usb/usbdi_util.h>
      68             : #include <dev/usb/usbdevs.h>
      69             : #include <dev/usb/usb_quirks.h>
      70             : #include <dev/usb/uhidev.h>
      71             : #include <dev/usb/ukbdvar.h>
      72             : 
      73             : #include <dev/wscons/wsconsio.h>
      74             : #include <dev/wscons/wskbdvar.h>
      75             : #include <dev/wscons/wsksymdef.h>
      76             : #include <dev/wscons/wsksymvar.h>
      77             : 
      78             : #include <dev/hid/hidkbdsc.h>
      79             : 
      80             : #ifdef UKBD_DEBUG
      81             : #define DPRINTF(x)      do { if (ukbddebug) printf x; } while (0)
      82             : #define DPRINTFN(n,x)   do { if (ukbddebug>(n)) printf x; } while (0)
      83             : int     ukbddebug = 0;
      84             : #else
      85             : #define DPRINTF(x)
      86             : #define DPRINTFN(n,x)
      87             : #endif
      88             : 
      89             : const kbd_t ukbd_countrylayout[1 + HCC_MAX] = {
      90             :         (kbd_t)-1,
      91             :         (kbd_t)-1,      /* arabic */
      92             :         KB_BE,          /* belgian */
      93             :         (kbd_t)-1,      /* canadian bilingual */
      94             :         KB_CF,          /* canadian french */
      95             :         (kbd_t)-1,      /* czech */
      96             :         KB_DK,          /* danish */
      97             :         (kbd_t)-1,      /* finnish */
      98             :         KB_FR,          /* french */
      99             :         KB_DE,          /* german */
     100             :         (kbd_t)-1,      /* greek */
     101             :         (kbd_t)-1,      /* hebrew */
     102             :         KB_HU,          /* hungary */
     103             :         (kbd_t)-1,      /* international (iso) */
     104             :         KB_IT,          /* italian */
     105             :         KB_JP,          /* japanese (katakana) */
     106             :         (kbd_t)-1,      /* korean */
     107             :         KB_LA,          /* latin american */
     108             :         (kbd_t)-1,      /* netherlands/dutch */
     109             :         KB_NO,          /* norwegian */
     110             :         (kbd_t)-1,      /* persian (farsi) */
     111             :         KB_PL,          /* polish */
     112             :         KB_PT,          /* portuguese */
     113             :         KB_RU,          /* russian */
     114             :         (kbd_t)-1,      /* slovakia */
     115             :         KB_ES,          /* spanish */
     116             :         KB_SV,          /* swedish */
     117             :         KB_SF,          /* swiss french */
     118             :         KB_SG,          /* swiss german */
     119             :         (kbd_t)-1,      /* switzerland */
     120             :         (kbd_t)-1,      /* taiwan */
     121             :         KB_TR,          /* turkish Q */
     122             :         KB_UK,          /* uk */
     123             :         KB_US,          /* us */
     124             :         (kbd_t)-1,      /* yugoslavia */
     125             :         (kbd_t)-1       /* turkish F */
     126             : };
     127             : 
     128             : struct ukbd_softc {
     129             :         struct uhidev           sc_hdev;
     130             : #define sc_ledsize              sc_hdev.sc_osize
     131             : 
     132             :         struct hidkbd           sc_kbd;
     133             :         int                     sc_spl;
     134             :         struct hid_location     sc_apple_fn;
     135             :         void                    (*sc_munge)(void *, uint8_t *, u_int);
     136             : 
     137             : #ifdef DDB
     138             :         struct timeout          sc_ddb; /* for entering DDB */
     139             : #endif
     140             : };
     141             : 
     142             : void    ukbd_cngetc(void *, u_int *, int *);
     143             : void    ukbd_cnpollc(void *, int);
     144             : void    ukbd_cnbell(void *, u_int, u_int, u_int);
     145             : void    ukbd_debugger(void *);
     146             : 
     147             : const struct wskbd_consops ukbd_consops = {
     148             :         ukbd_cngetc,
     149             :         ukbd_cnpollc,
     150             :         ukbd_cnbell,
     151             : #ifdef DDB
     152             :         ukbd_debugger,
     153             : #endif
     154             : };
     155             : 
     156             : void    ukbd_intr(struct uhidev *addr, void *ibuf, u_int len);
     157             : 
     158             : void    ukbd_db_enter(void *);
     159             : int     ukbd_enable(void *, int);
     160             : void    ukbd_set_leds(void *, int);
     161             : int     ukbd_ioctl(void *, u_long, caddr_t, int, struct proc *);
     162             : 
     163             : const struct wskbd_accessops ukbd_accessops = {
     164             :         ukbd_enable,
     165             :         ukbd_set_leds,
     166             :         ukbd_ioctl,
     167             : };
     168             : 
     169             : int     ukbd_match(struct device *, void *, void *);
     170             : void    ukbd_attach(struct device *, struct device *, void *);
     171             : int     ukbd_detach(struct device *, int);
     172             : 
     173             : struct cfdriver ukbd_cd = {
     174             :         NULL, "ukbd", DV_DULL
     175             : };
     176             : 
     177             : const struct cfattach ukbd_ca = {
     178             :         sizeof(struct ukbd_softc), ukbd_match, ukbd_attach, ukbd_detach
     179             : };
     180             : 
     181             : struct ukbd_translation {
     182             :         uint8_t original;
     183             :         uint8_t translation;
     184             : };
     185             : 
     186             : #ifdef __loongson__
     187             : void    ukbd_gdium_munge(void *, uint8_t *, u_int);
     188             : #endif
     189             : void    ukbd_apple_munge(void *, uint8_t *, u_int);
     190             : void    ukbd_apple_mba_munge(void *, uint8_t *, u_int);
     191             : void    ukbd_apple_iso_munge(void *, uint8_t *, u_int);
     192             : void    ukbd_apple_iso_mba_munge(void *, uint8_t *, u_int);
     193             : void    ukbd_apple_translate(void *, uint8_t *, u_int,
     194             :             const struct ukbd_translation *, u_int);
     195             : uint8_t ukbd_translate(const struct ukbd_translation *, size_t, uint8_t);
     196             : 
     197             : int
     198           0 : ukbd_match(struct device *parent, void *match, void *aux)
     199             : {
     200           0 :         struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux;
     201           0 :         int size;
     202           0 :         void *desc;
     203             : 
     204           0 :         uhidev_get_report_desc(uha->parent, &desc, &size);
     205           0 :         if (!hid_is_collection(desc, size, uha->reportid,
     206             :             HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD)))
     207           0 :                 return (UMATCH_NONE);
     208             : 
     209           0 :         return (UMATCH_IFACECLASS);
     210           0 : }
     211             : 
     212             : void
     213           0 : ukbd_attach(struct device *parent, struct device *self, void *aux)
     214             : {
     215           0 :         struct ukbd_softc *sc = (struct ukbd_softc *)self;
     216           0 :         struct hidkbd *kbd = &sc->sc_kbd;
     217           0 :         struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux;
     218             :         struct usb_hid_descriptor *hid;
     219           0 :         u_int32_t quirks, qflags = 0;
     220           0 :         int dlen, repid;
     221             :         int console = 1;
     222           0 :         void *desc;
     223             :         kbd_t layout = (kbd_t)-1;
     224             : 
     225           0 :         sc->sc_hdev.sc_intr = ukbd_intr;
     226           0 :         sc->sc_hdev.sc_parent = uha->parent;
     227           0 :         sc->sc_hdev.sc_udev = uha->uaa->device;
     228           0 :         sc->sc_hdev.sc_report_id = uha->reportid;
     229             : 
     230           0 :         uhidev_get_report_desc(uha->parent, &desc, &dlen);
     231           0 :         repid = uha->reportid;
     232           0 :         sc->sc_hdev.sc_isize = hid_report_size(desc, dlen, hid_input, repid);
     233           0 :         sc->sc_hdev.sc_osize = hid_report_size(desc, dlen, hid_output, repid);
     234           0 :         sc->sc_hdev.sc_fsize = hid_report_size(desc, dlen, hid_feature, repid);
     235             : 
     236             :          /*
     237             :           * Since the HID-Proxy is always detected before any
     238             :           * real keyboard, do not let it grab the console.
     239             :           */
     240           0 :         if (uha->uaa->vendor == USB_VENDOR_APPLE &&
     241           0 :             uha->uaa->product == USB_PRODUCT_APPLE_BLUETOOTH_HCI)
     242           0 :                 console = 0;
     243             : 
     244           0 :         quirks = usbd_get_quirks(sc->sc_hdev.sc_udev)->uq_flags;
     245           0 :         if (quirks & UQ_SPUR_BUT_UP)
     246           0 :                 qflags |= HIDKBD_SPUR_BUT_UP;
     247             : 
     248           0 :         if (hidkbd_attach(self, kbd, console, qflags, repid, desc, dlen) != 0)
     249           0 :                 return;
     250             : 
     251           0 :         if (uha->uaa->vendor == USB_VENDOR_APPLE) {
     252           0 :                 if (hid_locate(desc, dlen, HID_USAGE2(HUP_APPLE, HUG_FN_KEY),
     253           0 :                     uha->reportid, hid_input, &sc->sc_apple_fn, &qflags)) {
     254           0 :                         if (qflags & HIO_VARIABLE) {
     255           0 :                                 switch (uha->uaa->product) {
     256             :                                 case USB_PRODUCT_APPLE_FOUNTAIN_ISO:
     257             :                                 case USB_PRODUCT_APPLE_GEYSER_ISO:
     258             :                                 case USB_PRODUCT_APPLE_WELLSPRING6_ISO:
     259             :                                 case USB_PRODUCT_APPLE_WELLSPRING8_ISO:
     260           0 :                                         sc->sc_munge = ukbd_apple_iso_munge;
     261           0 :                                         break;
     262             :                                 case USB_PRODUCT_APPLE_WELLSPRING_ISO:
     263             :                                 case USB_PRODUCT_APPLE_WELLSPRING4_ISO:
     264             :                                 case USB_PRODUCT_APPLE_WELLSPRING4A_ISO:
     265           0 :                                         sc->sc_munge = ukbd_apple_iso_mba_munge;
     266           0 :                                         break;
     267             :                                 case USB_PRODUCT_APPLE_WELLSPRING_ANSI:
     268             :                                 case USB_PRODUCT_APPLE_WELLSPRING_JIS:
     269             :                                 case USB_PRODUCT_APPLE_WELLSPRING4_ANSI:
     270             :                                 case USB_PRODUCT_APPLE_WELLSPRING4_JIS:
     271             :                                 case USB_PRODUCT_APPLE_WELLSPRING4A_ANSI:
     272             :                                 case USB_PRODUCT_APPLE_WELLSPRING4A_JIS:
     273           0 :                                         sc->sc_munge = ukbd_apple_mba_munge;
     274           0 :                                         break;
     275             :                                 default:
     276           0 :                                         sc->sc_munge = ukbd_apple_munge;
     277           0 :                                         break;
     278             :                                 }
     279             :                         }
     280             :                 }
     281             :         }
     282             : 
     283           0 :         if (uha->uaa->vendor == USB_VENDOR_TOPRE &&
     284           0 :             uha->uaa->product == USB_PRODUCT_TOPRE_HHKB) {
     285             :                 /* ignore country code on purpose */
     286             :         } else {
     287             :                 usb_interface_descriptor_t *id;
     288             : 
     289           0 :                 id = usbd_get_interface_descriptor(uha->uaa->iface);
     290           0 :                 hid = usbd_get_hid_descriptor(uha->uaa->device, id);
     291             : 
     292           0 :                 if (hid->bCountryCode <= HCC_MAX)
     293           0 :                         layout = ukbd_countrylayout[hid->bCountryCode];
     294             : #ifdef DIAGNOSTIC
     295           0 :                 if (hid->bCountryCode != 0)
     296           0 :                         printf(", country code %d", hid->bCountryCode);
     297             : #endif
     298             :         }
     299           0 :         if (layout == (kbd_t)-1) {
     300             : #ifdef UKBD_LAYOUT
     301             :                 layout = UKBD_LAYOUT;
     302             : #else
     303             :                 layout = KB_US | KB_DEFAULT;
     304             : #endif
     305           0 :         }
     306             : 
     307           0 :         printf("\n");
     308             : 
     309             : #ifdef __loongson__
     310             :         if (uha->uaa->vendor == USB_VENDOR_CYPRESS &&
     311             :             uha->uaa->product == USB_PRODUCT_CYPRESS_LPRDK)
     312             :                 sc->sc_munge = ukbd_gdium_munge;
     313             : #endif
     314             : 
     315           0 :         if (kbd->sc_console_keyboard) {
     316             :                 extern struct wskbd_mapdata ukbd_keymapdata;
     317             : 
     318             :                 DPRINTF(("ukbd_attach: console keyboard sc=%p\n", sc));
     319           0 :                 ukbd_keymapdata.layout = layout;
     320           0 :                 wskbd_cnattach(&ukbd_consops, sc, &ukbd_keymapdata);
     321           0 :                 ukbd_enable(sc, 1);
     322           0 :         }
     323             : 
     324             :         /* Flash the leds; no real purpose, just shows we're alive. */
     325           0 :         ukbd_set_leds(sc, WSKBD_LED_SCROLL | WSKBD_LED_NUM |
     326             :                           WSKBD_LED_CAPS | WSKBD_LED_COMPOSE);
     327           0 :         usbd_delay_ms(sc->sc_hdev.sc_udev, 400);
     328           0 :         ukbd_set_leds(sc, 0);
     329             : 
     330           0 :         hidkbd_attach_wskbd(kbd, layout, &ukbd_accessops);
     331             : 
     332             : #ifdef DDB
     333           0 :         timeout_set(&sc->sc_ddb, ukbd_db_enter, sc);
     334             : #endif
     335           0 : }
     336             : 
     337             : int
     338           0 : ukbd_detach(struct device *self, int flags)
     339             : {
     340           0 :         struct ukbd_softc *sc = (struct ukbd_softc *)self;
     341           0 :         struct hidkbd *kbd = &sc->sc_kbd;
     342             :         int rv;
     343             : 
     344           0 :         rv = hidkbd_detach(kbd, flags);
     345             : 
     346             :         /* The console keyboard does not get a disable call, so check pipe. */
     347           0 :         if (sc->sc_hdev.sc_state & UHIDEV_OPEN)
     348           0 :                 uhidev_close(&sc->sc_hdev);
     349             : 
     350           0 :         return (rv);
     351             : }
     352             : 
     353             : void
     354           0 : ukbd_intr(struct uhidev *addr, void *ibuf, u_int len)
     355             : {
     356           0 :         struct ukbd_softc *sc = (struct ukbd_softc *)addr;
     357           0 :         struct hidkbd *kbd = &sc->sc_kbd;
     358             : 
     359           0 :         if (kbd->sc_enabled != 0) {
     360           0 :                 if (sc->sc_munge != NULL)
     361           0 :                         (*sc->sc_munge)(sc, (uint8_t *)ibuf, len);
     362           0 :                 hidkbd_input(kbd, (uint8_t *)ibuf, len);
     363           0 :         }
     364           0 : }
     365             : 
     366             : int
     367           0 : ukbd_enable(void *v, int on)
     368             : {
     369           0 :         struct ukbd_softc *sc = v;
     370           0 :         struct hidkbd *kbd = &sc->sc_kbd;
     371             :         int rv;
     372             : 
     373           0 :         if (on && usbd_is_dying(sc->sc_hdev.sc_udev))
     374           0 :                 return EIO;
     375             : 
     376           0 :         if ((rv = hidkbd_enable(kbd, on)) != 0)
     377           0 :                 return rv;
     378             : 
     379           0 :         if (on) {
     380           0 :                 return uhidev_open(&sc->sc_hdev);
     381             :         } else {
     382           0 :                 uhidev_close(&sc->sc_hdev);
     383           0 :                 return 0;
     384             :         }
     385           0 : }
     386             : 
     387             : void
     388           0 : ukbd_set_leds(void *v, int leds)
     389             : {
     390           0 :         struct ukbd_softc *sc = v;
     391           0 :         struct hidkbd *kbd = &sc->sc_kbd;
     392           0 :         u_int8_t res;
     393             : 
     394           0 :         if (usbd_is_dying(sc->sc_hdev.sc_udev))
     395           0 :                 return;
     396             : 
     397           0 :         if (sc->sc_ledsize && hidkbd_set_leds(kbd, leds, &res) != 0)
     398           0 :                 uhidev_set_report_async(sc->sc_hdev.sc_parent,
     399           0 :                     UHID_OUTPUT_REPORT, sc->sc_hdev.sc_report_id, &res, 1);
     400           0 : }
     401             : 
     402             : int
     403           0 : ukbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
     404             : {
     405           0 :         struct ukbd_softc *sc = v;
     406           0 :         struct hidkbd *kbd = &sc->sc_kbd;
     407             :         int rc;
     408             : 
     409           0 :         switch (cmd) {
     410             :         case WSKBDIO_GTYPE:
     411           0 :                 *(int *)data = WSKBD_TYPE_USB;
     412           0 :                 return (0);
     413             :         case WSKBDIO_SETLEDS:
     414           0 :                 ukbd_set_leds(v, *(int *)data);
     415           0 :                 return (0);
     416             :         default:
     417           0 :                 rc = uhidev_ioctl(&sc->sc_hdev, cmd, data, flag, p);
     418           0 :                 if (rc != -1)
     419           0 :                         return rc;
     420             :                 else
     421           0 :                         return hidkbd_ioctl(kbd, cmd, data, flag, p);
     422             :         }
     423           0 : }
     424             : 
     425             : /* Console interface. */
     426             : void
     427           0 : ukbd_cngetc(void *v, u_int *type, int *data)
     428             : {
     429           0 :         struct ukbd_softc *sc = v;
     430           0 :         struct hidkbd *kbd = &sc->sc_kbd;
     431             : 
     432             :         DPRINTFN(0,("ukbd_cngetc: enter\n"));
     433           0 :         kbd->sc_polling = 1;
     434           0 :         while (kbd->sc_npollchar <= 0)
     435           0 :                 usbd_dopoll(sc->sc_hdev.sc_udev);
     436           0 :         kbd->sc_polling = 0;
     437           0 :         hidkbd_cngetc(kbd, type, data);
     438             :         DPRINTFN(0,("ukbd_cngetc: return 0x%02x\n", *data));
     439           0 : }
     440             : 
     441             : void
     442           0 : ukbd_cnpollc(void *v, int on)
     443             : {
     444           0 :         struct ukbd_softc *sc = v;
     445             : 
     446             :         DPRINTFN(2,("ukbd_cnpollc: sc=%p on=%d\n", v, on));
     447             : 
     448           0 :         if (on)
     449           0 :                 sc->sc_spl = splusb();
     450             :         else
     451           0 :                 splx(sc->sc_spl);
     452           0 :         usbd_set_polling(sc->sc_hdev.sc_udev, on);
     453           0 : }
     454             : 
     455             : void
     456           0 : ukbd_cnbell(void *v, u_int pitch, u_int period, u_int volume)
     457             : {
     458           0 :         hidkbd_bell(pitch, period, volume, 1);
     459           0 : }
     460             : 
     461             : #ifdef DDB
     462             : void
     463           0 : ukbd_debugger(void *v)
     464             : {
     465           0 :         struct ukbd_softc *sc = v;
     466             : 
     467             :         /*
     468             :          * For the console keyboard we can't deliver CTL-ALT-ESC
     469             :          * from the interrupt routine.  Doing so would start
     470             :          * polling from inside the interrupt routine and that
     471             :          * loses bigtime.
     472             :          */
     473           0 :         timeout_add(&sc->sc_ddb, 1);
     474           0 : }
     475             : 
     476             : void
     477           0 : ukbd_db_enter(void *xsc)
     478             : {
     479           0 :         db_enter();
     480           0 : }
     481             : #endif
     482             : 
     483             : int
     484           0 : ukbd_cnattach(void)
     485             : {
     486             :         struct ukbd_softc *sc;
     487             :         int i;
     488             : 
     489             :         /*
     490             :          * XXX USB requires too many parts of the kernel to be running
     491             :          * XXX in order to work, so we can't do much for the console
     492             :          * XXX keyboard until autconfiguration has run its course.
     493             :          */
     494           0 :         hidkbd_is_console = 1;
     495             : 
     496           0 :         if (!cold) {
     497             :                 /*
     498             :                  * When switching console dynamically force all USB keyboards
     499             :                  * to re-attach and possibly became the 'console' keyboard.
     500             :                  */
     501           0 :                 for (i = 0; i < ukbd_cd.cd_ndevs; i++) {
     502           0 :                         if ((sc = ukbd_cd.cd_devs[i]) != NULL) {
     503           0 :                                 usb_needs_reattach(sc->sc_hdev.sc_udev);
     504           0 :                                 break;
     505             :                         }
     506             :                 }
     507             :         }
     508             : 
     509           0 :         return (0);
     510             : }
     511             : 
     512             : uint8_t
     513           0 : ukbd_translate(const struct ukbd_translation *table, size_t tsize,
     514             :     uint8_t keycode)
     515             : {
     516           0 :         for (; tsize != 0; table++, tsize--)
     517           0 :                 if (table->original == keycode)
     518           0 :                         return table->translation;
     519           0 :         return 0;
     520           0 : }
     521             : 
     522             : void
     523           0 : ukbd_apple_translate(void *vsc, uint8_t *ibuf, u_int ilen,
     524             :     const struct ukbd_translation* trans, u_int tlen)
     525             : {
     526           0 :         struct ukbd_softc *sc = vsc;
     527           0 :         struct hidkbd *kbd = &sc->sc_kbd;
     528             :         uint8_t *pos, *spos, *epos, xlat;
     529             : 
     530           0 :         spos = ibuf + kbd->sc_keycodeloc.pos / 8;
     531           0 :         epos = spos + kbd->sc_nkeycode;
     532             : 
     533           0 :         for (pos = spos; pos != epos; pos++) {
     534           0 :                 xlat = ukbd_translate(trans, tlen, *pos);
     535           0 :                 if (xlat != 0)
     536           0 :                         *pos = xlat;
     537             :         }
     538           0 : }
     539             : 
     540             : void
     541           0 : ukbd_apple_munge(void *vsc, uint8_t *ibuf, u_int ilen)
     542             : {
     543           0 :         struct ukbd_softc *sc = vsc;
     544             : 
     545             :         static const struct ukbd_translation apple_fn_trans[] = {
     546             :                 { 40, 73 },     /* return -> insert */
     547             :                 { 42, 76 },     /* backspace -> delete */
     548             : #ifdef notyet
     549             :                 { 58, 0 },      /* F1 -> screen brightness down */
     550             :                 { 59, 0 },      /* F2 -> screen brightness up */
     551             :                 { 60, 0 },      /* F3 */
     552             :                 { 61, 0 },      /* F4 */
     553             :                 { 62, 0 },      /* F5 -> keyboard backlight down */
     554             :                 { 63, 0 },      /* F6 -> keyboard backlight up */
     555             :                 { 64, 0 },      /* F7 -> audio back */
     556             :                 { 65, 0 },      /* F8 -> audio pause/play */
     557             :                 { 66, 0 },      /* F9 -> audio next */
     558             : #endif
     559             : #ifdef __macppc__
     560             :                 { 60, 127 },    /* F3 -> audio mute */
     561             :                 { 61, 129 },    /* F4 -> audio lower */
     562             :                 { 62, 128 },    /* F5 -> audio raise */
     563             : #else
     564             :                 { 67, 127 },    /* F10 -> audio mute */
     565             :                 { 68, 129 },    /* F11 -> audio lower */
     566             :                 { 69, 128 },    /* F12 -> audio raise */
     567             : #endif
     568             :                 { 79, 77 },     /* right -> end */
     569             :                 { 80, 74 },     /* left -> home */
     570             :                 { 81, 78 },     /* down -> page down */
     571             :                 { 82, 75 }      /* up -> page up */
     572             :         };
     573             : 
     574           0 :         if (!hid_get_data(ibuf, ilen, &sc->sc_apple_fn))
     575           0 :                 return;
     576             : 
     577           0 :         ukbd_apple_translate(vsc, ibuf, ilen, apple_fn_trans,
     578             :             nitems(apple_fn_trans));
     579           0 : }
     580             : 
     581             : void
     582           0 : ukbd_apple_mba_munge(void *vsc, uint8_t *ibuf, u_int ilen)
     583             : {
     584           0 :         struct ukbd_softc *sc = vsc;
     585             : 
     586             :         static const struct ukbd_translation apple_fn_trans[] = {
     587             :                 { 40, 73 },     /* return -> insert */
     588             :                 { 42, 76 },     /* backspace -> delete */
     589             : #ifdef notyet
     590             :                 { 58, 0 },      /* F1 -> screen brightness down */
     591             :                 { 59, 0 },      /* F2 -> screen brightness up */
     592             :                 { 60, 0 },      /* F3 */
     593             :                 { 61, 0 },      /* F4 */
     594             :                 { 62, 0 },      /* F5 */
     595             :                 { 63, 0 },      /* F6 -> audio back */
     596             :                 { 64, 0 },      /* F7 -> audio pause/play */
     597             :                 { 65, 0 },      /* F8 -> audio next */
     598             : #endif
     599             :                 { 66, 127 },    /* F9 -> audio mute */
     600             :                 { 67, 129 },    /* F10 -> audio lower */
     601             :                 { 68, 128 },    /* F11 -> audio raise */
     602             : #ifdef notyet
     603             :                 { 69, 0 },      /* F12 -> eject */
     604             : #endif
     605             :                 { 79, 77 },     /* right -> end */
     606             :                 { 80, 74 },     /* left -> home */
     607             :                 { 81, 78 },     /* down -> page down */
     608             :                 { 82, 75 }      /* up -> page up */
     609             :         };
     610             : 
     611           0 :         if (!hid_get_data(ibuf, ilen, &sc->sc_apple_fn))
     612           0 :                 return;
     613             : 
     614           0 :         ukbd_apple_translate(vsc, ibuf, ilen, apple_fn_trans,
     615             :             nitems(apple_fn_trans));
     616           0 : }
     617             : 
     618             : void
     619           0 : ukbd_apple_iso_munge(void *vsc, uint8_t *ibuf, u_int ilen)
     620             : {
     621             :         static const struct ukbd_translation apple_iso_trans[] = {
     622             :                 { 53, 100 },    /* less -> grave */
     623             :                 { 100, 53 },
     624             :         };
     625             : 
     626           0 :         ukbd_apple_translate(vsc, ibuf, ilen, apple_iso_trans,
     627             :             nitems(apple_iso_trans));
     628           0 :         ukbd_apple_munge(vsc, ibuf, ilen);
     629           0 : }
     630             : 
     631             : void
     632           0 : ukbd_apple_iso_mba_munge(void *vsc, uint8_t *ibuf, u_int ilen)
     633             : {
     634             :         static const struct ukbd_translation apple_iso_trans[] = {
     635             :                 { 53, 100 },    /* less -> grave */
     636             :                 { 100, 53 },
     637             :         };
     638             : 
     639           0 :         ukbd_apple_translate(vsc, ibuf, ilen, apple_iso_trans,
     640             :             nitems(apple_iso_trans));
     641           0 :         ukbd_apple_mba_munge(vsc, ibuf, ilen);
     642           0 : }
     643             : 
     644             : #ifdef __loongson__
     645             : /*
     646             :  * Software Fn- translation for Gdium Liberty keyboard.
     647             :  */
     648             : #define GDIUM_FN_CODE   0x82
     649             : void
     650             : ukbd_gdium_munge(void *vsc, uint8_t *ibuf, u_int ilen)
     651             : {
     652             :         struct ukbd_softc *sc = vsc;
     653             :         struct hidkbd *kbd = &sc->sc_kbd;
     654             :         uint8_t *pos, *spos, *epos, xlat;
     655             :         int fn;
     656             : 
     657             :         static const struct ukbd_translation gdium_fn_trans[] = {
     658             : #ifdef notyet
     659             :                 { 58, 0 },      /* F1 -> toggle camera */
     660             :                 { 59, 0 },      /* F2 -> toggle wireless */
     661             : #endif
     662             :                 { 60, 127 },    /* F3 -> audio mute */
     663             :                 { 61, 128 },    /* F4 -> audio raise */
     664             :                 { 62, 129 },    /* F5 -> audio lower */
     665             : #ifdef notyet
     666             :                 { 63, 0 },      /* F6 -> toggle ext. video */
     667             :                 { 64, 0 },      /* F7 -> toggle mouse */
     668             :                 { 65, 0 },      /* F8 -> brightness up */
     669             :                 { 66, 0 },      /* F9 -> brightness down */
     670             :                 { 67, 0 },      /* F10 -> suspend */
     671             :                 { 68, 0 },      /* F11 -> user1 */
     672             :                 { 69, 0 },      /* F12 -> user2 */
     673             :                 { 70, 0 },      /* print screen -> sysrq */
     674             : #endif
     675             :                 { 76, 71 },     /* delete -> scroll lock */
     676             :                 { 81, 78 },     /* down -> page down */
     677             :                 { 82, 75 }      /* up -> page up */
     678             :         };
     679             : 
     680             :         spos = ibuf + kbd->sc_keycodeloc.pos / 8;
     681             :         epos = spos + kbd->sc_nkeycode;
     682             : 
     683             :         /*
     684             :          * Check for Fn key being down and remove it from the report.
     685             :          */
     686             : 
     687             :         fn = 0;
     688             :         for (pos = spos; pos != epos; pos++)
     689             :                 if (*pos == GDIUM_FN_CODE) {
     690             :                         fn = 1;
     691             :                         *pos = 0;
     692             :                         break;
     693             :                 }
     694             : 
     695             :         /*
     696             :          * Rewrite keycodes on the fly to perform Fn-key translation.
     697             :          * Keycodes without a translation are passed unaffected.
     698             :          */
     699             : 
     700             :         if (fn != 0)
     701             :                 for (pos = spos; pos != epos; pos++) {
     702             :                         xlat = ukbd_translate(gdium_fn_trans,
     703             :                             nitems(gdium_fn_trans), *pos);
     704             :                         if (xlat != 0)
     705             :                                 *pos = xlat;
     706             :                 }
     707             : 
     708             : }
     709             : #endif

Generated by: LCOV version 1.13