VirtualBox

source: vbox/trunk/src/VBox/RDP/client/serial.c@ 8725

Last change on this file since 8725 was 7826, checked in by vboxsync, 17 years ago

Export modified rdesktop version including USB support to OSE. It's GPL anyway.

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