/[rdesktop]/jpeg/rdesktop/trunk/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 /jpeg/rdesktop/trunk/serial.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 865 - (show annotations)
Tue Mar 15 11:25:50 2005 UTC (19 years, 2 months ago) by stargo
Original Path: sourceforge.net/trunk/rdesktop/serial.c
File MIME type: text/plain
File size: 26358 byte(s)
remove C++-style comments

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

  ViewVC Help
Powered by ViewVC 1.1.26