sysmouse.c revision 66860
156043Syokota/*- 256043Syokota * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 356043Syokota * All rights reserved. 456043Syokota * 556043Syokota * Redistribution and use in source and binary forms, with or without 656043Syokota * modification, are permitted provided that the following conditions 756043Syokota * are met: 856043Syokota * 1. Redistributions of source code must retain the above copyright 956043Syokota * notice, this list of conditions and the following disclaimer as 1056043Syokota * the first lines of this file unmodified. 1156043Syokota * 2. Redistributions in binary form must reproduce the above copyright 1256043Syokota * notice, this list of conditions and the following disclaimer in the 1356043Syokota * documentation and/or other materials provided with the distribution. 1456043Syokota * 1556043Syokota * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 1656043Syokota * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1756043Syokota * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1856043Syokota * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 1956043Syokota * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2056043Syokota * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2156043Syokota * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2256043Syokota * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2356043Syokota * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2456043Syokota * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2556043Syokota * 2656043Syokota * $FreeBSD: head/sys/dev/syscons/sysmouse.c 66860 2000-10-09 08:08:36Z phk $ 2756043Syokota */ 2856043Syokota 2956043Syokota#include "opt_syscons.h" 3056043Syokota 3156043Syokota#include <sys/param.h> 3256043Syokota#include <sys/systm.h> 3356043Syokota#include <sys/conf.h> 3456043Syokota#include <sys/proc.h> 3556043Syokota#include <sys/tty.h> 3656043Syokota#include <sys/kernel.h> 3766834Sphk#include <sys/consio.h> 3866860Sphk#include <sys/mouse.h> 3956043Syokota 4056043Syokota#include <dev/syscons/syscons.h> 4156043Syokota 4256043Syokota#ifndef SC_NO_SYSMOUSE 4356043Syokota 4456043Syokota#define CDEV_MAJOR 12 /* major number, shared with syscons */ 4556043Syokota#define SC_MOUSE 128 /* minor number */ 4656043Syokota 4756043Syokotastatic d_open_t smopen; 4856043Syokotastatic d_close_t smclose; 4956043Syokotastatic d_ioctl_t smioctl; 5056043Syokota 5156043Syokotastatic struct cdevsw sm_cdevsw = { 5256043Syokota /* open */ smopen, 5356043Syokota /* close */ smclose, 5456043Syokota /* read */ ttyread, 5556043Syokota /* write */ nowrite, 5656043Syokota /* ioctl */ smioctl, 5756043Syokota /* poll */ ttypoll, 5856043Syokota /* mmap */ nommap, 5956043Syokota /* strategy */ nostrategy, 6056043Syokota /* name */ "sysmouse", 6156043Syokota /* maj */ CDEV_MAJOR, 6256043Syokota /* dump */ nodump, 6356043Syokota /* psize */ nopsize, 6456043Syokota /* flags */ D_TTY, 6556043Syokota /* bmaj */ -1 6656043Syokota}; 6756043Syokota 6856043Syokota/* local variables */ 6956043Syokotastatic struct tty *sysmouse_tty; 7056043Syokotastatic int mouse_level; /* sysmouse protocol level */ 7156043Syokotastatic mousestatus_t mouse_status; 7256043Syokota 7356043Syokotastatic void smstart(struct tty *tp); 7456043Syokotastatic int smparam(struct tty *tp, struct termios *t); 7556043Syokota 7656043Syokotastatic int 7756043Syokotasmopen(dev_t dev, int flag, int mode, struct proc *p) 7856043Syokota{ 7956043Syokota struct tty *tp; 8056043Syokota 8156043Syokota DPRINTF(5, ("smopen: dev:%d,%d, vty:%d\n", 8256043Syokota major(dev), minor(dev), SC_VTY(dev))); 8356043Syokota 8456043Syokota#if 0 8556043Syokota if (SC_VTY(dev) != SC_MOUSE) 8656043Syokota return ENXIO; 8756043Syokota#endif 8856043Syokota 8956043Syokota tp = dev->si_tty = ttymalloc(dev->si_tty); 9056043Syokota if (!(tp->t_state & TS_ISOPEN)) { 9156043Syokota tp->t_oproc = smstart; 9256043Syokota tp->t_param = smparam; 9356043Syokota tp->t_stop = nottystop; 9456043Syokota tp->t_dev = dev; 9556043Syokota ttychars(tp); 9656043Syokota tp->t_iflag = TTYDEF_IFLAG; 9756043Syokota tp->t_oflag = TTYDEF_OFLAG; 9856043Syokota tp->t_cflag = TTYDEF_CFLAG; 9956043Syokota tp->t_lflag = TTYDEF_LFLAG; 10056043Syokota tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 10156043Syokota smparam(tp, &tp->t_termios); 10256043Syokota (*linesw[tp->t_line].l_modem)(tp, 1); 10356043Syokota } else if (tp->t_state & TS_XCLUDE && suser(p)) { 10456043Syokota return EBUSY; 10556043Syokota } 10656043Syokota 10756043Syokota return (*linesw[tp->t_line].l_open)(dev, tp); 10856043Syokota} 10956043Syokota 11056043Syokotastatic int 11156043Syokotasmclose(dev_t dev, int flag, int mode, struct proc *p) 11256043Syokota{ 11356043Syokota struct tty *tp; 11456043Syokota int s; 11556043Syokota 11656043Syokota tp = dev->si_tty; 11756043Syokota s = spltty(); 11856043Syokota mouse_level = 0; 11956043Syokota (*linesw[tp->t_line].l_close)(tp, flag); 12056043Syokota ttyclose(tp); 12156043Syokota splx(s); 12256043Syokota 12356043Syokota return 0; 12456043Syokota} 12556043Syokota 12656043Syokotastatic void 12756043Syokotasmstart(struct tty *tp) 12856043Syokota{ 12956043Syokota struct clist *rbp; 13056043Syokota u_char buf[PCBURST]; 13156043Syokota int s; 13256043Syokota 13356043Syokota s = spltty(); 13456043Syokota if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) { 13556043Syokota tp->t_state |= TS_BUSY; 13656043Syokota rbp = &tp->t_outq; 13756043Syokota while (rbp->c_cc) 13856043Syokota q_to_b(rbp, buf, PCBURST); 13956043Syokota tp->t_state &= ~TS_BUSY; 14056043Syokota ttwwakeup(tp); 14156043Syokota } 14256043Syokota splx(s); 14356043Syokota} 14456043Syokota 14556043Syokotastatic int 14656043Syokotasmparam(struct tty *tp, struct termios *t) 14756043Syokota{ 14856043Syokota tp->t_ispeed = t->c_ispeed; 14956043Syokota tp->t_ospeed = t->c_ospeed; 15056043Syokota tp->t_cflag = t->c_cflag; 15156043Syokota return 0; 15256043Syokota} 15356043Syokota 15456043Syokotastatic int 15556043Syokotasmioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 15656043Syokota{ 15756043Syokota struct tty *tp; 15856043Syokota mousehw_t *hw; 15956043Syokota mousemode_t *mode; 16056043Syokota int error; 16156043Syokota int s; 16256043Syokota 16356043Syokota tp = dev->si_tty; 16456043Syokota switch (cmd) { 16556043Syokota 16656043Syokota case MOUSE_GETHWINFO: /* get device information */ 16756043Syokota hw = (mousehw_t *)data; 16856043Syokota hw->buttons = 10; /* XXX unknown */ 16956043Syokota hw->iftype = MOUSE_IF_SYSMOUSE; 17056043Syokota hw->type = MOUSE_MOUSE; 17156043Syokota hw->model = MOUSE_MODEL_GENERIC; 17256043Syokota hw->hwid = 0; 17356043Syokota return 0; 17456043Syokota 17556043Syokota case MOUSE_GETMODE: /* get protocol/mode */ 17656043Syokota mode = (mousemode_t *)data; 17756043Syokota mode->level = mouse_level; 17856043Syokota switch (mode->level) { 17956043Syokota case 0: /* emulate MouseSystems protocol */ 18056043Syokota mode->protocol = MOUSE_PROTO_MSC; 18156043Syokota mode->rate = -1; /* unknown */ 18256043Syokota mode->resolution = -1; /* unknown */ 18356043Syokota mode->accelfactor = 0; /* disabled */ 18456043Syokota mode->packetsize = MOUSE_MSC_PACKETSIZE; 18556043Syokota mode->syncmask[0] = MOUSE_MSC_SYNCMASK; 18656043Syokota mode->syncmask[1] = MOUSE_MSC_SYNC; 18756043Syokota break; 18856043Syokota 18956043Syokota case 1: /* sysmouse protocol */ 19056043Syokota mode->protocol = MOUSE_PROTO_SYSMOUSE; 19156043Syokota mode->rate = -1; 19256043Syokota mode->resolution = -1; 19356043Syokota mode->accelfactor = 0; 19456043Syokota mode->packetsize = MOUSE_SYS_PACKETSIZE; 19556043Syokota mode->syncmask[0] = MOUSE_SYS_SYNCMASK; 19656043Syokota mode->syncmask[1] = MOUSE_SYS_SYNC; 19756043Syokota break; 19856043Syokota } 19956043Syokota return 0; 20056043Syokota 20156043Syokota case MOUSE_SETMODE: /* set protocol/mode */ 20256043Syokota mode = (mousemode_t *)data; 20365129Syokota if (mode->level == -1) 20465129Syokota ; /* don't change the current setting */ 20565129Syokota else if ((mode->level < 0) || (mode->level > 1)) 20656043Syokota return EINVAL; 20765129Syokota else 20865129Syokota mouse_level = mode->level; 20956043Syokota return 0; 21056043Syokota 21156043Syokota case MOUSE_GETLEVEL: /* get operation level */ 21256043Syokota *(int *)data = mouse_level; 21356043Syokota return 0; 21456043Syokota 21556043Syokota case MOUSE_SETLEVEL: /* set operation level */ 21656043Syokota if ((*(int *)data < 0) || (*(int *)data > 1)) 21756043Syokota return EINVAL; 21856043Syokota mouse_level = *(int *)data; 21956043Syokota return 0; 22056043Syokota 22156043Syokota case MOUSE_GETSTATUS: /* get accumulated mouse events */ 22256043Syokota s = spltty(); 22356043Syokota *(mousestatus_t *)data = mouse_status; 22456043Syokota mouse_status.flags = 0; 22556043Syokota mouse_status.obutton = mouse_status.button; 22656043Syokota mouse_status.dx = 0; 22756043Syokota mouse_status.dy = 0; 22856043Syokota mouse_status.dz = 0; 22956043Syokota splx(s); 23056043Syokota return 0; 23156043Syokota 23256043Syokota#if notyet 23356043Syokota case MOUSE_GETVARS: /* get internal mouse variables */ 23456043Syokota case MOUSE_SETVARS: /* set internal mouse variables */ 23556043Syokota return ENODEV; 23656043Syokota#endif 23756043Syokota 23856043Syokota case MOUSE_READSTATE: /* read status from the device */ 23956043Syokota case MOUSE_READDATA: /* read data from the device */ 24056043Syokota return ENODEV; 24156043Syokota } 24256043Syokota 24356043Syokota error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 24456043Syokota if (error != ENOIOCTL) 24556043Syokota return error; 24656043Syokota error = ttioctl(tp, cmd, data, flag); 24756043Syokota if (error != ENOIOCTL) 24856043Syokota return error; 24956043Syokota return ENOTTY; 25056043Syokota} 25156043Syokota 25256043Syokotastatic void 25356043Syokotasm_attach_mouse(void *unused) 25456043Syokota{ 25556043Syokota dev_t dev; 25656043Syokota 25756043Syokota dev = make_dev(&sm_cdevsw, SC_MOUSE, UID_ROOT, GID_WHEEL, 0600, 25856043Syokota "sysmouse"); 25956043Syokota dev->si_tty = sysmouse_tty = ttymalloc(sysmouse_tty); 26056043Syokota /* sysmouse doesn't have scr_stat */ 26156043Syokota} 26256043Syokota 26356043SyokotaSYSINIT(sysmouse, SI_SUB_DRIVERS, SI_ORDER_MIDDLE + CDEV_MAJOR, 26456043Syokota sm_attach_mouse, NULL) 26556043Syokota 26656043Syokotaint 26756043Syokotasysmouse_event(mouse_info_t *info) 26856043Syokota{ 26956043Syokota /* MOUSE_BUTTON?DOWN -> MOUSE_MSC_BUTTON?UP */ 27056043Syokota static int butmap[8] = { 27156043Syokota MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, 27256043Syokota MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, 27356043Syokota MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP, 27456043Syokota MOUSE_MSC_BUTTON3UP, 27556043Syokota MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP, 27656043Syokota MOUSE_MSC_BUTTON2UP, 27756043Syokota MOUSE_MSC_BUTTON1UP, 27856043Syokota 0, 27956043Syokota }; 28056043Syokota u_char buf[8]; 28156043Syokota int x, y, z; 28256043Syokota int i; 28356043Syokota 28456043Syokota switch (info->operation) { 28556043Syokota case MOUSE_ACTION: 28656043Syokota mouse_status.button = info->u.data.buttons; 28756043Syokota /* FALL THROUGH */ 28856043Syokota case MOUSE_MOTION_EVENT: 28956043Syokota x = info->u.data.x; 29056043Syokota y = info->u.data.y; 29156043Syokota z = info->u.data.z; 29256043Syokota break; 29356043Syokota case MOUSE_BUTTON_EVENT: 29456043Syokota x = y = z = 0; 29556043Syokota if (info->u.event.value > 0) 29656043Syokota mouse_status.button |= info->u.event.id; 29756043Syokota else 29856043Syokota mouse_status.button &= ~info->u.event.id; 29956043Syokota break; 30056043Syokota default: 30156043Syokota return 0; 30256043Syokota } 30356043Syokota 30456043Syokota mouse_status.dx += x; 30556043Syokota mouse_status.dy += y; 30656043Syokota mouse_status.dz += z; 30756043Syokota mouse_status.flags |= ((x || y || z) ? MOUSE_POSCHANGED : 0) 30856043Syokota | (mouse_status.obutton ^ mouse_status.button); 30956043Syokota if (mouse_status.flags == 0) 31056043Syokota return 0; 31156043Syokota 31256043Syokota if ((sysmouse_tty == NULL) || !(sysmouse_tty->t_state & TS_ISOPEN)) 31356043Syokota return mouse_status.flags; 31456043Syokota 31556043Syokota /* the first five bytes are compatible with MouseSystems' */ 31656043Syokota buf[0] = MOUSE_MSC_SYNC 31756043Syokota | butmap[mouse_status.button & MOUSE_STDBUTTONS]; 31856043Syokota x = imax(imin(x, 255), -256); 31956043Syokota buf[1] = x >> 1; 32056043Syokota buf[3] = x - buf[1]; 32156043Syokota y = -imax(imin(y, 255), -256); 32256043Syokota buf[2] = y >> 1; 32356043Syokota buf[4] = y - buf[2]; 32456043Syokota for (i = 0; i < MOUSE_MSC_PACKETSIZE; ++i) 32556043Syokota (*linesw[sysmouse_tty->t_line].l_rint)(buf[i], sysmouse_tty); 32656043Syokota if (mouse_level >= 1) { 32756043Syokota /* extended part */ 32856043Syokota z = imax(imin(z, 127), -128); 32956043Syokota buf[5] = (z >> 1) & 0x7f; 33056043Syokota buf[6] = (z - (z >> 1)) & 0x7f; 33156043Syokota /* buttons 4-10 */ 33256043Syokota buf[7] = (~mouse_status.button >> 3) & 0x7f; 33356043Syokota for (i = MOUSE_MSC_PACKETSIZE; i < MOUSE_SYS_PACKETSIZE; ++i) 33456043Syokota (*linesw[sysmouse_tty->t_line].l_rint)(buf[i], 33556043Syokota sysmouse_tty); 33656043Syokota } 33756043Syokota 33856043Syokota return mouse_status.flags; 33956043Syokota} 34056043Syokota 34156043Syokota#endif /* !SC_NO_SYSMOUSE */ 342