1 /* -*- c-basic-offset: 8 -*- 2 rdesktop: A Remote Desktop Protocol client. 3 4 Copyright (C) Matthew Chapman 1999-2005 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License along 17 with this program; if not, write to the Free Software Foundation, Inc., 18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 */ 20 #include <unistd.h> 21 #include <fcntl.h> 22 #include <termios.h> 23 #include <strings.h> 24 #include <sys/ioctl.h> 25 26 #ifdef HAVE_SYS_MODEM_H 27 #include <sys/modem.h> 28 #endif 29 #ifdef HAVE_SYS_FILIO_H 30 #include <sys/filio.h> 31 #endif 32 #ifdef HAVE_SYS_STRTIO_H 33 #include <sys/strtio.h> 34 #endif 35 36 #include "rdesktop.h" 37 38 #ifdef WITH_DEBUG_SERIAL 39 #define DEBUG_SERIAL(args) printf args; 40 #else 41 #define DEBUG_SERIAL(args) 42 #endif 43 44 #define FILE_DEVICE_SERIAL_PORT 0x1b 45 46 #define SERIAL_SET_BAUD_RATE 1 47 #define SERIAL_SET_QUEUE_SIZE 2 48 #define SERIAL_SET_LINE_CONTROL 3 49 #define SERIAL_SET_BREAK_ON 4 50 #define SERIAL_SET_BREAK_OFF 5 51 #define SERIAL_IMMEDIATE_CHAR 6 52 #define SERIAL_SET_TIMEOUTS 7 53 #define SERIAL_GET_TIMEOUTS 8 54 #define SERIAL_SET_DTR 9 55 #define SERIAL_CLR_DTR 10 56 #define SERIAL_RESET_DEVICE 11 57 #define SERIAL_SET_RTS 12 58 #define SERIAL_CLR_RTS 13 59 #define SERIAL_SET_XOFF 14 60 #define SERIAL_SET_XON 15 61 #define SERIAL_GET_WAIT_MASK 16 62 #define SERIAL_SET_WAIT_MASK 17 63 #define SERIAL_WAIT_ON_MASK 18 64 #define SERIAL_PURGE 19 65 #define SERIAL_GET_BAUD_RATE 20 66 #define SERIAL_GET_LINE_CONTROL 21 67 #define SERIAL_GET_CHARS 22 68 #define SERIAL_SET_CHARS 23 69 #define SERIAL_GET_HANDFLOW 24 70 #define SERIAL_SET_HANDFLOW 25 71 #define SERIAL_GET_MODEMSTATUS 26 72 #define SERIAL_GET_COMMSTATUS 27 73 #define SERIAL_XOFF_COUNTER 28 74 #define SERIAL_GET_PROPERTIES 29 75 #define SERIAL_GET_DTRRTS 30 76 #define SERIAL_LSRMST_INSERT 31 77 #define SERIAL_CONFIG_SIZE 32 78 #define SERIAL_GET_COMMCONFIG 33 79 #define SERIAL_SET_COMMCONFIG 34 80 #define SERIAL_GET_STATS 35 81 #define SERIAL_CLEAR_STATS 36 82 #define SERIAL_GET_MODEM_CONTROL 37 83 #define SERIAL_SET_MODEM_CONTROL 38 84 #define SERIAL_SET_FIFO_CONTROL 39 85 86 #define STOP_BITS_1 0 87 #define STOP_BITS_2 2 88 89 #define NO_PARITY 0 90 #define ODD_PARITY 1 91 #define EVEN_PARITY 2 92 93 #define SERIAL_PURGE_TXABORT 0x00000001 94 #define SERIAL_PURGE_RXABORT 0x00000002 95 #define SERIAL_PURGE_TXCLEAR 0x00000004 96 #define SERIAL_PURGE_RXCLEAR 0x00000008 97 98 /* SERIAL_WAIT_ON_MASK */ 99 #define SERIAL_EV_RXCHAR 0x0001 /* Any Character received */ 100 #define SERIAL_EV_RXFLAG 0x0002 /* Received certain character */ 101 #define SERIAL_EV_TXEMPTY 0x0004 /* Transmitt Queue Empty */ 102 #define SERIAL_EV_CTS 0x0008 /* CTS changed state */ 103 #define SERIAL_EV_DSR 0x0010 /* DSR changed state */ 104 #define SERIAL_EV_RLSD 0x0020 /* RLSD changed state */ 105 #define SERIAL_EV_BREAK 0x0040 /* BREAK received */ 106 #define SERIAL_EV_ERR 0x0080 /* Line status error occurred */ 107 #define SERIAL_EV_RING 0x0100 /* Ring signal detected */ 108 #define SERIAL_EV_PERR 0x0200 /* Printer error occured */ 109 #define SERIAL_EV_RX80FULL 0x0400 /* Receive buffer is 80 percent full */ 110 #define SERIAL_EV_EVENT1 0x0800 /* Provider specific event 1 */ 111 #define SERIAL_EV_EVENT2 0x1000 /* Provider specific event 2 */ 112 113 /* Modem Status */ 114 #define SERIAL_MS_DTR 0x01 115 #define SERIAL_MS_RTS 0x02 116 #define SERIAL_MS_CTS 0x10 117 #define SERIAL_MS_DSR 0x20 118 #define SERIAL_MS_RNG 0x40 119 #define SERIAL_MS_CAR 0x80 120 121 /* Handflow */ 122 #define SERIAL_DTR_CONTROL 0x01 123 #define SERIAL_CTS_HANDSHAKE 0x08 124 #define SERIAL_ERROR_ABORT 0x80000000 125 126 #define SERIAL_XON_HANDSHAKE 0x01 127 #define SERIAL_XOFF_HANDSHAKE 0x02 128 #define SERIAL_DSR_SENSITIVITY 0x40 129 130 #define SERIAL_CHAR_EOF 0 131 #define SERIAL_CHAR_ERROR 1 132 #define SERIAL_CHAR_BREAK 2 133 #define SERIAL_CHAR_EVENT 3 134 #define SERIAL_CHAR_XON 4 135 #define SERIAL_CHAR_XOFF 5 136 137 #ifndef CRTSCTS 138 #define CRTSCTS 0 139 #endif 140 141 /* FIONREAD should really do the same thing as TIOCINQ, where it is 142 * not available */ 143 #if !defined(TIOCINQ) && defined(FIONREAD) 144 #define TIOCINQ FIONREAD 145 #endif 146 #if !defined(TIOCOUTQ) && defined(FIONWRITE) 147 #define TIOCOUTQ FIONWRITE 148 #endif 149 150 static SERIAL_DEVICE * 151 get_serial_info(RDPCLIENT * This, NTHANDLE handle) 152 { 153 int index; 154 155 for (index = 0; index < RDPDR_MAX_DEVICES; index++) 156 { 157 if (handle == This->rdpdr_device[index].handle) 158 return (SERIAL_DEVICE *) This->rdpdr_device[index].pdevice_data; 159 } 160 return NULL; 161 } 162 163 static BOOL 164 get_termios(SERIAL_DEVICE * pser_inf, NTHANDLE serial_fd) 165 { 166 speed_t speed; 167 struct termios *ptermios; 168 169 ptermios = pser_inf->ptermios; 170 171 if (tcgetattr(serial_fd, ptermios) == -1) 172 return False; 173 174 speed = cfgetispeed(ptermios); 175 switch (speed) 176 { 177 #ifdef B75 178 case B75: 179 pser_inf->baud_rate = 75; 180 break; 181 #endif 182 #ifdef B110 183 case B110: 184 pser_inf->baud_rate = 110; 185 break; 186 #endif 187 #ifdef B134 188 case B134: 189 pser_inf->baud_rate = 134; 190 break; 191 #endif 192 #ifdef B150 193 case B150: 194 pser_inf->baud_rate = 150; 195 break; 196 #endif 197 #ifdef B300 198 case B300: 199 pser_inf->baud_rate = 300; 200 break; 201 #endif 202 #ifdef B600 203 case B600: 204 pser_inf->baud_rate = 600; 205 break; 206 #endif 207 #ifdef B1200 208 case B1200: 209 pser_inf->baud_rate = 1200; 210 break; 211 #endif 212 #ifdef B1800 213 case B1800: 214 pser_inf->baud_rate = 1800; 215 break; 216 #endif 217 #ifdef B2400 218 case B2400: 219 pser_inf->baud_rate = 2400; 220 break; 221 #endif 222 #ifdef B4800 223 case B4800: 224 pser_inf->baud_rate = 4800; 225 break; 226 #endif 227 #ifdef B9600 228 case B9600: 229 pser_inf->baud_rate = 9600; 230 break; 231 #endif 232 #ifdef B19200 233 case B19200: 234 pser_inf->baud_rate = 19200; 235 break; 236 #endif 237 #ifdef B38400 238 case B38400: 239 pser_inf->baud_rate = 38400; 240 break; 241 #endif 242 #ifdef B57600 243 case B57600: 244 pser_inf->baud_rate = 57600; 245 break; 246 #endif 247 #ifdef B115200 248 case B115200: 249 pser_inf->baud_rate = 115200; 250 break; 251 #endif 252 #ifdef B230400 253 case B230400: 254 pser_inf->baud_rate = 230400; 255 break; 256 #endif 257 #ifdef B460800 258 case B460800: 259 pser_inf->baud_rate = 460800; 260 break; 261 #endif 262 default: 263 pser_inf->baud_rate = 9600; 264 break; 265 } 266 267 speed = cfgetospeed(ptermios); 268 pser_inf->dtr = (speed == B0) ? 0 : 1; 269 270 pser_inf->stop_bits = (ptermios->c_cflag & CSTOPB) ? STOP_BITS_2 : STOP_BITS_1; 271 pser_inf->parity = 272 (ptermios-> 273 c_cflag & PARENB) ? ((ptermios-> 274 c_cflag & PARODD) ? ODD_PARITY : EVEN_PARITY) : NO_PARITY; 275 switch (ptermios->c_cflag & CSIZE) 276 { 277 case CS5: 278 pser_inf->word_length = 5; 279 break; 280 case CS6: 281 pser_inf->word_length = 6; 282 break; 283 case CS7: 284 pser_inf->word_length = 7; 285 break; 286 default: 287 pser_inf->word_length = 8; 288 break; 289 } 290 291 if (ptermios->c_cflag & CRTSCTS) 292 { 293 pser_inf->control = SERIAL_DTR_CONTROL | SERIAL_CTS_HANDSHAKE | SERIAL_ERROR_ABORT; 294 } 295 else 296 { 297 pser_inf->control = SERIAL_DTR_CONTROL | SERIAL_ERROR_ABORT; 298 } 299 300 pser_inf->xonoff = SERIAL_DSR_SENSITIVITY; 301 if (ptermios->c_iflag & IXON) 302 pser_inf->xonoff |= SERIAL_XON_HANDSHAKE; 303 304 if (ptermios->c_iflag & IXOFF) 305 pser_inf->xonoff |= SERIAL_XOFF_HANDSHAKE; 306 307 pser_inf->chars[SERIAL_CHAR_XON] = ptermios->c_cc[VSTART]; 308 pser_inf->chars[SERIAL_CHAR_XOFF] = ptermios->c_cc[VSTOP]; 309 pser_inf->chars[SERIAL_CHAR_EOF] = ptermios->c_cc[VEOF]; 310 pser_inf->chars[SERIAL_CHAR_BREAK] = ptermios->c_cc[VINTR]; 311 pser_inf->chars[SERIAL_CHAR_ERROR] = ptermios->c_cc[VKILL]; 312 313 return True; 314 } 315 316 static void 317 set_termios(SERIAL_DEVICE * pser_inf, NTHANDLE serial_fd) 318 { 319 speed_t speed; 320 321 struct termios *ptermios; 322 323 ptermios = pser_inf->ptermios; 324 325 326 switch (pser_inf->baud_rate) 327 { 328 #ifdef B75 329 case 75: 330 speed = B75; 331 break; 332 #endif 333 #ifdef B110 334 case 110: 335 speed = B110; 336 break; 337 #endif 338 #ifdef B134 339 case 134: 340 speed = B134; 341 break; 342 #endif 343 #ifdef B150 344 case 150: 345 speed = B150; 346 break; 347 #endif 348 #ifdef B300 349 case 300: 350 speed = B300; 351 break; 352 #endif 353 #ifdef B600 354 case 600: 355 speed = B600; 356 break; 357 #endif 358 #ifdef B1200 359 case 1200: 360 speed = B1200; 361 break; 362 #endif 363 #ifdef B1800 364 case 1800: 365 speed = B1800; 366 break; 367 #endif 368 #ifdef B2400 369 case 2400: 370 speed = B2400; 371 break; 372 #endif 373 #ifdef B4800 374 case 4800: 375 speed = B4800; 376 break; 377 #endif 378 #ifdef B9600 379 case 9600: 380 speed = B9600; 381 break; 382 #endif 383 #ifdef B19200 384 case 19200: 385 speed = B19200; 386 break; 387 #endif 388 #ifdef B38400 389 case 38400: 390 speed = B38400; 391 break; 392 #endif 393 #ifdef B57600 394 case 57600: 395 speed = B57600; 396 break; 397 #endif 398 #ifdef B115200 399 case 115200: 400 speed = B115200; 401 break; 402 #endif 403 #ifdef B230400 404 case 230400: 405 speed = B115200; 406 break; 407 #endif 408 #ifdef B460800 409 case 460800: 410 speed = B115200; 411 break; 412 #endif 413 default: 414 speed = B9600; 415 break; 416 } 417 418 #ifdef CBAUD 419 ptermios->c_cflag &= ~CBAUD; 420 ptermios->c_cflag |= speed; 421 #else 422 /* on systems with separate ispeed and ospeed, we can remember the speed 423 in ispeed while changing DTR with ospeed */ 424 cfsetispeed(pser_inf->ptermios, speed); 425 cfsetospeed(pser_inf->ptermios, pser_inf->dtr ? speed : 0); 426 #endif 427 428 ptermios->c_cflag &= ~(CSTOPB | PARENB | PARODD | CSIZE | CRTSCTS); 429 switch (pser_inf->stop_bits) 430 { 431 case STOP_BITS_2: 432 ptermios->c_cflag |= CSTOPB; 433 break; 434 default: 435 ptermios->c_cflag &= ~CSTOPB; 436 break; 437 } 438 439 switch (pser_inf->parity) 440 { 441 case EVEN_PARITY: 442 ptermios->c_cflag |= PARENB; 443 break; 444 case ODD_PARITY: 445 ptermios->c_cflag |= PARENB | PARODD; 446 break; 447 case NO_PARITY: 448 ptermios->c_cflag &= ~(PARENB | PARODD); 449 break; 450 } 451 452 switch (pser_inf->word_length) 453 { 454 case 5: 455 ptermios->c_cflag |= CS5; 456 break; 457 case 6: 458 ptermios->c_cflag |= CS6; 459 break; 460 case 7: 461 ptermios->c_cflag |= CS7; 462 break; 463 default: 464 ptermios->c_cflag |= CS8; 465 break; 466 } 467 468 #if 0 469 if (pser_inf->rts) 470 ptermios->c_cflag |= CRTSCTS; 471 else 472 ptermios->c_cflag &= ~CRTSCTS; 473 #endif 474 475 if (pser_inf->control & SERIAL_CTS_HANDSHAKE) 476 { 477 ptermios->c_cflag |= CRTSCTS; 478 } 479 else 480 { 481 ptermios->c_cflag &= ~CRTSCTS; 482 } 483 484 485 if (pser_inf->xonoff & SERIAL_XON_HANDSHAKE) 486 { 487 ptermios->c_iflag |= IXON | IMAXBEL; 488 } 489 if (pser_inf->xonoff & SERIAL_XOFF_HANDSHAKE) 490 { 491 ptermios->c_iflag |= IXOFF | IMAXBEL; 492 } 493 494 if ((pser_inf->xonoff & (SERIAL_XOFF_HANDSHAKE | SERIAL_XON_HANDSHAKE)) == 0) 495 { 496 ptermios->c_iflag &= ~IXON; 497 ptermios->c_iflag &= ~IXOFF; 498 } 499 500 ptermios->c_cc[VSTART] = pser_inf->chars[SERIAL_CHAR_XON]; 501 ptermios->c_cc[VSTOP] = pser_inf->chars[SERIAL_CHAR_XOFF]; 502 ptermios->c_cc[VEOF] = pser_inf->chars[SERIAL_CHAR_EOF]; 503 ptermios->c_cc[VINTR] = pser_inf->chars[SERIAL_CHAR_BREAK]; 504 ptermios->c_cc[VKILL] = pser_inf->chars[SERIAL_CHAR_ERROR]; 505 506 tcsetattr(serial_fd, TCSANOW, ptermios); 507 } 508 509 /* Enumeration of devices from rdesktop.c */ 510 /* returns numer of units found and initialized. */ 511 /* optarg looks like ':com1=/dev/ttyS0' */ 512 /* when it arrives to this function. */ 513 /* :com1=/dev/ttyS0,com2=/dev/ttyS1 */ 514 int 515 serial_enum_devices(RDPCLIENT * This, uint32 * id, char *optarg) 516 { 517 SERIAL_DEVICE *pser_inf; 518 519 char *pos = optarg; 520 char *pos2; 521 int count = 0; 522 523 /* skip the first colon */ 524 optarg++; 525 while ((pos = next_arg(optarg, ',')) && *id < RDPDR_MAX_DEVICES) 526 { 527 /* Init data structures for device */ 528 pser_inf = (SERIAL_DEVICE *) xmalloc(sizeof(SERIAL_DEVICE)); 529 pser_inf->ptermios = (struct termios *) xmalloc(sizeof(struct termios)); 530 memset(pser_inf->ptermios, 0, sizeof(struct termios)); 531 pser_inf->pold_termios = (struct termios *) xmalloc(sizeof(struct termios)); 532 memset(pser_inf->pold_termios, 0, sizeof(struct termios)); 533 534 pos2 = next_arg(optarg, '='); 535 strcpy(This->rdpdr_device[*id].name, optarg); 536 537 toupper_str(This->rdpdr_device[*id].name); 538 539 This->rdpdr_device[*id].local_path = xmalloc(strlen(pos2) + 1); 540 strcpy(This->rdpdr_device[*id].local_path, pos2); 541 printf("SERIAL %s to %s\n", This->rdpdr_device[*id].name, 542 This->rdpdr_device[*id].local_path); 543 /* set device type */ 544 This->rdpdr_device[*id].device_type = DEVICE_TYPE_SERIAL; 545 This->rdpdr_device[*id].pdevice_data = (void *) pser_inf; 546 count++; 547 (*id)++; 548 549 optarg = pos; 550 } 551 return count; 552 } 553 554 static NTSTATUS 555 serial_create(RDPCLIENT * This, uint32 device_id, uint32 access, uint32 share_mode, uint32 disposition, 556 uint32 flags_and_attributes, char *filename, NTHANDLE * handle) 557 { 558 NTHANDLE serial_fd; 559 SERIAL_DEVICE *pser_inf; 560 struct termios *ptermios; 561 562 pser_inf = (SERIAL_DEVICE *) This->rdpdr_device[device_id].pdevice_data; 563 ptermios = pser_inf->ptermios; 564 serial_fd = open(This->rdpdr_device[device_id].local_path, O_RDWR | O_NOCTTY | O_NONBLOCK); 565 566 if (serial_fd == -1) 567 { 568 perror("open"); 569 return STATUS_ACCESS_DENIED; 570 } 571 572 if (!get_termios(pser_inf, serial_fd)) 573 { 574 printf("INFO: SERIAL %s access denied\n", This->rdpdr_device[device_id].name); 575 fflush(stdout); 576 return STATUS_ACCESS_DENIED; 577 } 578 579 /* Store handle for later use */ 580 This->rdpdr_device[device_id].handle = serial_fd; 581 582 /* some sane information */ 583 DEBUG_SERIAL(("INFO: SERIAL %s to %s\nINFO: speed %u baud, stop bits %u, parity %u, word length %u bits, dtr %u, rts %u\n", This->rdpdr_device[device_id].name, This->rdpdr_device[device_id].local_path, pser_inf->baud_rate, pser_inf->stop_bits, pser_inf->parity, pser_inf->word_length, pser_inf->dtr, pser_inf->rts)); 584 585 pser_inf->ptermios->c_iflag &= 586 ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); 587 pser_inf->ptermios->c_oflag &= ~OPOST; 588 pser_inf->ptermios->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); 589 pser_inf->ptermios->c_cflag &= ~(CSIZE | PARENB); 590 pser_inf->ptermios->c_cflag |= CS8; 591 592 tcsetattr(serial_fd, TCSANOW, pser_inf->ptermios); 593 594 pser_inf->event_txempty = 0; 595 pser_inf->event_cts = 0; 596 pser_inf->event_dsr = 0; 597 pser_inf->event_rlsd = 0; 598 pser_inf->event_pending = 0; 599 600 *handle = serial_fd; 601 602 /* all read and writes should be non blocking */ 603 if (fcntl(*handle, F_SETFL, O_NONBLOCK) == -1) 604 perror("fcntl"); 605 606 pser_inf->read_total_timeout_constant = 5; 607 608 return STATUS_SUCCESS; 609 } 610 611 static NTSTATUS 612 serial_close(RDPCLIENT * This, NTHANDLE handle) 613 { 614 int i = get_device_index(This, handle); 615 if (i >= 0) 616 This->rdpdr_device[i].handle = 0; 617 618 rdpdr_abort_io(This, handle, 0, STATUS_TIMEOUT); 619 close(handle); 620 return STATUS_SUCCESS; 621 } 622 623 static NTSTATUS 624 serial_read(RDPCLIENT * This, NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result) 625 { 626 long timeout; 627 SERIAL_DEVICE *pser_inf; 628 struct termios *ptermios; 629 #ifdef WITH_DEBUG_SERIAL 630 int bytes_inqueue; 631 #endif 632 633 634 timeout = 90; 635 pser_inf = get_serial_info(This, handle); 636 ptermios = pser_inf->ptermios; 637 638 /* Set timeouts kind of like the windows serial timeout parameters. Multiply timeout 639 with requested read size */ 640 if (pser_inf->read_total_timeout_multiplier | pser_inf->read_total_timeout_constant) 641 { 642 timeout = 643 (pser_inf->read_total_timeout_multiplier * length + 644 pser_inf->read_total_timeout_constant + 99) / 100; 645 } 646 else if (pser_inf->read_interval_timeout) 647 { 648 timeout = (pser_inf->read_interval_timeout * length + 99) / 100; 649 } 650 651 /* If a timeout is set, do a blocking read, which times out after some time. 652 It will make rdesktop less responsive, but it will improve serial performance, by not 653 reading one character at a time. */ 654 if (timeout == 0) 655 { 656 ptermios->c_cc[VTIME] = 0; 657 ptermios->c_cc[VMIN] = 0; 658 } 659 else 660 { 661 ptermios->c_cc[VTIME] = timeout; 662 ptermios->c_cc[VMIN] = 1; 663 } 664 tcsetattr(handle, TCSANOW, ptermios); 665 666 #if defined(WITH_DEBUG_SERIAL) && defined(TIOCINQ) 667 ioctl(handle, TIOCINQ, &bytes_inqueue); 668 DEBUG_SERIAL(("serial_read inqueue: %d expected %d\n", bytes_inqueue, length)); 669 #endif 670 671 *result = read(handle, data, length); 672 673 #ifdef WITH_DEBUG_SERIAL 674 DEBUG_SERIAL(("serial_read Bytes %d\n", *result)); 675 if (*result > 0) 676 hexdump(data, *result); 677 #endif 678 679 return STATUS_SUCCESS; 680 } 681 682 static NTSTATUS 683 serial_write(RDPCLIENT * This, NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result) 684 { 685 SERIAL_DEVICE *pser_inf; 686 687 pser_inf = get_serial_info(This, handle); 688 689 *result = write(handle, data, length); 690 691 if (*result > 0) 692 pser_inf->event_txempty = *result; 693 694 DEBUG_SERIAL(("serial_write length %d, offset %d result %d\n", length, offset, *result)); 695 696 return STATUS_SUCCESS; 697 } 698 699 static NTSTATUS 700 serial_device_control(RDPCLIENT * This, NTHANDLE handle, uint32 request, STREAM in, STREAM out) 701 { 702 int flush_mask, purge_mask; 703 uint32 result, modemstate; 704 uint8 immediate; 705 SERIAL_DEVICE *pser_inf; 706 struct termios *ptermios; 707 708 if ((request >> 16) != FILE_DEVICE_SERIAL_PORT) 709 return STATUS_INVALID_PARAMETER; 710 711 pser_inf = get_serial_info(This, handle); 712 ptermios = pser_inf->ptermios; 713 714 /* extract operation */ 715 request >>= 2; 716 request &= 0xfff; 717 718 switch (request) 719 { 720 case SERIAL_SET_BAUD_RATE: 721 in_uint32_le(in, pser_inf->baud_rate); 722 set_termios(pser_inf, handle); 723 DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_BAUD_RATE %d\n", 724 pser_inf->baud_rate)); 725 break; 726 case SERIAL_GET_BAUD_RATE: 727 out_uint32_le(out, pser_inf->baud_rate); 728 DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_BAUD_RATE %d\n", 729 pser_inf->baud_rate)); 730 break; 731 case SERIAL_SET_QUEUE_SIZE: 732 in_uint32_le(in, pser_inf->queue_in_size); 733 in_uint32_le(in, pser_inf->queue_out_size); 734 DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_QUEUE_SIZE in %d out %d\n", 735 pser_inf->queue_in_size, pser_inf->queue_out_size)); 736 break; 737 case SERIAL_SET_LINE_CONTROL: 738 in_uint8(in, pser_inf->stop_bits); 739 in_uint8(in, pser_inf->parity); 740 in_uint8(in, pser_inf->word_length); 741 set_termios(pser_inf, handle); 742 DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_LINE_CONTROL stop %d parity %d word %d\n", pser_inf->stop_bits, pser_inf->parity, pser_inf->word_length)); 743 break; 744 case SERIAL_GET_LINE_CONTROL: 745 DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_LINE_CONTROL\n")); 746 out_uint8(out, pser_inf->stop_bits); 747 out_uint8(out, pser_inf->parity); 748 out_uint8(out, pser_inf->word_length); 749 break; 750 case SERIAL_IMMEDIATE_CHAR: 751 DEBUG_SERIAL(("serial_ioctl -> SERIAL_IMMEDIATE_CHAR\n")); 752 in_uint8(in, immediate); 753 serial_write(This, handle, &immediate, 1, 0, &result); 754 break; 755 case SERIAL_CONFIG_SIZE: 756 DEBUG_SERIAL(("serial_ioctl -> SERIAL_CONFIG_SIZE\n")); 757 out_uint32_le(out, 0); 758 break; 759 case SERIAL_GET_CHARS: 760 DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_CHARS\n")); 761 out_uint8a(out, pser_inf->chars, 6); 762 break; 763 case SERIAL_SET_CHARS: 764 DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_CHARS\n")); 765 in_uint8a(in, pser_inf->chars, 6); 766 #ifdef WITH_DEBUG_SERIAL 767 hexdump(pser_inf->chars, 6); 768 #endif 769 set_termios(pser_inf, handle); 770 break; 771 case SERIAL_GET_HANDFLOW: 772 DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_HANDFLOW\n")); 773 get_termios(pser_inf, handle); 774 out_uint32_le(out, pser_inf->control); 775 out_uint32_le(out, pser_inf->xonoff); /* Xon/Xoff */ 776 out_uint32_le(out, pser_inf->onlimit); 777 out_uint32_le(out, pser_inf->offlimit); 778 break; 779 case SERIAL_SET_HANDFLOW: 780 in_uint32_le(in, pser_inf->control); 781 in_uint32_le(in, pser_inf->xonoff); 782 in_uint32_le(in, pser_inf->onlimit); 783 in_uint32_le(in, pser_inf->offlimit); 784 DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_HANDFLOW %x %x %x %x\n", 785 pser_inf->control, pser_inf->xonoff, pser_inf->onlimit, 786 pser_inf->onlimit)); 787 set_termios(pser_inf, handle); 788 break; 789 case SERIAL_SET_TIMEOUTS: 790 in_uint32(in, pser_inf->read_interval_timeout); 791 in_uint32(in, pser_inf->read_total_timeout_multiplier); 792 in_uint32(in, pser_inf->read_total_timeout_constant); 793 in_uint32(in, pser_inf->write_total_timeout_multiplier); 794 in_uint32(in, pser_inf->write_total_timeout_constant); 795 DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_TIMEOUTS read timeout %d %d %d\n", 796 pser_inf->read_interval_timeout, 797 pser_inf->read_total_timeout_multiplier, 798 pser_inf->read_total_timeout_constant)); 799 break; 800 case SERIAL_GET_TIMEOUTS: 801 DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_TIMEOUTS read timeout %d %d %d\n", 802 pser_inf->read_interval_timeout, 803 pser_inf->read_total_timeout_multiplier, 804 pser_inf->read_total_timeout_constant)); 805 806 out_uint32(out, pser_inf->read_interval_timeout); 807 out_uint32(out, pser_inf->read_total_timeout_multiplier); 808 out_uint32(out, pser_inf->read_total_timeout_constant); 809 out_uint32(out, pser_inf->write_total_timeout_multiplier); 810 out_uint32(out, pser_inf->write_total_timeout_constant); 811 break; 812 case SERIAL_GET_WAIT_MASK: 813 DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_WAIT_MASK %X\n", 814 pser_inf->wait_mask)); 815 out_uint32(out, pser_inf->wait_mask); 816 break; 817 case SERIAL_SET_WAIT_MASK: 818 in_uint32(in, pser_inf->wait_mask); 819 DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_WAIT_MASK %X\n", 820 pser_inf->wait_mask)); 821 break; 822 case SERIAL_SET_DTR: 823 DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_DTR\n")); 824 ioctl(handle, TIOCMGET, &result); 825 result |= TIOCM_DTR; 826 ioctl(handle, TIOCMSET, &result); 827 pser_inf->dtr = 1; 828 break; 829 case SERIAL_CLR_DTR: 830 DEBUG_SERIAL(("serial_ioctl -> SERIAL_CLR_DTR\n")); 831 ioctl(handle, TIOCMGET, &result); 832 result &= ~TIOCM_DTR; 833 ioctl(handle, TIOCMSET, &result); 834 pser_inf->dtr = 0; 835 break; 836 case SERIAL_SET_RTS: 837 DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_RTS\n")); 838 ioctl(handle, TIOCMGET, &result); 839 result |= TIOCM_RTS; 840 ioctl(handle, TIOCMSET, &result); 841 pser_inf->rts = 1; 842 break; 843 case SERIAL_CLR_RTS: 844 DEBUG_SERIAL(("serial_ioctl -> SERIAL_CLR_RTS\n")); 845 ioctl(handle, TIOCMGET, &result); 846 result &= ~TIOCM_RTS; 847 ioctl(handle, TIOCMSET, &result); 848 pser_inf->rts = 0; 849 break; 850 case SERIAL_GET_MODEMSTATUS: 851 modemstate = 0; 852 #ifdef TIOCMGET 853 ioctl(handle, TIOCMGET, &result); 854 if (result & TIOCM_CTS) 855 modemstate |= SERIAL_MS_CTS; 856 if (result & TIOCM_DSR) 857 modemstate |= SERIAL_MS_DSR; 858 if (result & TIOCM_RNG) 859 modemstate |= SERIAL_MS_RNG; 860 if (result & TIOCM_CAR) 861 modemstate |= SERIAL_MS_CAR; 862 if (result & TIOCM_DTR) 863 modemstate |= SERIAL_MS_DTR; 864 if (result & TIOCM_RTS) 865 modemstate |= SERIAL_MS_RTS; 866 #endif 867 DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_MODEMSTATUS %X\n", modemstate)); 868 out_uint32_le(out, modemstate); 869 break; 870 case SERIAL_GET_COMMSTATUS: 871 out_uint32_le(out, 0); /* Errors */ 872 out_uint32_le(out, 0); /* Hold reasons */ 873 874 result = 0; 875 #ifdef TIOCINQ 876 ioctl(handle, TIOCINQ, &result); 877 #endif 878 out_uint32_le(out, result); /* Amount in in queue */ 879 if (result) 880 DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_COMMSTATUS in queue %d\n", 881 result)); 882 883 result = 0; 884 #ifdef TIOCOUTQ 885 ioctl(handle, TIOCOUTQ, &result); 886 #endif 887 out_uint32_le(out, result); /* Amount in out queue */ 888 if (result) 889 DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_COMMSTATUS out queue %d\n", result)); 890 891 out_uint8(out, 0); /* EofReceived */ 892 out_uint8(out, 0); /* WaitForImmediate */ 893 break; 894 case SERIAL_PURGE: 895 in_uint32(in, purge_mask); 896 DEBUG_SERIAL(("serial_ioctl -> SERIAL_PURGE purge_mask %X\n", purge_mask)); 897 flush_mask = 0; 898 if (purge_mask & SERIAL_PURGE_TXCLEAR) 899 flush_mask |= TCOFLUSH; 900 if (purge_mask & SERIAL_PURGE_RXCLEAR) 901 flush_mask |= TCIFLUSH; 902 if (flush_mask != 0) 903 tcflush(handle, flush_mask); 904 if (purge_mask & SERIAL_PURGE_TXABORT) 905 rdpdr_abort_io(This, handle, 4, STATUS_CANCELLED); 906 if (purge_mask & SERIAL_PURGE_RXABORT) 907 rdpdr_abort_io(This, handle, 3, STATUS_CANCELLED); 908 break; 909 case SERIAL_WAIT_ON_MASK: 910 DEBUG_SERIAL(("serial_ioctl -> SERIAL_WAIT_ON_MASK %X\n", 911 pser_inf->wait_mask)); 912 pser_inf->event_pending = 1; 913 if (serial_get_event(This, handle, &result)) 914 { 915 DEBUG_SERIAL(("WAIT end event = %x\n", result)); 916 out_uint32_le(out, result); 917 break; 918 } 919 return STATUS_PENDING; 920 break; 921 case SERIAL_SET_BREAK_ON: 922 DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_BREAK_ON\n")); 923 tcsendbreak(handle, 0); 924 break; 925 case SERIAL_RESET_DEVICE: 926 DEBUG_SERIAL(("serial_ioctl -> SERIAL_RESET_DEVICE\n")); 927 break; 928 case SERIAL_SET_BREAK_OFF: 929 DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_BREAK_OFF\n")); 930 break; 931 case SERIAL_SET_XOFF: 932 DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_XOFF\n")); 933 break; 934 case SERIAL_SET_XON: 935 DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_XON\n")); 936 tcflow(handle, TCION); 937 break; 938 default: 939 unimpl("SERIAL IOCTL %d\n", request); 940 return STATUS_INVALID_PARAMETER; 941 } 942 943 return STATUS_SUCCESS; 944 } 945 946 BOOL 947 serial_get_event(RDPCLIENT * This, NTHANDLE handle, uint32 * result) 948 { 949 int index; 950 SERIAL_DEVICE *pser_inf; 951 int bytes; 952 BOOL ret = False; 953 954 *result = 0; 955 index = get_device_index(This, handle); 956 if (index < 0) 957 return False; 958 959 #ifdef TIOCINQ 960 pser_inf = (SERIAL_DEVICE *) This->rdpdr_device[index].pdevice_data; 961 962 ioctl(handle, TIOCINQ, &bytes); 963 964 if (bytes > 0) 965 { 966 DEBUG_SERIAL(("serial_get_event Bytes %d\n", bytes)); 967 if (bytes > pser_inf->event_rlsd) 968 { 969 pser_inf->event_rlsd = bytes; 970 if (pser_inf->wait_mask & SERIAL_EV_RLSD) 971 { 972 DEBUG_SERIAL(("Event -> SERIAL_EV_RLSD \n")); 973 *result |= SERIAL_EV_RLSD; 974 ret = True; 975 } 976 977 } 978 979 if ((bytes > 1) && (pser_inf->wait_mask & SERIAL_EV_RXFLAG)) 980 { 981 DEBUG_SERIAL(("Event -> SERIAL_EV_RXFLAG Bytes %d\n", bytes)); 982 *result |= SERIAL_EV_RXFLAG; 983 ret = True; 984 } 985 if ((pser_inf->wait_mask & SERIAL_EV_RXCHAR)) 986 { 987 DEBUG_SERIAL(("Event -> SERIAL_EV_RXCHAR Bytes %d\n", bytes)); 988 *result |= SERIAL_EV_RXCHAR; 989 ret = True; 990 } 991 992 } 993 else 994 { 995 pser_inf->event_rlsd = 0; 996 } 997 #endif 998 999 #ifdef TIOCOUTQ 1000 ioctl(handle, TIOCOUTQ, &bytes); 1001 if ((bytes == 0) 1002 && (pser_inf->event_txempty > 0) && (pser_inf->wait_mask & SERIAL_EV_TXEMPTY)) 1003 { 1004 1005 DEBUG_SERIAL(("Event -> SERIAL_EV_TXEMPTY\n")); 1006 *result |= SERIAL_EV_TXEMPTY; 1007 ret = True; 1008 } 1009 pser_inf->event_txempty = bytes; 1010 #endif 1011 1012 ioctl(handle, TIOCMGET, &bytes); 1013 if ((bytes & TIOCM_DSR) != pser_inf->event_dsr) 1014 { 1015 pser_inf->event_dsr = bytes & TIOCM_DSR; 1016 if (pser_inf->wait_mask & SERIAL_EV_DSR) 1017 { 1018 DEBUG_SERIAL(("event -> SERIAL_EV_DSR %s\n", 1019 (bytes & TIOCM_DSR) ? "ON" : "OFF")); 1020 *result |= SERIAL_EV_DSR; 1021 ret = True; 1022 } 1023 } 1024 1025 if ((bytes & TIOCM_CTS) != pser_inf->event_cts) 1026 { 1027 pser_inf->event_cts = bytes & TIOCM_CTS; 1028 if (pser_inf->wait_mask & SERIAL_EV_CTS) 1029 { 1030 DEBUG_SERIAL((" EVENT-> SERIAL_EV_CTS %s\n", 1031 (bytes & TIOCM_CTS) ? "ON" : "OFF")); 1032 *result |= SERIAL_EV_CTS; 1033 ret = True; 1034 } 1035 } 1036 1037 if (ret) 1038 pser_inf->event_pending = 0; 1039 1040 return ret; 1041 } 1042 1043 /* Read timeout for a given file descripter (device) when adding fd's to select() */ 1044 BOOL 1045 serial_get_timeout(RDPCLIENT * This, NTHANDLE handle, uint32 length, uint32 * timeout, uint32 * itv_timeout) 1046 { 1047 int index; 1048 SERIAL_DEVICE *pser_inf; 1049 1050 index = get_device_index(This, handle); 1051 if (index < 0) 1052 return True; 1053 1054 if (This->rdpdr_device[index].device_type != DEVICE_TYPE_SERIAL) 1055 { 1056 return False; 1057 } 1058 1059 pser_inf = (SERIAL_DEVICE *) This->rdpdr_device[index].pdevice_data; 1060 1061 *timeout = 1062 pser_inf->read_total_timeout_multiplier * length + 1063 pser_inf->read_total_timeout_constant; 1064 *itv_timeout = pser_inf->read_interval_timeout; 1065 return True; 1066 } 1067 1068 DEVICE_FNS serial_fns = { 1069 serial_create, 1070 serial_close, 1071 serial_read, 1072 serial_write, 1073 serial_device_control 1074 }; 1075