sysmouse.c revision 193018
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 193018 2009-05-29 06:41:23Z ed $"); 30119420Sobrien 3156043Syokota#include "opt_syscons.h" 3256043Syokota 3356043Syokota#include <sys/param.h> 3456043Syokota#include <sys/systm.h> 35164033Srwatson#include <sys/priv.h> 36181905Sed#include <sys/serial.h> 3756043Syokota#include <sys/tty.h> 3856043Syokota#include <sys/kernel.h> 3966834Sphk#include <sys/consio.h> 4066860Sphk#include <sys/mouse.h> 4156043Syokota 4256043Syokota#include <dev/syscons/syscons.h> 4356043Syokota 4456043Syokota#ifndef SC_NO_SYSMOUSE 4556043Syokota 4656043Syokota/* local variables */ 4756043Syokotastatic struct tty *sysmouse_tty; 4856043Syokotastatic int mouse_level; /* sysmouse protocol level */ 4956043Syokotastatic mousestatus_t mouse_status; 5056043Syokota 51181905Sedstatic void 52181905Sedsmdev_close(struct tty *tp) 5356043Syokota{ 5456043Syokota mouse_level = 0; 5556043Syokota} 5656043Syokota 5756043Syokotastatic int 58181905Sedsmdev_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td) 5956043Syokota{ 6056043Syokota mousehw_t *hw; 6156043Syokota mousemode_t *mode; 6256043Syokota 6356043Syokota switch (cmd) { 6456043Syokota 6556043Syokota case MOUSE_GETHWINFO: /* get device information */ 6656043Syokota hw = (mousehw_t *)data; 6756043Syokota hw->buttons = 10; /* XXX unknown */ 6856043Syokota hw->iftype = MOUSE_IF_SYSMOUSE; 6956043Syokota hw->type = MOUSE_MOUSE; 7056043Syokota hw->model = MOUSE_MODEL_GENERIC; 7156043Syokota hw->hwid = 0; 7256043Syokota return 0; 7356043Syokota 7456043Syokota case MOUSE_GETMODE: /* get protocol/mode */ 7556043Syokota mode = (mousemode_t *)data; 7656043Syokota mode->level = mouse_level; 7756043Syokota switch (mode->level) { 7856043Syokota case 0: /* emulate MouseSystems protocol */ 7956043Syokota mode->protocol = MOUSE_PROTO_MSC; 8056043Syokota mode->rate = -1; /* unknown */ 8156043Syokota mode->resolution = -1; /* unknown */ 8256043Syokota mode->accelfactor = 0; /* disabled */ 8356043Syokota mode->packetsize = MOUSE_MSC_PACKETSIZE; 8456043Syokota mode->syncmask[0] = MOUSE_MSC_SYNCMASK; 8556043Syokota mode->syncmask[1] = MOUSE_MSC_SYNC; 8656043Syokota break; 8756043Syokota 8856043Syokota case 1: /* sysmouse protocol */ 8956043Syokota mode->protocol = MOUSE_PROTO_SYSMOUSE; 9056043Syokota mode->rate = -1; 9156043Syokota mode->resolution = -1; 9256043Syokota mode->accelfactor = 0; 9356043Syokota mode->packetsize = MOUSE_SYS_PACKETSIZE; 9456043Syokota mode->syncmask[0] = MOUSE_SYS_SYNCMASK; 9556043Syokota mode->syncmask[1] = MOUSE_SYS_SYNC; 9656043Syokota break; 9756043Syokota } 9856043Syokota return 0; 9956043Syokota 10056043Syokota case MOUSE_SETMODE: /* set protocol/mode */ 10156043Syokota mode = (mousemode_t *)data; 10265129Syokota if (mode->level == -1) 10365129Syokota ; /* don't change the current setting */ 10465129Syokota else if ((mode->level < 0) || (mode->level > 1)) 10556043Syokota return EINVAL; 10665129Syokota else 10765129Syokota mouse_level = mode->level; 10856043Syokota return 0; 10956043Syokota 11056043Syokota case MOUSE_GETLEVEL: /* get operation level */ 11156043Syokota *(int *)data = mouse_level; 11256043Syokota return 0; 11356043Syokota 11456043Syokota case MOUSE_SETLEVEL: /* set operation level */ 11556043Syokota if ((*(int *)data < 0) || (*(int *)data > 1)) 11656043Syokota return EINVAL; 11756043Syokota mouse_level = *(int *)data; 11856043Syokota return 0; 11956043Syokota 12056043Syokota case MOUSE_GETSTATUS: /* get accumulated mouse events */ 12156043Syokota *(mousestatus_t *)data = mouse_status; 12256043Syokota mouse_status.flags = 0; 12356043Syokota mouse_status.obutton = mouse_status.button; 12456043Syokota mouse_status.dx = 0; 12556043Syokota mouse_status.dy = 0; 12656043Syokota mouse_status.dz = 0; 12756043Syokota return 0; 12856043Syokota 129153072Sru#ifdef notyet 13056043Syokota case MOUSE_GETVARS: /* get internal mouse variables */ 13156043Syokota case MOUSE_SETVARS: /* set internal mouse variables */ 13256043Syokota return ENODEV; 13356043Syokota#endif 13456043Syokota 13556043Syokota case MOUSE_READSTATE: /* read status from the device */ 13656043Syokota case MOUSE_READDATA: /* read data from the device */ 13756043Syokota return ENODEV; 13856043Syokota } 13956043Syokota 140181905Sed return (ENOIOCTL); 14156043Syokota} 14256043Syokota 143181905Sedstatic int 144181905Sedsmdev_param(struct tty *tp, struct termios *t) 14556043Syokota{ 14656043Syokota 147181905Sed /* 148181905Sed * Set the output baud rate to zero. The mouse device supports 149181905Sed * no output, so we don't want to waste buffers. 150181905Sed */ 151184771Sed t->c_ispeed = TTYDEF_SPEED; 152181905Sed t->c_ospeed = B0; 153136505Sphk 154181905Sed return (0); 15556043Syokota} 15656043Syokota 157181905Sedstatic struct ttydevsw smdev_ttydevsw = { 158181905Sed .tsw_flags = TF_NOPREFIX, 159181905Sed .tsw_close = smdev_close, 160181905Sed .tsw_ioctl = smdev_ioctl, 161181905Sed .tsw_param = smdev_param, 162181905Sed}; 163181905Sed 164181905Sedstatic void 165181905Sedsm_attach_mouse(void *unused) 166181905Sed{ 167193018Sed sysmouse_tty = tty_alloc(&smdev_ttydevsw, NULL); 168181905Sed tty_makedev(sysmouse_tty, NULL, "sysmouse"); 169181905Sed} 170181905Sed 171177253SrwatsonSYSINIT(sysmouse, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, sm_attach_mouse, NULL); 17256043Syokota 17356043Syokotaint 17456043Syokotasysmouse_event(mouse_info_t *info) 17556043Syokota{ 17656043Syokota /* MOUSE_BUTTON?DOWN -> MOUSE_MSC_BUTTON?UP */ 17756043Syokota static int butmap[8] = { 17856043Syokota MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, 17956043Syokota MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, 18056043Syokota MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP, 18156043Syokota MOUSE_MSC_BUTTON3UP, 18256043Syokota MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP, 18356043Syokota MOUSE_MSC_BUTTON2UP, 18456043Syokota MOUSE_MSC_BUTTON1UP, 18556043Syokota 0, 18656043Syokota }; 18756043Syokota u_char buf[8]; 18856043Syokota int x, y, z; 189182109Sed int i, flags = 0; 19056043Syokota 191182109Sed tty_lock(sysmouse_tty); 192182109Sed 19356043Syokota switch (info->operation) { 19456043Syokota case MOUSE_ACTION: 19556043Syokota mouse_status.button = info->u.data.buttons; 19656043Syokota /* FALL THROUGH */ 19756043Syokota case MOUSE_MOTION_EVENT: 19856043Syokota x = info->u.data.x; 19956043Syokota y = info->u.data.y; 20056043Syokota z = info->u.data.z; 20156043Syokota break; 20256043Syokota case MOUSE_BUTTON_EVENT: 20356043Syokota x = y = z = 0; 20456043Syokota if (info->u.event.value > 0) 20556043Syokota mouse_status.button |= info->u.event.id; 20656043Syokota else 20756043Syokota mouse_status.button &= ~info->u.event.id; 20856043Syokota break; 20956043Syokota default: 210182109Sed goto done; 21156043Syokota } 21256043Syokota 21356043Syokota mouse_status.dx += x; 21456043Syokota mouse_status.dy += y; 21556043Syokota mouse_status.dz += z; 21656043Syokota mouse_status.flags |= ((x || y || z) ? MOUSE_POSCHANGED : 0) 21756043Syokota | (mouse_status.obutton ^ mouse_status.button); 218182109Sed flags = mouse_status.flags; 219182109Sed if (flags == 0 || !tty_opened(sysmouse_tty)) 220182109Sed goto done; 22156043Syokota 22256043Syokota /* the first five bytes are compatible with MouseSystems' */ 22356043Syokota buf[0] = MOUSE_MSC_SYNC 22456043Syokota | butmap[mouse_status.button & MOUSE_STDBUTTONS]; 22556043Syokota x = imax(imin(x, 255), -256); 22656043Syokota buf[1] = x >> 1; 22756043Syokota buf[3] = x - buf[1]; 22856043Syokota y = -imax(imin(y, 255), -256); 22956043Syokota buf[2] = y >> 1; 23056043Syokota buf[4] = y - buf[2]; 23156043Syokota for (i = 0; i < MOUSE_MSC_PACKETSIZE; ++i) 232181905Sed ttydisc_rint(sysmouse_tty, buf[i], 0); 23356043Syokota if (mouse_level >= 1) { 23456043Syokota /* extended part */ 23556043Syokota z = imax(imin(z, 127), -128); 23656043Syokota buf[5] = (z >> 1) & 0x7f; 23756043Syokota buf[6] = (z - (z >> 1)) & 0x7f; 23856043Syokota /* buttons 4-10 */ 23956043Syokota buf[7] = (~mouse_status.button >> 3) & 0x7f; 24056043Syokota for (i = MOUSE_MSC_PACKETSIZE; i < MOUSE_SYS_PACKETSIZE; ++i) 241181905Sed ttydisc_rint(sysmouse_tty, buf[i], 0); 24256043Syokota } 243181905Sed ttydisc_rint_done(sysmouse_tty); 24456043Syokota 245182109Seddone: tty_unlock(sysmouse_tty); 246182109Sed return (flags); 24756043Syokota} 24856043Syokota 24956043Syokota#endif /* !SC_NO_SYSMOUSE */ 250