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


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

FreeBSD/Linux Kernel Cross Reference
sys/dev/hpc/hpf1275a_tty.c

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

    1 /*      $NetBSD: hpf1275a_tty.c,v 1.23 2008/04/06 20:28:36 cegger Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2004 Valeriy E. Ushakov
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. The name of the author may not be used to endorse or promote products
   16  *    derived from this software without specific prior written permission
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __KERNEL_RCSID(0, "$NetBSD: hpf1275a_tty.c,v 1.23 2008/04/06 20:28:36 cegger Exp $");
   32 
   33 #include "opt_wsdisplay_compat.h"
   34 
   35 #include <sys/param.h>
   36 #include <sys/kernel.h>
   37 #include <sys/conf.h>
   38 #include <sys/device.h>
   39 #include <sys/tty.h>
   40 #include <sys/fcntl.h>
   41 #include <sys/proc.h>
   42 #include <sys/systm.h>
   43 #include <sys/kauth.h>
   44 
   45 #include <dev/wscons/wsconsio.h>
   46 #include <dev/wscons/wskbdvar.h>
   47 #include <dev/wscons/wsksymdef.h>
   48 #include <dev/wscons/wsksymvar.h>
   49 
   50 #include <dev/pckbport/wskbdmap_mfii.h>
   51 #ifdef WSDISPLAY_COMPAT_RAWKBD
   52 #include <dev/hpc/pckbd_encode.h>
   53 #endif
   54 
   55 
   56 extern struct cfdriver hpf1275a_cd;
   57 
   58 struct hpf1275a_softc {
   59         struct device sc_dev;
   60 
   61         struct tty *sc_tp;              /* back reference to the tty */
   62         struct device *sc_wskbd;        /* wskbd child */
   63         int sc_enabled;
   64 #ifdef WSDISPLAY_COMPAT_RAWKBD
   65         int sc_rawkbd;
   66 #endif
   67 };
   68 
   69 
   70 /* pseudo-device initialization */
   71 extern void     hpf1275aattach(int);
   72 
   73 /* line discipline methods */
   74 static int      hpf1275a_open(dev_t, struct tty *);
   75 static int      hpf1275a_close(struct tty *, int);
   76 static int      hpf1275a_input(int, struct tty *);
   77 
   78 /* autoconf(9) methods */
   79 static int      hpf1275a_match(struct device *, struct cfdata *, void *);
   80 static void     hpf1275a_attach(struct device *, struct device *, void *);
   81 static int      hpf1275a_detach(struct device *, int);
   82 
   83 /* wskbd(4) accessops */
   84 static int      hpf1275a_wskbd_enable(void *, int);
   85 static void     hpf1275a_wskbd_set_leds(void *, int);
   86 static int      hpf1275a_wskbd_ioctl(void *, u_long, void *, int,
   87                                      struct lwp *);
   88 
   89 
   90 /* 
   91  * It doesn't need to be exported, as only hpf1275aattach() uses it,
   92  * but there's no "official" way to make it static.
   93  */
   94 CFATTACH_DECL(hpf1275a, sizeof(struct hpf1275a_softc),
   95     hpf1275a_match, hpf1275a_attach, hpf1275a_detach, NULL);
   96 
   97 
   98 static struct linesw hpf1275a_disc = {
   99         .l_name = "hpf1275a",
  100         .l_open = hpf1275a_open,
  101         .l_close = hpf1275a_close,
  102         .l_read = ttyerrio,
  103         .l_write = ttyerrio,
  104         .l_ioctl = ttynullioctl,
  105         .l_rint = hpf1275a_input,
  106         .l_start = ttstart,
  107         .l_modem = nullmodem,
  108         .l_poll = ttpoll
  109 };
  110 
  111 
  112 static const struct wskbd_accessops hpf1275a_wskbd_accessops = {
  113         hpf1275a_wskbd_enable,
  114         hpf1275a_wskbd_set_leds,
  115         hpf1275a_wskbd_ioctl
  116 };
  117 
  118 
  119 static const struct wskbd_mapdata hpf1275a_wskbd_keymapdata = {
  120         pckbd_keydesctab, KB_US
  121 };
  122 
  123 
  124 /* F1275A scancodes -> XT scancodes so that we can use pckbd_keydesctab. */
  125 static const uint8_t hpf1275a_to_xtscan[128] = {
  126         [0x04] = 30,            /* a */
  127         [0x05] = 48,            /* b */
  128         [0x06] = 46,            /* c */
  129         [0x07] = 32,            /* d */
  130         [0x08] = 18,            /* e */
  131         [0x09] = 33,            /* f */
  132         [0x0a] = 34,            /* g */
  133         [0x0b] = 35,            /* h */
  134         [0x0c] = 23,            /* i */
  135         [0x0d] = 36,            /* j */
  136         [0x0e] = 37,            /* k */
  137         [0x0f] = 38,            /* l */
  138         [0x10] = 50,            /* m */
  139         [0x11] = 49,            /* n */
  140         [0x12] = 24,            /* o */
  141         [0x13] = 25,            /* p */
  142         [0x14] = 16,            /* q */
  143         [0x15] = 19,            /* r */
  144         [0x16] = 31,            /* s */
  145         [0x17] = 20,            /* t */
  146         [0x18] = 22,            /* u */
  147         [0x19] = 47,            /* v */
  148         [0x1a] = 17,            /* w */
  149         [0x1b] = 45,            /* x */
  150         [0x1c] = 21,            /* y */
  151         [0x1d] = 44,            /* z */
  152 
  153         [0x1e] = 2,             /* 1 */
  154         [0x1f] = 3,             /* 2 */
  155         [0x20] = 4,             /* 3 */
  156         [0x21] = 5,             /* 4 */
  157         [0x22] = 6,             /* 5 */
  158         [0x23] = 7,             /* 6 */
  159         [0x24] = 8,             /* 7 */
  160         [0x25] = 9,             /* 8 */
  161         [0x26] = 10,            /* 9 */
  162         [0x27] = 11,            /* 0 */
  163 
  164         [0x28] = 28,            /* Enter */
  165 
  166         [0x29] = 1,             /* ESC */
  167         [0x2a] = 14,            /* Backspace */
  168         [0x2b] = 15,            /* Tab */
  169         [0x2c] = 57,            /* Space */
  170 
  171         [0x2d] = 12,            /* - */
  172         [0x2e] = 13,            /* = */
  173         [0x2f] = 26,            /* [ */
  174         [0x30] = 27,            /* ] */
  175         [0x31] = 43,            /* \ */
  176 
  177         [0x33] = 39,            /* ; */
  178         [0x34] = 40,            /* ' */
  179         [0x35] = 41,            /* ` */
  180         [0x36] = 51,            /* , */
  181         [0x37] = 52,            /* . */
  182         [0x38] = 53,            /* / */
  183 
  184         [0x3a] = 59,            /* F1 */
  185         [0x3b] = 60,            /* F2 */
  186         [0x3c] = 61,            /* F3 */
  187         [0x3d] = 62,            /* F4 */
  188         [0x3e] = 63,            /* F5 */
  189         [0x3f] = 64,            /* F6 */
  190         [0x40] = 65,            /* F7 */
  191         [0x41] = 66,            /* F8 */
  192 
  193         [0x42] = 68,            /* "OK" -> F10 */
  194         [0x43] = 87,            /* "Cancel" -> F11 */
  195 
  196         [0x4c] = 211,           /* Del */
  197 
  198         [0x4f] = 205,           /* Right */
  199         [0x50] = 203,           /* Left  */
  200         [0x51] = 208,           /* Down  */
  201         [0x52] = 200,           /* Up    */
  202 
  203         [0x53] = 67,            /* "task switch" -> F9 */
  204 
  205         [0x65] = 221,           /* windows */
  206         [0x66] = 88,            /* "keyboard" -> F12 */
  207 
  208         [0x74] = 42,            /* Shift (left) */
  209         [0x75] = 54,            /* Shift (right) */
  210         [0x76] = 56,            /* Alt (left) */
  211         [0x77] = 184,           /* Fn -> AltGr == Mode Switch */
  212         [0x78] = 29,            /* Control (left) */
  213 };
  214 
  215 
  216 /*
  217  * Pseudo-device initialization routine called from main().
  218  */
  219 void
  220 hpf1275aattach(int n)
  221 {
  222         int error;
  223 
  224         error = ttyldisc_attach(&hpf1275a_disc);
  225         if (error) {
  226                 printf("%s: unable to register line discipline, error = %d\n",
  227                        hpf1275a_cd.cd_name, error);
  228                 return;
  229         }
  230 
  231         error = config_cfattach_attach(hpf1275a_cd.cd_name, &hpf1275a_ca);
  232         if (error) {
  233                 printf("%s: unable to register cfattach, error = %d\n",
  234                        hpf1275a_cd.cd_name, error);
  235                 config_cfdriver_detach(&hpf1275a_cd);
  236                 (void) ttyldisc_detach(&hpf1275a_disc);
  237         }
  238 }
  239 
  240 
  241 /*
  242  * Autoconf match routine.
  243  *
  244  * XXX: unused: config_attach_pseudo(9) does not call ca_match.
  245  */
  246 static int
  247 hpf1275a_match(struct device *self,
  248                struct cfdata *cfdata, void *arg)
  249 {
  250 
  251         /* pseudo-device; always present */
  252         return (1);
  253 }
  254 
  255 
  256 /*
  257  * Autoconf attach routine.  Called by config_attach_pseudo(9) when we
  258  * open the line discipline.
  259  */
  260 static void
  261 hpf1275a_attach(struct device *parent,
  262                 struct device *self, void *aux)
  263 {
  264         struct hpf1275a_softc *sc = device_private(self);
  265         struct wskbddev_attach_args wska;
  266 
  267         wska.console = 0;
  268         wska.keymap = &hpf1275a_wskbd_keymapdata;
  269         wska.accessops = &hpf1275a_wskbd_accessops;
  270         wska.accesscookie = sc;
  271 
  272         sc->sc_enabled = 0;
  273 #ifdef WSDISPLAY_COMPAT_RAWKBD
  274         sc->sc_rawkbd = 0;
  275 #endif
  276         sc->sc_wskbd = config_found(self, &wska, wskbddevprint);
  277 }
  278 
  279 
  280 /*
  281  * Autoconf detach routine.  Called when we close the line discipline.
  282  */
  283 static int
  284 hpf1275a_detach(struct device *self, int flags)
  285 {
  286         struct hpf1275a_softc *sc = device_private(self);
  287         int error;
  288 
  289         if (sc->sc_wskbd == NULL)
  290                 return (0);
  291 
  292         error = config_detach(sc->sc_wskbd, 0);
  293 
  294         return (error);
  295 }
  296 
  297 
  298 /*
  299  * Line discipline open routine.
  300  */
  301 static int
  302 hpf1275a_open(dev_t dev, struct tty *tp)
  303 {
  304         static struct cfdata hpf1275a_cfdata = {
  305                 .cf_name = "hpf1275a",
  306                 .cf_atname = "hpf1275a",
  307                 .cf_unit = 0,
  308                 .cf_fstate = FSTATE_STAR,
  309         };
  310         struct lwp *l = curlwp;         /* XXX */
  311         struct hpf1275a_softc *sc;
  312         int error, s;
  313 
  314         if ((error = kauth_authorize_device_tty(l->l_cred,
  315                         KAUTH_DEVICE_TTY_OPEN, tp)))
  316                 return (error);
  317 
  318         s = spltty();
  319 
  320         if (tp->t_linesw == &hpf1275a_disc) {
  321                 splx(s);
  322                 return 0;
  323         }
  324 
  325         sc = (struct hpf1275a_softc *)config_attach_pseudo(&hpf1275a_cfdata);
  326         if (sc == NULL) {
  327                 splx(s);
  328                 return (EIO);
  329         }
  330 
  331         tp->t_sc = sc;
  332         sc->sc_tp = tp;
  333 
  334         splx(s);
  335         return (0);
  336 }
  337 
  338 
  339 /*
  340  * Line discipline close routine.
  341  */
  342 static int
  343 hpf1275a_close(struct tty *tp, int flag)
  344 {
  345         struct hpf1275a_softc *sc = tp->t_sc;
  346         int s;
  347 
  348         s = spltty();
  349         mutex_spin_enter(&tty_lock);
  350         ttyflush(tp, FREAD | FWRITE);
  351         mutex_spin_exit(&tty_lock);      /* XXX */
  352         ttyldisc_release(tp->t_linesw);
  353         tp->t_linesw = ttyldisc_default();
  354         if (sc != NULL) {
  355                 tp->t_sc = NULL;
  356                 if (sc->sc_tp == tp)
  357                         config_detach(&sc->sc_dev, 0);
  358         }
  359         splx(s);
  360         return (0);
  361 }
  362 
  363 
  364 /*
  365  * Feed input from the keyboard to wskbd(4).
  366  */
  367 static int
  368 hpf1275a_input(int c, struct tty *tp)
  369 {
  370         struct hpf1275a_softc *sc = tp->t_sc;
  371         int code;
  372         u_int type;
  373         int xtscan;
  374 
  375         if (!sc->sc_enabled)
  376                 return (0);
  377 
  378         if (c & TTY_ERRORMASK)
  379                 return (0);     /* TODO? */
  380 
  381         code = c & TTY_CHARMASK;
  382         if (code & 0x80) {
  383                 type = WSCONS_EVENT_KEY_UP;
  384                 code &= ~0x80;
  385         } else
  386                 type = WSCONS_EVENT_KEY_DOWN;
  387 
  388         xtscan = hpf1275a_to_xtscan[code];
  389         if (xtscan == 0) {
  390                 aprint_error_dev(&sc->sc_dev, "unknown code 0x%x\n", code);
  391                 return (0);
  392         }
  393 
  394         KASSERT(sc->sc_wskbd != NULL);
  395 
  396 #ifdef WSDISPLAY_COMPAT_RAWKBD
  397         if (sc->sc_rawkbd) {
  398                 u_char data[16];
  399                 int n;
  400 
  401                 n = pckbd_encode(type, xtscan, data);
  402                 wskbd_rawinput(sc->sc_wskbd, data, n);
  403         } else
  404 #endif
  405                 wskbd_input(sc->sc_wskbd, type, xtscan);
  406 
  407         return (0);
  408 }
  409 
  410 
  411 static int
  412 hpf1275a_wskbd_enable(void *self, int on)
  413 {
  414         struct hpf1275a_softc *sc = self;
  415 
  416         sc->sc_enabled = on;
  417         return (0);
  418 }
  419 
  420 
  421 /* ARGSUSED */
  422 static void
  423 hpf1275a_wskbd_set_leds(void *self, int leds)
  424 {
  425 
  426         /* this keyboard has no leds; nothing to do */
  427         return;
  428 }
  429 
  430 
  431 static int
  432 hpf1275a_wskbd_ioctl(void *self, u_long cmd, void *data, int flag,
  433                      struct lwp *l)
  434 {
  435 #ifdef WSDISPLAY_COMPAT_RAWKBD
  436         struct hpf1275a_softc *sc = self;
  437 #endif
  438 
  439         switch (cmd) {
  440         case WSKBDIO_GTYPE:
  441                 *(int *)data = WSKBD_TYPE_HPC_KBD; /* may be use new type? */
  442                 return (0);
  443 
  444         case WSKBDIO_GETLEDS:
  445                 *(int *)data = 0; /* this keyboard has no leds */
  446                 return (0);
  447 
  448 #ifdef WSDISPLAY_COMPAT_RAWKBD
  449         case WSKBDIO_SETMODE:
  450                 sc->sc_rawkbd = (*(int *)data == WSKBD_RAW);
  451                 return (0);
  452 #endif
  453 
  454         default:
  455                 return (EPASSTHROUGH);
  456         }
  457 }

Cache object: 850eed7ab2615fc01c7d1ff8fe3917fa


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


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