ReactOS 0.4.15-dev-8119-g4fb2fdb
serial.c
Go to the documentation of this file.
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
150static SERIAL_DEVICE *
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
163static BOOL
164get_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 {
294 }
295 else
296 {
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
316static void
317set_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 */
514int
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
554static NTSTATUS
555serial_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");
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);
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
611static NTSTATUS
613{
615 if (i >= 0)
616 This->rdpdr_device[i].handle = 0;
617
619 close(handle);
620 return STATUS_SUCCESS;
621}
622
623static NTSTATUS
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 */
641 {
642 timeout =
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
672
673#ifdef WITH_DEBUG_SERIAL
674 DEBUG_SERIAL(("serial_read Bytes %d\n", *result));
675 if (*result > 0)
677#endif
678
679 return STATUS_SUCCESS;
680}
681
682static NTSTATUS
684{
685 SERIAL_DEVICE *pser_inf;
686
687 pser_inf = get_serial_info(This, handle);
688
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
699static NTSTATUS
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)
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 {
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;
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;
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;
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;
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;
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;
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;
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;
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;
795 DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_TIMEOUTS read timeout %d %d %d\n",
796 pser_inf->read_interval_timeout,
798 pser_inf->read_total_timeout_constant));
799 break;
801 DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_TIMEOUTS read timeout %d %d %d\n",
802 pser_inf->read_interval_timeout,
804 pser_inf->read_total_timeout_constant));
805
811 break;
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;
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;
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;
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)
906 if (purge_mask & SERIAL_PURGE_RXABORT)
908 break;
910 DEBUG_SERIAL(("serial_ioctl -> SERIAL_WAIT_ON_MASK %X\n",
911 pser_inf->wait_mask));
912 pser_inf->event_pending = 1;
914 {
915 DEBUG_SERIAL(("WAIT end event = %x\n", result));
917 break;
918 }
919 return STATUS_PENDING;
920 break;
922 DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_BREAK_ON\n"));
923 tcsendbreak(handle, 0);
924 break;
926 DEBUG_SERIAL(("serial_ioctl -> SERIAL_RESET_DEVICE\n"));
927 break;
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);
941 }
942
943 return STATUS_SUCCESS;
944}
945
946BOOL
948{
949 int index;
950 SERIAL_DEVICE *pser_inf;
951 int bytes;
952 BOOL ret = False;
953
954 *result = 0;
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"));
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));
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));
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"));
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"));
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"));
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() */
1044BOOL
1046{
1047 int index;
1048 SERIAL_DEVICE *pser_inf;
1049
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 =
1064 *itv_timeout = pser_inf->read_interval_timeout;
1065 return True;
1066}
1067
1074};
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define read
Definition: acwin.h:96
#define open
Definition: acwin.h:95
#define close
Definition: acwin.h:98
#define write
Definition: acwin.h:97
static unsigned char bytes[4]
Definition: adnsresfilter.c:74
LONG NTSTATUS
Definition: precomp.h:26
#define DEVICE_TYPE_SERIAL
Definition: constants.h:485
#define RDPDR_MAX_DEVICES
Definition: constants.h:484
#define out_uint32_le(s, v)
Definition: parse.h:59
#define in_uint32(s, v)
Definition: parse.h:83
#define out_uint8(s, v)
Definition: parse.h:92
#define in_uint8a(s, v, n)
Definition: parse.h:90
#define in_uint8(s, v)
Definition: parse.h:88
#define out_uint32(s, v)
Definition: parse.h:85
#define in_uint32_le(s, v)
Definition: parse.h:56
#define out_uint8a(s, v, n)
Definition: parse.h:94
RD_BOOL rdpdr_abort_io(uint32 fd, uint32 major, RD_NTSTATUS status)
char * next_arg(char *src, char needle)
Definition: rdesktop.c:1174
int get_device_index(RD_NTHANDLE handle)
void unimpl(char *format,...)
Definition: uimain.c:801
void hexdump(unsigned char *p, unsigned int len)
Definition: shimdbg.c:234
void toupper_str(char *p)
Definition: rdesktop.c:1223
void * xmalloc(int size)
Definition: uimain.c:747
unsigned int uint32
Definition: types.h:32
#define False
Definition: types.h:25
#define True
Definition: types.h:24
unsigned char uint8
Definition: types.h:28
const char * optarg
Definition: getopt.c:49
#define index(s, c)
Definition: various.h:29
#define NULL
Definition: types.h:112
unsigned int BOOL
Definition: ntddk_ex.h:94
#define printf
Definition: freeldr.h:97
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLuint index
Definition: glext.h:6031
GLuint in
Definition: glext.h:9616
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLuint GLint GLboolean GLint GLenum access
Definition: glext.h:7866
GLuint64EXT * result
Definition: glext.h:11304
GLuint id
Definition: glext.h:5910
GLintptr offset
Definition: glext.h:5920
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define O_RDWR
Definition: fcntl.h:36
#define stdout
Definition: stdio.h:99
_CRTIMP void __cdecl perror(_In_opt_z_ const char *_ErrMsg)
_Check_return_opt_ _CRTIMP int __cdecl fflush(_Inout_opt_ FILE *_File)
const char * filename
Definition: ioapi.h:137
#define SERIAL_MS_RNG
Definition: serial.c:118
#define SERIAL_EV_TXEMPTY
Definition: serial.c:101
#define SERIAL_DSR_SENSITIVITY
Definition: serial.c:128
#define SERIAL_CHAR_XOFF
Definition: serial.c:135
#define SERIAL_WAIT_ON_MASK
Definition: serial.c:63
#define SERIAL_SET_BREAK_ON
Definition: serial.c:49
#define STOP_BITS_2
Definition: serial.c:87
#define SERIAL_SET_TIMEOUTS
Definition: serial.c:52
#define SERIAL_SET_HANDFLOW
Definition: serial.c:70
#define SERIAL_XOFF_HANDSHAKE
Definition: serial.c:127
#define SERIAL_PURGE_TXCLEAR
Definition: serial.c:95
#define SERIAL_CONFIG_SIZE
Definition: serial.c:77
static NTSTATUS serial_device_control(RDPCLIENT *This, NTHANDLE handle, uint32 request, STREAM in, STREAM out)
Definition: serial.c:700
#define SERIAL_CLR_DTR
Definition: serial.c:55
static NTSTATUS serial_create(RDPCLIENT *This, uint32 device_id, uint32 access, uint32 share_mode, uint32 disposition, uint32 flags_and_attributes, char *filename, NTHANDLE *handle)
Definition: serial.c:555
#define SERIAL_CLR_RTS
Definition: serial.c:58
#define EVEN_PARITY
Definition: serial.c:91
#define SERIAL_SET_LINE_CONTROL
Definition: serial.c:48
#define STOP_BITS_1
Definition: serial.c:86
#define SERIAL_PURGE_RXCLEAR
Definition: serial.c:96
#define SERIAL_CHAR_EOF
Definition: serial.c:130
#define SERIAL_EV_RXCHAR
Definition: serial.c:99
#define FILE_DEVICE_SERIAL_PORT
Definition: serial.c:44
#define SERIAL_CHAR_BREAK
Definition: serial.c:132
DEVICE_FNS serial_fns
Definition: serial.c:1068
#define SERIAL_GET_MODEMSTATUS
Definition: serial.c:71
#define SERIAL_SET_BREAK_OFF
Definition: serial.c:50
static BOOL get_termios(SERIAL_DEVICE *pser_inf, NTHANDLE serial_fd)
Definition: serial.c:164
BOOL serial_get_event(RDPCLIENT *This, NTHANDLE handle, uint32 *result)
Definition: serial.c:947
#define SERIAL_SET_RTS
Definition: serial.c:57
#define SERIAL_SET_CHARS
Definition: serial.c:68
#define SERIAL_EV_DSR
Definition: serial.c:103
#define SERIAL_EV_RXFLAG
Definition: serial.c:100
#define SERIAL_SET_XON
Definition: serial.c:60
#define SERIAL_GET_COMMSTATUS
Definition: serial.c:72
#define SERIAL_ERROR_ABORT
Definition: serial.c:124
#define SERIAL_SET_QUEUE_SIZE
Definition: serial.c:47
#define SERIAL_SET_BAUD_RATE
Definition: serial.c:46
#define CRTSCTS
Definition: serial.c:138
#define SERIAL_MS_RTS
Definition: serial.c:115
#define NO_PARITY
Definition: serial.c:89
#define SERIAL_GET_TIMEOUTS
Definition: serial.c:53
static NTSTATUS serial_read(RDPCLIENT *This, NTHANDLE handle, uint8 *data, uint32 length, uint32 offset, uint32 *result)
Definition: serial.c:624
#define SERIAL_MS_DSR
Definition: serial.c:117
#define SERIAL_MS_CAR
Definition: serial.c:119
#define SERIAL_CTS_HANDSHAKE
Definition: serial.c:123
#define SERIAL_EV_RLSD
Definition: serial.c:104
#define ODD_PARITY
Definition: serial.c:90
#define SERIAL_PURGE_RXABORT
Definition: serial.c:94
#define SERIAL_PURGE
Definition: serial.c:64
#define SERIAL_SET_WAIT_MASK
Definition: serial.c:62
#define SERIAL_GET_CHARS
Definition: serial.c:67
#define SERIAL_GET_BAUD_RATE
Definition: serial.c:65
#define SERIAL_DTR_CONTROL
Definition: serial.c:122
#define SERIAL_SET_DTR
Definition: serial.c:54
#define SERIAL_GET_HANDFLOW
Definition: serial.c:69
#define SERIAL_GET_LINE_CONTROL
Definition: serial.c:66
static void set_termios(SERIAL_DEVICE *pser_inf, NTHANDLE serial_fd)
Definition: serial.c:317
#define SERIAL_EV_CTS
Definition: serial.c:102
#define SERIAL_CHAR_XON
Definition: serial.c:134
#define SERIAL_XON_HANDSHAKE
Definition: serial.c:126
static NTSTATUS serial_close(RDPCLIENT *This, NTHANDLE handle)
Definition: serial.c:612
#define SERIAL_RESET_DEVICE
Definition: serial.c:56
#define SERIAL_GET_WAIT_MASK
Definition: serial.c:61
BOOL serial_get_timeout(RDPCLIENT *This, NTHANDLE handle, uint32 length, uint32 *timeout, uint32 *itv_timeout)
Definition: serial.c:1045
#define SERIAL_CHAR_ERROR
Definition: serial.c:131
#define SERIAL_PURGE_TXABORT
Definition: serial.c:93
#define SERIAL_IMMEDIATE_CHAR
Definition: serial.c:51
static NTSTATUS serial_write(RDPCLIENT *This, NTHANDLE handle, uint8 *data, uint32 length, uint32 offset, uint32 *result)
Definition: serial.c:683
static SERIAL_DEVICE * get_serial_info(RDPCLIENT *This, NTHANDLE handle)
Definition: serial.c:151
#define SERIAL_MS_DTR
Definition: serial.c:114
#define SERIAL_SET_XOFF
Definition: serial.c:59
#define DEBUG_SERIAL(args)
Definition: serial.c:41
#define SERIAL_MS_CTS
Definition: serial.c:116
int serial_enum_devices(RDPCLIENT *This, uint32 *id, char *optarg)
Definition: serial.c:515
#define O_NONBLOCK
Definition: port.h:158
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
#define STATUS_PENDING
Definition: ntstatus.h:82
static FILE * out
Definition: regtests2xml.c:44
#define memset(x, y, z)
Definition: compat.h:39
#define STATUS_SUCCESS
Definition: shellext.h:65
struct termios * ptermios
Definition: types.h:240
struct termios * pold_termios
Definition: types.h:240
uint32 read_interval_timeout
Definition: types.h:234
uint32 read_total_timeout_multiplier
Definition: types.h:235
uint32 write_total_timeout_multiplier
Definition: types.h:237
uint32 write_total_timeout_constant
Definition: types.h:237
uint32 read_total_timeout_constant
Definition: types.h:236
Definition: tftpd.h:86
Definition: parse.h:23
Definition: dhcpd.h:245
#define ECHO
Definition: telnetd.h:34
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
int ret
#define ioctl
Definition: wintirpc.h:60