sysmouse.c revision 119420
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 */ 2756043Syokota 28119420Sobrien#include <sys/cdefs.h> 29119420Sobrien__FBSDID("$FreeBSD: head/sys/dev/syscons/sysmouse.c 119420 2003-08-24 18:17:24Z obrien $"); 30119420Sobrien 3156043Syokota#include "opt_syscons.h" 3256043Syokota 3356043Syokota#include <sys/param.h> 3456043Syokota#include <sys/systm.h> 3556043Syokota#include <sys/conf.h> 3656043Syokota#include <sys/tty.h> 3756043Syokota#include <sys/kernel.h> 3866834Sphk#include <sys/consio.h> 3966860Sphk#include <sys/mouse.h> 4056043Syokota 4156043Syokota#include <dev/syscons/syscons.h> 4256043Syokota 4356043Syokota#ifndef SC_NO_SYSMOUSE 4456043Syokota 4556043Syokota#define CDEV_MAJOR 12 /* major number, shared with syscons */ 4656043Syokota#define SC_MOUSE 128 /* minor number */ 4756043Syokota 4856043Syokotastatic d_open_t smopen; 4956043Syokotastatic d_close_t smclose; 5056043Syokotastatic d_ioctl_t smioctl; 5156043Syokota 5256043Syokotastatic struct cdevsw sm_cdevsw = { 53111815Sphk .d_open = smopen, 54111815Sphk .d_close = smclose, 55111815Sphk .d_read = ttyread, 56111815Sphk .d_ioctl = smioctl, 57111815Sphk .d_poll = ttypoll, 58111815Sphk .d_name = "sysmouse", 59111815Sphk .d_maj = CDEV_MAJOR, 60111815Sphk .d_flags = D_TTY, 6156043Syokota}; 6256043Syokota 6356043Syokota/* local variables */ 6456043Syokotastatic struct tty *sysmouse_tty; 6556043Syokotastatic int mouse_level; /* sysmouse protocol level */ 6656043Syokotastatic mousestatus_t mouse_status; 6756043Syokota 6856043Syokotastatic void smstart(struct tty *tp); 6956043Syokotastatic int smparam(struct tty *tp, struct termios *t); 7056043Syokota 7156043Syokotastatic int 7283366Sjuliansmopen(dev_t dev, int flag, int mode, struct thread *td) 7356043Syokota{ 7456043Syokota struct tty *tp; 7556043Syokota 7656043Syokota DPRINTF(5, ("smopen: dev:%d,%d, vty:%d\n", 7756043Syokota major(dev), minor(dev), SC_VTY(dev))); 7856043Syokota 7956043Syokota#if 0 8056043Syokota if (SC_VTY(dev) != SC_MOUSE) 8156043Syokota return ENXIO; 8256043Syokota#endif 8356043Syokota 8456043Syokota tp = dev->si_tty = ttymalloc(dev->si_tty); 8556043Syokota if (!(tp->t_state & TS_ISOPEN)) { 8679344Syokota sysmouse_tty = tp; 8756043Syokota tp->t_oproc = smstart; 8856043Syokota tp->t_param = smparam; 8956043Syokota tp->t_stop = nottystop; 9056043Syokota tp->t_dev = dev; 9156043Syokota ttychars(tp); 9256043Syokota tp->t_iflag = TTYDEF_IFLAG; 9356043Syokota tp->t_oflag = TTYDEF_OFLAG; 9456043Syokota tp->t_cflag = TTYDEF_CFLAG; 9556043Syokota tp->t_lflag = TTYDEF_LFLAG; 9656043Syokota tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 9756043Syokota smparam(tp, &tp->t_termios); 9856043Syokota (*linesw[tp->t_line].l_modem)(tp, 1); 9993593Sjhb } else if (tp->t_state & TS_XCLUDE && suser(td)) { 10056043Syokota return EBUSY; 10156043Syokota } 10256043Syokota 10356043Syokota return (*linesw[tp->t_line].l_open)(dev, tp); 10456043Syokota} 10556043Syokota 10656043Syokotastatic int 10783366Sjuliansmclose(dev_t dev, int flag, int mode, struct thread *td) 10856043Syokota{ 10956043Syokota struct tty *tp; 11056043Syokota int s; 11156043Syokota 11256043Syokota tp = dev->si_tty; 11356043Syokota s = spltty(); 11456043Syokota mouse_level = 0; 11556043Syokota (*linesw[tp->t_line].l_close)(tp, flag); 11656043Syokota ttyclose(tp); 11756043Syokota splx(s); 11856043Syokota 11956043Syokota return 0; 12056043Syokota} 12156043Syokota 12256043Syokotastatic void 12356043Syokotasmstart(struct tty *tp) 12456043Syokota{ 12556043Syokota struct clist *rbp; 12656043Syokota u_char buf[PCBURST]; 12756043Syokota int s; 12856043Syokota 12956043Syokota s = spltty(); 13056043Syokota if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) { 13156043Syokota tp->t_state |= TS_BUSY; 13256043Syokota rbp = &tp->t_outq; 13356043Syokota while (rbp->c_cc) 13456043Syokota q_to_b(rbp, buf, PCBURST); 13556043Syokota tp->t_state &= ~TS_BUSY; 13656043Syokota ttwwakeup(tp); 13756043Syokota } 13856043Syokota splx(s); 13956043Syokota} 14056043Syokota 14156043Syokotastatic int 14256043Syokotasmparam(struct tty *tp, struct termios *t) 14356043Syokota{ 14456043Syokota tp->t_ispeed = t->c_ispeed; 14556043Syokota tp->t_ospeed = t->c_ospeed; 14656043Syokota tp->t_cflag = t->c_cflag; 14756043Syokota return 0; 14856043Syokota} 14956043Syokota 15056043Syokotastatic int 15183366Sjuliansmioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td) 15256043Syokota{ 15356043Syokota struct tty *tp; 15456043Syokota mousehw_t *hw; 15556043Syokota mousemode_t *mode; 15656043Syokota int error; 15756043Syokota int s; 15856043Syokota 15956043Syokota tp = dev->si_tty; 16056043Syokota switch (cmd) { 16156043Syokota 16256043Syokota case MOUSE_GETHWINFO: /* get device information */ 16356043Syokota hw = (mousehw_t *)data; 16456043Syokota hw->buttons = 10; /* XXX unknown */ 16556043Syokota hw->iftype = MOUSE_IF_SYSMOUSE; 16656043Syokota hw->type = MOUSE_MOUSE; 16756043Syokota hw->model = MOUSE_MODEL_GENERIC; 16856043Syokota hw->hwid = 0; 16956043Syokota return 0; 17056043Syokota 17156043Syokota case MOUSE_GETMODE: /* get protocol/mode */ 17256043Syokota mode = (mousemode_t *)data; 17356043Syokota mode->level = mouse_level; 17456043Syokota switch (mode->level) { 17556043Syokota case 0: /* emulate MouseSystems protocol */ 17656043Syokota mode->protocol = MOUSE_PROTO_MSC; 17756043Syokota mode->rate = -1; /* unknown */ 17856043Syokota mode->resolution = -1; /* unknown */ 17956043Syokota mode->accelfactor = 0; /* disabled */ 18056043Syokota mode->packetsize = MOUSE_MSC_PACKETSIZE; 18156043Syokota mode->syncmask[0] = MOUSE_MSC_SYNCMASK; 18256043Syokota mode->syncmask[1] = MOUSE_MSC_SYNC; 18356043Syokota break; 18456043Syokota 18556043Syokota case 1: /* sysmouse protocol */ 18656043Syokota mode->protocol = MOUSE_PROTO_SYSMOUSE; 18756043Syokota mode->rate = -1; 18856043Syokota mode->resolution = -1; 18956043Syokota mode->accelfactor = 0; 19056043Syokota mode->packetsize = MOUSE_SYS_PACKETSIZE; 19156043Syokota mode->syncmask[0] = MOUSE_SYS_SYNCMASK; 19256043Syokota mode->syncmask[1] = MOUSE_SYS_SYNC; 19356043Syokota break; 19456043Syokota } 19556043Syokota return 0; 19656043Syokota 19756043Syokota case MOUSE_SETMODE: /* set protocol/mode */ 19856043Syokota mode = (mousemode_t *)data; 19965129Syokota if (mode->level == -1) 20065129Syokota ; /* don't change the current setting */ 20165129Syokota else if ((mode->level < 0) || (mode->level > 1)) 20256043Syokota return EINVAL; 20365129Syokota else 20465129Syokota mouse_level = mode->level; 20556043Syokota return 0; 20656043Syokota 20756043Syokota case MOUSE_GETLEVEL: /* get operation level */ 20856043Syokota *(int *)data = mouse_level; 20956043Syokota return 0; 21056043Syokota 21156043Syokota case MOUSE_SETLEVEL: /* set operation level */ 21256043Syokota if ((*(int *)data < 0) || (*(int *)data > 1)) 21356043Syokota return EINVAL; 21456043Syokota mouse_level = *(int *)data; 21556043Syokota return 0; 21656043Syokota 21756043Syokota case MOUSE_GETSTATUS: /* get accumulated mouse events */ 21856043Syokota s = spltty(); 21956043Syokota *(mousestatus_t *)data = mouse_status; 22056043Syokota mouse_status.flags = 0; 22156043Syokota mouse_status.obutton = mouse_status.button; 22256043Syokota mouse_status.dx = 0; 22356043Syokota mouse_status.dy = 0; 22456043Syokota mouse_status.dz = 0; 22556043Syokota splx(s); 22656043Syokota return 0; 22756043Syokota 22856043Syokota#if notyet 22956043Syokota case MOUSE_GETVARS: /* get internal mouse variables */ 23056043Syokota case MOUSE_SETVARS: /* set internal mouse variables */ 23156043Syokota return ENODEV; 23256043Syokota#endif 23356043Syokota 23456043Syokota case MOUSE_READSTATE: /* read status from the device */ 23556043Syokota case MOUSE_READDATA: /* read data from the device */ 23656043Syokota return ENODEV; 23756043Syokota } 23856043Syokota 23983366Sjulian error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td); 24056043Syokota if (error != ENOIOCTL) 24156043Syokota return error; 24256043Syokota error = ttioctl(tp, cmd, data, flag); 24356043Syokota if (error != ENOIOCTL) 24456043Syokota return error; 24556043Syokota return ENOTTY; 24656043Syokota} 24756043Syokota 24856043Syokotastatic void 24956043Syokotasm_attach_mouse(void *unused) 25056043Syokota{ 25156043Syokota dev_t dev; 25256043Syokota 25356043Syokota dev = make_dev(&sm_cdevsw, SC_MOUSE, UID_ROOT, GID_WHEEL, 0600, 25456043Syokota "sysmouse"); 25556043Syokota /* sysmouse doesn't have scr_stat */ 25656043Syokota} 25756043Syokota 25856043SyokotaSYSINIT(sysmouse, SI_SUB_DRIVERS, SI_ORDER_MIDDLE + CDEV_MAJOR, 25956043Syokota sm_attach_mouse, NULL) 26056043Syokota 26156043Syokotaint 26256043Syokotasysmouse_event(mouse_info_t *info) 26356043Syokota{ 26456043Syokota /* MOUSE_BUTTON?DOWN -> MOUSE_MSC_BUTTON?UP */ 26556043Syokota static int butmap[8] = { 26656043Syokota MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, 26756043Syokota MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, 26856043Syokota MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP, 26956043Syokota MOUSE_MSC_BUTTON3UP, 27056043Syokota MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP, 27156043Syokota MOUSE_MSC_BUTTON2UP, 27256043Syokota MOUSE_MSC_BUTTON1UP, 27356043Syokota 0, 27456043Syokota }; 27556043Syokota u_char buf[8]; 27656043Syokota int x, y, z; 27756043Syokota int i; 27856043Syokota 27956043Syokota switch (info->operation) { 28056043Syokota case MOUSE_ACTION: 28156043Syokota mouse_status.button = info->u.data.buttons; 28256043Syokota /* FALL THROUGH */ 28356043Syokota case MOUSE_MOTION_EVENT: 28456043Syokota x = info->u.data.x; 28556043Syokota y = info->u.data.y; 28656043Syokota z = info->u.data.z; 28756043Syokota break; 28856043Syokota case MOUSE_BUTTON_EVENT: 28956043Syokota x = y = z = 0; 29056043Syokota if (info->u.event.value > 0) 29156043Syokota mouse_status.button |= info->u.event.id; 29256043Syokota else 29356043Syokota mouse_status.button &= ~info->u.event.id; 29456043Syokota break; 29556043Syokota default: 29656043Syokota return 0; 29756043Syokota } 29856043Syokota 29956043Syokota mouse_status.dx += x; 30056043Syokota mouse_status.dy += y; 30156043Syokota mouse_status.dz += z; 30256043Syokota mouse_status.flags |= ((x || y || z) ? MOUSE_POSCHANGED : 0) 30356043Syokota | (mouse_status.obutton ^ mouse_status.button); 30456043Syokota if (mouse_status.flags == 0) 30556043Syokota return 0; 30656043Syokota 30756043Syokota if ((sysmouse_tty == NULL) || !(sysmouse_tty->t_state & TS_ISOPEN)) 30856043Syokota return mouse_status.flags; 30956043Syokota 31056043Syokota /* the first five bytes are compatible with MouseSystems' */ 31156043Syokota buf[0] = MOUSE_MSC_SYNC 31256043Syokota | butmap[mouse_status.button & MOUSE_STDBUTTONS]; 31356043Syokota x = imax(imin(x, 255), -256); 31456043Syokota buf[1] = x >> 1; 31556043Syokota buf[3] = x - buf[1]; 31656043Syokota y = -imax(imin(y, 255), -256); 31756043Syokota buf[2] = y >> 1; 31856043Syokota buf[4] = y - buf[2]; 31956043Syokota for (i = 0; i < MOUSE_MSC_PACKETSIZE; ++i) 32056043Syokota (*linesw[sysmouse_tty->t_line].l_rint)(buf[i], sysmouse_tty); 32156043Syokota if (mouse_level >= 1) { 32256043Syokota /* extended part */ 32356043Syokota z = imax(imin(z, 127), -128); 32456043Syokota buf[5] = (z >> 1) & 0x7f; 32556043Syokota buf[6] = (z - (z >> 1)) & 0x7f; 32656043Syokota /* buttons 4-10 */ 32756043Syokota buf[7] = (~mouse_status.button >> 3) & 0x7f; 32856043Syokota for (i = MOUSE_MSC_PACKETSIZE; i < MOUSE_SYS_PACKETSIZE; ++i) 32956043Syokota (*linesw[sysmouse_tty->t_line].l_rint)(buf[i], 33056043Syokota sysmouse_tty); 33156043Syokota } 33256043Syokota 33356043Syokota return mouse_status.flags; 33456043Syokota} 33556043Syokota 33656043Syokota#endif /* !SC_NO_SYSMOUSE */ 337