1 /** 2 ** Copyright (c) 1995 Michael Smith, All rights reserved. 3 ** 4 ** Redistribution and use in source and binary forms, with or without 5 ** modification, are permitted provided that the following conditions 6 ** are met: 7 ** 1. Redistributions of source code must retain the above copyright 8 ** notice, this list of conditions and the following disclaimer as 9 ** the first lines of this file unmodified. 10 ** 2. Redistributions in binary form must reproduce the above copyright 11 ** notice, this list of conditions and the following disclaimer in the 12 ** documentation and/or other materials provided with the distribution. 13 ** 3. All advertising materials mentioning features or use of this software 14 ** must display the following acknowledgment: 15 ** This product includes software developed by Michael Smith. 16 ** 4. The name of the author may not be used to endorse or promote products 17 ** derived from this software without specific prior written permission. 18 ** 19 ** 20 ** THIS SOFTWARE IS PROVIDED BY Michael Smith ``AS IS'' AND ANY 21 ** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 ** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Michael Smith BE LIABLE FOR 24 ** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 27 ** BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 28 ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 29 ** OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 30 ** EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 ** 32 ** 33 ** $Id: moused.c,v 1.3 1996/09/09 18:47:47 sos Exp $ 34 **/ 35 36 /** 37 ** MOUSED.C 38 ** 39 ** Mouse daemon : listens to serial port for mouse data stream, 40 ** interprets same and passes ioctls off to the console driver. 41 ** 42 ** The mouse interface functions are derived closely from the mouse 43 ** handler in the XFree86 X server. Many thanks to the XFree86 people 44 ** for their great work! 45 ** 46 **/ 47 48 #include <stdio.h> 49 #include <stdlib.h> 50 #include <string.h> 51 #include <limits.h> 52 #include <errno.h> 53 #include <fcntl.h> 54 #include <termios.h> 55 #include <machine/console.h> 56 57 #define debug(fmt,args...) \ 58 if (debug&&nodaemon) fprintf(stderr,"%s: " fmt "\n", progname, ##args) 59 60 char *progname; 61 int debug = 0; 62 int nodaemon = 0; 63 64 void usage(void); 65 66 #define R_UNKNOWN 0 67 #define R_MICROSOFT 1 68 #define R_MOUSESYS 2 69 #define R_MMSERIES 3 70 #define R_LOGITECH 4 71 #define R_BUSMOUSE 5 72 #define R_LOGIMAN 6 73 #define R_PS_2 7 74 #define R_MMHITAB 8 75 76 char *rnames[] = { 77 "xxx", 78 "microsoft", 79 "mousesystems", 80 "mmseries", 81 "logitech", 82 "busmouse", 83 "mouseman", 84 "ps/2", 85 "mmhitab", 86 NULL 87 }; 88 89 unsigned short rodentcflags[] = 90 { 91 0, /* nomouse */ 92 (CS7 | CREAD | CLOCAL | HUPCL ), /* MicroSoft */ 93 (CS8 | CSTOPB | CREAD | CLOCAL | HUPCL ), /* MouseSystems */ 94 (CS8 | PARENB | PARODD | CREAD | CLOCAL | HUPCL ), /* MMSeries */ 95 (CS8 | CSTOPB | CREAD | CLOCAL | HUPCL ), /* Logitech */ 96 0, /* BusMouse */ 97 (CS7 | CREAD | CLOCAL | HUPCL ), /* MouseMan */ 98 0, /* PS/2 */ 99 (CS8 | CREAD | CLOCAL | HUPCL ), /* MMHitTablet */ 100 }; 101 102 103 typedef struct 104 { 105 int 106 dx,dy, 107 buttons; 108 } ACTIVITY; 109 110 111 struct rodentparam 112 { 113 int 114 baudrate, 115 samplerate, 116 flags, 117 rtype, 118 lastbuttons, 119 buttons, 120 mfd, 121 cleardtr, 122 clearrts; 123 124 char 125 *portname; 126 127 } rodent = { baudrate : 1200, 128 samplerate : 0, 129 flags : 0, 130 rtype : R_UNKNOWN, 131 lastbuttons : 0, 132 buttons : 0, 133 mfd : -1, 134 portname : NULL, 135 cleardtr : 0, 136 clearrts : 0}; 137 138 #define ChordMiddle 1 139 140 void r_init(void); 141 ACTIVITY *r_protocol(u_char b); 142 void setmousespeed(int old, int new, unsigned cflag); 143 144 void 145 main(int argc, char *argv[]) 146 { 147 int c,i,cfd; 148 u_char b; 149 ACTIVITY *act; 150 struct termios t; 151 struct mouse_info mouse; 152 int saved_buttons = 0; 153 154 progname = argv[0]; 155 156 while((c = getopt(argc,argv,"cdfsp:t:h?RDS:")) != EOF) 157 switch(c) 158 { 159 case 'c': 160 rodent.flags |= ChordMiddle; 161 break; 162 163 case 'd': 164 debug = 1; 165 break; 166 167 case 'f': 168 nodaemon = 1; 169 break; 170 171 case 'p': 172 rodent.portname = optarg; 173 break; 174 175 case 's': 176 rodent.baudrate = 9600; 177 break; 178 179 case 'R': 180 rodent.clearrts = 1; 181 break; 182 183 case 'D': 184 rodent.cleardtr = 1; 185 break; 186 187 case 'S': 188 rodent.baudrate = atoi(optarg); 189 debug("rodent baudrate %d", rodent.baudrate); 190 break; 191 192 case 't': 193 for (i = 0; rnames[i]; i++) 194 if (!strcmp(optarg,rnames[i])) 195 { 196 debug("rodent is %s",rnames[i]); 197 rodent.rtype = i; 198 break; 199 } 200 if (rnames[i]) 201 break; 202 warnx("no such mouse type `%s'",optarg); 203 usage(); 204 205 case 'h': 206 case '?': 207 default: 208 usage(); 209 } 210 211 switch(rodent.rtype) 212 { 213 case R_BUSMOUSE: 214 if (!rodent.portname) 215 rodent.portname = "/dev/mse0"; 216 break; 217 case R_PS_2: 218 if (!rodent.portname) 219 rodent.portname = "/dev/psm0"; 220 break; 221 default: 222 if (rodent.portname) 223 break; 224 warnx("No port name specified"); 225 usage(); 226 } 227 228 if ((rodent.mfd = open(rodent.portname, O_RDWR, 0)) == -1) 229 { 230 warn("Can't open %s",rodent.portname); 231 usage(); 232 } 233 r_init(); /* call init function */ 234 235 if ((cfd = open("/dev/consolectl", O_RDWR, 0)) == -1) 236 err(1, "open(/dev/consolectl)"); 237 238 if (!nodaemon) 239 if (daemon(0,0)) 240 { 241 err(1, "daemon() failed"); 242 } 243 244 for(;;) 245 { 246 i = read(rodent.mfd,&b,1); /* get a byte */ 247 if (i != 1) /* read returned or error; goodbye */ 248 { 249 debug("read returned %d : %s exiting",i,strerror(errno)); 250 close(rodent.mfd); 251 exit(1); 252 } 253 act = r_protocol(b); /* pass byte to handler */ 254 if (act) /* handler detected action */ 255 { 256 mouse.operation = MOUSE_ACTION; 257 mouse.u.data.x = act->dx; 258 mouse.u.data.y = act->dy; 259 mouse.u.data.buttons = act->buttons; 260 ioctl(cfd, CONS_MOUSECTL, &mouse); 261 debug("Activity : buttons 0x%02x dx %d dy %d", 262 act->buttons,act->dx,act->dy); 263 } 264 } 265 } 266 267 268 /** 269 ** usage 270 ** 271 ** Complain, and free the CPU for more worthy tasks 272 **/ 273 void 274 usage(void) 275 { 276 fprintf(stderr, 277 " Usage is %s [options] -p <port> -t <mousetype>\n" 278 " Options are -s Select 9600 baud mouse.\n" 279 " -f Don't become a daemon\n" 280 " -d Enable debugging messages\n" 281 " -c Enable ChordMiddle option\n" 282 " -R Lower RTS\n" 283 " -D Lower DTR\n" 284 " -S baud Select explicit baud (1200..9600).\n" 285 " <mousetype> should be one of :\n" 286 " microsoft\n" 287 " mousesystems\n" 288 " mmseries\n" 289 " logitech\n" 290 " busmouse\n" 291 " mouseman\n" 292 " ps/2\n" 293 " mmhittab\n" 294 ,progname); 295 296 exit(1); 297 } 298 299 300 /** 301 ** Mouse interface code, courtesy of XFree86 3.1.2. 302 ** 303 ** Note: Various bits have been trimmed, and in my shortsighted enthusiasm 304 ** to clean, reformat and rationalise naming, it's quite possible that 305 ** some things in here have been broken. 306 ** 307 ** I hope not 8) 308 ** 309 ** The following code is derived from a module marked : 310 **/ 311 312 /* $XConsortium: xf86_Mouse.c,v 1.2 94/10/12 20:33:21 kaleb Exp $ */ 313 /* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86_Mouse.c,v 3.2 1995/01/28 314 17:03:40 dawes Exp $ */ 315 /* 316 * 317 * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. 318 * Copyright 1993 by David Dawes <dawes@physics.su.oz.au> 319 * 320 * Permission to use, copy, modify, distribute, and sell this software and its 321 * documentation for any purpose is hereby granted without fee, provided that 322 * the above copyright notice appear in all copies and that both that 323 * copyright notice and this permission notice appear in supporting 324 * documentation, and that the names of Thomas Roell and David Dawes not be 325 * used in advertising or publicity pertaining to distribution of the 326 * software without specific, written prior permission. Thomas Roell 327 * and David Dawes makes no representations about the suitability of this 328 * software for any purpose. It is provided "as is" without express or 329 * implied warranty. 330 * 331 * THOMAS ROELL AND DAVID DAWES DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 332 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 333 * FITNESS, IN NO EVENT SHALL THOMAS ROELL OR DAVID DAWES BE LIABLE FOR ANY 334 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER 335 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF 336 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 337 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 338 * 339 */ 340 341 342 void 343 r_init(void) 344 { 345 /** 346 ** This comment is a little out of context here, but it contains 347 ** some useful information... 348 ******************************************************************** 349 ** 350 ** The following lines take care of the Logitech MouseMan protocols. 351 ** 352 ** NOTE: There are different versions of both MouseMan and TrackMan! 353 ** Hence I add another protocol P_LOGIMAN, which the user can 354 ** specify as MouseMan in his XF86Config file. This entry was 355 ** formerly handled as a special case of P_MS. However, people 356 ** who don't have the middle button problem, can still specify 357 ** Microsoft and use P_MS. 358 ** 359 ** By default, these mice should use a 3 byte Microsoft protocol 360 ** plus a 4th byte for the middle button. However, the mouse might 361 ** have switched to a different protocol before we use it, so I send 362 ** the proper sequence just in case. 363 ** 364 ** NOTE: - all commands to (at least the European) MouseMan have to 365 ** be sent at 1200 Baud. 366 ** - each command starts with a '*'. 367 ** - whenever the MouseMan receives a '*', it will switch back 368 ** to 1200 Baud. Hence I have to select the desired protocol 369 ** first, then select the baud rate. 370 ** 371 ** The protocols supported by the (European) MouseMan are: 372 ** - 5 byte packed binary protocol, as with the Mouse Systems 373 ** mouse. Selected by sequence "*U". 374 ** - 2 button 3 byte MicroSoft compatible protocol. Selected 375 ** by sequence "*V". 376 ** - 3 button 3+1 byte MicroSoft compatible protocol (default). 377 ** Selected by sequence "*X". 378 ** 379 ** The following baud rates are supported: 380 ** - 1200 Baud (default). Selected by sequence "*n". 381 ** - 9600 Baud. Selected by sequence "*q". 382 ** 383 ** Selecting a sample rate is no longer supported with the MouseMan! 384 ** Some additional lines in xf86Config.c take care of ill configured 385 ** baud rates and sample rates. (The user will get an error.) 386 */ 387 388 389 if (rodent.rtype == R_LOGIMAN) 390 { 391 setmousespeed(1200, 1200, rodentcflags[R_LOGIMAN]); 392 write(rodent.mfd, "*X", 2); 393 setmousespeed(1200, rodent.baudrate, rodentcflags[R_LOGIMAN]); 394 } else { 395 if ((rodent.rtype != R_BUSMOUSE) && (rodent.rtype != R_PS_2)) 396 { 397 /* try all likely settings */ 398 setmousespeed(9600, rodent.baudrate, rodentcflags[rodent.rtype]); 399 setmousespeed(4800, rodent.baudrate, rodentcflags[rodent.rtype]); 400 setmousespeed(2400, rodent.baudrate, rodentcflags[rodent.rtype]); 401 setmousespeed(1200, rodent.baudrate, rodentcflags[rodent.rtype]); 402 403 if (rodent.rtype == R_LOGITECH) { 404 write(rodent.mfd, "S", 1); 405 setmousespeed(rodent.baudrate, rodent.baudrate, 406 rodentcflags[R_MMSERIES]); 407 } 408 409 if (rodent.rtype == R_MMHITAB) { 410 char speedcmd; 411 /* 412 * Initialize Hitachi PUMA Plus - Model 1212E to desired settings. 413 * The tablet must be configured to be in MM mode, NO parity, 414 * Binary Format. xf86Info.sampleRate controls the sensativity 415 * of the tablet. We only use this tablet for it's 4-button puck 416 * so we don't run in "Absolute Mode" 417 */ 418 write(rodent.mfd, "z8", 2); /* Set Parity = "NONE" */ 419 usleep(50000); 420 write(rodent.mfd, "zb", 2); /* Set Format = "Binary" */ 421 usleep(50000); 422 write(rodent.mfd, "@", 1); /* Set Report Mode = "Stream" */ 423 usleep(50000); 424 write(rodent.mfd, "R", 1); /* Set Output Rate = "45 rps" */ 425 usleep(50000); 426 write(rodent.mfd, "I\x20", 2); /* Set Incrememtal Mode "20" */ 427 usleep(50000); 428 write(rodent.mfd, "E", 1); /* Set Data Type = "Relative */ 429 usleep(50000); 430 431 /* These sample rates translate to 'lines per inch' on the 432 Hitachi tablet */ 433 if (rodent.samplerate <= 40) speedcmd = 'g'; 434 else if (rodent.samplerate <= 100) speedcmd = 'd'; 435 else if (rodent.samplerate <= 200) speedcmd = 'e'; 436 else if (rodent.samplerate <= 500) speedcmd = 'h'; 437 else if (rodent.samplerate <= 1000) speedcmd = 'j'; 438 else speedcmd = 'd'; 439 write(rodent.mfd, &speedcmd, 1); 440 usleep(50000); 441 442 write(rodent.mfd, "\021", 1); /* Resume DATA output */ 443 } else { 444 if (rodent.samplerate <= 0) write(rodent.mfd, "O", 1); 445 else if (rodent.samplerate <= 15) write(rodent.mfd, "J", 1); 446 else if (rodent.samplerate <= 27) write(rodent.mfd, "K", 1); 447 else if (rodent.samplerate <= 42) write(rodent.mfd, "L", 1); 448 else if (rodent.samplerate <= 60) write(rodent.mfd, "R", 1); 449 else if (rodent.samplerate <= 85) write(rodent.mfd, "M", 1); 450 else if (rodent.samplerate <= 125) write(rodent.mfd, "Q", 1); 451 else write(rodent.mfd, "N", 1); 452 } 453 } 454 } 455 if (rodent.rtype == R_MOUSESYS && (rodent.cleardtr)) 456 { 457 int val = TIOCM_DTR; 458 ioctl(rodent.mfd, TIOCMBIC, &val); 459 } 460 if (rodent.rtype == R_MOUSESYS && (rodent.clearrts)) 461 { 462 int val = TIOCM_RTS; 463 ioctl(rodent.mfd, TIOCMBIC, &val); 464 } 465 } 466 467 ACTIVITY * 468 r_protocol(u_char rBuf) 469 { 470 static int pBufP = 0; 471 static unsigned char pBuf[8]; 472 static ACTIVITY act; 473 474 static unsigned char proto[10][5] = { 475 /* hd_mask hd_id dp_mask dp_id nobytes */ 476 { 0, 0, 0, 0, 0 }, /* nomouse */ 477 { 0x40, 0x40, 0x40, 0x00, 3 }, /* MicroSoft */ 478 { 0xf8, 0x80, 0x00, 0x00, 5 }, /* MouseSystems */ 479 { 0xe0, 0x80, 0x80, 0x00, 3 }, /* MMSeries */ 480 { 0xe0, 0x80, 0x80, 0x00, 3 }, /* Logitech */ 481 { 0xf8, 0x80, 0x00, 0x00, 5 }, /* BusMouse */ 482 { 0x40, 0x40, 0x40, 0x00, 3 }, /* MouseMan */ 483 { 0xc0, 0x00, 0x00, 0x00, 3 }, /* PS/2 mouse */ 484 { 0xe0, 0x80, 0x80, 0x00, 3 }, /* MM_HitTablet */ 485 }; 486 487 debug("received char 0x%x",(int)rBuf); 488 489 /* 490 * Hack for resyncing: We check here for a package that is: 491 * a) illegal (detected by wrong data-package header) 492 * b) invalid (0x80 == -128 and that might be wrong for MouseSystems) 493 * c) bad header-package 494 * 495 * NOTE: b) is a voilation of the MouseSystems-Protocol, since values of 496 * -128 are allowed, but since they are very seldom we can easily 497 * use them as package-header with no button pressed. 498 * NOTE/2: On a PS/2 mouse any byte is valid as a data byte. Furthermore, 499 * 0x80 is not valid as a header byte. For a PS/2 mouse we skip 500 * checking data bytes. 501 * For resyncing a PS/2 mouse we require the two most significant 502 * bits in the header byte to be 0. These are the overflow bits, 503 * and in case of an overflow we actually lose sync. Overflows 504 * are very rare, however, and we quickly gain sync again after 505 * an overflow condition. This is the best we can do. (Actually, 506 * we could use bit 0x08 in the header byte for resyncing, since 507 * that bit is supposed to be always on, but nobody told 508 * Microsoft...) 509 */ 510 511 if (pBufP != 0 && rodent.rtype != R_PS_2 && 512 ((rBuf & proto[rodent.rtype][2]) != proto[rodent.rtype][3] 513 || rBuf == 0x80)) 514 { 515 pBufP = 0; /* skip package */ 516 } 517 518 if (pBufP == 0 && 519 (rBuf & proto[rodent.rtype][0]) != proto[rodent.rtype][1]) 520 { 521 /* 522 * Hack for Logitech MouseMan Mouse - Middle button 523 * 524 * Unfortunately this mouse has variable length packets: the standard 525 * Microsoft 3 byte packet plus an optional 4th byte whenever the 526 * middle button status changes. 527 * 528 * We have already processed the standard packet with the movement 529 * and button info. Now post an event message with the old status 530 * of the left and right buttons and the updated middle button. 531 */ 532 533 /* 534 * Even worse, different MouseMen and TrackMen differ in the 4th 535 * byte: some will send 0x00/0x20, others 0x01/0x21, or even 536 * 0x02/0x22, so I have to strip off the lower bits. 537 */ 538 if ((rodent.rtype == R_MICROSOFT || rodent.rtype == R_LOGIMAN) 539 && (char)(rBuf & ~0x23) == 0) 540 { 541 act.buttons = ((int)(rBuf & 0x20) >> 4) 542 | (rodent.lastbuttons & 0x05); 543 rodent.lastbuttons = act.buttons; /* save new button state */ 544 return(&act); 545 } 546 547 return(NULL); /* skip package */ 548 } 549 550 pBuf[pBufP++] = rBuf; 551 if (pBufP != proto[rodent.rtype][4]) return(NULL); 552 553 /* 554 * assembly full package 555 */ 556 557 debug("Assembled full packet (len %d) %x,%x,%x,%x,%x", 558 proto[rodent.rtype][4], pBuf[0],pBuf[1],pBuf[2],pBuf[3],pBuf[4]); 559 560 switch(rodent.rtype) 561 { 562 case R_LOGIMAN: /* MouseMan / TrackMan */ 563 case R_MICROSOFT: /* Microsoft */ 564 if (rodent.flags & ChordMiddle) 565 act.buttons = (((int) pBuf[0] & 0x30) == 0x30) ? 2 : 566 ((int)(pBuf[0]&0x20)>>3) | ((int)(pBuf[0]&0x10)>>4); 567 else 568 act.buttons = (rodent.lastbuttons & 2) 569 | ((int)(pBuf[0] & 0x20) >> 3) 570 | ((int)(pBuf[0] & 0x10) >> 4); 571 act.dx = (char)(((pBuf[0] & 0x03) << 6) | (pBuf[1] & 0x3F)); 572 act.dy = (char)(((pBuf[0] & 0x0C) << 4) | (pBuf[2] & 0x3F)); 573 break; 574 575 case R_MOUSESYS: /* Mouse Systems Corp */ 576 act.buttons = (~pBuf[0]) & 0x07; 577 act.dx = (char)(pBuf[1]) + (char)(pBuf[3]); 578 act.dy = - ((char)(pBuf[2]) + (char)(pBuf[4])); 579 break; 580 581 case R_MMHITAB: /* MM_HitTablet */ 582 act.buttons = pBuf[0] & 0x07; 583 if (act.buttons != 0) 584 act.buttons = 1 << (act.buttons - 1); 585 act.dx = (pBuf[0] & 0x10) ? pBuf[1] : - pBuf[1]; 586 act.dy = (pBuf[0] & 0x08) ? - pBuf[2] : pBuf[2]; 587 break; 588 589 case R_MMSERIES: /* MM Series */ 590 case R_LOGITECH: /* Logitech Mice */ 591 act.buttons = pBuf[0] & 0x07; 592 act.dx = (pBuf[0] & 0x10) ? pBuf[1] : - pBuf[1]; 593 act.dy = (pBuf[0] & 0x08) ? - pBuf[2] : pBuf[2]; 594 break; 595 596 case R_BUSMOUSE: /* BusMouse */ 597 act.buttons = (~pBuf[0]) & 0x07; 598 act.dx = (char)pBuf[1]; 599 act.dy = - (char)pBuf[2]; 600 break; 601 602 case R_PS_2: /* PS/2 mouse */ 603 act.buttons = (pBuf[0] & 0x04) >> 1 | /* Middle */ 604 (pBuf[0] & 0x02) >> 1 | /* Right */ 605 (pBuf[0] & 0x01) << 2; /* Left */ 606 act.dx = (pBuf[0] & 0x10) ? pBuf[1]-256 : pBuf[1]; 607 act.dy = (pBuf[0] & 0x20) ? -(pBuf[2]-256) : -pBuf[2]; 608 break; 609 } 610 pBufP = 0; 611 return(&act); 612 } 613 614 /* $XConsortium: posix_tty.c,v 1.3 95/01/05 20:42:55 kaleb Exp $ */ 615 /* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/shared/posix_tty.c,v 3.4 1995/01/28 17:05:03 dawes Exp $ */ 616 /* 617 * Copyright 1993 by David Dawes <dawes@physics.su.oz.au> 618 * 619 * Permission to use, copy, modify, distribute, and sell this software and its 620 * documentation for any purpose is hereby granted without fee, provided that 621 * the above copyright notice appear in all copies and that both that 622 * copyright notice and this permission notice appear in supporting 623 * documentation, and that the name of David Dawes 624 * not be used in advertising or publicity pertaining to distribution of 625 * the software without specific, written prior permission. 626 * David Dawes makes no representations about the suitability of this 627 * software for any purpose. It is provided "as is" without express or 628 * implied warranty. 629 * 630 * DAVID DAWES DISCLAIMS ALL WARRANTIES WITH REGARD TO 631 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 632 * FITNESS, IN NO EVENT SHALL DAVID DAWES BE LIABLE FOR 633 * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER 634 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF 635 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 636 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 637 * 638 */ 639 640 641 void 642 setmousespeed(old, new, cflag) 643 int old; 644 int new; 645 unsigned cflag; 646 { 647 struct termios tty; 648 char *c; 649 650 if (tcgetattr(rodent.mfd, &tty) < 0) 651 { 652 err(1, "Warning: unable to get status of mouse fd"); 653 } 654 655 tty.c_iflag = IGNBRK | IGNPAR; 656 tty.c_oflag = 0; 657 tty.c_lflag = 0; 658 tty.c_cflag = (tcflag_t)cflag; 659 tty.c_cc[VTIME] = 0; 660 tty.c_cc[VMIN] = 1; 661 662 switch (old) 663 { 664 case 9600: 665 cfsetispeed(&tty, B9600); 666 cfsetospeed(&tty, B9600); 667 break; 668 case 4800: 669 cfsetispeed(&tty, B4800); 670 cfsetospeed(&tty, B4800); 671 break; 672 case 2400: 673 cfsetispeed(&tty, B2400); 674 cfsetospeed(&tty, B2400); 675 break; 676 case 1200: 677 default: 678 cfsetispeed(&tty, B1200); 679 cfsetospeed(&tty, B1200); 680 } 681 682 if (tcsetattr(rodent.mfd, TCSADRAIN, &tty) < 0) 683 { 684 err(1, "Unable to set status of mouse fd"); 685 } 686 687 switch (new) 688 { 689 case 9600: 690 c = "*q"; 691 cfsetispeed(&tty, B9600); 692 cfsetospeed(&tty, B9600); 693 break; 694 case 4800: 695 c = "*p"; 696 cfsetispeed(&tty, B4800); 697 cfsetospeed(&tty, B4800); 698 break; 699 case 2400: 700 c = "*o"; 701 cfsetispeed(&tty, B2400); 702 cfsetospeed(&tty, B2400); 703 break; 704 case 1200: 705 default: 706 c = "*n"; 707 cfsetispeed(&tty, B1200); 708 cfsetospeed(&tty, B1200); 709 } 710 711 if (rodent.rtype == R_LOGIMAN || rodent.rtype == R_LOGITECH) 712 { 713 if (write(rodent.mfd, c, 2) != 2) 714 { 715 err(1, "Unable to write to mouse fd"); 716 } 717 } 718 usleep(100000); 719 720 if (tcsetattr(rodent.mfd, TCSADRAIN, &tty) < 0) 721 { 722 err(1,"Unable to set status of mouse fd"); 723 } 724 } 725