/[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 686 - (show annotations)
Thu Apr 29 19:41:49 2004 UTC (20 years, 1 month ago) by stargo
File MIME type: text/plain
File size: 15588 byte(s)
Fix compilation on hp/ux

1 #include <unistd.h>
2 #include <fcntl.h>
3 #include <termios.h>
4 #include <strings.h>
5 #include "rdesktop.h"
6
7 #define FILE_DEVICE_SERIAL_PORT 0x1b
8
9 #define SERIAL_SET_BAUD_RATE 1
10 #define SERIAL_SET_QUEUE_SIZE 2
11 #define SERIAL_SET_LINE_CONTROL 3
12 #define SERIAL_SET_BREAK_ON 4
13 #define SERIAL_SET_BREAK_OFF 5
14 #define SERIAL_IMMEDIATE_CHAR 6
15 #define SERIAL_SET_TIMEOUTS 7
16 #define SERIAL_GET_TIMEOUTS 8
17 #define SERIAL_SET_DTR 9
18 #define SERIAL_CLR_DTR 10
19 #define SERIAL_RESET_DEVICE 11
20 #define SERIAL_SET_RTS 12
21 #define SERIAL_CLR_RTS 13
22 #define SERIAL_SET_XOFF 14
23 #define SERIAL_SET_XON 15
24 #define SERIAL_GET_WAIT_MASK 16
25 #define SERIAL_SET_WAIT_MASK 17
26 #define SERIAL_WAIT_ON_MASK 18
27 #define SERIAL_PURGE 19
28 #define SERIAL_GET_BAUD_RATE 20
29 #define SERIAL_GET_LINE_CONTROL 21
30 #define SERIAL_GET_CHARS 22
31 #define SERIAL_SET_CHARS 23
32 #define SERIAL_GET_HANDFLOW 24
33 #define SERIAL_SET_HANDFLOW 25
34 #define SERIAL_GET_MODEMSTATUS 26
35 #define SERIAL_GET_COMMSTATUS 27
36 #define SERIAL_XOFF_COUNTER 28
37 #define SERIAL_GET_PROPERTIES 29
38 #define SERIAL_GET_DTRRTS 30
39 #define SERIAL_LSRMST_INSERT 31
40 #define SERIAL_CONFIG_SIZE 32
41 #define SERIAL_GET_COMMCONFIG 33
42 #define SERIAL_SET_COMMCONFIG 34
43 #define SERIAL_GET_STATS 35
44 #define SERIAL_CLEAR_STATS 36
45 #define SERIAL_GET_MODEM_CONTROL 37
46 #define SERIAL_SET_MODEM_CONTROL 38
47 #define SERIAL_SET_FIFO_CONTROL 39
48
49 #define STOP_BITS_1 0
50 #define STOP_BITS_2 2
51
52 #define NO_PARITY 0
53 #define ODD_PARITY 1
54 #define EVEN_PARITY 2
55
56 #define SERIAL_PURGE_TXABORT 0x00000001
57 #define SERIAL_PURGE_RXABORT 0x00000002
58 #define SERIAL_PURGE_TXCLEAR 0x00000004
59 #define SERIAL_PURGE_RXCLEAR 0x00000008
60
61 /* SERIAL_WAIT_ON_MASK */
62 #define SERIAL_EV_RXCHAR 0x0001 // Any Character received
63 #define SERIAL_EV_RXFLAG 0x0002 // Received certain character
64 #define SERIAL_EV_TXEMPTY 0x0004 // Transmitt Queue Empty
65 #define SERIAL_EV_CTS 0x0008 // CTS changed state
66 #define SERIAL_EV_DSR 0x0010 // DSR changed state
67 #define SERIAL_EV_RLSD 0x0020 // RLSD changed state
68 #define SERIAL_EV_BREAK 0x0040 // BREAK received
69 #define SERIAL_EV_ERR 0x0080 // Line status error occurred
70 #define SERIAL_EV_RING 0x0100 // Ring signal detected
71 #define SERIAL_EV_PERR 0x0200 // Printer error occured
72 #define SERIAL_EV_RX80FULL 0x0400 // Receive buffer is 80 percent full
73 #define SERIAL_EV_EVENT1 0x0800 // Provider specific event 1
74 #define SERIAL_EV_EVENT2 0x1000 // Provider specific event 2
75
76 #ifndef CRTSCTS
77 #define CRTSCTS 0
78 #endif
79
80
81 extern RDPDR_DEVICE g_rdpdr_device[];
82
83 static SERIAL_DEVICE *
84 get_serial_info(HANDLE handle)
85 {
86 int index;
87
88 for (index = 0; index < RDPDR_MAX_DEVICES; index++)
89 {
90 if (handle == g_rdpdr_device[index].handle)
91 return (SERIAL_DEVICE *) g_rdpdr_device[index].pdevice_data;
92 }
93 return NULL;
94 }
95
96 static BOOL
97 get_termios(SERIAL_DEVICE * pser_inf, HANDLE serial_fd)
98 {
99 speed_t speed;
100 struct termios *ptermios;
101
102 ptermios = pser_inf->ptermios;
103
104 if (tcgetattr(serial_fd, ptermios) == -1)
105 return False;
106
107 speed = cfgetispeed(ptermios);
108 switch (speed)
109 {
110 #ifdef B75
111 case B75:
112 pser_inf->baud_rate = 75;
113 break;
114 #endif
115 #ifdef B110
116 case B110:
117 pser_inf->baud_rate = 110;
118 break;
119 #endif
120 #ifdef B134
121 case B134:
122 pser_inf->baud_rate = 134;
123 break;
124 #endif
125 #ifdef B150
126 case B150:
127 pser_inf->baud_rate = 150;
128 break;
129 #endif
130 #ifdef B300
131 case B300:
132 pser_inf->baud_rate = 300;
133 break;
134 #endif
135 #ifdef B600
136 case B600:
137 pser_inf->baud_rate = 600;
138 break;
139 #endif
140 #ifdef B1200
141 case B1200:
142 pser_inf->baud_rate = 1200;
143 break;
144 #endif
145 #ifdef B1800
146 case B1800:
147 pser_inf->baud_rate = 1800;
148 break;
149 #endif
150 #ifdef B2400
151 case B2400:
152 pser_inf->baud_rate = 2400;
153 break;
154 #endif
155 #ifdef B4800
156 case B4800:
157 pser_inf->baud_rate = 4800;
158 break;
159 #endif
160 #ifdef B9600
161 case B9600:
162 pser_inf->baud_rate = 9600;
163 break;
164 #endif
165 #ifdef B19200
166 case B19200:
167 pser_inf->baud_rate = 19200;
168 break;
169 #endif
170 #ifdef B38400
171 case B38400:
172 pser_inf->baud_rate = 38400;
173 break;
174 #endif
175 #ifdef B57600
176 case B57600:
177 pser_inf->baud_rate = 57600;
178 break;
179 #endif
180 #ifdef B115200
181 case B115200:
182 pser_inf->baud_rate = 115200;
183 break;
184 #endif
185 default:
186 pser_inf->baud_rate = 0;
187 break;
188 }
189
190 speed = cfgetospeed(ptermios);
191 pser_inf->dtr = (speed == B0) ? 0 : 1;
192
193 pser_inf->stop_bits = (ptermios->c_cflag & CSTOPB) ? STOP_BITS_2 : STOP_BITS_1;
194 pser_inf->parity =
195 (ptermios->
196 c_cflag & PARENB) ? ((ptermios->
197 c_cflag & PARODD) ? ODD_PARITY : EVEN_PARITY) : NO_PARITY;
198 switch (ptermios->c_cflag & CSIZE)
199 {
200 case CS5:
201 pser_inf->word_length = 5;
202 break;
203 case CS6:
204 pser_inf->word_length = 6;
205 break;
206 case CS7:
207 pser_inf->word_length = 7;
208 break;
209 default:
210 pser_inf->word_length = 8;
211 break;
212 }
213
214 pser_inf->rts = (ptermios->c_cflag & CRTSCTS) ? 1 : 0;
215
216 return True;
217 }
218
219 static void
220 set_termios(SERIAL_DEVICE * pser_inf, HANDLE serial_fd)
221 {
222 speed_t speed;
223
224 struct termios *ptermios;
225
226 ptermios = pser_inf->ptermios;
227
228
229 switch (pser_inf->baud_rate)
230 {
231 #ifdef B75
232 case 75:
233 speed = B75;
234 break;
235 #endif
236 #ifdef B110
237 case 110:
238 speed = B110;
239 break;
240 #endif
241 #ifdef B134
242 case 134:
243 speed = B134;
244 break;
245 #endif
246 #ifdef B150
247 case 150:
248 speed = B150;
249 break;
250 #endif
251 #ifdef B300
252 case 300:
253 speed = B300;
254 break;
255 #endif
256 #ifdef B600
257 case 600:
258 speed = B600;
259 break;
260 #endif
261 #ifdef B1200
262 case 1200:
263 speed = B1200;
264 break;
265 #endif
266 #ifdef B1800
267 case 1800:
268 speed = B1800;
269 break;
270 #endif
271 #ifdef B2400
272 case 2400:
273 speed = B2400;
274 break;
275 #endif
276 #ifdef B4800
277 case 4800:
278 speed = B4800;
279 break;
280 #endif
281 #ifdef B9600
282 case 9600:
283 speed = B9600;
284 break;
285 #endif
286 #ifdef B19200
287 case 19200:
288 speed = B19200;
289 break;
290 #endif
291 #ifdef B38400
292 case 38400:
293 speed = B38400;
294 break;
295 #endif
296 #ifdef B57600
297 case 57600:
298 speed = B57600;
299 break;
300 #endif
301 #ifdef B115200
302 case 115200:
303 speed = B115200;
304 break;
305 #endif
306 default:
307 speed = B0;
308 break;
309 }
310
311 /* on systems with separate ispeed and ospeed, we can remember the speed
312 in ispeed while changing DTR with ospeed */
313 cfsetispeed(pser_inf->ptermios, speed);
314 cfsetospeed(pser_inf->ptermios, pser_inf->dtr ? speed : 0);
315
316 ptermios->c_cflag &= ~(CSTOPB | PARENB | PARODD | CSIZE | CRTSCTS);
317 switch (pser_inf->stop_bits)
318 {
319 case STOP_BITS_2:
320 ptermios->c_cflag |= CSTOPB;
321 break;
322 }
323
324 switch (pser_inf->parity)
325 {
326 case EVEN_PARITY:
327 ptermios->c_cflag |= PARENB;
328 break;
329 case ODD_PARITY:
330 ptermios->c_cflag |= PARENB | PARODD;
331 break;
332 }
333
334 switch (pser_inf->word_length)
335 {
336 case 5:
337 ptermios->c_cflag |= CS5;
338 break;
339 case 6:
340 ptermios->c_cflag |= CS6;
341 break;
342 case 7:
343 ptermios->c_cflag |= CS7;
344 break;
345 default:
346 ptermios->c_cflag |= CS8;
347 break;
348 }
349
350 if (pser_inf->rts)
351 ptermios->c_cflag |= CRTSCTS;
352
353 tcsetattr(serial_fd, TCSANOW, ptermios);
354 }
355
356 /* Enumeration of devices from rdesktop.c */
357 /* returns numer of units found and initialized. */
358 /* optarg looks like ':com1=/dev/ttyS0' */
359 /* when it arrives to this function. */
360 /* :com1=/dev/ttyS0,com2=/dev/ttyS1 */
361 int
362 serial_enum_devices(uint32 * id, char *optarg)
363 {
364 SERIAL_DEVICE *pser_inf;
365
366 char *pos = optarg;
367 char *pos2;
368 int count = 0;
369
370 // skip the first colon
371 optarg++;
372 while ((pos = next_arg(optarg, ',')) && *id < RDPDR_MAX_DEVICES)
373 {
374 // Init data structures for device
375 pser_inf = (SERIAL_DEVICE *) xmalloc(sizeof(SERIAL_DEVICE));
376 pser_inf->ptermios = (struct termios *) xmalloc(sizeof(struct termios));
377 pser_inf->pold_termios = (struct termios *) xmalloc(sizeof(struct termios));
378
379 pos2 = next_arg(optarg, '=');
380 strcpy(g_rdpdr_device[*id].name, optarg);
381
382 toupper_str(g_rdpdr_device[*id].name);
383
384 g_rdpdr_device[*id].local_path = xmalloc(strlen(pos2) + 1);
385 strcpy(g_rdpdr_device[*id].local_path, pos2);
386 printf("SERIAL %s to %s\n", g_rdpdr_device[*id].name,
387 g_rdpdr_device[*id].local_path);
388 // set device type
389 g_rdpdr_device[*id].device_type = DEVICE_TYPE_SERIAL;
390 g_rdpdr_device[*id].pdevice_data = (void *) pser_inf;
391 count++;
392 (*id)++;
393
394 optarg = pos;
395 }
396 return count;
397 }
398
399 static NTSTATUS
400 serial_create(uint32 device_id, uint32 access, uint32 share_mode, uint32 disposition,
401 uint32 flags_and_attributes, char *filename, HANDLE * handle)
402 {
403 HANDLE serial_fd;
404 SERIAL_DEVICE *pser_inf;
405 struct termios *ptermios;
406
407 pser_inf = (SERIAL_DEVICE *) g_rdpdr_device[device_id].pdevice_data;
408 ptermios = pser_inf->ptermios;
409 serial_fd = open(g_rdpdr_device[device_id].local_path, O_RDWR | O_NOCTTY);
410
411 if (serial_fd == -1)
412 {
413 perror("open");
414 return STATUS_ACCESS_DENIED;
415 }
416
417 if (!get_termios(pser_inf, serial_fd))
418 {
419 printf("INFO: SERIAL %s access denied\n", g_rdpdr_device[device_id].name);
420 fflush(stdout);
421 return STATUS_ACCESS_DENIED;
422 }
423
424 // Store handle for later use
425 g_rdpdr_device[device_id].handle = serial_fd;
426
427 /* some sane information */
428 printf("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);
429
430 printf("INFO: use stty to change settings\n");
431
432 /* ptermios->c_cflag = B115200 | CRTSCTS | CS8 | CLOCAL | CREAD;
433 ptermios->c_cflag |= CREAD;
434 ptermios->c_lflag |= ICANON;
435 ptermios->c_iflag = IGNPAR | ICRNL;
436
437 tcsetattr(serial_fd, TCSANOW, ptermios);
438 */
439
440 *handle = serial_fd;
441
442 /* all read and writes should be non blocking */
443 if (fcntl(*handle, F_SETFL, O_NONBLOCK) == -1)
444 perror("fcntl");
445
446 return STATUS_SUCCESS;
447 }
448
449 static NTSTATUS
450 serial_close(HANDLE handle)
451 {
452 int i = get_device_index(handle);
453 if (i >= 0)
454 g_rdpdr_device[i].handle = 0;
455 close(handle);
456 return STATUS_SUCCESS;
457 }
458
459 static NTSTATUS
460 serial_read(HANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
461 {
462 long timeout;
463 SERIAL_DEVICE *pser_inf;
464 struct termios *ptermios;
465
466 timeout = 90;
467 pser_inf = get_serial_info(handle);
468 ptermios = pser_inf->ptermios;
469
470 // Set timeouts kind of like the windows serial timeout parameters. Multiply timeout
471 // with requested read size
472 if (pser_inf->read_total_timeout_multiplier | pser_inf->read_total_timeout_constant)
473 {
474 timeout =
475 (pser_inf->read_total_timeout_multiplier * length +
476 pser_inf->read_total_timeout_constant + 99) / 100;
477 }
478 else if (pser_inf->read_interval_timeout)
479 {
480 timeout = (pser_inf->read_interval_timeout * length + 99) / 100;
481 }
482
483 // If a timeout is set, do a blocking read, which times out after some time.
484 // It will make rdesktop less responsive, but it will improve serial performance, by not
485 // reading one character at a time.
486 if (timeout == 0)
487 {
488 ptermios->c_cc[VTIME] = 0;
489 ptermios->c_cc[VMIN] = 0;
490 }
491 else
492 {
493 ptermios->c_cc[VTIME] = timeout;
494 ptermios->c_cc[VMIN] = 1;
495 }
496 tcsetattr(handle, TCSANOW, ptermios);
497
498
499 *result = read(handle, data, length);
500
501 //hexdump(data, *read);
502
503 return STATUS_SUCCESS;
504 }
505
506 static NTSTATUS
507 serial_write(HANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
508 {
509 *result = write(handle, data, length);
510 return STATUS_SUCCESS;
511 }
512
513 static NTSTATUS
514 serial_device_control(HANDLE handle, uint32 request, STREAM in, STREAM out)
515 {
516 #if 0
517 int flush_mask, purge_mask;
518 #endif
519 uint32 result;
520 uint8 immediate;
521 SERIAL_DEVICE *pser_inf;
522 struct termios *ptermios;
523
524 if ((request >> 16) != FILE_DEVICE_SERIAL_PORT)
525 return STATUS_INVALID_PARAMETER;
526
527 pser_inf = get_serial_info(handle);
528 ptermios = pser_inf->ptermios;
529
530 /* extract operation */
531 request >>= 2;
532 request &= 0xfff;
533
534 printf("SERIAL IOCTL %d\n", request);
535
536 switch (request)
537 {
538 case SERIAL_SET_BAUD_RATE:
539 in_uint32_le(in, pser_inf->baud_rate);
540 set_termios(pser_inf, handle);
541 break;
542 case SERIAL_GET_BAUD_RATE:
543 out_uint32_le(out, pser_inf->baud_rate);
544 break;
545 case SERIAL_SET_QUEUE_SIZE:
546 in_uint32_le(in, pser_inf->queue_in_size);
547 in_uint32_le(in, pser_inf->queue_out_size);
548 break;
549 case SERIAL_SET_LINE_CONTROL:
550 in_uint8(in, pser_inf->stop_bits);
551 in_uint8(in, pser_inf->parity);
552 in_uint8(in, pser_inf->word_length);
553 set_termios(pser_inf, handle);
554 break;
555 case SERIAL_GET_LINE_CONTROL:
556 out_uint8(out, pser_inf->stop_bits);
557 out_uint8(out, pser_inf->parity);
558 out_uint8(out, pser_inf->word_length);
559 break;
560 case SERIAL_IMMEDIATE_CHAR:
561 in_uint8(in, immediate);
562 serial_write(handle, &immediate, 1, 0, &result);
563 break;
564 case SERIAL_CONFIG_SIZE:
565 out_uint32_le(out, 0);
566 break;
567 case SERIAL_GET_CHARS:
568 out_uint8s(out, 6);
569 break;
570 case SERIAL_SET_CHARS:
571 in_uint8s(in, 6);
572 break;
573 case SERIAL_GET_HANDFLOW:
574 out_uint32_le(out, 0);
575 out_uint32_le(out, 3); /* Xon/Xoff */
576 out_uint32_le(out, 0);
577 out_uint32_le(out, 0);
578 break;
579 case SERIAL_SET_HANDFLOW:
580 in_uint8s(in, 16);
581 break;
582 case SERIAL_SET_TIMEOUTS:
583 in_uint8s(in, 20);
584 break;
585 case SERIAL_GET_TIMEOUTS:
586 out_uint8s(out, 20);
587 break;
588 case SERIAL_GET_WAIT_MASK:
589 out_uint32(out, pser_inf->wait_mask);
590 break;
591 case SERIAL_SET_WAIT_MASK:
592 in_uint32(in, pser_inf->wait_mask);
593 break;
594 case SERIAL_SET_DTR:
595 pser_inf->dtr = 1;
596 set_termios(pser_inf, handle);
597 break;
598 case SERIAL_CLR_DTR:
599 pser_inf->dtr = 0;
600 set_termios(pser_inf, handle);
601 break;
602 case SERIAL_SET_RTS:
603 pser_inf->rts = 1;
604 set_termios(pser_inf, handle);
605 break;
606 case SERIAL_CLR_RTS:
607 pser_inf->rts = 0;
608 set_termios(pser_inf, handle);
609 break;
610 case SERIAL_GET_MODEMSTATUS:
611 out_uint32_le(out, 0); /* Errors */
612 break;
613 case SERIAL_GET_COMMSTATUS:
614 out_uint32_le(out, 0); /* Errors */
615 out_uint32_le(out, 0); /* Hold reasons */
616 out_uint32_le(out, 0); /* Amount in in queue */
617 out_uint32_le(out, 0); /* Amount in out queue */
618 out_uint8(out, 0); /* EofReceived */
619 out_uint8(out, 0); /* WaitForImmediate */
620 break;
621 #if 0
622 case SERIAL_PURGE:
623 printf("SERIAL_PURGE\n");
624 in_uint32(in, purge_mask);
625 if (purge_mask & 0x04)
626 flush_mask |= TCOFLUSH;
627 if (purge_mask & 0x08)
628 flush_mask |= TCIFLUSH;
629 if (flush_mask != 0)
630 tcflush(handle, flush_mask);
631 if (purge_mask & 0x01)
632 rdpdr_abort_io(handle, 4, STATUS_CANCELLED);
633 if (purge_mask & 0x02)
634 rdpdr_abort_io(handle, 3, STATUS_CANCELLED);
635 break;
636 case SERIAL_WAIT_ON_MASK:
637 /* XXX implement me */
638 out_uint32_le(out, pser_inf->wait_mask);
639 break;
640 case SERIAL_SET_BREAK_ON:
641 tcsendbreak(serial_fd, 0);
642 break;
643 case SERIAL_RESET_DEVICE:
644 case SERIAL_SET_BREAK_OFF:
645 case SERIAL_SET_XOFF:
646 case SERIAL_SET_XON:
647 /* ignore */
648 break;
649 #endif
650 default:
651 unimpl("SERIAL IOCTL %d\n", request);
652 return STATUS_INVALID_PARAMETER;
653 }
654
655 return STATUS_SUCCESS;
656 }
657
658 /* Read timeout for a given file descripter (device) when adding fd's to select() */
659 BOOL
660 serial_get_timeout(HANDLE handle, uint32 length, uint32 * timeout, uint32 * itv_timeout)
661 {
662 int index;
663 SERIAL_DEVICE *pser_inf;
664
665 index = get_device_index(handle);
666 if (index < 0)
667 return True;
668
669 if (g_rdpdr_device[index].device_type != DEVICE_TYPE_SERIAL)
670 {
671 return False;
672 }
673
674 pser_inf = (SERIAL_DEVICE *) g_rdpdr_device[index].pdevice_data;
675
676 *timeout =
677 pser_inf->read_total_timeout_multiplier * length +
678 pser_inf->read_total_timeout_constant;
679 *itv_timeout = pser_inf->read_interval_timeout;
680 return True;
681 }
682
683 DEVICE_FNS serial_fns = {
684 serial_create,
685 serial_close,
686 serial_read,
687 serial_write,
688 serial_device_control
689 };

  ViewVC Help
Powered by ViewVC 1.1.26