/[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 592 - (show annotations)
Fri Jan 30 14:10:32 2004 UTC (20 years, 4 months ago) by n-ki
File MIME type: text/plain
File size: 13498 byte(s)
reworked the asyncio some and completed it. parallel and serial uses it now. disk.c is a likely candidate for the future, but there are some problems with disk.c that we will have to look into first. parallel and serial works better, they do not hang the session, but are still yerky at large chunks... possibly we could split the chunks, but the terminal server does not seem to like partial transfers, i've tried some variations.. :) fns->write() could be split in smaller pieces, but what should the thresholds be.

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

  ViewVC Help
Powered by ViewVC 1.1.26