VirtualBox

source: vbox/trunk/src/VBox/RDP/client-1.8.4/serial.c@ 77807

Last change on this file since 77807 was 55123, checked in by vboxsync, 9 years ago

rdesktop 1.8.3 modified for VBox

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette