/[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 602 - (show annotations)
Sat Feb 7 17:32:21 2004 UTC (20 years, 2 months ago) by stargo
File MIME type: text/plain
File size: 13501 byte(s)
Cleanup some warnings (from SUNWspro-compiler)

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(uint32 *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