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

          Line data    Source code
       1             : /* $OpenBSD: wsdisplay_compat_usl.c,v 1.32 2017/01/23 04:43:46 deraadt Exp $ */
       2             : /* $NetBSD: wsdisplay_compat_usl.c,v 1.12 2000/03/23 07:01:47 thorpej Exp $ */
       3             : 
       4             : /*
       5             :  * Copyright (c) 1998
       6             :  *      Matthias Drochner.  All rights reserved.
       7             :  *
       8             :  * Redistribution and use in source and binary forms, with or without
       9             :  * modification, are permitted provided that the following conditions
      10             :  * are met:
      11             :  * 1. Redistributions of source code must retain the above copyright
      12             :  *    notice, this list of conditions and the following disclaimer.
      13             :  * 2. Redistributions in binary form must reproduce the above copyright
      14             :  *    notice, this list of conditions and the following disclaimer in the
      15             :  *    documentation and/or other materials provided with the distribution.
      16             :  *
      17             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
      18             :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      19             :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      20             :  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
      21             :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      22             :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      23             :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      24             :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      25             :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      26             :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      27             :  *
      28             :  */
      29             : 
      30             : #include <sys/param.h>
      31             : #include <sys/systm.h>
      32             : #include <sys/timeout.h>
      33             : #include <sys/kernel.h>
      34             : #include <sys/proc.h>
      35             : #include <sys/signalvar.h>
      36             : #include <sys/malloc.h>
      37             : #include <sys/errno.h>
      38             : #include <sys/fcntl.h>
      39             : 
      40             : #include <dev/wscons/wsconsio.h>
      41             : #include <dev/wscons/wsdisplayvar.h>
      42             : #include <dev/wscons/wscons_callbacks.h>
      43             : #include <dev/wscons/wsdisplay_usl_io.h>
      44             : 
      45             : #ifdef WSDISPLAY_DEBUG
      46             : #define DPRINTF(x)       if (wsdisplaydebug) printf x
      47             : int     wsdisplaydebug = 0;
      48             : #else
      49             : #define DPRINTF(x)
      50             : #endif
      51             : 
      52             : struct usl_syncdata {
      53             :         struct wsscreen *s_scr;
      54             :         struct process *s_process;
      55             :         pid_t s_pid;
      56             :         int s_flags;
      57             : #define SF_DETACHPENDING 1
      58             : #define SF_ATTACHPENDING 2
      59             :         int s_acqsig, s_relsig;
      60             :         int s_frsig; /* unused */
      61             :         void (*s_callback)(void *, int, int);
      62             :         void *s_cbarg;
      63             :         struct timeout s_attach_ch;
      64             :         struct timeout s_detach_ch;
      65             : };
      66             : 
      67             : int usl_sync_init(struct wsscreen *, struct usl_syncdata **,
      68             :                        struct process *, int, int, int);
      69             : void usl_sync_done(struct usl_syncdata *);
      70             : int usl_sync_check(struct usl_syncdata *);
      71             : struct usl_syncdata *usl_sync_get(struct wsscreen *);
      72             : 
      73             : int usl_detachproc(void *, int, void (*)(void *, int, int), void *);
      74             : int usl_detachack(struct usl_syncdata *, int);
      75             : void usl_detachtimeout(void *);
      76             : int usl_attachproc(void *, int, void (*)(void *, int, int), void *);
      77             : int usl_attachack(struct usl_syncdata *, int);
      78             : void usl_attachtimeout(void *);
      79             : 
      80             : static const struct wscons_syncops usl_syncops = {
      81             :         usl_detachproc,
      82             :         usl_attachproc,
      83             : #define _usl_sync_check ((int (*)(void *))usl_sync_check)
      84             :         _usl_sync_check,
      85             : #define _usl_sync_destroy ((void (*)(void *))usl_sync_done)
      86             :         _usl_sync_destroy
      87             : };
      88             : 
      89             : #ifndef WSCOMPAT_USL_SYNCTIMEOUT
      90             : #define WSCOMPAT_USL_SYNCTIMEOUT 5 /* seconds */
      91             : #endif
      92             : static int wscompat_usl_synctimeout = WSCOMPAT_USL_SYNCTIMEOUT;
      93             : 
      94             : int
      95           0 : usl_sync_init(struct wsscreen *scr, struct usl_syncdata **sdp,
      96             :     struct process *pr, int acqsig, int relsig, int frsig)
      97             : {
      98             :         struct usl_syncdata *sd;
      99             :         int res;
     100             : 
     101           0 :         if (acqsig <= 0 || acqsig >= NSIG || relsig <= 0 || relsig >= NSIG ||
     102           0 :             frsig <= 0 || frsig >= NSIG)
     103           0 :                 return (EINVAL);
     104           0 :         sd = malloc(sizeof(*sd), M_DEVBUF, M_NOWAIT);
     105           0 :         if (!sd)
     106           0 :                 return (ENOMEM);
     107           0 :         sd->s_scr = scr;
     108           0 :         sd->s_process = pr;
     109           0 :         sd->s_pid = pr->ps_pid;
     110           0 :         sd->s_flags = 0;
     111           0 :         sd->s_acqsig = acqsig;
     112           0 :         sd->s_relsig = relsig;
     113           0 :         sd->s_frsig = frsig;
     114           0 :         timeout_set(&sd->s_attach_ch, usl_attachtimeout, sd);
     115           0 :         timeout_set(&sd->s_detach_ch, usl_detachtimeout, sd);
     116           0 :         res = wsscreen_attach_sync(scr, &usl_syncops, sd);
     117           0 :         if (res) {
     118           0 :                 free(sd, M_DEVBUF, sizeof(*sd));
     119           0 :                 return (res);
     120             :         }
     121           0 :         *sdp = sd;
     122           0 :         return (0);
     123           0 : }
     124             : 
     125             : void
     126           0 : usl_sync_done(struct usl_syncdata *sd)
     127             : {
     128           0 :         if (sd->s_flags & SF_DETACHPENDING) {
     129           0 :                 timeout_del(&sd->s_detach_ch);
     130           0 :                 (*sd->s_callback)(sd->s_cbarg, 0, 0);
     131           0 :         }
     132           0 :         if (sd->s_flags & SF_ATTACHPENDING) {
     133           0 :                 timeout_del(&sd->s_attach_ch);
     134           0 :                 (*sd->s_callback)(sd->s_cbarg, ENXIO, 0);
     135           0 :         }
     136           0 :         wsscreen_detach_sync(sd->s_scr);
     137           0 :         free(sd, M_DEVBUF, sizeof(*sd));
     138           0 : }
     139             : 
     140             : int
     141           0 : usl_sync_check(struct usl_syncdata *sd)
     142             : {
     143           0 :         if (sd->s_process == prfind(sd->s_pid))
     144           0 :                 return (1);
     145             :         DPRINTF(("usl_sync_check: process %d died\n", sd->s_pid));
     146           0 :         usl_sync_done(sd);
     147           0 :         return (0);
     148           0 : }
     149             : 
     150             : struct usl_syncdata *
     151           0 : usl_sync_get(struct wsscreen *scr)
     152             : {
     153           0 :         struct usl_syncdata *sd;
     154             : 
     155           0 :         if (wsscreen_lookup_sync(scr, &usl_syncops, (void **)&sd))
     156           0 :                 return (0);
     157           0 :         return (sd);
     158           0 : }
     159             : 
     160             : int
     161           0 : usl_detachproc(void *cookie, int waitok, void (*callback)(void *, int, int),
     162             :     void *cbarg)
     163             : {
     164           0 :         struct usl_syncdata *sd = cookie;
     165             : 
     166           0 :         if (!usl_sync_check(sd))
     167           0 :                 return (0);
     168             : 
     169             :         /* we really need a callback */
     170           0 :         if (!callback)
     171           0 :                 return (EINVAL);
     172             : 
     173             :         /*
     174             :          * Normally, this is called from the controlling process.
     175             :          * It is supposed to reply with a VT_RELDISP ioctl(), so
     176             :          * it is not useful to tsleep() here.
     177             :          */
     178           0 :         sd->s_callback = callback;
     179           0 :         sd->s_cbarg = cbarg;
     180           0 :         sd->s_flags |= SF_DETACHPENDING;
     181           0 :         prsignal(sd->s_process, sd->s_relsig);
     182           0 :         timeout_add_sec(&sd->s_detach_ch, wscompat_usl_synctimeout);
     183             : 
     184           0 :         return (EAGAIN);
     185           0 : }
     186             : 
     187             : int
     188           0 : usl_detachack(struct usl_syncdata *sd, int ack)
     189             : {
     190           0 :         if (!(sd->s_flags & SF_DETACHPENDING)) {
     191             :                 DPRINTF(("usl_detachack: not detaching\n"));
     192           0 :                 return (EINVAL);
     193             :         }
     194             : 
     195           0 :         timeout_del(&sd->s_detach_ch);
     196           0 :         sd->s_flags &= ~SF_DETACHPENDING;
     197             : 
     198           0 :         if (sd->s_callback)
     199           0 :                 (*sd->s_callback)(sd->s_cbarg, (ack ? 0 : EIO), 1);
     200             : 
     201           0 :         return (0);
     202           0 : }
     203             : 
     204             : void
     205           0 : usl_detachtimeout(void *arg)
     206             : {
     207           0 :         struct usl_syncdata *sd = arg;
     208             : 
     209             :         DPRINTF(("usl_detachtimeout\n"));
     210             : 
     211           0 :         if (!(sd->s_flags & SF_DETACHPENDING)) {
     212             :                 DPRINTF(("usl_detachtimeout: not detaching\n"));
     213           0 :                 return;
     214             :         }
     215             : 
     216           0 :         sd->s_flags &= ~SF_DETACHPENDING;
     217             : 
     218           0 :         if (sd->s_callback)
     219           0 :                 (*sd->s_callback)(sd->s_cbarg, EIO, 0);
     220             : 
     221           0 :         (void) usl_sync_check(sd);
     222           0 : }
     223             : 
     224             : int
     225           0 : usl_attachproc(void *cookie, int waitok, void (*callback)(void *, int, int),
     226             :     void *cbarg)
     227             : {
     228           0 :         struct usl_syncdata *sd = cookie;
     229             : 
     230           0 :         if (!usl_sync_check(sd))
     231           0 :                 return (0);
     232             : 
     233             :         /* we really need a callback */
     234           0 :         if (!callback)
     235           0 :                 return (EINVAL);
     236             : 
     237           0 :         sd->s_callback = callback;
     238           0 :         sd->s_cbarg = cbarg;
     239           0 :         sd->s_flags |= SF_ATTACHPENDING;
     240           0 :         prsignal(sd->s_process, sd->s_acqsig);
     241           0 :         timeout_add_sec(&sd->s_attach_ch, wscompat_usl_synctimeout);
     242             : 
     243           0 :         return (EAGAIN);
     244           0 : }
     245             : 
     246             : int
     247           0 : usl_attachack(struct usl_syncdata *sd, int ack)
     248             : {
     249           0 :         if (!(sd->s_flags & SF_ATTACHPENDING)) {
     250             :                 DPRINTF(("usl_attachack: not attaching\n"));
     251           0 :                 return (EINVAL);
     252             :         }
     253             : 
     254           0 :         timeout_del(&sd->s_attach_ch);
     255           0 :         sd->s_flags &= ~SF_ATTACHPENDING;
     256             : 
     257           0 :         if (sd->s_callback)
     258           0 :                 (*sd->s_callback)(sd->s_cbarg, (ack ? 0 : EIO), 1);
     259             : 
     260           0 :         return (0);
     261           0 : }
     262             : 
     263             : void
     264           0 : usl_attachtimeout(void *arg)
     265             : {
     266           0 :         struct usl_syncdata *sd = arg;
     267             : 
     268             :         DPRINTF(("usl_attachtimeout\n"));
     269             : 
     270           0 :         if (!(sd->s_flags & SF_ATTACHPENDING)) {
     271             :                 DPRINTF(("usl_attachtimeout: not attaching\n"));
     272           0 :                 return;
     273             :         }
     274             : 
     275           0 :         sd->s_flags &= ~SF_ATTACHPENDING;
     276             : 
     277           0 :         if (sd->s_callback)
     278           0 :                 (*sd->s_callback)(sd->s_cbarg, EIO, 0);
     279             : 
     280           0 :         (void) usl_sync_check(sd);
     281           0 : }
     282             : 
     283             : int
     284           0 : wsdisplay_usl_ioctl1(struct wsdisplay_softc *sc, u_long cmd, caddr_t data,
     285             :     int flag, struct proc *p)
     286             : {
     287             :         int idx, maxidx;
     288             : 
     289           0 :         switch (cmd) {
     290             :             case VT_OPENQRY:
     291           0 :                 maxidx = wsdisplay_maxscreenidx(sc);
     292           0 :                 for (idx = 0; idx <= maxidx; idx++) {
     293           0 :                         if (wsdisplay_screenstate(sc, idx) == 0) {
     294           0 :                                 *(int *)data = idx + 1;
     295           0 :                                 return (0);
     296             :                         }
     297             :                 }
     298           0 :                 return (ENXIO);
     299             :             case VT_GETACTIVE:
     300           0 :                 idx = wsdisplay_getactivescreen(sc);
     301           0 :                 *(int *)data = idx + 1;
     302           0 :                 return (0);
     303             :             case VT_ACTIVATE:
     304           0 :                 if ((flag & FWRITE) == 0)
     305           0 :                         return (EACCES);
     306           0 :                 idx = *(int *)data - 1;
     307           0 :                 if (idx < 0)
     308           0 :                         return (EINVAL);
     309           0 :                 return (wsdisplay_switch((struct device *)sc, idx, 1));
     310             :             case VT_WAITACTIVE:
     311           0 :                 if ((flag & FWRITE) == 0)
     312           0 :                         return (EACCES);
     313           0 :                 idx = *(int *)data - 1;
     314           0 :                 if (idx < 0)
     315           0 :                         return (EINVAL);
     316           0 :                 return (wsscreen_switchwait(sc, idx));
     317             :             case VT_GETSTATE:
     318             : #define ss ((struct vt_stat *)data)
     319           0 :                 idx = wsdisplay_getactivescreen(sc);
     320           0 :                 ss->v_active = idx + 1;
     321           0 :                 ss->v_state = 0;
     322           0 :                 maxidx = wsdisplay_maxscreenidx(sc);
     323           0 :                 for (idx = 0; idx <= maxidx; idx++)
     324           0 :                         if (wsdisplay_screenstate(sc, idx) == EBUSY)
     325           0 :                                 ss->v_state |= (1 << (idx + 1));
     326             : #undef ss
     327           0 :                 return (0);
     328             : 
     329             :             default:
     330           0 :                 return (-1);
     331             :         }
     332             : 
     333             :         return (0);
     334           0 : }
     335             : 
     336             : int
     337           0 : wsdisplay_usl_ioctl2(struct wsdisplay_softc *sc, struct wsscreen *scr,
     338             :     u_long cmd, caddr_t data, int flag, struct proc *p)
     339             : {
     340           0 :         int intarg, res;
     341             :         u_long req;
     342             :         void *arg;
     343           0 :         struct usl_syncdata *sd;
     344           0 :         struct wskbd_bell_data bd;
     345             : 
     346           0 :         switch (cmd) {
     347             :             case VT_SETMODE:
     348           0 :                 if ((flag & FWRITE) == 0)
     349           0 :                         return (EACCES);
     350             : #define newmode ((struct vt_mode *)data)
     351           0 :                 if (newmode->mode == VT_PROCESS) {
     352           0 :                         res = usl_sync_init(scr, &sd, p->p_p, newmode->acqsig,
     353           0 :                                             newmode->relsig, newmode->frsig);
     354           0 :                         if (res)
     355           0 :                                 return (res);
     356             :                 } else {
     357           0 :                         sd = usl_sync_get(scr);
     358           0 :                         if (sd)
     359           0 :                                 usl_sync_done(sd);
     360             :                 }
     361             : #undef newmode
     362           0 :                 return (0);
     363             :             case VT_GETMODE:
     364             : #define cmode ((struct vt_mode *)data)
     365           0 :                 sd = usl_sync_get(scr);
     366           0 :                 if (sd) {
     367           0 :                         cmode->mode = VT_PROCESS;
     368           0 :                         cmode->relsig = sd->s_relsig;
     369           0 :                         cmode->acqsig = sd->s_acqsig;
     370           0 :                         cmode->frsig = sd->s_frsig;
     371           0 :                 } else
     372           0 :                         cmode->mode = VT_AUTO;
     373             : #undef cmode
     374           0 :                 return (0);
     375             :             case VT_RELDISP:
     376           0 :                 if ((flag & FWRITE) == 0)
     377           0 :                         return (EACCES);
     378             : #define d (*(int *)data)
     379           0 :                 sd = usl_sync_get(scr);
     380           0 :                 if (!sd)
     381           0 :                         return (EINVAL);
     382           0 :                 switch (d) {
     383             :                     case VT_FALSE:
     384             :                     case VT_TRUE:
     385           0 :                         return (usl_detachack(sd, (d == VT_TRUE)));
     386             :                     case VT_ACKACQ:
     387           0 :                         return (usl_attachack(sd, 1));
     388             :                     default:
     389           0 :                         return (EINVAL);
     390             :                 }
     391             : #undef d
     392             :                 return (0);
     393             : 
     394             :             case KDENABIO:
     395             :             case KDDISABIO:
     396           0 :                 if ((flag & FWRITE) == 0)
     397           0 :                         return (EACCES);
     398             :                 /*
     399             :                  * This is a lie, but non-x86 platforms are not supposed to
     400             :                  * issue these ioctls anyway.
     401             :                  */
     402           0 :                 return (0);
     403             : 
     404             :             case KDSETRAD:
     405           0 :                 if ((flag & FWRITE) == 0)
     406           0 :                         return (EACCES);
     407             :                 /* XXX ignore for now */
     408           0 :                 return (0);
     409             : 
     410             :             default:
     411           0 :                 return (-1);
     412             : 
     413             :             /*
     414             :              * the following are converted to wsdisplay ioctls
     415             :              */
     416             :             case KDSETMODE:
     417           0 :                 if ((flag & FWRITE) == 0)
     418           0 :                         return (EACCES);
     419             :                 req = WSDISPLAYIO_SMODE;
     420             : #define d (*(int *)data)
     421           0 :                 switch (d) {
     422             :                     case KD_GRAPHICS:
     423           0 :                         intarg = WSDISPLAYIO_MODE_MAPPED;
     424           0 :                         break;
     425             :                     case KD_TEXT:
     426           0 :                         intarg = WSDISPLAYIO_MODE_EMUL;
     427           0 :                         break;
     428             :                     default:
     429           0 :                         return (EINVAL);
     430             :                 }
     431             : #undef d
     432             :                 arg = &intarg;
     433           0 :                 break;
     434             :             case KDMKTONE:
     435           0 :                 if ((flag & FWRITE) == 0)
     436           0 :                         return (EACCES);
     437             :                 req = WSKBDIO_COMPLEXBELL;
     438             : #define d (*(int *)data)
     439           0 :                 if (d) {
     440             : #define PCVT_SYSBEEPF   1193182
     441           0 :                         if (d >> 16) {
     442           0 :                                 bd.which = WSKBD_BELL_DOPERIOD;
     443           0 :                         bd.period = d >> 16; /* ms */
     444           0 :                         }
     445             :                         else
     446           0 :                                 bd.which = 0;
     447           0 :                         if (d & 0xffff) {
     448           0 :                                 bd.which |= WSKBD_BELL_DOPITCH;
     449           0 :                                 bd.pitch = PCVT_SYSBEEPF/(d & 0xffff); /* Hz */
     450           0 :                         }
     451             :                 } else
     452           0 :                         bd.which = 0; /* default */
     453             : #undef d
     454             :                 arg = &bd;
     455           0 :                 break;
     456             :             case KDSETLED:
     457           0 :                 if ((flag & FWRITE) == 0)
     458           0 :                         return (EACCES);
     459             :                 req = WSKBDIO_SETLEDS;
     460           0 :                 intarg = 0;
     461             : #define d (*(int *)data)
     462           0 :                 if (d & LED_CAP)
     463           0 :                         intarg |= WSKBD_LED_CAPS;
     464           0 :                 if (d & LED_NUM)
     465           0 :                         intarg |= WSKBD_LED_NUM;
     466           0 :                 if (d & LED_SCR)
     467           0 :                         intarg |= WSKBD_LED_SCROLL;
     468             : #undef d
     469             :                 arg = &intarg;
     470           0 :                 break;
     471             :             case KDGETLED:
     472             :                 req = WSKBDIO_GETLEDS;
     473             :                 arg = &intarg;
     474           0 :                 break;
     475             : #ifdef WSDISPLAY_COMPAT_RAWKBD
     476             :             case KDSKBMODE:
     477           0 :                 if ((flag & FWRITE) == 0)
     478           0 :                         return (EACCES);
     479             :                 req = WSKBDIO_SETMODE;
     480           0 :                 switch (*(int *)data) {
     481             :                     case K_RAW:
     482           0 :                         intarg = WSKBD_RAW;
     483           0 :                         break;
     484             :                     case K_XLATE:
     485           0 :                         intarg = WSKBD_TRANSLATED;
     486           0 :                         break;
     487             :                     default:
     488           0 :                         return (EINVAL);
     489             :                 }
     490             :                 arg = &intarg;
     491           0 :                 break;
     492             :             case KDGKBMODE:
     493             :                 req = WSKBDIO_GETMODE;
     494             :                 arg = &intarg;
     495           0 :                 break;
     496             : #endif
     497             :         }
     498             : 
     499           0 :         res = wsdisplay_internal_ioctl(sc, scr, req, arg, flag, p);
     500           0 :         if (res)
     501           0 :                 return (res);
     502             : 
     503           0 :         switch (cmd) {
     504             :             case KDGETLED:
     505             : #define d (*(int *)data)
     506           0 :                 d = 0;
     507           0 :                 if (intarg & WSKBD_LED_CAPS)
     508           0 :                         d |= LED_CAP;
     509           0 :                 if (intarg & WSKBD_LED_NUM)
     510           0 :                         d |= LED_NUM;
     511           0 :                 if (intarg & WSKBD_LED_SCROLL)
     512           0 :                         d |= LED_SCR;
     513             : #undef d
     514             :                 break;
     515             : #ifdef WSDISPLAY_COMPAT_RAWKBD
     516             :             case KDGKBMODE:
     517           0 :                 *(int *)data = (intarg == WSKBD_RAW ? K_RAW : K_XLATE);
     518           0 :                 break;
     519             : #endif
     520             :         }
     521             : 
     522           0 :         return (0);
     523           0 : }

Generated by: LCOV version 1.13