LCOV - code coverage report
Current view: top level - dev/pckbc - pckbd.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 291 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: pckbd.c,v 1.45 2018/05/22 10:53:47 mpi Exp $ */
       2             : /* $NetBSD: pckbd.c,v 1.24 2000/06/05 22:20:57 sommerfeld Exp $ */
       3             : 
       4             : /*-
       5             :  * Copyright (c) 1998 The NetBSD Foundation, Inc.
       6             :  * All rights reserved.
       7             :  *
       8             :  * This code is derived from software contributed to The NetBSD Foundation
       9             :  * by Charles M. Hannum.
      10             :  *
      11             :  * Redistribution and use in source and binary forms, with or without
      12             :  * modification, are permitted provided that the following conditions
      13             :  * are met:
      14             :  * 1. Redistributions of source code must retain the above copyright
      15             :  *    notice, this list of conditions and the following disclaimer.
      16             :  * 2. Redistributions in binary form must reproduce the above copyright
      17             :  *    notice, this list of conditions and the following disclaimer in the
      18             :  *    documentation and/or other materials provided with the distribution.
      19             :  *
      20             :  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
      21             :  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
      22             :  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
      23             :  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
      24             :  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      25             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      26             :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      27             :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      28             :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      29             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      30             :  * POSSIBILITY OF SUCH DAMAGE.
      31             :  */
      32             : 
      33             : /*-
      34             :  * Copyright (c) 1990 The Regents of the University of California.
      35             :  * All rights reserved.
      36             :  *
      37             :  * This code is derived from software contributed to Berkeley by
      38             :  * William Jolitz and Don Ahn.
      39             :  *
      40             :  * Redistribution and use in source and binary forms, with or without
      41             :  * modification, are permitted provided that the following conditions
      42             :  * are met:
      43             :  * 1. Redistributions of source code must retain the above copyright
      44             :  *    notice, this list of conditions and the following disclaimer.
      45             :  * 2. Redistributions in binary form must reproduce the above copyright
      46             :  *    notice, this list of conditions and the following disclaimer in the
      47             :  *    documentation and/or other materials provided with the distribution.
      48             :  * 3. Neither the name of the University nor the names of its contributors
      49             :  *    may be used to endorse or promote products derived from this software
      50             :  *    without specific prior written permission.
      51             :  *
      52             :  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      53             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      54             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      55             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      56             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      57             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      58             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      59             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      60             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      61             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      62             :  * SUCH DAMAGE.
      63             :  *
      64             :  *      @(#)pccons.c    5.11 (Berkeley) 5/21/91
      65             :  */
      66             : 
      67             : /*
      68             :  * code to work keyboard for PC-style console
      69             :  */
      70             : 
      71             : #include <sys/param.h>
      72             : #include <sys/systm.h>
      73             : #include <sys/device.h>
      74             : #include <sys/malloc.h>
      75             : #include <sys/ioctl.h>
      76             : 
      77             : #include <machine/bus.h>
      78             : 
      79             : #include <dev/ic/pckbcvar.h>
      80             : #include <dev/pckbc/pckbdreg.h>
      81             : #include <dev/pckbc/pmsreg.h>
      82             : 
      83             : #include <dev/wscons/wsconsio.h>
      84             : #include <dev/wscons/wskbdvar.h>
      85             : #include <dev/wscons/wsksymdef.h>
      86             : #include <dev/wscons/wsksymvar.h>
      87             : 
      88             : #include <dev/pckbc/wskbdmap_mfii.h>
      89             : 
      90             : struct pckbd_internal {
      91             :         int t_isconsole;
      92             :         pckbc_tag_t t_kbctag;
      93             :         pckbc_slot_t t_kbcslot;
      94             : 
      95             :         int t_translating;
      96             :         int t_table;
      97             : 
      98             :         int t_lastchar;
      99             :         int t_extended;
     100             :         int t_extended1;
     101             :         int t_releasing;
     102             : 
     103             :         struct pckbd_softc *t_sc; /* back pointer */
     104             : };
     105             : 
     106             : struct pckbd_softc {
     107             :         struct  device sc_dev;
     108             : 
     109             :         struct pckbd_internal *id;
     110             :         int sc_enabled;
     111             : 
     112             :         int sc_ledstate;
     113             : 
     114             :         struct device *sc_wskbddev;
     115             : #ifdef WSDISPLAY_COMPAT_RAWKBD
     116             :         int     rawkbd;
     117             :         u_int   sc_rawcnt;
     118             :         char    sc_rawbuf[3];
     119             : #endif
     120             : };
     121             : 
     122             : static int pckbd_is_console(pckbc_tag_t, pckbc_slot_t);
     123             : 
     124             : int pckbdprobe(struct device *, void *, void *);
     125             : void pckbdattach(struct device *, struct device *, void *);
     126             : int pckbdactivate(struct device *, int);
     127             : 
     128             : struct cfattach pckbd_ca = {
     129             :         sizeof(struct pckbd_softc), 
     130             :         pckbdprobe, 
     131             :         pckbdattach, 
     132             :         NULL, 
     133             :         pckbdactivate
     134             : };
     135             : 
     136             : int     pckbd_enable(void *, int);
     137             : void    pckbd_set_leds(void *, int);
     138             : int     pckbd_ioctl(void *, u_long, caddr_t, int, struct proc *);
     139             : 
     140             : const struct wskbd_accessops pckbd_accessops = {
     141             :         pckbd_enable,
     142             :         pckbd_set_leds,
     143             :         pckbd_ioctl,
     144             : };
     145             : 
     146             : void    pckbd_cngetc(void *, u_int *, int *);
     147             : void    pckbd_cnpollc(void *, int);
     148             : void    pckbd_cnbell(void *, u_int, u_int, u_int);
     149             : 
     150             : const struct wskbd_consops pckbd_consops = {
     151             :         pckbd_cngetc,
     152             :         pckbd_cnpollc,
     153             :         pckbd_cnbell,
     154             : };
     155             : 
     156             : const struct wskbd_mapdata pckbd_keymapdata = {
     157             :         pckbd_keydesctab,
     158             : #ifdef PCKBD_LAYOUT
     159             :         PCKBD_LAYOUT,
     160             : #else
     161             :         KB_US | KB_DEFAULT,
     162             : #endif
     163             : };
     164             : 
     165             : /*
     166             :  * Hackish support for a bell on the PC Keyboard; when a suitable feeper
     167             :  * is found, it attaches itself into the pckbd driver here.
     168             :  */
     169             : void    (*pckbd_bell_fn)(void *, u_int, u_int, u_int, int);
     170             : void    *pckbd_bell_fn_arg;
     171             : 
     172             : void    pckbd_bell(u_int, u_int, u_int, int);
     173             : 
     174             : int     pckbd_scancode_translate(struct pckbd_internal *, int);
     175             : int     pckbd_set_xtscancode(pckbc_tag_t, pckbc_slot_t,
     176             :             struct pckbd_internal *);
     177             : void    pckbd_init(struct pckbd_internal *, pckbc_tag_t, pckbc_slot_t, int);
     178             : void    pckbd_input(void *, int);
     179             : 
     180             : static int      pckbd_decode(struct pckbd_internal *, int,
     181             :                                   u_int *, int *);
     182             : static int      pckbd_led_encode(int);
     183             : 
     184             : struct pckbd_internal pckbd_consdata;
     185             : 
     186             : int
     187           0 : pckbdactivate(struct device *self, int act)
     188             : {
     189           0 :         struct pckbd_softc *sc = (struct pckbd_softc *)self;
     190             :         int rv = 0;
     191           0 :         u_char cmd[1];
     192             : 
     193           0 :         switch(act) {
     194             :         case DVACT_RESUME:
     195           0 :                 if (sc->sc_enabled) {
     196             :                         /*
     197             :                          * Some keyboards are not enabled after a reset,
     198             :                          * so make sure it is enabled now.
     199             :                          */
     200           0 :                         cmd[0] = KBC_ENABLE;
     201           0 :                         (void) pckbc_poll_cmd(sc->id->t_kbctag,
     202           0 :                             sc->id->t_kbcslot, cmd, 1, 0, NULL, 0);
     203             :                         /* XXX - also invoke pckbd_set_xtscancode() too? */
     204           0 :                 }
     205             :                 break;
     206             :         }
     207             : 
     208           0 :         rv = config_activate_children(self, act);
     209             : 
     210           0 :         return (rv);
     211           0 : }
     212             : 
     213             : int
     214           0 : pckbd_set_xtscancode(pckbc_tag_t kbctag, pckbc_slot_t kbcslot,
     215             :     struct pckbd_internal *id)
     216             : {
     217             :         int table = 3;
     218             : 
     219           0 :         if (pckbc_xt_translation(kbctag)) {
     220             : #ifdef DEBUG
     221             :                 printf("pckbd: enabling of translation failed\n");
     222             : #endif
     223             :                 /*
     224             :                  * Since the keyboard controller can not translate scan
     225             :                  * codes to the XT set (#1), we would like to request
     226             :                  * this exact set. However it is likely that the
     227             :                  * controller does not support it either.
     228             :                  *
     229             :                  * So try scan code set #2 as well, which this driver
     230             :                  * knows how to translate.
     231             :                  */
     232             :                 table = 2;
     233           0 :                 if (id != NULL)
     234           0 :                         id->t_translating = 0;
     235             :         } else {
     236           0 :                 if (id != NULL) {
     237           0 :                         id->t_translating = 1;
     238           0 :                         if (id->t_table == 0) {
     239             :                                 /*
     240             :                                  * Don't bother explicitly setting into set 2,
     241             :                                  * it's the default.
     242             :                                  */
     243           0 :                                 id->t_table = 2;
     244           0 :                                 return (0);
     245             :                         }
     246             :                 }
     247             :         }
     248             : 
     249             :         /* keep falling back until we hit a table that looks usable. */
     250           0 :         for (; table >= 1; table--) {
     251           0 :                 u_char cmd[2];
     252             : #ifdef DEBUG
     253             :                 printf("pckbd: trying table %d\n", table);
     254             : #endif
     255           0 :                 cmd[0] = KBC_SETTABLE;
     256           0 :                 cmd[1] = table;
     257           0 :                 if (pckbc_poll_cmd(kbctag, kbcslot, cmd, 2, 0, NULL, 0)) {
     258             : #ifdef DEBUG
     259             :                         printf("pckbd: table set of %d failed\n", table);
     260             : #endif
     261           0 :                         if (table > 1) {
     262           0 :                                 cmd[0] = KBC_RESET;
     263           0 :                                 (void)pckbc_poll_cmd(kbctag, kbcslot, cmd,
     264             :                                     1, 1, NULL, 1);
     265           0 :                                 pckbc_flush(kbctag, kbcslot);
     266             : 
     267           0 :                                 continue;
     268             :                         }
     269             :                 }
     270             : 
     271             :                 /*
     272             :                  * the 8042 took the table set request, however, not all that
     273             :                  * report they can work with table 3 actually work, so ask what
     274             :                  * table it reports it's in.
     275             :                  */
     276           0 :                 if (table == 3) {
     277           0 :                         u_char resp[1];
     278             : 
     279           0 :                         cmd[0] = KBC_SETTABLE;
     280           0 :                         cmd[1] = 0;
     281           0 :                         if (pckbc_poll_cmd(kbctag, kbcslot, cmd, 2, 1, resp, 0)) {
     282             :                                 /*
     283             :                                  * query failed, step down to table 2 to be
     284             :                                  * safe.
     285             :                                  */
     286             : #ifdef DEBUG
     287             :                                 printf("pckbd: table 3 verification failed\n");
     288             : #endif
     289           0 :                                 continue;
     290           0 :                         } else if (resp[0] == 3) {
     291             : #ifdef DEBUG
     292             :                                 printf("pckbd: settling on table 3\n");
     293             : #endif
     294           0 :                                 break;
     295             :                         }
     296             : #ifdef DEBUG
     297             :                         else
     298             :                                 printf("pckbd: table \"%x\" != 3, trying 2\n",
     299             :                                         resp[0]);
     300             : #endif
     301           0 :                 } else {
     302             : #ifdef DEBUG
     303             :                         printf("pckbd: settling on table %d\n", table);
     304             : #endif
     305           0 :                         break;
     306             :                 }
     307           0 :         }
     308             : 
     309           0 :         if (table == 0)
     310           0 :                 return (1);
     311             : 
     312           0 :         if (id != NULL)
     313           0 :                 id->t_table = table;
     314             : 
     315           0 :         return (0);
     316           0 : }
     317             : 
     318             : static int
     319           0 : pckbd_is_console(pckbc_tag_t tag, pckbc_slot_t slot)
     320             : {
     321           0 :         return (pckbd_consdata.t_isconsole &&
     322           0 :                 (tag == pckbd_consdata.t_kbctag) &&
     323           0 :                 (slot == pckbd_consdata.t_kbcslot));
     324             : }
     325             : 
     326             : /*
     327             :  * these are both bad jokes
     328             :  */
     329             : int
     330           0 : pckbdprobe(struct device *parent, void *match, void *aux)
     331             : {
     332           0 :         struct cfdata *cf = match;
     333           0 :         struct pckbc_attach_args *pa = aux;
     334           0 :         u_char cmd[1], resp[1];
     335             :         int res;
     336             : 
     337             :         /*
     338             :          * XXX There are rumours that a keyboard can be connected
     339             :          * to the aux port as well. For me, this didn't work.
     340             :          * For further experiments, allow it if explicitly
     341             :          * wired in the config file.
     342             :          */
     343           0 :         if ((pa->pa_slot != PCKBC_KBD_SLOT) &&
     344           0 :             (cf->cf_loc[PCKBCCF_SLOT] == PCKBCCF_SLOT_DEFAULT))
     345           0 :                 return (0);
     346             : 
     347             :         /* Flush any garbage. */
     348           0 :         pckbc_flush(pa->pa_tag, pa->pa_slot);
     349             : 
     350             :         /* Reset the keyboard. */
     351           0 :         cmd[0] = KBC_RESET;
     352           0 :         res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 1, resp, 1);
     353           0 :         if (res) {
     354             : #ifdef DEBUG
     355             :                 printf("pckbdprobe: reset error %d\n", res);
     356             : #endif
     357             :                 /*
     358             :                  * There is probably no keyboard connected.
     359             :                  * Let the probe succeed if the keyboard is used
     360             :                  * as console input - it can be connected later.
     361             :                  */
     362             : #if defined(__i386__) || defined(__amd64__)
     363             :                 /*
     364             :                  * However, on legacy-free PCs, there might really
     365             :                  * be no PS/2 connector at all; in that case, do not
     366             :                  * even try to attach; ukbd will take over as console.
     367             :                  */
     368           0 :                 if (res == ENXIO) {
     369             :                         /* check cf_flags from parent */
     370           0 :                         struct cfdata *cf = parent->dv_cfdata;
     371           0 :                         if (!ISSET(cf->cf_flags, PCKBCF_FORCE_KEYBOARD_PRESENT))
     372           0 :                                 return 0;
     373           0 :                 }
     374             : #endif
     375           0 :                 return (pckbd_is_console(pa->pa_tag, pa->pa_slot) ? 1 : 0);
     376             :         }
     377           0 :         if (resp[0] != KBR_RSTDONE) {
     378           0 :                 printf("pckbdprobe: reset response 0x%x\n", resp[0]);
     379           0 :                 return (0);
     380             :         }
     381             : 
     382             :         /*
     383             :          * Some keyboards seem to leave a second ack byte after the reset.
     384             :          * This is kind of stupid, but we account for them anyway by just
     385             :          * flushing the buffer.
     386             :          */
     387           0 :         pckbc_flush(pa->pa_tag, pa->pa_slot);
     388             : 
     389           0 :         return (2);
     390           0 : }
     391             : 
     392             : void
     393           0 : pckbdattach(struct device *parent, struct device *self, void *aux)
     394             : {
     395           0 :         struct pckbd_softc *sc = (void *)self;
     396           0 :         struct pckbc_attach_args *pa = aux;
     397             :         int isconsole;
     398           0 :         struct wskbddev_attach_args a;
     399           0 :         u_char cmd[1];
     400             : 
     401           0 :         isconsole = pckbd_is_console(pa->pa_tag, pa->pa_slot);
     402             : 
     403           0 :         if (isconsole) {
     404           0 :                 sc->id = &pckbd_consdata;
     405           0 :                 if (sc->id->t_table == 0)
     406           0 :                         pckbd_set_xtscancode(pa->pa_tag, pa->pa_slot, sc->id);
     407             : 
     408             :                 /*
     409             :                  * Some keyboards are not enabled after a reset,
     410             :                  * so make sure it is enabled now.
     411             :                  */
     412           0 :                 cmd[0] = KBC_ENABLE;
     413           0 :                 (void) pckbc_poll_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
     414           0 :                     cmd, 1, 0, NULL, 0);
     415           0 :                 sc->sc_enabled = 1;
     416           0 :         } else {
     417           0 :                 sc->id = malloc(sizeof(struct pckbd_internal),
     418             :                                 M_DEVBUF, M_WAITOK);
     419           0 :                 pckbd_init(sc->id, pa->pa_tag, pa->pa_slot, 0);
     420           0 :                 pckbd_set_xtscancode(pa->pa_tag, pa->pa_slot, sc->id);
     421             : 
     422             :                 /* no interrupts until enabled */
     423           0 :                 cmd[0] = KBC_DISABLE;
     424           0 :                 (void) pckbc_poll_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
     425           0 :                                       cmd, 1, 0, NULL, 0);
     426           0 :                 sc->sc_enabled = 0;
     427             :         }
     428             : 
     429           0 :         sc->id->t_sc = sc;
     430             : 
     431           0 :         pckbc_set_inputhandler(sc->id->t_kbctag, sc->id->t_kbcslot,
     432           0 :                                pckbd_input, sc, sc->sc_dev.dv_xname);
     433             : 
     434           0 :         a.console = isconsole;
     435             : 
     436           0 :         a.keymap = &pckbd_keymapdata;
     437             : 
     438           0 :         a.accessops = &pckbd_accessops;
     439           0 :         a.accesscookie = sc;
     440             : 
     441           0 :         printf("\n");
     442             : 
     443             :         /*
     444             :          * Attach the wskbd, saving a handle to it.
     445             :          */
     446           0 :         sc->sc_wskbddev = config_found(self, &a, wskbddevprint);
     447           0 : }
     448             : 
     449             : int
     450           0 : pckbd_enable(void *v, int on)
     451             : {
     452           0 :         struct pckbd_softc *sc = v;
     453           0 :         u_char cmd[1];
     454             :         int res;
     455             : 
     456           0 :         if (on) {
     457           0 :                 if (sc->sc_enabled)
     458           0 :                         return (EBUSY);
     459             : 
     460           0 :                 pckbc_slot_enable(sc->id->t_kbctag, sc->id->t_kbcslot, 1);
     461             : 
     462           0 :                 cmd[0] = KBC_ENABLE;
     463           0 :                 res = pckbc_poll_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
     464           0 :                                         cmd, 1, 0, NULL, 0);
     465           0 :                 if (res) {
     466           0 :                         printf("pckbd_enable: command error\n");
     467           0 :                         return (res);
     468             :                 }
     469             : 
     470           0 :                 res = pckbd_set_xtscancode(sc->id->t_kbctag,
     471           0 :                                            sc->id->t_kbcslot, sc->id);
     472           0 :                 if (res)
     473           0 :                         return (res);
     474             : 
     475           0 :                 sc->sc_enabled = 1;
     476           0 :         } else {
     477           0 :                 if (sc->id->t_isconsole)
     478           0 :                         return (EBUSY);
     479             : 
     480           0 :                 cmd[0] = KBC_DISABLE;
     481           0 :                 res = pckbc_enqueue_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
     482           0 :                                         cmd, 1, 0, 1, 0);
     483           0 :                 if (res) {
     484           0 :                         printf("pckbd_disable: command error\n");
     485           0 :                         return (res);
     486             :                 }
     487             : 
     488           0 :                 pckbc_slot_enable(sc->id->t_kbctag, sc->id->t_kbcslot, 0);
     489             : 
     490           0 :                 sc->sc_enabled = 0;
     491             :         }
     492             : 
     493           0 :         return (0);
     494           0 : }
     495             : 
     496             : const u_int8_t pckbd_xtbl[] = {
     497             : /* 0x00 */
     498             :         0,
     499             :         0x43,           /* F9 */
     500             :         0,
     501             :         0x3f,           /* F5 */
     502             :         0x3d,           /* F3 */
     503             :         0x3b,           /* F1 */
     504             :         0x3c,           /* F2 */
     505             :         0x58,           /* F12 */
     506             :         0x40,           /* F6 according to documentation */
     507             :         0x44,           /* F10 */
     508             :         0x42,           /* F8 */
     509             :         0x40,           /* F6 according to experimentation */
     510             :         0x3e,           /* F4 */
     511             :         0x0f,           /* Tab */
     512             :         0x29,           /* ` ~ */
     513             :         0,
     514             : /* 0x10 */
     515             :         0,
     516             :         0x38,           /* Left Alt */
     517             :         0x2a,           /* Left Shift */
     518             :         0,
     519             :         0x1d,           /* Left Ctrl */
     520             :         0x10,           /* q */
     521             :         0x02,           /* 1 ! */
     522             :         0,
     523             :         0,
     524             :         0,
     525             :         0x2c,           /* z */
     526             :         0x1f,           /* s */
     527             :         0x1e,           /* a */
     528             :         0x11,           /* w */
     529             :         0x03,           /* 2 @ */
     530             :         0,
     531             : /* 0x20 */      
     532             :         0,
     533             :         0x2e,           /* c */
     534             :         0x2d,           /* x */
     535             :         0x20,           /* d */
     536             :         0x12,           /* e */
     537             :         0x05,           /* 4 $ */
     538             :         0x04,           /* 3 # */
     539             :         0,
     540             :         0,
     541             :         0x39,           /* Space */
     542             :         0x2f,           /* v */
     543             :         0x21,           /* f */
     544             :         0x14,           /* t */
     545             :         0x13,           /* r */
     546             :         0x06,           /* 5 % */
     547             :         0,
     548             : /* 0x30 */
     549             :         0,
     550             :         0x31,           /* n */
     551             :         0x30,           /* b */
     552             :         0x23,           /* h */
     553             :         0x22,           /* g */
     554             :         0x15,           /* y */
     555             :         0x07,           /* 6 ^ */
     556             :         0,
     557             :         0,
     558             :         0,
     559             :         0x32,           /* m */
     560             :         0x24,           /* j */
     561             :         0x16,           /* u */
     562             :         0x08,           /* 7 & */
     563             :         0x09,           /* 8 * */
     564             :         0,
     565             : /* 0x40 */
     566             :         0,
     567             :         0x33,           /* , < */
     568             :         0x25,           /* k */
     569             :         0x17,           /* i */
     570             :         0x18,           /* o */
     571             :         0x0b,           /* 0 ) */
     572             :         0x0a,           /* 9 ( */
     573             :         0,
     574             :         0,
     575             :         0x34,           /* . > */
     576             :         0x35,           /* / ? */
     577             :         0x26,           /* l */
     578             :         0x27,           /* ; : */
     579             :         0x19,           /* p */
     580             :         0x0c,           /* - _ */
     581             :         0,
     582             : /* 0x50 */
     583             :         0,
     584             :         0,
     585             :         0x28,           /* ' " */
     586             :         0,
     587             :         0x1a,           /* [ { */
     588             :         0x0d,           /* = + */
     589             :         0,
     590             :         0,
     591             :         0x3a,           /* Caps Lock */
     592             :         0x36,           /* Right Shift */
     593             :         0x1c,           /* Return */
     594             :         0x1b,           /* ] } */
     595             :         0,
     596             :         0x2b,           /* \ | */
     597             :         0,
     598             :         0,
     599             : /* 0x60 */
     600             :         0,
     601             :         0,
     602             :         0,
     603             :         0,
     604             :         0,
     605             :         0,
     606             :         0x0e,           /* Back Space */
     607             :         0,
     608             :         0,
     609             :         0x4f,           /* KP 1 */
     610             :         0,
     611             :         0x4b,           /* KP 4 */
     612             :         0x47,           /* KP 7 */
     613             :         0,
     614             :         0,
     615             :         0,
     616             : /* 0x70 */
     617             :         0x52,           /* KP 0 */
     618             :         0x53,           /* KP . */
     619             :         0x50,           /* KP 2 */
     620             :         0x4c,           /* KP 5 */
     621             :         0x4d,           /* KP 6 */
     622             :         0x48,           /* KP 8 */
     623             :         0x01,           /* Escape */
     624             :         0x45,           /* Num Lock */
     625             :         0x57,           /* F11 */
     626             :         0x4e,           /* KP + */
     627             :         0x51,           /* KP 3 */
     628             :         0x4a,           /* KP - */
     629             :         0x37,           /* KP * */
     630             :         0x49,           /* KP 9 */
     631             :         0x46,           /* Scroll Lock */
     632             :         0,
     633             : /* 0x80 */
     634             :         0,
     635             :         0,
     636             :         0,
     637             :         0x41,           /* F7 (produced as an actual 8 bit code) */
     638             :         0               /* Alt-Print Screen */
     639             : };
     640             : 
     641             : const u_int8_t pckbd_xtbl_ext[] = {
     642             : /* 0x00 */
     643             :         0,
     644             :         0,
     645             :         0,
     646             :         0,
     647             :         0,
     648             :         0,
     649             :         0,
     650             :         0,
     651             :         0,
     652             :         0,
     653             :         0,
     654             :         0,
     655             :         0,
     656             :         0,
     657             :         0,
     658             : /* 0x10 */
     659             :         0,
     660             :         0x38,           /* Right Alt */
     661             :         0,              /* E0 12, to be ignored */
     662             :         0,
     663             :         0x1d,           /* Right Ctrl */
     664             :         0,
     665             :         0,
     666             :         0,
     667             :         0,
     668             :         0,
     669             :         0,
     670             :         0,
     671             :         0,
     672             :         0,
     673             :         0,
     674             :         0,
     675             : /* 0x20 */
     676             :         0,
     677             :         0,
     678             :         0,
     679             :         0,
     680             :         0,
     681             :         0,
     682             :         0,
     683             :         0,
     684             :         0,
     685             :         0,
     686             :         0,
     687             :         0,
     688             :         0,
     689             :         0,
     690             :         0,
     691             :         0,
     692             : /* 0x30 */
     693             :         0,
     694             :         0,
     695             :         0,
     696             :         0,
     697             :         0,
     698             :         0,
     699             :         0,
     700             :         0,
     701             :         0,
     702             :         0,
     703             :         0,
     704             :         0,
     705             :         0,
     706             :         0,
     707             :         0,
     708             :         0,
     709             : /* 0x40 */
     710             :         0,
     711             :         0,
     712             :         0,
     713             :         0,
     714             :         0,
     715             :         0,
     716             :         0,
     717             :         0,
     718             :         0,
     719             :         0,
     720             :         0x55,           /* KP / */
     721             :         0,
     722             :         0,
     723             :         0,
     724             :         0,
     725             :         0,
     726             : /* 0x50 */
     727             :         0,
     728             :         0,
     729             :         0,
     730             :         0,
     731             :         0,
     732             :         0,
     733             :         0,
     734             :         0,
     735             :         0,
     736             :         0,
     737             :         0x1c,           /* KP Return */
     738             :         0,
     739             :         0,
     740             :         0,
     741             :         0,
     742             :         0,
     743             : /* 0x60 */
     744             :         0,
     745             :         0,
     746             :         0,
     747             :         0,
     748             :         0,
     749             :         0,
     750             :         0,
     751             :         0,
     752             :         0,
     753             :         0x4f,           /* End */
     754             :         0,
     755             :         0x4b,           /* Left */
     756             :         0x47,           /* Home */
     757             :         0,
     758             :         0,
     759             :         0,
     760             : /* 0x70 */
     761             :         0x52,           /* Insert */
     762             :         0x53,           /* Delete */
     763             :         0x50,           /* Down */
     764             :         0,
     765             :         0x4d,           /* Right */
     766             :         0x48,           /* Up */
     767             :         0,
     768             :         0,
     769             :         0,
     770             :         0,
     771             :         0x51,           /* Page Down */
     772             :         0,
     773             :         0x37,           /* Print Screen */
     774             :         0x49,           /* Page Up */
     775             :         0x46,           /* Ctrl-Break */
     776             :         0
     777             : };
     778             : 
     779             : /*
     780             :  * Translate scan codes from set 2 to set 1
     781             :  */
     782             : int
     783           0 : pckbd_scancode_translate(struct pckbd_internal *id, int datain)
     784             : {
     785           0 :         if (id->t_translating != 0 || id->t_table == 1)
     786           0 :                 return datain;
     787             : 
     788           0 :         if (datain == KBR_BREAK) {
     789           0 :                 id->t_releasing = 0x80;      /* next keycode is a release */
     790           0 :                 return 0;       /* consume scancode */
     791             :         }
     792             : 
     793             :         /*
     794             :          * Convert BREAK sequence (14 77 -> 1D 45)
     795             :          */
     796           0 :         if (id->t_extended1 == 2 && datain == 0x14)
     797           0 :                 return 0x1d | id->t_releasing;
     798           0 :         else if (id->t_extended1 == 1 && datain == 0x77)
     799           0 :                 return 0x45 | id->t_releasing;
     800             : 
     801           0 :         if (id->t_extended != 0) {
     802           0 :                 if (datain >= sizeof pckbd_xtbl_ext)
     803           0 :                         datain = 0;
     804             :                 else
     805           0 :                         datain = pckbd_xtbl_ext[datain];
     806             :         } else {
     807           0 :                 if (datain >= sizeof pckbd_xtbl)
     808           0 :                         datain = 0;
     809             :                 else
     810           0 :                         datain = pckbd_xtbl[datain];
     811             :         }
     812             : 
     813           0 :         if (datain == 0) {
     814             :                 /*
     815             :                  * We don't know how to translate this scan code, but
     816             :                  * we can't silently eat it either (because there might
     817             :                  * have been an extended byte transmitted already).
     818             :                  * Hopefully this value will be harmless to the upper
     819             :                  * layers.
     820             :                  */
     821           0 :                 return 0xff;
     822             :         }
     823             : 
     824           0 :         return datain | id->t_releasing;
     825           0 : }
     826             : 
     827             : static int
     828           0 : pckbd_decode(struct pckbd_internal *id, int datain, u_int *type, int *dataout)
     829             : {
     830             :         int key;
     831             :         int releasing;
     832             : 
     833           0 :         if (datain == KBR_EXTENDED0) {
     834           0 :                 id->t_extended = 0x80;
     835           0 :                 return 0;
     836           0 :         } else if (datain == KBR_EXTENDED1) {
     837           0 :                 id->t_extended1 = 2;
     838           0 :                 return 0;
     839             :         }
     840             : 
     841           0 :         releasing = datain & 0x80;
     842           0 :         datain &= 0x7f;
     843             : 
     844             :         /*
     845             :          * process BREAK key sequence (EXT1 1D 45 / EXT1 9D C5):
     846             :          * map to (unused) code 7F
     847             :          */
     848           0 :         if (id->t_extended1 == 2 && datain == 0x1d) {
     849           0 :                 id->t_extended1 = 1;
     850           0 :                 return 0;
     851           0 :         } else if (id->t_extended1 == 1 && datain == 0x45) {
     852             :                 id->t_extended1 = 0;
     853             :                 datain = 0x7f;
     854           0 :         } else
     855             :                 id->t_extended1 = 0;
     856             : 
     857           0 :         if (id->t_translating != 0 || id->t_table == 1) {
     858           0 :                 id->t_releasing = releasing;
     859           0 :         } else {
     860             :                 /* id->t_releasing computed in pckbd_scancode_translate() */
     861             :         }
     862             : 
     863             :         /* map extended keys to (unused) codes 128-254 */
     864           0 :         key = datain | id->t_extended;
     865           0 :         id->t_extended = 0;
     866             : 
     867           0 :         if (id->t_releasing) {
     868           0 :                 id->t_releasing = 0;
     869           0 :                 id->t_lastchar = 0;
     870           0 :                 *type = WSCONS_EVENT_KEY_UP;
     871           0 :         } else {
     872             :                 /* Always ignore typematic keys */
     873           0 :                 if (key == id->t_lastchar)
     874           0 :                         return 0;
     875           0 :                 id->t_lastchar = key;
     876           0 :                 *type = WSCONS_EVENT_KEY_DOWN;
     877             :         }
     878             : 
     879           0 :         *dataout = key;
     880           0 :         return 1;
     881           0 : }
     882             : 
     883             : void
     884           0 : pckbd_init(struct pckbd_internal *t, pckbc_tag_t kbctag, pckbc_slot_t kbcslot,
     885             :     int console)
     886             : {
     887           0 :         bzero(t, sizeof(struct pckbd_internal));
     888             : 
     889           0 :         t->t_isconsole = console;
     890           0 :         t->t_kbctag = kbctag;
     891           0 :         t->t_kbcslot = kbcslot;
     892           0 : }
     893             : 
     894             : static int
     895           0 : pckbd_led_encode(int led)
     896             : {
     897             :         int res;
     898             : 
     899             :         res = 0;
     900             : 
     901           0 :         if (led & WSKBD_LED_SCROLL)
     902           0 :                 res |= 0x01;
     903           0 :         if (led & WSKBD_LED_NUM)
     904           0 :                 res |= 0x02;
     905           0 :         if (led & WSKBD_LED_CAPS)
     906           0 :                 res |= 0x04;
     907           0 :         return(res);
     908             : }
     909             : 
     910             : void
     911           0 : pckbd_set_leds(void *v, int leds)
     912             : {
     913           0 :         struct pckbd_softc *sc = v;
     914           0 :         u_char cmd[2];
     915             : 
     916           0 :         cmd[0] = KBC_MODEIND;
     917           0 :         cmd[1] = pckbd_led_encode(leds);
     918           0 :         sc->sc_ledstate = leds;
     919             : 
     920           0 :         (void) pckbc_enqueue_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
     921           0 :                                  cmd, 2, 0, 0, 0);
     922           0 : }
     923             : 
     924             : /*
     925             :  * Got a console receive interrupt -
     926             :  * the console processor wants to give us a character.
     927             :  */
     928             : void
     929           0 : pckbd_input(void *vsc, int data)
     930             : {
     931           0 :         struct pckbd_softc *sc = vsc;
     932           0 :         int rc, type, key;
     933             : 
     934           0 :         data = pckbd_scancode_translate(sc->id, data);
     935           0 :         if (data == 0)
     936           0 :                 return;
     937             : 
     938           0 :         rc = pckbd_decode(sc->id, data, &type, &key);
     939             : 
     940             : #ifdef WSDISPLAY_COMPAT_RAWKBD
     941           0 :         if (sc->rawkbd) {
     942           0 :                 sc->sc_rawbuf[sc->sc_rawcnt++] = (char)data;
     943             : 
     944           0 :                 if (rc != 0 || sc->sc_rawcnt == sizeof(sc->sc_rawbuf)) {
     945           0 :                         wskbd_rawinput(sc->sc_wskbddev, sc->sc_rawbuf,
     946           0 :                             sc->sc_rawcnt);
     947           0 :                         sc->sc_rawcnt = 0;
     948           0 :                 }
     949             : 
     950             :                 /*
     951             :                  * Pass audio keys to wskbd_input anyway.
     952             :                  */
     953           0 :                 if (rc == 0 || (key != 160 && key != 174 && key != 176))
     954           0 :                         return;
     955             :         }
     956             : #endif
     957           0 :         if (rc != 0)
     958           0 :                 wskbd_input(sc->sc_wskbddev, type, key);
     959           0 : }
     960             : 
     961             : int
     962           0 : pckbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
     963             : {
     964           0 :         struct pckbd_softc *sc = v;
     965             : 
     966           0 :         switch (cmd) {
     967             :             case WSKBDIO_GTYPE:
     968           0 :                 *(int *)data = WSKBD_TYPE_PC_XT;
     969           0 :                 return 0;
     970             :             case WSKBDIO_SETLEDS: {
     971           0 :                 char cmd[2];
     972             :                 int res;
     973           0 :                 cmd[0] = KBC_MODEIND;
     974           0 :                 cmd[1] = pckbd_led_encode(*(int *)data);
     975           0 :                 sc->sc_ledstate = *(int *)data & (WSKBD_LED_SCROLL |
     976             :                     WSKBD_LED_NUM | WSKBD_LED_CAPS);
     977           0 :                 res = pckbc_enqueue_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
     978           0 :                                         cmd, 2, 0, 1, 0);
     979             :                 return (res);
     980           0 :                 }
     981             :             case WSKBDIO_GETLEDS:
     982           0 :                 *(int *)data = sc->sc_ledstate;
     983           0 :                 return (0);
     984             :             case WSKBDIO_COMPLEXBELL:
     985             : #define d ((struct wskbd_bell_data *)data)
     986             :                 /*
     987             :                  * Keyboard can't beep directly; we have an
     988             :                  * externally-provided global hook to do this.
     989             :                  */
     990           0 :                 pckbd_bell(d->pitch, d->period, d->volume, 0);
     991             : #undef d
     992           0 :                 return (0);
     993             : #ifdef WSDISPLAY_COMPAT_RAWKBD
     994             :             case WSKBDIO_SETMODE:
     995           0 :                 sc->rawkbd = (*(int *)data == WSKBD_RAW);
     996           0 :                 return (0);
     997             : #endif
     998             :         }
     999           0 :         return -1;
    1000           0 : }
    1001             : 
    1002             : void
    1003           0 : pckbd_bell(u_int pitch, u_int period, u_int volume, int poll)
    1004             : {
    1005             : 
    1006           0 :         if (pckbd_bell_fn != NULL)
    1007           0 :                 (*pckbd_bell_fn)(pckbd_bell_fn_arg, pitch, period,
    1008             :                     volume, poll);
    1009           0 : }
    1010             : 
    1011             : void
    1012           0 : pckbd_hookup_bell(void (*fn)(void *, u_int, u_int, u_int, int), void *arg)
    1013             : {
    1014             : 
    1015           0 :         if (pckbd_bell_fn == NULL) {
    1016           0 :                 pckbd_bell_fn = fn;
    1017           0 :                 pckbd_bell_fn_arg = arg;
    1018           0 :         }
    1019           0 : }
    1020             : 
    1021             : int
    1022           0 : pckbd_cnattach(pckbc_tag_t kbctag)
    1023             : {
    1024             : 
    1025           0 :         pckbd_init(&pckbd_consdata, kbctag, PCKBC_KBD_SLOT, 1);
    1026             : 
    1027           0 :         wskbd_cnattach(&pckbd_consops, &pckbd_consdata, &pckbd_keymapdata);
    1028             : 
    1029           0 :         return (0);
    1030             : }
    1031             : 
    1032             : /* ARGSUSED */
    1033             : void
    1034           0 : pckbd_cngetc(void *v, u_int *type, int *data)
    1035             : {
    1036           0 :         struct pckbd_internal *t = v;
    1037             :         int val;
    1038             : 
    1039           0 :         for (;;) {
    1040           0 :                 val = pckbc_poll_data(t->t_kbctag, t->t_kbcslot);
    1041           0 :                 if (val == -1)
    1042           0 :                         continue;
    1043             : 
    1044           0 :                 val = pckbd_scancode_translate(t, val);
    1045           0 :                 if (val == 0)
    1046           0 :                         continue;
    1047             : 
    1048           0 :                 if (pckbd_decode(t, val, type, data))
    1049             :                         return;
    1050             :         }
    1051           0 : }
    1052             : 
    1053             : void
    1054           0 : pckbd_cnpollc(void *v, int on)
    1055             : {
    1056           0 :         struct pckbd_internal *t = v;
    1057             : 
    1058           0 :         pckbc_set_poll(t->t_kbctag, t->t_kbcslot, on);
    1059             : 
    1060             :         /*
    1061             :          * If we enter ukc or ddb before having attached the console
    1062             :          * keyboard we need to probe its scan code set.
    1063             :          */
    1064           0 :         if (t->t_table == 0) {
    1065           0 :                 char cmd[1];
    1066             : 
    1067           0 :                 pckbc_flush(t->t_kbctag, t->t_kbcslot);
    1068           0 :                 pckbd_set_xtscancode(t->t_kbctag, t->t_kbcslot, t);
    1069             : 
    1070             :                 /* Just to be sure. */
    1071           0 :                 cmd[0] = KBC_ENABLE;
    1072           0 :                 pckbc_poll_cmd(t->t_kbctag, PCKBC_KBD_SLOT, cmd, 1, 0, NULL, 0);
    1073           0 :         }
    1074           0 : }
    1075             : 
    1076             : void
    1077           0 : pckbd_cnbell(void *v, u_int pitch, u_int period, u_int volume)
    1078             : {
    1079             : 
    1080           0 :         pckbd_bell(pitch, period, volume, 1);
    1081           0 : }
    1082             : 
    1083             : struct cfdriver pckbd_cd = {
    1084             :         NULL, "pckbd", DV_DULL
    1085             : };

Generated by: LCOV version 1.13