/[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 580 - (show annotations)
Fri Jan 23 08:35:52 2004 UTC (20 years, 4 months ago) by astrand
Original Path: sourceforge.net/trunk/rdesktop/serial.c
File MIME type: text/plain
File size: 12788 byte(s)
Ran indent-all.sh

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

  ViewVC Help
Powered by ViewVC 1.1.26