home *** CD-ROM | disk | FTP | other *** search
- /* Based on:
- * simple driver for serial mouse
- * Andrew Haylett, 14th December 1992
- * and on the driver in XFree86.
- * Edited for svgalib (hhanemaa@cs.ruu.nl).
- * This probably doesn't work with all types of bus mouse.
- * HH: Added PS/2 mouse support.
- * Fixed Logitech support thanks to Daniel Jackson.
- * MouseSystems movement overflow fixed by Steve VanDevender.
- * Logitech fixed again.
- * Michael: Added support for controlling DTR and RTS.
- */
-
- /* This file is included by mouse.c. */
-
- #include <unistd.h>
- #include <termios.h>
- #include <sys/ioctl.h>
- #include <fcntl.h>
- #include <time.h>
-
-
- /* #define DEBUG */
-
- static int mtype;
- static int mbaud = 1200; /* Should be 1200. */
- static int msample;
- static char *mdev;
- static int mfd = -1;
- static int mfdmode = 0; /* 0 means don't wait (NDELAY) */
- static int m_modem_ctl = 0;
-
- /* Settings found on mouse open.. Probably std termios should be restored as well*/
- static unsigned long mold_modem_info; /* original state of DTR/RTS */
- static char mmodem_info_valid = 0; /* ==0 means: couldn't get it: old kernel? */
-
- static const unsigned short cflag[6] =
- {
- (CS7 | CREAD | CLOCAL | HUPCL ), /* MicroSoft */
- (CS8 | CSTOPB | CREAD | CLOCAL | HUPCL ), /* MouseSystems */
- (CS8 | PARENB | PARODD | CREAD | CLOCAL | HUPCL ), /* MMSeries */
- (CS8 | CSTOPB | CREAD | CLOCAL | HUPCL ), /* Logitech */
- 0, /* BusMouse */
- 0 /* PS/2 */
- };
-
- static const unsigned char proto[6][5] =
- {
- /* hd_mask hd_id dp_mask dp_id nobytes */
- { 0x40, 0x40, 0x40, 0x00, 3 }, /* MicroSoft */
- { 0xf8, 0x80, 0x00, 0x00, 5 }, /* MouseSystems */
- { 0xe0, 0x80, 0x80, 0x00, 3 }, /* MMSeries */
- { 0xe0, 0x80, 0x00, 0x00, 3 }, /* Logitech */
- { 0xf8, 0x80, 0x00, 0x00, 5 }, /* BusMouse */
- { 0xc0, 0x00, 0x00, 0x00, 3 }, /* PS/2 mouse */
- };
-
- static void
- ms_setspeed(const int old, const int new,
- const unsigned short c_cflag)
- {
- struct termios tty;
- char *c;
-
- tcgetattr(mfd, &tty);
-
- tty.c_iflag = IGNBRK | IGNPAR;
- tty.c_oflag = 0;
- tty.c_lflag = 0;
- tty.c_line = 0;
- tty.c_cc[VTIME] = 0;
- tty.c_cc[VMIN] = 1;
-
- switch (old)
- {
- case 9600: tty.c_cflag = c_cflag | B9600; break;
- case 4800: tty.c_cflag = c_cflag | B4800; break;
- case 2400: tty.c_cflag = c_cflag | B2400; break;
- case 1200:
- default: tty.c_cflag = c_cflag | B1200; break;
- }
-
- tcsetattr(mfd, TCSAFLUSH, &tty);
-
- switch (new)
- {
- case 9600: c = "*q"; tty.c_cflag = c_cflag | B9600; break;
- case 4800: c = "*p"; tty.c_cflag = c_cflag | B4800; break;
- case 2400: c = "*o"; tty.c_cflag = c_cflag | B2400; break;
- case 1200:
- default: c = "*n"; tty.c_cflag = c_cflag | B1200; break;
- }
-
- write(mfd, c, 2);
- usleep(10000);
- tcsetattr(mfd, TCSAFLUSH, &tty);
- }
-
- static int
- ms_init()
- {
- /* Added O_NDELAY here. */
- if ((mfd = open(mdev, O_RDWR | O_NDELAY)) < 0)
- return -1;
-
- if (mtype == MOUSE_BUSMOUSE || mtype == MOUSE_PS2)
- m_modem_ctl=0;
-
- /* If no signal will change there is no need to restore
- or safe original settings. */
- if(!m_modem_ctl)
- mmodem_info_valid=0;
- else
- {
- /* Get current modem signals; keep silent on errors.. */
- mmodem_info_valid= !ioctl(mfd, TIOCMGET, &mold_modem_info);
-
- if(mmodem_info_valid)
- {
- unsigned long param=mold_modem_info;
-
- /* Prepare new stat: */
-
- /*set DTR as ordered..*/
- if(m_modem_ctl&MOUSE_CHG_DTR)
- {
- param&= ~TIOCM_DTR;
- if(m_modem_ctl&MOUSE_DTR_HIGH)
- param|=TIOCM_DTR;
- }
-
- /*set RTS as ordered..*/
- if(m_modem_ctl&MOUSE_CHG_RTS)
- {
- param&= ~TIOCM_RTS;
- if(m_modem_ctl&MOUSE_RTS_HIGH)
- param|=TIOCM_RTS;
- }
-
- if(ioctl(mfd, TIOCMSET, ¶m))
- mmodem_info_valid=0; /* No try to restore if this failed */
- }
- }
-
- if (mtype != MOUSE_BUSMOUSE && mtype != MOUSE_PS2)
- {
- ms_setspeed(9600, mbaud, cflag[mtype]);
- ms_setspeed(4800, mbaud, cflag[mtype]);
- ms_setspeed(2400, mbaud, cflag[mtype]);
- ms_setspeed(1200, mbaud, cflag[mtype]);
-
- if (mtype == MOUSE_LOGITECH)
- {
- write(mfd, "S", 1);
- ms_setspeed(mbaud, mbaud, cflag[MOUSE_MMSERIES]);
- }
-
- if (msample <= 0) write(mfd, "O", 1);
- else if (msample <= 15) write(mfd, "J", 1);
- else if (msample <= 27) write(mfd, "K", 1);
- else if (msample <= 42) write(mfd, "L", 1);
- else if (msample <= 60) write(mfd, "R", 1);
- else if (msample <= 85) write(mfd, "M", 1);
- else if (msample <= 125) write(mfd, "Q", 1);
- else write(mfd, "N", 1);
- }
- return 0;
- }
-
- /* Scooped from X driver. */
- static inline void
- ms_close() {
- if (mfd == -1)
- return;
- if (mtype == MOUSE_LOGITECH) {
- write(mfd, "U", 1);
- ms_setspeed(mbaud, 1200, cflag[MOUSE_LOGITECH]);
- }
-
- /* Try to restore modem signals if we could get them. */
- if(mmodem_info_valid)
- ioctl(mfd, TIOCMSET, &mold_modem_info);
-
- close(mfd);
- }
-
-
-
- #define MOUSEBUFFERSIZE 256
-
- static int
- get_ms_event( int wait )
- /*
- Changed to process multiple packets.
- wait value:
- 0 Process any mouse events, and return status.
- 1 Wait for mouse event, then return.
-
- Status indicates whether an event was processed.
- */
- {
- static unsigned char buf[MOUSEBUFFERSIZE];
- static int nu_bytes = 0;
- char event_handled = 0;
- int bytesread;
- int i;
- int but;
- int dx, dy;
- int j;
-
- if (mfd == -1)
- return -1;
-
- again:
-
- if (mfdmode == 1) {
- /* We don't want to wait, set NDELAY mode. */
- fcntl(mfd, F_SETFL, O_RDONLY | O_NDELAY);
- mfdmode = 0;
- }
-
- bytesread = read(mfd, &buf[nu_bytes], MOUSEBUFFERSIZE - nu_bytes);
-
- i = 0;
-
- if (bytesread >= 1)
- nu_bytes += bytesread;
-
- #ifdef DEBUG
- printf("#bytes in buffer: %d\n", nu_bytes);
- #endif
-
- handle_packets:
-
- /* Handle packets in buffer. */
-
- #ifdef DEBUG
- printf("Bytes left in buffer: %d, packet is %d bytes\n",
- nu_bytes - i, proto[mtype][4]);
- #endif
-
- if (nu_bytes - i < proto[mtype][4])
- /* No full packet available. */
- if (wait == 0 || (wait == 1 && event_handled)) {
- if (i >= nu_bytes) {
- nu_bytes = 0;
- i = 0;
- }
- else {
- /* Move partial packet to front of buffer. */
- for (j = i; j < nu_bytes; j++)
- buf[j - i] = buf[j];
- nu_bytes -= i;
- }
- return event_handled;
- }
- else { /* (wait == 1 && !event_handled) */
- if (i >= nu_bytes) {
- nu_bytes = 0;
- i = 0;
- }
- /* Wait mode, we'll sleep on reads. */
- fcntl(mfd, F_SETFL, O_RDONLY);
- mfdmode = 1;
- read(mfd, &buf[nu_bytes], 1);
- nu_bytes++;
- if (nu_bytes - i < proto[mtype][4])
- /* Not a complete packet. */
- goto again;
- }
-
- /* Check header byte. */
- if ((buf[i] & proto[mtype][0]) != proto[mtype][1]) {
- /* Not a header byte. */
- i++;
- goto handle_packets;
- }
-
- /* Check whether it's a valid data packet. */
- if (mtype != MOUSE_PS2)
- for (j = 1; j < proto[mtype][4]; j++)
- if ((buf[i + j] & proto[mtype][2]) != proto[mtype][3]
- || buf[i + j] == 0x80) {
- i = i + j + 1;
- goto handle_packets;
- }
-
- /* Construct the event. */
- switch (mtype) {
- case MOUSE_MICROSOFT: /* Microsoft */
- default:
- but = ((buf[i] & 0x20) >> 3) | ((buf[i] & 0x10) >> 4);
- dx = (char)(((buf[i] & 0x03) << 6) | (buf[i + 1] & 0x3F));
- dy = (char)(((buf[i] & 0x0C) << 4) | (buf[i + 2] & 0x3F));
- break;
- case MOUSE_MOUSESYSTEMS: /* Mouse Systems Corp */
- but = (~buf[i]) & 0x07;
- dx = (char)(buf[i + 1]);
- dx += (char)(buf[i + 3]);
- dy = - ((char)(buf[i + 2]));
- dy -= (char)(buf[i + 4]);
- break;
- case MOUSE_MMSERIES: /* MM Series */
- case MOUSE_LOGITECH: /* Logitech */
- but = buf[i] & 0x07;
- dx = (buf[i] & 0x10) ? buf[i + 1] : - buf[i + 1];
- dy = (buf[i] & 0x08) ? - buf[i + 2] : buf[i + 2];
- break;
- case MOUSE_BUSMOUSE: /* BusMouse */
- but = (~buf[i]) & 0x07;
- dx = (char)buf[i + 1];
- dy = - (char)buf[i + 2];
- break;
- case MOUSE_PS2: /* PS/2 mouse */
- but = (buf[i] & 0x04) >> 1 | /* Middle */
- (buf[i] & 0x02) >> 1 | /* Right */
- (buf[i] & 0x01) << 2; /* Left */
- dx = (buf[i] & 0x10) ? buf[i + 1]-256 : buf[i + 1];
- dy = (buf[i] & 0x20) ? -(buf[i + 2]-256) : -buf[i + 2];
- break;
- }
-
- __mouse_eventhandler(but, dx, dy);
-
- i += proto[mtype][4];
- event_handled = 1;
-
- goto handle_packets;
- }
-