posix_tty.c (14188B)
1 /* 2 * Copyright 1993-2003 by The XFree86 Project, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 * SOFTWARE. 21 * 22 * Except as contained in this notice, the name of the XFree86 Project shall 23 * not be used in advertising or otherwise to promote the sale, use or other 24 * dealings in this Software without prior written authorization from the 25 * XFree86 Project. 26 */ 27 /* 28 * 29 * Copyright (c) 1997 Metro Link Incorporated 30 * 31 * Permission is hereby granted, free of charge, to any person obtaining a 32 * copy of this software and associated documentation files (the "Software"), 33 * to deal in the Software without restriction, including without limitation 34 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 35 * and/or sell copies of the Software, and to permit persons to whom the 36 * Software is furnished to do so, subject to the following conditions: 37 * 38 * The above copyright notice and this permission notice shall be included in 39 * all copies or substantial portions of the Software. 40 * 41 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 42 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 43 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 44 * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 45 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 46 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 47 * SOFTWARE. 48 * 49 * Except as contained in this notice, the name of the Metro Link shall not be 50 * used in advertising or otherwise to promote the sale, use or other dealings 51 * in this Software without prior written authorization from Metro Link. 52 * 53 */ 54 55 #ifdef HAVE_XORG_CONFIG_H 56 #include <xorg-config.h> 57 #endif 58 59 #include <X11/X.h> 60 #include <xserver_poll.h> 61 #include "xf86.h" 62 #include "xf86Priv.h" 63 #include "xf86_OSlib.h" 64 65 static int 66 GetBaud(int baudrate) 67 { 68 #ifdef B300 69 if (baudrate == 300) 70 return B300; 71 #endif 72 #ifdef B1200 73 if (baudrate == 1200) 74 return B1200; 75 #endif 76 #ifdef B2400 77 if (baudrate == 2400) 78 return B2400; 79 #endif 80 #ifdef B4800 81 if (baudrate == 4800) 82 return B4800; 83 #endif 84 #ifdef B9600 85 if (baudrate == 9600) 86 return B9600; 87 #endif 88 #ifdef B19200 89 if (baudrate == 19200) 90 return B19200; 91 #endif 92 #ifdef B38400 93 if (baudrate == 38400) 94 return B38400; 95 #endif 96 #ifdef B57600 97 if (baudrate == 57600) 98 return B57600; 99 #endif 100 #ifdef B115200 101 if (baudrate == 115200) 102 return B115200; 103 #endif 104 #ifdef B230400 105 if (baudrate == 230400) 106 return B230400; 107 #endif 108 #ifdef B460800 109 if (baudrate == 460800) 110 return B460800; 111 #endif 112 return 0; 113 } 114 115 int 116 xf86OpenSerial(XF86OptionPtr options) 117 { 118 struct termios t; 119 int fd, i; 120 char *dev; 121 122 dev = xf86SetStrOption(options, "Device", NULL); 123 if (!dev) { 124 xf86Msg(X_ERROR, "xf86OpenSerial: No Device specified.\n"); 125 return -1; 126 } 127 128 fd = xf86CheckIntOption(options, "fd", -1); 129 130 if (fd == -1) 131 SYSCALL(fd = open(dev, O_RDWR | O_NONBLOCK)); 132 133 if (fd == -1) { 134 xf86Msg(X_ERROR, 135 "xf86OpenSerial: Cannot open device %s\n\t%s.\n", 136 dev, strerror(errno)); 137 free(dev); 138 return -1; 139 } 140 141 if (!isatty(fd)) { 142 /* Allow non-tty devices to be opened. */ 143 free(dev); 144 return fd; 145 } 146 147 /* set up default port parameters */ 148 SYSCALL(tcgetattr(fd, &t)); 149 t.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR 150 | IGNCR | ICRNL | IXON); 151 t.c_oflag &= ~OPOST; 152 t.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); 153 t.c_cflag &= ~(CSIZE | PARENB); 154 t.c_cflag |= CS8 | CLOCAL; 155 156 cfsetispeed(&t, B9600); 157 cfsetospeed(&t, B9600); 158 t.c_cc[VMIN] = 1; 159 t.c_cc[VTIME] = 0; 160 161 SYSCALL(tcsetattr(fd, TCSANOW, &t)); 162 163 if (xf86SetSerial(fd, options) == -1) { 164 SYSCALL(close(fd)); 165 free(dev); 166 return -1; 167 } 168 169 SYSCALL(i = fcntl(fd, F_GETFL, 0)); 170 if (i == -1) { 171 SYSCALL(close(fd)); 172 free(dev); 173 return -1; 174 } 175 i &= ~O_NONBLOCK; 176 SYSCALL(i = fcntl(fd, F_SETFL, i)); 177 if (i == -1) { 178 SYSCALL(close(fd)); 179 free(dev); 180 return -1; 181 } 182 free(dev); 183 return fd; 184 } 185 186 int 187 xf86SetSerial(int fd, XF86OptionPtr options) 188 { 189 struct termios t; 190 int val; 191 char *s; 192 int baud, r; 193 194 if (fd < 0) 195 return -1; 196 197 /* Don't try to set parameters for non-tty devices. */ 198 if (!isatty(fd)) 199 return 0; 200 201 SYSCALL(tcgetattr(fd, &t)); 202 203 if ((val = xf86SetIntOption(options, "BaudRate", 0))) { 204 if ((baud = GetBaud(val))) { 205 cfsetispeed(&t, baud); 206 cfsetospeed(&t, baud); 207 } 208 else { 209 xf86Msg(X_ERROR, "Invalid Option BaudRate value: %d\n", val); 210 return -1; 211 } 212 } 213 214 if ((val = xf86SetIntOption(options, "StopBits", 0))) { 215 switch (val) { 216 case 1: 217 t.c_cflag &= ~(CSTOPB); 218 break; 219 case 2: 220 t.c_cflag |= CSTOPB; 221 break; 222 default: 223 xf86Msg(X_ERROR, "Invalid Option StopBits value: %d\n", val); 224 return -1; 225 break; 226 } 227 } 228 229 if ((val = xf86SetIntOption(options, "DataBits", 0))) { 230 switch (val) { 231 case 5: 232 t.c_cflag &= ~(CSIZE); 233 t.c_cflag |= CS5; 234 break; 235 case 6: 236 t.c_cflag &= ~(CSIZE); 237 t.c_cflag |= CS6; 238 break; 239 case 7: 240 t.c_cflag &= ~(CSIZE); 241 t.c_cflag |= CS7; 242 break; 243 case 8: 244 t.c_cflag &= ~(CSIZE); 245 t.c_cflag |= CS8; 246 break; 247 default: 248 xf86Msg(X_ERROR, "Invalid Option DataBits value: %d\n", val); 249 return -1; 250 break; 251 } 252 } 253 254 if ((s = xf86SetStrOption(options, "Parity", NULL))) { 255 if (xf86NameCmp(s, "Odd") == 0) { 256 t.c_cflag |= PARENB | PARODD; 257 } 258 else if (xf86NameCmp(s, "Even") == 0) { 259 t.c_cflag |= PARENB; 260 t.c_cflag &= ~(PARODD); 261 } 262 else if (xf86NameCmp(s, "None") == 0) { 263 t.c_cflag &= ~(PARENB); 264 } 265 else { 266 xf86Msg(X_ERROR, "Invalid Option Parity value: %s\n", s); 267 free(s); 268 return -1; 269 } 270 free(s); 271 } 272 273 if ((val = xf86SetIntOption(options, "Vmin", -1)) != -1) { 274 t.c_cc[VMIN] = val; 275 } 276 if ((val = xf86SetIntOption(options, "Vtime", -1)) != -1) { 277 t.c_cc[VTIME] = val; 278 } 279 280 if ((s = xf86SetStrOption(options, "FlowControl", NULL))) { 281 xf86MarkOptionUsedByName(options, "FlowControl"); 282 if (xf86NameCmp(s, "Xoff") == 0) { 283 t.c_iflag |= IXOFF; 284 } 285 else if (xf86NameCmp(s, "Xon") == 0) { 286 t.c_iflag |= IXON; 287 } 288 else if (xf86NameCmp(s, "XonXoff") == 0) { 289 t.c_iflag |= IXON | IXOFF; 290 } 291 else if (xf86NameCmp(s, "None") == 0) { 292 t.c_iflag &= ~(IXON | IXOFF); 293 } 294 else { 295 xf86Msg(X_ERROR, "Invalid Option FlowControl value: %s\n", s); 296 free(s); 297 return -1; 298 } 299 free(s); 300 } 301 302 if ((xf86SetBoolOption(options, "ClearDTR", FALSE))) { 303 #ifdef CLEARDTR_SUPPORT 304 #if defined(TIOCMBIC) 305 val = TIOCM_DTR; 306 SYSCALL(ioctl(fd, TIOCMBIC, &val)); 307 #else 308 SYSCALL(ioctl(fd, TIOCCDTR, NULL)); 309 #endif 310 #else 311 xf86Msg(X_WARNING, "Option ClearDTR not supported on this OS\n"); 312 return -1; 313 #endif 314 xf86MarkOptionUsedByName(options, "ClearDTR"); 315 } 316 317 if ((xf86SetBoolOption(options, "ClearRTS", FALSE))) { 318 xf86Msg(X_WARNING, "Option ClearRTS not supported on this OS\n"); 319 return -1; 320 xf86MarkOptionUsedByName(options, "ClearRTS"); 321 } 322 323 SYSCALL(r = tcsetattr(fd, TCSANOW, &t)); 324 return r; 325 } 326 327 int 328 xf86SetSerialSpeed(int fd, int speed) 329 { 330 struct termios t; 331 int baud, r; 332 333 if (fd < 0) 334 return -1; 335 336 /* Don't try to set parameters for non-tty devices. */ 337 if (!isatty(fd)) 338 return 0; 339 340 SYSCALL(tcgetattr(fd, &t)); 341 342 if ((baud = GetBaud(speed))) { 343 cfsetispeed(&t, baud); 344 cfsetospeed(&t, baud); 345 } 346 else { 347 xf86Msg(X_ERROR, "Invalid Option BaudRate value: %d\n", speed); 348 return -1; 349 } 350 351 SYSCALL(r = tcsetattr(fd, TCSANOW, &t)); 352 return r; 353 } 354 355 int 356 xf86ReadSerial(int fd, void *buf, int count) 357 { 358 int r; 359 int i; 360 361 SYSCALL(r = read(fd, buf, count)); 362 DebugF("ReadingSerial: 0x%x", (unsigned char) *(((unsigned char *) buf))); 363 for (i = 1; i < r; i++) 364 DebugF(", 0x%x", (unsigned char) *(((unsigned char *) buf) + i)); 365 DebugF("\n"); 366 return r; 367 } 368 369 int 370 xf86WriteSerial(int fd, const void *buf, int count) 371 { 372 int r; 373 int i; 374 375 DebugF("WritingSerial: 0x%x", (unsigned char) *(((unsigned char *) buf))); 376 for (i = 1; i < count; i++) 377 DebugF(", 0x%x", (unsigned char) *(((unsigned char *) buf) + i)); 378 DebugF("\n"); 379 SYSCALL(r = write(fd, buf, count)); 380 return r; 381 } 382 383 int 384 xf86CloseSerial(int fd) 385 { 386 int r; 387 388 SYSCALL(r = close(fd)); 389 return r; 390 } 391 392 int 393 xf86WaitForInput(int fd, int timeout) 394 { 395 int r; 396 struct pollfd poll_fd; 397 398 poll_fd.fd = fd; 399 poll_fd.events = POLLIN; 400 401 /* convert microseconds to milliseconds */ 402 timeout = (timeout + 999) / 1000; 403 404 if (fd >= 0) { 405 SYSCALL(r = xserver_poll(&poll_fd, 1, timeout)); 406 } 407 else { 408 SYSCALL(r = xserver_poll(&poll_fd, 0, timeout)); 409 } 410 xf86ErrorFVerb(9, "poll returned %d\n", r); 411 return r; 412 } 413 414 int 415 xf86SerialSendBreak(int fd, int duration) 416 { 417 int r; 418 419 SYSCALL(r = tcsendbreak(fd, duration)); 420 return r; 421 422 } 423 424 int 425 xf86FlushInput(int fd) 426 { 427 struct pollfd poll_fd; 428 /* this needs to be big enough to flush an evdev event. */ 429 char c[256]; 430 431 DebugF("FlushingSerial\n"); 432 if (tcflush(fd, TCIFLUSH) == 0) 433 return 0; 434 435 poll_fd.fd = fd; 436 poll_fd.events = POLLIN; 437 while (xserver_poll(&poll_fd, 1, 0) > 0) { 438 if (read(fd, &c, sizeof(c)) < 1) 439 return 0; 440 } 441 return 0; 442 } 443 444 static struct states { 445 int xf; 446 int os; 447 } modemStates[] = { 448 #ifdef TIOCM_LE 449 { 450 XF86_M_LE, TIOCM_LE}, 451 #endif 452 #ifdef TIOCM_DTR 453 { 454 XF86_M_DTR, TIOCM_DTR}, 455 #endif 456 #ifdef TIOCM_RTS 457 { 458 XF86_M_RTS, TIOCM_RTS}, 459 #endif 460 #ifdef TIOCM_ST 461 { 462 XF86_M_ST, TIOCM_ST}, 463 #endif 464 #ifdef TIOCM_SR 465 { 466 XF86_M_SR, TIOCM_SR}, 467 #endif 468 #ifdef TIOCM_CTS 469 { 470 XF86_M_CTS, TIOCM_CTS}, 471 #endif 472 #ifdef TIOCM_CAR 473 { 474 XF86_M_CAR, TIOCM_CAR}, 475 #elif defined(TIOCM_CD) 476 { 477 XF86_M_CAR, TIOCM_CD}, 478 #endif 479 #ifdef TIOCM_RNG 480 { 481 XF86_M_RNG, TIOCM_RNG}, 482 #elif defined(TIOCM_RI) 483 { 484 XF86_M_CAR, TIOCM_RI}, 485 #endif 486 #ifdef TIOCM_DSR 487 { 488 XF86_M_DSR, TIOCM_DSR}, 489 #endif 490 }; 491 492 static int numStates = ARRAY_SIZE(modemStates); 493 494 static int 495 xf2osState(int state) 496 { 497 int i; 498 int ret = 0; 499 500 for (i = 0; i < numStates; i++) 501 if (state & modemStates[i].xf) 502 ret |= modemStates[i].os; 503 return ret; 504 } 505 506 static int 507 os2xfState(int state) 508 { 509 int i; 510 int ret = 0; 511 512 for (i = 0; i < numStates; i++) 513 if (state & modemStates[i].os) 514 ret |= modemStates[i].xf; 515 return ret; 516 } 517 518 static int 519 getOsStateMask(void) 520 { 521 int i; 522 int ret = 0; 523 524 for (i = 0; i < numStates; i++) 525 ret |= modemStates[i].os; 526 return ret; 527 } 528 529 static int osStateMask = 0; 530 531 int 532 xf86SetSerialModemState(int fd, int state) 533 { 534 int ret; 535 int s; 536 537 if (fd < 0) 538 return -1; 539 540 /* Don't try to set parameters for non-tty devices. */ 541 if (!isatty(fd)) 542 return 0; 543 544 #ifndef TIOCMGET 545 return -1; 546 #else 547 if (!osStateMask) 548 osStateMask = getOsStateMask(); 549 550 state = xf2osState(state); 551 SYSCALL((ret = ioctl(fd, TIOCMGET, &s))); 552 if (ret < 0) 553 return -1; 554 s &= ~osStateMask; 555 s |= state; 556 SYSCALL((ret = ioctl(fd, TIOCMSET, &s))); 557 if (ret < 0) 558 return -1; 559 else 560 return 0; 561 #endif 562 } 563 564 int 565 xf86GetSerialModemState(int fd) 566 { 567 int ret; 568 int s; 569 570 if (fd < 0) 571 return -1; 572 573 /* Don't try to set parameters for non-tty devices. */ 574 if (!isatty(fd)) 575 return 0; 576 577 #ifndef TIOCMGET 578 return -1; 579 #else 580 SYSCALL((ret = ioctl(fd, TIOCMGET, &s))); 581 if (ret < 0) 582 return -1; 583 return os2xfState(s); 584 #endif 585 } 586 587 int 588 xf86SerialModemSetBits(int fd, int bits) 589 { 590 int ret; 591 int s; 592 593 if (fd < 0) 594 return -1; 595 596 /* Don't try to set parameters for non-tty devices. */ 597 if (!isatty(fd)) 598 return 0; 599 600 #ifndef TIOCMGET 601 return -1; 602 #else 603 s = xf2osState(bits); 604 SYSCALL((ret = ioctl(fd, TIOCMBIS, &s))); 605 return ret; 606 #endif 607 } 608 609 int 610 xf86SerialModemClearBits(int fd, int bits) 611 { 612 int ret; 613 int s; 614 615 if (fd < 0) 616 return -1; 617 618 /* Don't try to set parameters for non-tty devices. */ 619 if (!isatty(fd)) 620 return 0; 621 622 #ifndef TIOCMGET 623 return -1; 624 #else 625 s = xf2osState(bits); 626 SYSCALL((ret = ioctl(fd, TIOCMBIC, &s))); 627 return ret; 628 #endif 629 }