sysmouse.c revision 136505
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 136505 2004-10-14 08:58:28Z phk $"); 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 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 = { 52126080Sphk .d_version = D_VERSION, 53111815Sphk .d_open = smopen, 54111815Sphk .d_close = smclose, 55111815Sphk .d_ioctl = smioctl, 56111815Sphk .d_name = "sysmouse", 57126080Sphk .d_flags = D_TTY | D_NEEDGIANT, 5856043Syokota}; 5956043Syokota 6056043Syokota/* local variables */ 6156043Syokotastatic struct tty *sysmouse_tty; 6256043Syokotastatic int mouse_level; /* sysmouse protocol level */ 6356043Syokotastatic mousestatus_t mouse_status; 6456043Syokota 6556043Syokotastatic void smstart(struct tty *tp); 6656043Syokotastatic int smparam(struct tty *tp, struct termios *t); 6756043Syokota 6856043Syokotastatic int 69130585Sphksmopen(struct cdev *dev, int flag, int mode, struct thread *td) 7056043Syokota{ 7156043Syokota struct tty *tp; 7256043Syokota 7356043Syokota DPRINTF(5, ("smopen: dev:%d,%d, vty:%d\n", 7456043Syokota major(dev), minor(dev), SC_VTY(dev))); 7556043Syokota 7656043Syokota#if 0 7756043Syokota if (SC_VTY(dev) != SC_MOUSE) 7856043Syokota return ENXIO; 7956043Syokota#endif 8056043Syokota 81136505Sphk tp = dev->si_tty; 8256043Syokota if (!(tp->t_state & TS_ISOPEN)) { 8356043Syokota ttychars(tp); 8456043Syokota tp->t_iflag = TTYDEF_IFLAG; 8556043Syokota tp->t_oflag = TTYDEF_OFLAG; 8656043Syokota tp->t_cflag = TTYDEF_CFLAG; 8756043Syokota tp->t_lflag = TTYDEF_LFLAG; 8856043Syokota tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 8956043Syokota smparam(tp, &tp->t_termios); 90130077Sphk ttyld_modem(tp, 1); 9193593Sjhb } else if (tp->t_state & TS_XCLUDE && suser(td)) { 9256043Syokota return EBUSY; 9356043Syokota } 9456043Syokota 95130077Sphk return ttyld_open(tp, dev); 9656043Syokota} 9756043Syokota 9856043Syokotastatic int 99130585Sphksmclose(struct cdev *dev, int flag, int mode, struct thread *td) 10056043Syokota{ 10156043Syokota struct tty *tp; 10256043Syokota int s; 10356043Syokota 10456043Syokota tp = dev->si_tty; 10556043Syokota s = spltty(); 10656043Syokota mouse_level = 0; 107130077Sphk ttyld_close(tp, flag); 108132226Sphk tty_close(tp); 10956043Syokota splx(s); 11056043Syokota 11156043Syokota return 0; 11256043Syokota} 11356043Syokota 11456043Syokotastatic void 11556043Syokotasmstart(struct tty *tp) 11656043Syokota{ 11756043Syokota struct clist *rbp; 11856043Syokota u_char buf[PCBURST]; 11956043Syokota int s; 12056043Syokota 12156043Syokota s = spltty(); 12256043Syokota if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) { 12356043Syokota tp->t_state |= TS_BUSY; 12456043Syokota rbp = &tp->t_outq; 12556043Syokota while (rbp->c_cc) 12656043Syokota q_to_b(rbp, buf, PCBURST); 12756043Syokota tp->t_state &= ~TS_BUSY; 12856043Syokota ttwwakeup(tp); 12956043Syokota } 13056043Syokota splx(s); 13156043Syokota} 13256043Syokota 13356043Syokotastatic int 13456043Syokotasmparam(struct tty *tp, struct termios *t) 13556043Syokota{ 13656043Syokota tp->t_ispeed = t->c_ispeed; 13756043Syokota tp->t_ospeed = t->c_ospeed; 13856043Syokota tp->t_cflag = t->c_cflag; 13956043Syokota return 0; 14056043Syokota} 14156043Syokota 14256043Syokotastatic int 143130585Sphksmioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) 14456043Syokota{ 14556043Syokota struct tty *tp; 14656043Syokota mousehw_t *hw; 14756043Syokota mousemode_t *mode; 14856043Syokota int s; 14956043Syokota 15056043Syokota tp = dev->si_tty; 15156043Syokota switch (cmd) { 15256043Syokota 15356043Syokota case MOUSE_GETHWINFO: /* get device information */ 15456043Syokota hw = (mousehw_t *)data; 15556043Syokota hw->buttons = 10; /* XXX unknown */ 15656043Syokota hw->iftype = MOUSE_IF_SYSMOUSE; 15756043Syokota hw->type = MOUSE_MOUSE; 15856043Syokota hw->model = MOUSE_MODEL_GENERIC; 15956043Syokota hw->hwid = 0; 16056043Syokota return 0; 16156043Syokota 16256043Syokota case MOUSE_GETMODE: /* get protocol/mode */ 16356043Syokota mode = (mousemode_t *)data; 16456043Syokota mode->level = mouse_level; 16556043Syokota switch (mode->level) { 16656043Syokota case 0: /* emulate MouseSystems protocol */ 16756043Syokota mode->protocol = MOUSE_PROTO_MSC; 16856043Syokota mode->rate = -1; /* unknown */ 16956043Syokota mode->resolution = -1; /* unknown */ 17056043Syokota mode->accelfactor = 0; /* disabled */ 17156043Syokota mode->packetsize = MOUSE_MSC_PACKETSIZE; 17256043Syokota mode->syncmask[0] = MOUSE_MSC_SYNCMASK; 17356043Syokota mode->syncmask[1] = MOUSE_MSC_SYNC; 17456043Syokota break; 17556043Syokota 17656043Syokota case 1: /* sysmouse protocol */ 17756043Syokota mode->protocol = MOUSE_PROTO_SYSMOUSE; 17856043Syokota mode->rate = -1; 17956043Syokota mode->resolution = -1; 18056043Syokota mode->accelfactor = 0; 18156043Syokota mode->packetsize = MOUSE_SYS_PACKETSIZE; 18256043Syokota mode->syncmask[0] = MOUSE_SYS_SYNCMASK; 18356043Syokota mode->syncmask[1] = MOUSE_SYS_SYNC; 18456043Syokota break; 18556043Syokota } 18656043Syokota return 0; 18756043Syokota 18856043Syokota case MOUSE_SETMODE: /* set protocol/mode */ 18956043Syokota mode = (mousemode_t *)data; 19065129Syokota if (mode->level == -1) 19165129Syokota ; /* don't change the current setting */ 19265129Syokota else if ((mode->level < 0) || (mode->level > 1)) 19356043Syokota return EINVAL; 19465129Syokota else 19565129Syokota mouse_level = mode->level; 19656043Syokota return 0; 19756043Syokota 19856043Syokota case MOUSE_GETLEVEL: /* get operation level */ 19956043Syokota *(int *)data = mouse_level; 20056043Syokota return 0; 20156043Syokota 20256043Syokota case MOUSE_SETLEVEL: /* set operation level */ 20356043Syokota if ((*(int *)data < 0) || (*(int *)data > 1)) 20456043Syokota return EINVAL; 20556043Syokota mouse_level = *(int *)data; 20656043Syokota return 0; 20756043Syokota 20856043Syokota case MOUSE_GETSTATUS: /* get accumulated mouse events */ 20956043Syokota s = spltty(); 21056043Syokota *(mousestatus_t *)data = mouse_status; 21156043Syokota mouse_status.flags = 0; 21256043Syokota mouse_status.obutton = mouse_status.button; 21356043Syokota mouse_status.dx = 0; 21456043Syokota mouse_status.dy = 0; 21556043Syokota mouse_status.dz = 0; 21656043Syokota splx(s); 21756043Syokota return 0; 21856043Syokota 21956043Syokota#if notyet 22056043Syokota case MOUSE_GETVARS: /* get internal mouse variables */ 22156043Syokota case MOUSE_SETVARS: /* set internal mouse variables */ 22256043Syokota return ENODEV; 22356043Syokota#endif 22456043Syokota 22556043Syokota case MOUSE_READSTATE: /* read status from the device */ 22656043Syokota case MOUSE_READDATA: /* read data from the device */ 22756043Syokota return ENODEV; 22856043Syokota } 22956043Syokota 230129944Sphk return(ttyioctl(dev, cmd, data, flag, td)); 23156043Syokota} 23256043Syokota 23356043Syokotastatic void 23456043Syokotasm_attach_mouse(void *unused) 23556043Syokota{ 236130585Sphk struct cdev *dev; 237136505Sphk struct tty *tp; 23856043Syokota 23956043Syokota dev = make_dev(&sm_cdevsw, SC_MOUSE, UID_ROOT, GID_WHEEL, 0600, 24056043Syokota "sysmouse"); 241136505Sphk dev->si_tty = tp = ttyalloc(); 242136505Sphk tp->t_oproc = smstart; 243136505Sphk tp->t_param = smparam; 244136505Sphk tp->t_stop = nottystop; 245136505Sphk tp->t_dev = dev; 246136505Sphk 247136505Sphk sysmouse_tty = tp; 24856043Syokota /* sysmouse doesn't have scr_stat */ 24956043Syokota} 25056043Syokota 251126076SphkSYSINIT(sysmouse, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, sm_attach_mouse, NULL) 25256043Syokota 25356043Syokotaint 25456043Syokotasysmouse_event(mouse_info_t *info) 25556043Syokota{ 25656043Syokota /* MOUSE_BUTTON?DOWN -> MOUSE_MSC_BUTTON?UP */ 25756043Syokota static int butmap[8] = { 25856043Syokota MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, 25956043Syokota MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, 26056043Syokota MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP, 26156043Syokota MOUSE_MSC_BUTTON3UP, 26256043Syokota MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP, 26356043Syokota MOUSE_MSC_BUTTON2UP, 26456043Syokota MOUSE_MSC_BUTTON1UP, 26556043Syokota 0, 26656043Syokota }; 26756043Syokota u_char buf[8]; 26856043Syokota int x, y, z; 26956043Syokota int i; 27056043Syokota 27156043Syokota switch (info->operation) { 27256043Syokota case MOUSE_ACTION: 27356043Syokota mouse_status.button = info->u.data.buttons; 27456043Syokota /* FALL THROUGH */ 27556043Syokota case MOUSE_MOTION_EVENT: 27656043Syokota x = info->u.data.x; 27756043Syokota y = info->u.data.y; 27856043Syokota z = info->u.data.z; 27956043Syokota break; 28056043Syokota case MOUSE_BUTTON_EVENT: 28156043Syokota x = y = z = 0; 28256043Syokota if (info->u.event.value > 0) 28356043Syokota mouse_status.button |= info->u.event.id; 28456043Syokota else 28556043Syokota mouse_status.button &= ~info->u.event.id; 28656043Syokota break; 28756043Syokota default: 28856043Syokota return 0; 28956043Syokota } 29056043Syokota 29156043Syokota mouse_status.dx += x; 29256043Syokota mouse_status.dy += y; 29356043Syokota mouse_status.dz += z; 29456043Syokota mouse_status.flags |= ((x || y || z) ? MOUSE_POSCHANGED : 0) 29556043Syokota | (mouse_status.obutton ^ mouse_status.button); 29656043Syokota if (mouse_status.flags == 0) 29756043Syokota return 0; 29856043Syokota 29956043Syokota if ((sysmouse_tty == NULL) || !(sysmouse_tty->t_state & TS_ISOPEN)) 30056043Syokota return mouse_status.flags; 30156043Syokota 30256043Syokota /* the first five bytes are compatible with MouseSystems' */ 30356043Syokota buf[0] = MOUSE_MSC_SYNC 30456043Syokota | butmap[mouse_status.button & MOUSE_STDBUTTONS]; 30556043Syokota x = imax(imin(x, 255), -256); 30656043Syokota buf[1] = x >> 1; 30756043Syokota buf[3] = x - buf[1]; 30856043Syokota y = -imax(imin(y, 255), -256); 30956043Syokota buf[2] = y >> 1; 31056043Syokota buf[4] = y - buf[2]; 31156043Syokota for (i = 0; i < MOUSE_MSC_PACKETSIZE; ++i) 312130077Sphk ttyld_rint(sysmouse_tty, buf[i]); 31356043Syokota if (mouse_level >= 1) { 31456043Syokota /* extended part */ 31556043Syokota z = imax(imin(z, 127), -128); 31656043Syokota buf[5] = (z >> 1) & 0x7f; 31756043Syokota buf[6] = (z - (z >> 1)) & 0x7f; 31856043Syokota /* buttons 4-10 */ 31956043Syokota buf[7] = (~mouse_status.button >> 3) & 0x7f; 32056043Syokota for (i = MOUSE_MSC_PACKETSIZE; i < MOUSE_SYS_PACKETSIZE; ++i) 321130095Sphk ttyld_rint(sysmouse_tty, buf[i]); 32256043Syokota } 32356043Syokota 32456043Syokota return mouse_status.flags; 32556043Syokota} 32656043Syokota 32756043Syokota#endif /* !SC_NO_SYSMOUSE */ 328