/[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 588 - (show annotations)
Thu Jan 29 11:47:14 2004 UTC (20 years, 4 months ago) by n-ki
File MIME type: text/plain
File size: 13395 byte(s)
remove global vars.  and put aio within ifdef

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 *handle = serial_fd;
403 return STATUS_SUCCESS;
404 }
405
406 static NTSTATUS
407 serial_close(HANDLE handle)
408 {
409 g_rdpdr_device[get_device_index(handle)].handle = 0;
410 close(handle);
411 return STATUS_SUCCESS;
412 }
413
414 NTSTATUS
415 serial_read(HANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
416 {
417 long timeout;
418 SERIAL_DEVICE *pser_inf;
419 struct termios *ptermios;
420
421 // timeout = 90;
422 pser_inf = get_serial_info(handle);
423 ptermios = pser_inf->ptermios;
424
425 #if 0
426 // Set timeouts kind of like the windows serial timeout parameters. Multiply timeout
427 // with requested read size
428 if (pser_inf->read_total_timeout_multiplier | pser_inf->read_total_timeout_constant)
429 {
430 timeout =
431 (pser_inf->read_total_timeout_multiplier * length +
432 pser_inf->read_total_timeout_constant + 99) / 100;
433 }
434 else if (pser_inf->read_interval_timeout)
435 {
436 timeout = (pser_inf->read_interval_timeout * length + 99) / 100;
437 }
438
439 // If a timeout is set, do a blocking read, which times out after some time.
440 // It will make rdesktop less responsive, but it will improve serial performance, by not
441 // reading one character at a time.
442 if (timeout == 0)
443 {
444 ptermios->c_cc[VTIME] = 0;
445 ptermios->c_cc[VMIN] = 0;
446 }
447 else
448 {
449 ptermios->c_cc[VTIME] = timeout;
450 ptermios->c_cc[VMIN] = 1;
451 }
452 tcsetattr(handle, TCSANOW, ptermios);
453 #endif
454 *result = read(handle, data, length);
455 return STATUS_SUCCESS;
456 }
457
458 NTSTATUS
459 serial_write(HANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
460 {
461 *result = write(handle, data, length);
462 return STATUS_SUCCESS;
463 }
464
465 static NTSTATUS
466 serial_device_control(HANDLE handle, uint32 request, STREAM in, STREAM out)
467 {
468 uint32 result;
469 uint8 immediate;
470 SERIAL_DEVICE *pser_inf;
471 struct termios *ptermios;
472
473 if ((request >> 16) != FILE_DEVICE_SERIAL_PORT)
474 return STATUS_INVALID_PARAMETER;
475
476 pser_inf = get_serial_info(handle);
477 ptermios = pser_inf->ptermios;
478
479 /* extract operation */
480 request >>= 2;
481 request &= 0xfff;
482
483 printf("SERIAL IOCTL %d\n", request);
484
485 switch (request)
486 {
487 case SERIAL_SET_BAUD_RATE:
488 in_uint32_le(in, pser_inf->baud_rate);
489 set_termios(pser_inf, handle);
490 break;
491 case SERIAL_GET_BAUD_RATE:
492 out_uint32_le(out, pser_inf->baud_rate);
493 break;
494 case SERIAL_SET_QUEUE_SIZE:
495 in_uint32_le(in, pser_inf->queue_in_size);
496 in_uint32_le(in, pser_inf->queue_out_size);
497 break;
498 case SERIAL_SET_LINE_CONTROL:
499 in_uint8(in, pser_inf->stop_bits);
500 in_uint8(in, pser_inf->parity);
501 in_uint8(in, pser_inf->word_length);
502 set_termios(pser_inf, handle);
503 break;
504 case SERIAL_GET_LINE_CONTROL:
505 out_uint8(out, pser_inf->stop_bits);
506 out_uint8(out, pser_inf->parity);
507 out_uint8(out, pser_inf->word_length);
508 break;
509 case SERIAL_IMMEDIATE_CHAR:
510 in_uint8(in, immediate);
511 serial_write(handle, &immediate, 1, 0, &result);
512 break;
513 case SERIAL_CONFIG_SIZE:
514 out_uint32_le(out, 0);
515 break;
516 case SERIAL_GET_CHARS:
517 out_uint8s(out, 6);
518 break;
519 case SERIAL_SET_CHARS:
520 in_uint8s(in, 6);
521 break;
522 case SERIAL_GET_HANDFLOW:
523 out_uint32_le(out, 0);
524 out_uint32_le(out, 3); /* Xon/Xoff */
525 out_uint32_le(out, 0);
526 out_uint32_le(out, 0);
527 break;
528 case SERIAL_SET_HANDFLOW:
529 in_uint8s(in, 16);
530 break;
531 case SERIAL_SET_TIMEOUTS:
532 in_uint8s(in, 20);
533 break;
534 case SERIAL_GET_TIMEOUTS:
535 out_uint8s(out, 20);
536 break;
537 case SERIAL_GET_WAIT_MASK:
538 out_uint32(out, pser_inf->wait_mask);
539 break;
540 case SERIAL_SET_WAIT_MASK:
541 in_uint32(in, pser_inf->wait_mask);
542 break;
543 case SERIAL_SET_DTR:
544 pser_inf->dtr = 1;
545 set_termios(pser_inf, handle);
546 break;
547 case SERIAL_CLR_DTR:
548 pser_inf->dtr = 0;
549 set_termios(pser_inf, handle);
550 break;
551 #if 0
552 case SERIAL_WAIT_ON_MASK:
553 /* XXX implement me */
554 break;
555 case SERIAL_SET_BREAK_ON:
556 tcsendbreak(serial_fd, 0);
557 break;
558 case SERIAL_PURGE:
559
560 printf("SERIAL_PURGE\n");
561 in_uint32(in, purge_mask);
562 if (purge_mask & 0x04)
563 flush_mask |= TCOFLUSH;
564 if (purge_mask & 0x08)
565 flush_mask |= TCIFLUSH;
566 if (flush_mask != 0)
567 tcflush(handle, flush_mask);
568 if (purge_mask & 0x01)
569 rdpdr_abort_io(handle, 4, STATUS_CANCELLED);
570 if (purge_mask & 0x02)
571 rdpdr_abort_io(handle, 3, STATUS_CANCELLED);
572 break;
573
574 case SERIAL_RESET_DEVICE:
575 case SERIAL_SET_BREAK_OFF:
576 case SERIAL_SET_RTS:
577 case SERIAL_CLR_RTS:
578 case SERIAL_SET_XOFF:
579 case SERIAL_SET_XON:
580 /* ignore */
581 break;
582 #endif
583
584 default:
585 unimpl("SERIAL IOCTL %d\n", request);
586 return STATUS_INVALID_PARAMETER;
587 }
588
589 return STATUS_SUCCESS;
590 }
591
592 /* Read timeout for a given file descripter (device) when adding fd's to select() */
593 BOOL
594 serial_get_timeout(HANDLE handle, uint32 length, uint32 * timeout, uint32 * itv_timeout)
595 {
596 int index;
597 SERIAL_DEVICE *pser_inf;
598
599 index = get_device_index(handle);
600
601 if (g_rdpdr_device[index].device_type != DEVICE_TYPE_SERIAL)
602 {
603 return False;
604 }
605
606 pser_inf = (SERIAL_DEVICE *) g_rdpdr_device[index].pdevice_data;
607
608 *timeout =
609 pser_inf->read_total_timeout_multiplier * length +
610 pser_inf->read_total_timeout_constant;
611 *itv_timeout = pser_inf->read_interval_timeout;
612 return True;
613 }
614
615 DEVICE_FNS serial_fns = {
616 serial_create,
617 serial_close,
618 serial_read,
619 serial_write,
620 serial_device_control
621 };

  ViewVC Help
Powered by ViewVC 1.1.26