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/syscons/sysmouse.c

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

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
    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 as
   12  *    the first lines of this file unmodified.
   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 AUTHORS ``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 AUTHORS 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/cdefs.h>
   31 __FBSDID("$FreeBSD$");
   32 
   33 #include "opt_evdev.h"
   34 #include "opt_syscons.h"
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/priv.h>
   39 #include <sys/serial.h>
   40 #include <sys/tty.h>
   41 #include <sys/ttydefaults.h>
   42 #include <sys/kernel.h>
   43 #include <sys/cons.h>
   44 #include <sys/consio.h>
   45 #include <sys/mouse.h>
   46 
   47 #include <dev/syscons/syscons.h>
   48 
   49 #ifdef EVDEV_SUPPORT
   50 #include <dev/evdev/input.h>
   51 #include <dev/evdev/evdev.h>
   52 #endif
   53 
   54 #ifndef SC_NO_SYSMOUSE
   55 
   56 /* local variables */
   57 static struct tty       *sysmouse_tty;
   58 static int              mouse_level;    /* sysmouse protocol level */
   59 static mousestatus_t    mouse_status;
   60 
   61 #ifdef EVDEV_SUPPORT
   62 static struct evdev_dev *sysmouse_evdev;
   63 
   64 static void
   65 smdev_evdev_init(void)
   66 {
   67         int i;
   68 
   69         sysmouse_evdev = evdev_alloc();
   70         evdev_set_name(sysmouse_evdev, "System mouse");
   71         evdev_set_phys(sysmouse_evdev, "sysmouse");
   72         evdev_set_id(sysmouse_evdev, BUS_VIRTUAL, 0, 0, 0);
   73         evdev_support_prop(sysmouse_evdev, INPUT_PROP_POINTER);
   74         evdev_support_event(sysmouse_evdev, EV_SYN);
   75         evdev_support_event(sysmouse_evdev, EV_REL);
   76         evdev_support_event(sysmouse_evdev, EV_KEY);
   77         evdev_support_rel(sysmouse_evdev, REL_X);
   78         evdev_support_rel(sysmouse_evdev, REL_Y);
   79         evdev_support_rel(sysmouse_evdev, REL_WHEEL);
   80         evdev_support_rel(sysmouse_evdev, REL_HWHEEL);
   81         for (i = 0; i < 8; i++)
   82                 evdev_support_key(sysmouse_evdev, BTN_MOUSE + i);
   83         if (evdev_register(sysmouse_evdev)) {
   84                 evdev_free(sysmouse_evdev);
   85                 sysmouse_evdev = NULL;
   86         }
   87 }
   88 
   89 static void
   90 smdev_evdev_write(int x, int y, int z, int buttons)
   91 {
   92 
   93         if (sysmouse_evdev == NULL || !(evdev_rcpt_mask & EVDEV_RCPT_SYSMOUSE))
   94                 return;
   95 
   96         evdev_push_event(sysmouse_evdev, EV_REL, REL_X, x);
   97         evdev_push_event(sysmouse_evdev, EV_REL, REL_Y, y);
   98         switch (evdev_sysmouse_t_axis) {
   99         case EVDEV_SYSMOUSE_T_AXIS_PSM:
  100                 switch (z) {
  101                 case 1:
  102                 case -1:
  103                         evdev_push_rel(sysmouse_evdev, REL_WHEEL, -z);
  104                         break;
  105                 case 2:
  106                 case -2:
  107                         evdev_push_rel(sysmouse_evdev, REL_HWHEEL, z / 2);
  108                         break;
  109                 }
  110                 break;
  111         case EVDEV_SYSMOUSE_T_AXIS_UMS:
  112                 if (buttons & (1 << 6))
  113                         evdev_push_rel(sysmouse_evdev, REL_HWHEEL, 1);
  114                 else if (buttons & (1 << 5))
  115                         evdev_push_rel(sysmouse_evdev, REL_HWHEEL, -1);
  116                 buttons &= ~((1 << 5)|(1 << 6));
  117                 /* PASSTHROUGH */
  118         case EVDEV_SYSMOUSE_T_AXIS_NONE:
  119         default:
  120                 evdev_push_rel(sysmouse_evdev, REL_WHEEL, -z);
  121         }
  122         evdev_push_mouse_btn(sysmouse_evdev, buttons);
  123         evdev_sync(sysmouse_evdev);
  124 }
  125 #endif
  126 
  127 static void
  128 smdev_close(struct tty *tp)
  129 {
  130         mouse_level = 0;
  131 }
  132 
  133 static int
  134 smdev_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td)
  135 {
  136         mousehw_t *hw;
  137         mousemode_t *mode;
  138 
  139         switch (cmd) {
  140         case MOUSE_GETHWINFO:   /* get device information */
  141                 hw = (mousehw_t *)data;
  142                 hw->buttons = 10;               /* XXX unknown */
  143                 hw->iftype = MOUSE_IF_SYSMOUSE;
  144                 hw->type = MOUSE_MOUSE;
  145                 hw->model = MOUSE_MODEL_GENERIC;
  146                 hw->hwid = 0;
  147                 return 0;
  148 
  149         case MOUSE_GETMODE:     /* get protocol/mode */
  150                 mode = (mousemode_t *)data;
  151                 mode->level = mouse_level;
  152                 switch (mode->level) {
  153                 case 0: /* emulate MouseSystems protocol */
  154                         mode->protocol = MOUSE_PROTO_MSC;
  155                         mode->rate = -1;                /* unknown */
  156                         mode->resolution = -1;  /* unknown */
  157                         mode->accelfactor = 0;  /* disabled */
  158                         mode->packetsize = MOUSE_MSC_PACKETSIZE;
  159                         mode->syncmask[0] = MOUSE_MSC_SYNCMASK;
  160                         mode->syncmask[1] = MOUSE_MSC_SYNC;
  161                         break;
  162 
  163                 case 1: /* sysmouse protocol */
  164                         mode->protocol = MOUSE_PROTO_SYSMOUSE;
  165                         mode->rate = -1;
  166                         mode->resolution = -1;
  167                         mode->accelfactor = 0;
  168                         mode->packetsize = MOUSE_SYS_PACKETSIZE;
  169                         mode->syncmask[0] = MOUSE_SYS_SYNCMASK;
  170                         mode->syncmask[1] = MOUSE_SYS_SYNC;
  171                         break;
  172                 }
  173                 return 0;
  174 
  175         case MOUSE_SETMODE:     /* set protocol/mode */
  176                 mode = (mousemode_t *)data;
  177                 if (mode->level == -1)
  178                         ;       /* don't change the current setting */
  179                 else if ((mode->level < 0) || (mode->level > 1))
  180                         return EINVAL;
  181                 else
  182                         mouse_level = mode->level;
  183                 return 0;
  184 
  185         case MOUSE_GETLEVEL:    /* get operation level */
  186                 *(int *)data = mouse_level;
  187                 return 0;
  188 
  189         case MOUSE_SETLEVEL:    /* set operation level */
  190                 if ((*(int *)data  < 0) || (*(int *)data > 1))
  191                         return EINVAL;
  192                 mouse_level = *(int *)data;
  193                 return 0;
  194 
  195         case MOUSE_GETSTATUS:   /* get accumulated mouse events */
  196                 *(mousestatus_t *)data = mouse_status;
  197                 mouse_status.flags = 0;
  198                 mouse_status.obutton = mouse_status.button;
  199                 mouse_status.dx = 0;
  200                 mouse_status.dy = 0;
  201                 mouse_status.dz = 0;
  202                 return 0;
  203 
  204         case MOUSE_READSTATE:   /* read status from the device */
  205         case MOUSE_READDATA:    /* read data from the device */
  206                 return ENODEV;
  207         }
  208 
  209         return (ENOIOCTL);
  210 }
  211 
  212 static int
  213 smdev_param(struct tty *tp, struct termios *t)
  214 {
  215 
  216         /*
  217          * Set the output baud rate to zero. The mouse device supports
  218          * no output, so we don't want to waste buffers.
  219          */
  220         t->c_ispeed = TTYDEF_SPEED;
  221         t->c_ospeed = B0;
  222 
  223         return (0);
  224 }
  225 
  226 static struct ttydevsw smdev_ttydevsw = {
  227         .tsw_flags      = TF_NOPREFIX,
  228         .tsw_close      = smdev_close,
  229         .tsw_ioctl      = smdev_ioctl,
  230         .tsw_param      = smdev_param,
  231 };
  232 
  233 static void
  234 sm_attach_mouse(void *unused)
  235 {
  236         if (!vty_enabled(VTY_SC))
  237                 return;
  238         sysmouse_tty = tty_alloc(&smdev_ttydevsw, NULL);
  239         tty_makedev(sysmouse_tty, NULL, "sysmouse");
  240 #ifdef EVDEV_SUPPORT
  241         smdev_evdev_init();
  242 #endif
  243 }
  244 
  245 SYSINIT(sysmouse, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, sm_attach_mouse, NULL);
  246 
  247 int
  248 sysmouse_event(mouse_info_t *info)
  249 {
  250         /* MOUSE_BUTTON?DOWN -> MOUSE_MSC_BUTTON?UP */
  251         static int butmap[8] = {
  252             MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP,
  253             MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP,
  254             MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP,
  255             MOUSE_MSC_BUTTON3UP,
  256             MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP,
  257             MOUSE_MSC_BUTTON2UP,
  258             MOUSE_MSC_BUTTON1UP,
  259             0,
  260         };
  261         u_char buf[8];
  262         int x, y, z;
  263         int i, flags = 0;
  264 
  265         tty_lock(sysmouse_tty);
  266 
  267         switch (info->operation) {
  268         case MOUSE_ACTION:
  269                 mouse_status.button = info->u.data.buttons;
  270                 /* FALL THROUGH */
  271         case MOUSE_MOTION_EVENT:
  272                 x = info->u.data.x;
  273                 y = info->u.data.y;
  274                 z = info->u.data.z;
  275                 break;
  276         case MOUSE_BUTTON_EVENT:
  277                 x = y = z = 0;
  278                 if (info->u.event.value > 0)
  279                         mouse_status.button |= info->u.event.id;
  280                 else
  281                         mouse_status.button &= ~info->u.event.id;
  282                 break;
  283         default:
  284                 goto done;
  285         }
  286 
  287         mouse_status.dx += x;
  288         mouse_status.dy += y;
  289         mouse_status.dz += z;
  290         mouse_status.flags |= ((x || y || z) ? MOUSE_POSCHANGED : 0)
  291                               | (mouse_status.obutton ^ mouse_status.button);
  292         flags = mouse_status.flags;
  293         if (flags == 0)
  294                 goto done;
  295 
  296 #ifdef EVDEV_SUPPORT
  297         smdev_evdev_write(x, y, z, mouse_status.button);
  298         if (evdev_is_grabbed(sysmouse_evdev))
  299                 goto done;
  300 #endif
  301 
  302         if (!tty_opened(sysmouse_tty))
  303                 goto done;
  304 
  305         /* the first five bytes are compatible with MouseSystems' */
  306         buf[0] = MOUSE_MSC_SYNC
  307                  | butmap[mouse_status.button & MOUSE_STDBUTTONS];
  308         x = imax(imin(x, 255), -256);
  309         buf[1] = x >> 1;
  310         buf[3] = x - buf[1];
  311         y = -imax(imin(y, 255), -256);
  312         buf[2] = y >> 1;
  313         buf[4] = y - buf[2];
  314         for (i = 0; i < MOUSE_MSC_PACKETSIZE; ++i)
  315                 ttydisc_rint(sysmouse_tty, buf[i], 0);
  316         if (mouse_level >= 1) {
  317                 /* extended part */
  318                 z = imax(imin(z, 127), -128);
  319                 buf[5] = (z >> 1) & 0x7f;
  320                 buf[6] = (z - (z >> 1)) & 0x7f;
  321                 /* buttons 4-10 */
  322                 buf[7] = (~mouse_status.button >> 3) & 0x7f;
  323                 for (i = MOUSE_MSC_PACKETSIZE; i < MOUSE_SYS_PACKETSIZE; ++i)
  324                         ttydisc_rint(sysmouse_tty, buf[i], 0);
  325         }
  326         ttydisc_rint_done(sysmouse_tty);
  327 
  328 done:   tty_unlock(sysmouse_tty);
  329         return (flags);
  330 }
  331 
  332 #endif /* !SC_NO_SYSMOUSE */

Cache object: 53bcbef1ddb65a6d3d3320f4a9482f71


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