1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
4 Copyright (C) Matthew Chapman 1999-2005
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.
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.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include <sys/ioctl.h>
26 #ifdef HAVE_SYS_MODEM_H
27 #include <sys/modem.h>
29 #ifdef HAVE_SYS_FILIO_H
30 #include <sys/filio.h>
32 #ifdef HAVE_SYS_STRTIO_H
33 #include <sys/strtio.h>
38 #ifdef WITH_DEBUG_SERIAL
39 #define DEBUG_SERIAL(args) printf args;
41 #define DEBUG_SERIAL(args)
44 #define FILE_DEVICE_SERIAL_PORT 0x1b
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
93 #define SERIAL_PURGE_TXABORT 0x00000001
94 #define SERIAL_PURGE_RXABORT 0x00000002
95 #define SERIAL_PURGE_TXCLEAR 0x00000004
96 #define SERIAL_PURGE_RXCLEAR 0x00000008
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 */
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
122 #define SERIAL_DTR_CONTROL 0x01
123 #define SERIAL_CTS_HANDSHAKE 0x08
124 #define SERIAL_ERROR_ABORT 0x80000000
126 #define SERIAL_XON_HANDSHAKE 0x01
127 #define SERIAL_XOFF_HANDSHAKE 0x02
128 #define SERIAL_DSR_SENSITIVITY 0x40
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
141 /* FIONREAD should really do the same thing as TIOCINQ, where it is
143 #if !defined(TIOCINQ) && defined(FIONREAD)
144 #define TIOCINQ FIONREAD
146 #if !defined(TIOCOUTQ) && defined(FIONWRITE)
147 #define TIOCOUTQ FIONWRITE
150 static SERIAL_DEVICE
*
151 get_serial_info(RDPCLIENT
* This
, NTHANDLE handle
)
155 for (index
= 0; index
< RDPDR_MAX_DEVICES
; index
++)
157 if (handle
== This
->rdpdr_device
[index
].handle
)
158 return (SERIAL_DEVICE
*) This
->rdpdr_device
[index
].pdevice_data
;
164 get_termios(SERIAL_DEVICE
* pser_inf
, NTHANDLE serial_fd
)
167 struct termios
*ptermios
;
169 ptermios
= pser_inf
->ptermios
;
171 if (tcgetattr(serial_fd
, ptermios
) == -1)
174 speed
= cfgetispeed(ptermios
);
179 pser_inf
->baud_rate
= 75;
184 pser_inf
->baud_rate
= 110;
189 pser_inf
->baud_rate
= 134;
194 pser_inf
->baud_rate
= 150;
199 pser_inf
->baud_rate
= 300;
204 pser_inf
->baud_rate
= 600;
209 pser_inf
->baud_rate
= 1200;
214 pser_inf
->baud_rate
= 1800;
219 pser_inf
->baud_rate
= 2400;
224 pser_inf
->baud_rate
= 4800;
229 pser_inf
->baud_rate
= 9600;
234 pser_inf
->baud_rate
= 19200;
239 pser_inf
->baud_rate
= 38400;
244 pser_inf
->baud_rate
= 57600;
249 pser_inf
->baud_rate
= 115200;
254 pser_inf
->baud_rate
= 230400;
259 pser_inf
->baud_rate
= 460800;
263 pser_inf
->baud_rate
= 9600;
267 speed
= cfgetospeed(ptermios
);
268 pser_inf
->dtr
= (speed
== B0
) ? 0 : 1;
270 pser_inf
->stop_bits
= (ptermios
->c_cflag
& CSTOPB
) ? STOP_BITS_2
: STOP_BITS_1
;
273 c_cflag
& PARENB
) ? ((ptermios
->
274 c_cflag
& PARODD
) ? ODD_PARITY
: EVEN_PARITY
) : NO_PARITY
;
275 switch (ptermios
->c_cflag
& CSIZE
)
278 pser_inf
->word_length
= 5;
281 pser_inf
->word_length
= 6;
284 pser_inf
->word_length
= 7;
287 pser_inf
->word_length
= 8;
291 if (ptermios
->c_cflag
& CRTSCTS
)
293 pser_inf
->control
= SERIAL_DTR_CONTROL
| SERIAL_CTS_HANDSHAKE
| SERIAL_ERROR_ABORT
;
297 pser_inf
->control
= SERIAL_DTR_CONTROL
| SERIAL_ERROR_ABORT
;
300 pser_inf
->xonoff
= SERIAL_DSR_SENSITIVITY
;
301 if (ptermios
->c_iflag
& IXON
)
302 pser_inf
->xonoff
|= SERIAL_XON_HANDSHAKE
;
304 if (ptermios
->c_iflag
& IXOFF
)
305 pser_inf
->xonoff
|= SERIAL_XOFF_HANDSHAKE
;
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
];
317 set_termios(SERIAL_DEVICE
* pser_inf
, NTHANDLE serial_fd
)
321 struct termios
*ptermios
;
323 ptermios
= pser_inf
->ptermios
;
326 switch (pser_inf
->baud_rate
)
419 ptermios
->c_cflag
&= ~CBAUD
;
420 ptermios
->c_cflag
|= speed
;
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);
428 ptermios
->c_cflag
&= ~(CSTOPB
| PARENB
| PARODD
| CSIZE
| CRTSCTS
);
429 switch (pser_inf
->stop_bits
)
432 ptermios
->c_cflag
|= CSTOPB
;
435 ptermios
->c_cflag
&= ~CSTOPB
;
439 switch (pser_inf
->parity
)
442 ptermios
->c_cflag
|= PARENB
;
445 ptermios
->c_cflag
|= PARENB
| PARODD
;
448 ptermios
->c_cflag
&= ~(PARENB
| PARODD
);
452 switch (pser_inf
->word_length
)
455 ptermios
->c_cflag
|= CS5
;
458 ptermios
->c_cflag
|= CS6
;
461 ptermios
->c_cflag
|= CS7
;
464 ptermios
->c_cflag
|= CS8
;
470 ptermios
->c_cflag
|= CRTSCTS
;
472 ptermios
->c_cflag
&= ~CRTSCTS
;
475 if (pser_inf
->control
& SERIAL_CTS_HANDSHAKE
)
477 ptermios
->c_cflag
|= CRTSCTS
;
481 ptermios
->c_cflag
&= ~CRTSCTS
;
485 if (pser_inf
->xonoff
& SERIAL_XON_HANDSHAKE
)
487 ptermios
->c_iflag
|= IXON
| IMAXBEL
;
489 if (pser_inf
->xonoff
& SERIAL_XOFF_HANDSHAKE
)
491 ptermios
->c_iflag
|= IXOFF
| IMAXBEL
;
494 if ((pser_inf
->xonoff
& (SERIAL_XOFF_HANDSHAKE
| SERIAL_XON_HANDSHAKE
)) == 0)
496 ptermios
->c_iflag
&= ~IXON
;
497 ptermios
->c_iflag
&= ~IXOFF
;
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
];
506 tcsetattr(serial_fd
, TCSANOW
, ptermios
);
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 */
515 serial_enum_devices(RDPCLIENT
* This
, uint32
* id
, char *optarg
)
517 SERIAL_DEVICE
*pser_inf
;
523 /* skip the first colon */
525 while ((pos
= next_arg(optarg
, ',')) && *id
< RDPDR_MAX_DEVICES
)
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
));
534 pos2
= next_arg(optarg
, '=');
535 strcpy(This
->rdpdr_device
[*id
].name
, optarg
);
537 toupper_str(This
->rdpdr_device
[*id
].name
);
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
;
555 serial_create(RDPCLIENT
* This
, uint32 device_id
, uint32 access
, uint32 share_mode
, uint32 disposition
,
556 uint32 flags_and_attributes
, char *filename
, NTHANDLE
* handle
)
559 SERIAL_DEVICE
*pser_inf
;
560 struct termios
*ptermios
;
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
);
569 return STATUS_ACCESS_DENIED
;
572 if (!get_termios(pser_inf
, serial_fd
))
574 printf("INFO: SERIAL %s access denied\n", This
->rdpdr_device
[device_id
].name
);
576 return STATUS_ACCESS_DENIED
;
579 /* Store handle for later use */
580 This
->rdpdr_device
[device_id
].handle
= serial_fd
;
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
));
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
;
592 tcsetattr(serial_fd
, TCSANOW
, pser_inf
->ptermios
);
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;
602 /* all read and writes should be non blocking */
603 if (fcntl(*handle
, F_SETFL
, O_NONBLOCK
) == -1)
606 pser_inf
->read_total_timeout_constant
= 5;
608 return STATUS_SUCCESS
;
612 serial_close(RDPCLIENT
* This
, NTHANDLE handle
)
614 int i
= get_device_index(This
, handle
);
616 This
->rdpdr_device
[i
].handle
= 0;
618 rdpdr_abort_io(This
, handle
, 0, STATUS_TIMEOUT
);
620 return STATUS_SUCCESS
;
624 serial_read(RDPCLIENT
* This
, NTHANDLE handle
, uint8
* data
, uint32 length
, uint32 offset
, uint32
* result
)
627 SERIAL_DEVICE
*pser_inf
;
628 struct termios
*ptermios
;
629 #ifdef WITH_DEBUG_SERIAL
635 pser_inf
= get_serial_info(This
, handle
);
636 ptermios
= pser_inf
->ptermios
;
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
)
643 (pser_inf
->read_total_timeout_multiplier
* length
+
644 pser_inf
->read_total_timeout_constant
+ 99) / 100;
646 else if (pser_inf
->read_interval_timeout
)
648 timeout
= (pser_inf
->read_interval_timeout
* length
+ 99) / 100;
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. */
656 ptermios
->c_cc
[VTIME
] = 0;
657 ptermios
->c_cc
[VMIN
] = 0;
661 ptermios
->c_cc
[VTIME
] = timeout
;
662 ptermios
->c_cc
[VMIN
] = 1;
664 tcsetattr(handle
, TCSANOW
, ptermios
);
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
));
671 *result
= read(handle
, data
, length
);
673 #ifdef WITH_DEBUG_SERIAL
674 DEBUG_SERIAL(("serial_read Bytes %d\n", *result
));
676 hexdump(data
, *result
);
679 return STATUS_SUCCESS
;
683 serial_write(RDPCLIENT
* This
, NTHANDLE handle
, uint8
* data
, uint32 length
, uint32 offset
, uint32
* result
)
685 SERIAL_DEVICE
*pser_inf
;
687 pser_inf
= get_serial_info(This
, handle
);
689 *result
= write(handle
, data
, length
);
692 pser_inf
->event_txempty
= *result
;
694 DEBUG_SERIAL(("serial_write length %d, offset %d result %d\n", length
, offset
, *result
));
696 return STATUS_SUCCESS
;
700 serial_device_control(RDPCLIENT
* This
, NTHANDLE handle
, uint32 request
, STREAM in
, STREAM out
)
702 int flush_mask
, purge_mask
;
703 uint32 result
, modemstate
;
705 SERIAL_DEVICE
*pser_inf
;
706 struct termios
*ptermios
;
708 if ((request
>> 16) != FILE_DEVICE_SERIAL_PORT
)
709 return STATUS_INVALID_PARAMETER
;
711 pser_inf
= get_serial_info(This
, handle
);
712 ptermios
= pser_inf
->ptermios
;
714 /* extract operation */
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
));
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
));
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
));
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
));
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
);
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
);
755 case SERIAL_CONFIG_SIZE
:
756 DEBUG_SERIAL(("serial_ioctl -> SERIAL_CONFIG_SIZE\n"));
757 out_uint32_le(out
, 0);
759 case SERIAL_GET_CHARS
:
760 DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_CHARS\n"));
761 out_uint8a(out
, pser_inf
->chars
, 6);
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);
769 set_termios(pser_inf
, handle
);
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
);
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
,
787 set_termios(pser_inf
, handle
);
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
));
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
));
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
);
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
);
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
));
823 DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_DTR\n"));
824 ioctl(handle
, TIOCMGET
, &result
);
826 ioctl(handle
, TIOCMSET
, &result
);
830 DEBUG_SERIAL(("serial_ioctl -> SERIAL_CLR_DTR\n"));
831 ioctl(handle
, TIOCMGET
, &result
);
832 result
&= ~TIOCM_DTR
;
833 ioctl(handle
, TIOCMSET
, &result
);
837 DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_RTS\n"));
838 ioctl(handle
, TIOCMGET
, &result
);
840 ioctl(handle
, TIOCMSET
, &result
);
844 DEBUG_SERIAL(("serial_ioctl -> SERIAL_CLR_RTS\n"));
845 ioctl(handle
, TIOCMGET
, &result
);
846 result
&= ~TIOCM_RTS
;
847 ioctl(handle
, TIOCMSET
, &result
);
850 case SERIAL_GET_MODEMSTATUS
:
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
;
867 DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_MODEMSTATUS %X\n", modemstate
));
868 out_uint32_le(out
, modemstate
);
870 case SERIAL_GET_COMMSTATUS
:
871 out_uint32_le(out
, 0); /* Errors */
872 out_uint32_le(out
, 0); /* Hold reasons */
876 ioctl(handle
, TIOCINQ
, &result
);
878 out_uint32_le(out
, result
); /* Amount in in queue */
880 DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_COMMSTATUS in queue %d\n",
885 ioctl(handle
, TIOCOUTQ
, &result
);
887 out_uint32_le(out
, result
); /* Amount in out queue */
889 DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_COMMSTATUS out queue %d\n", result
));
891 out_uint8(out
, 0); /* EofReceived */
892 out_uint8(out
, 0); /* WaitForImmediate */
895 in_uint32(in
, purge_mask
);
896 DEBUG_SERIAL(("serial_ioctl -> SERIAL_PURGE purge_mask %X\n", purge_mask
));
898 if (purge_mask
& SERIAL_PURGE_TXCLEAR
)
899 flush_mask
|= TCOFLUSH
;
900 if (purge_mask
& SERIAL_PURGE_RXCLEAR
)
901 flush_mask
|= TCIFLUSH
;
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
);
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
))
915 DEBUG_SERIAL(("WAIT end event = %x\n", result
));
916 out_uint32_le(out
, result
);
919 return STATUS_PENDING
;
921 case SERIAL_SET_BREAK_ON
:
922 DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_BREAK_ON\n"));
923 tcsendbreak(handle
, 0);
925 case SERIAL_RESET_DEVICE
:
926 DEBUG_SERIAL(("serial_ioctl -> SERIAL_RESET_DEVICE\n"));
928 case SERIAL_SET_BREAK_OFF
:
929 DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_BREAK_OFF\n"));
931 case SERIAL_SET_XOFF
:
932 DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_XOFF\n"));
935 DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_XON\n"));
936 tcflow(handle
, TCION
);
939 unimpl("SERIAL IOCTL %d\n", request
);
940 return STATUS_INVALID_PARAMETER
;
943 return STATUS_SUCCESS
;
947 serial_get_event(RDPCLIENT
* This
, NTHANDLE handle
, uint32
* result
)
950 SERIAL_DEVICE
*pser_inf
;
955 index
= get_device_index(This
, handle
);
960 pser_inf
= (SERIAL_DEVICE
*) This
->rdpdr_device
[index
].pdevice_data
;
962 ioctl(handle
, TIOCINQ
, &bytes
);
966 DEBUG_SERIAL(("serial_get_event Bytes %d\n", bytes
));
967 if (bytes
> pser_inf
->event_rlsd
)
969 pser_inf
->event_rlsd
= bytes
;
970 if (pser_inf
->wait_mask
& SERIAL_EV_RLSD
)
972 DEBUG_SERIAL(("Event -> SERIAL_EV_RLSD \n"));
973 *result
|= SERIAL_EV_RLSD
;
979 if ((bytes
> 1) && (pser_inf
->wait_mask
& SERIAL_EV_RXFLAG
))
981 DEBUG_SERIAL(("Event -> SERIAL_EV_RXFLAG Bytes %d\n", bytes
));
982 *result
|= SERIAL_EV_RXFLAG
;
985 if ((pser_inf
->wait_mask
& SERIAL_EV_RXCHAR
))
987 DEBUG_SERIAL(("Event -> SERIAL_EV_RXCHAR Bytes %d\n", bytes
));
988 *result
|= SERIAL_EV_RXCHAR
;
995 pser_inf
->event_rlsd
= 0;
1000 ioctl(handle
, TIOCOUTQ
, &bytes
);
1002 && (pser_inf
->event_txempty
> 0) && (pser_inf
->wait_mask
& SERIAL_EV_TXEMPTY
))
1005 DEBUG_SERIAL(("Event -> SERIAL_EV_TXEMPTY\n"));
1006 *result
|= SERIAL_EV_TXEMPTY
;
1009 pser_inf
->event_txempty
= bytes
;
1012 ioctl(handle
, TIOCMGET
, &bytes
);
1013 if ((bytes
& TIOCM_DSR
) != pser_inf
->event_dsr
)
1015 pser_inf
->event_dsr
= bytes
& TIOCM_DSR
;
1016 if (pser_inf
->wait_mask
& SERIAL_EV_DSR
)
1018 DEBUG_SERIAL(("event -> SERIAL_EV_DSR %s\n",
1019 (bytes
& TIOCM_DSR
) ? "ON" : "OFF"));
1020 *result
|= SERIAL_EV_DSR
;
1025 if ((bytes
& TIOCM_CTS
) != pser_inf
->event_cts
)
1027 pser_inf
->event_cts
= bytes
& TIOCM_CTS
;
1028 if (pser_inf
->wait_mask
& SERIAL_EV_CTS
)
1030 DEBUG_SERIAL((" EVENT-> SERIAL_EV_CTS %s\n",
1031 (bytes
& TIOCM_CTS
) ? "ON" : "OFF"));
1032 *result
|= SERIAL_EV_CTS
;
1038 pser_inf
->event_pending
= 0;
1043 /* Read timeout for a given file descripter (device) when adding fd's to select() */
1045 serial_get_timeout(RDPCLIENT
* This
, NTHANDLE handle
, uint32 length
, uint32
* timeout
, uint32
* itv_timeout
)
1048 SERIAL_DEVICE
*pser_inf
;
1050 index
= get_device_index(This
, handle
);
1054 if (This
->rdpdr_device
[index
].device_type
!= DEVICE_TYPE_SERIAL
)
1059 pser_inf
= (SERIAL_DEVICE
*) This
->rdpdr_device
[index
].pdevice_data
;
1062 pser_inf
->read_total_timeout_multiplier
* length
+
1063 pser_inf
->read_total_timeout_constant
;
1064 *itv_timeout
= pser_inf
->read_interval_timeout
;
1068 DEVICE_FNS serial_fns
= {
1073 serial_device_control