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