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