/[rdesktop]/sourceforge.net/trunk/rdesktop/serial.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /sourceforge.net/trunk/rdesktop/serial.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 799 - (show annotations)
Sat Nov 6 17:27:45 2004 UTC (19 years, 6 months ago) by stargo
File MIME type: text/plain
File size: 25989 byte(s)
*BSD fixes (tested with OpenBSD)
No more need to include anything in proto.h on BSDs

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

  ViewVC Help
Powered by ViewVC 1.1.26