/[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

Annotation of /jpeg/rdesktop/trunk/serial.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 588 - (hide annotations)
Thu Jan 29 11:47:14 2004 UTC (20 years, 3 months ago) by n-ki
Original Path: sourceforge.net/trunk/rdesktop/serial.c
File MIME type: text/plain
File size: 13395 byte(s)
remove global vars.  and put aio within ifdef

1 matthewc 432 #include <unistd.h>
2     #include <fcntl.h>
3     #include <termios.h>
4 stargo 570 #include <strings.h>
5 matthewc 432 #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 astrand 580 extern RDPDR_DEVICE g_rdpdr_device[];
57 n-ki 569
58 n-ki 588 SERIAL_DEVICE *
59     get_serial_info(HANDLE handle)
60 matthewc 432 {
61 astrand 580 int index;
62 matthewc 432
63 astrand 580 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 n-ki 569 }
70 matthewc 432
71 n-ki 569 BOOL
72 astrand 580 get_termios(SERIAL_DEVICE * pser_inf, HANDLE serial_fd)
73 n-ki 569 {
74 astrand 580 speed_t speed;
75     struct termios *ptermios;
76 n-ki 569
77 astrand 580 ptermios = pser_inf->ptermios;
78 n-ki 569
79 astrand 580 if (tcgetattr(serial_fd, ptermios) == -1)
80     return False;
81 n-ki 569
82 astrand 580 speed = cfgetispeed(ptermios);
83     switch (speed)
84     {
85 stargo 545 #ifdef B75
86 astrand 580 case B75:
87     pser_inf->baud_rate = 75;
88     break;
89 stargo 545 #endif
90     #ifdef B110
91 astrand 580 case B110:
92     pser_inf->baud_rate = 110;
93     break;
94 stargo 545 #endif
95     #ifdef B134
96 astrand 580 case B134:
97     pser_inf->baud_rate = 134;
98     break;
99 stargo 545 #endif
100     #ifdef B150
101 astrand 580 case B150:
102     pser_inf->baud_rate = 150;
103     break;
104 stargo 545 #endif
105     #ifdef B300
106 astrand 580 case B300:
107     pser_inf->baud_rate = 300;
108     break;
109 stargo 545 #endif
110     #ifdef B600
111 astrand 580 case B600:
112     pser_inf->baud_rate = 600;
113     break;
114 stargo 545 #endif
115     #ifdef B1200
116 astrand 580 case B1200:
117     pser_inf->baud_rate = 1200;
118     break;
119 stargo 545 #endif
120     #ifdef B1800
121 astrand 580 case B1800:
122     pser_inf->baud_rate = 1800;
123     break;
124 stargo 545 #endif
125     #ifdef B2400
126 astrand 580 case B2400:
127     pser_inf->baud_rate = 2400;
128     break;
129 stargo 545 #endif
130     #ifdef B4800
131 astrand 580 case B4800:
132     pser_inf->baud_rate = 4800;
133     break;
134 stargo 545 #endif
135     #ifdef B9600
136 astrand 580 case B9600:
137     pser_inf->baud_rate = 9600;
138     break;
139 stargo 545 #endif
140     #ifdef B19200
141 astrand 580 case B19200:
142     pser_inf->baud_rate = 19200;
143     break;
144 stargo 545 #endif
145     #ifdef B38400
146 astrand 580 case B38400:
147     pser_inf->baud_rate = 38400;
148     break;
149 stargo 545 #endif
150     #ifdef B57600
151 astrand 580 case B57600:
152     pser_inf->baud_rate = 57600;
153     break;
154 stargo 545 #endif
155     #ifdef B115200
156 astrand 580 case B115200:
157     pser_inf->baud_rate = 115200;
158     break;
159 stargo 545 #endif
160 astrand 580 default:
161     pser_inf->baud_rate = 0;
162     break;
163     }
164 matthewc 432
165 astrand 580 speed = cfgetospeed(ptermios);
166     pser_inf->dtr = (speed == B0) ? 0 : 1;
167 matthewc 432
168 astrand 580 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 matthewc 432
189 astrand 580 return True;
190 matthewc 432 }
191    
192     static void
193 n-ki 588 set_termios(SERIAL_DEVICE * pser_inf, HANDLE serial_fd)
194 matthewc 432 {
195     speed_t speed;
196    
197 n-ki 588 struct termios *ptermios;
198    
199     ptermios = pser_inf->ptermios;
200    
201    
202     switch (pser_inf->baud_rate)
203 matthewc 432 {
204 stargo 545 #ifdef B75
205 astrand 580 case 75:
206     speed = B75;
207     break;
208 stargo 545 #endif
209     #ifdef B110
210 astrand 580 case 110:
211     speed = B110;
212     break;
213 stargo 545 #endif
214     #ifdef B134
215 astrand 580 case 134:
216     speed = B134;
217     break;
218 stargo 545 #endif
219     #ifdef B150
220 astrand 580 case 150:
221     speed = B150;
222     break;
223 stargo 545 #endif
224     #ifdef B300
225 astrand 580 case 300:
226     speed = B300;
227     break;
228 stargo 545 #endif
229     #ifdef B600
230 astrand 580 case 600:
231     speed = B600;
232     break;
233 stargo 545 #endif
234     #ifdef B1200
235 astrand 580 case 1200:
236     speed = B1200;
237     break;
238 stargo 545 #endif
239     #ifdef B1800
240 astrand 580 case 1800:
241     speed = B1800;
242     break;
243 stargo 545 #endif
244     #ifdef B2400
245 astrand 580 case 2400:
246     speed = B2400;
247     break;
248 stargo 545 #endif
249     #ifdef B4800
250 astrand 580 case 4800:
251     speed = B4800;
252     break;
253 stargo 545 #endif
254     #ifdef B9600
255 astrand 580 case 9600:
256     speed = B9600;
257     break;
258 stargo 545 #endif
259     #ifdef B19200
260 astrand 580 case 19200:
261     speed = B19200;
262     break;
263 stargo 545 #endif
264     #ifdef B38400
265 astrand 580 case 38400:
266     speed = B38400;
267     break;
268 stargo 545 #endif
269     #ifdef B57600
270 astrand 580 case 57600:
271     speed = B57600;
272     break;
273 stargo 545 #endif
274     #ifdef B115200
275 astrand 580 case 115200:
276     speed = B115200;
277     break;
278 stargo 545 #endif
279 astrand 580 default:
280     speed = B0;
281     break;
282 matthewc 432 }
283    
284     /* on systems with separate ispeed and ospeed, we can remember the speed
285     in ispeed while changing DTR with ospeed */
286 n-ki 588 cfsetispeed(pser_inf->ptermios, speed);
287     cfsetospeed(pser_inf->ptermios, pser_inf->dtr ? speed : 0);
288 matthewc 432
289 n-ki 588 ptermios->c_cflag &= ~(CSTOPB | PARENB | PARODD | CSIZE);
290     switch (pser_inf->stop_bits)
291 matthewc 432 {
292     case STOP_BITS_2:
293 n-ki 588 ptermios->c_cflag |= CSTOPB;
294 matthewc 432 break;
295     }
296 n-ki 588 switch (pser_inf->parity)
297 matthewc 432 {
298     case EVEN_PARITY:
299 n-ki 588 ptermios->c_cflag |= PARENB;
300 matthewc 432 break;
301     case ODD_PARITY:
302 n-ki 588 ptermios->c_cflag |= PARENB | PARODD;
303 matthewc 432 break;
304     }
305 n-ki 588 switch (pser_inf->word_length)
306 matthewc 432 {
307 astrand 435 case 5:
308 n-ki 588 ptermios->c_cflag |= CS5;
309 astrand 435 break;
310     case 6:
311 n-ki 588 ptermios->c_cflag |= CS6;
312 astrand 435 break;
313     case 7:
314 n-ki 588 ptermios->c_cflag |= CS7;
315 astrand 435 break;
316     default:
317 n-ki 588 ptermios->c_cflag |= CS8;
318 astrand 435 break;
319 matthewc 432 }
320    
321 n-ki 588 tcsetattr(serial_fd, TCSANOW, ptermios);
322 matthewc 432 }
323    
324 n-ki 569 /* 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 n-ki 578 /* :com1=/dev/ttyS0,com2=/dev/ttyS1 */
329 n-ki 569 int
330 astrand 580 serial_enum_devices(int *id, char *optarg)
331 matthewc 432 {
332 astrand 580 SERIAL_DEVICE *pser_inf;
333 matthewc 432
334 n-ki 578 char *pos = optarg;
335     char *pos2;
336     int count = 0;
337 matthewc 432
338 n-ki 578 // skip the first colon
339     optarg++;
340     while ((pos = next_arg(optarg, ',')) && *id < RDPDR_MAX_DEVICES)
341     {
342 n-ki 569 // 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 n-ki 578 pos2 = next_arg(optarg, '=');
348     strcpy(g_rdpdr_device[*id].name, optarg);
349 n-ki 569
350 n-ki 578 toupper_str(g_rdpdr_device[*id].name);
351 n-ki 569
352 n-ki 578 g_rdpdr_device[*id].local_path = xmalloc(strlen(pos2) + 1);
353     strcpy(g_rdpdr_device[*id].local_path, pos2);
354 astrand 580 printf("SERIAL %s to %s\n", g_rdpdr_device[*id].name,
355     g_rdpdr_device[*id].local_path);
356 n-ki 569 // set device type
357     g_rdpdr_device[*id].device_type = DEVICE_TYPE_SERIAL;
358     g_rdpdr_device[*id].pdevice_data = (void *) pser_inf;
359 n-ki 578 count++;
360 n-ki 569 (*id)++;
361    
362 n-ki 578 optarg = pos;
363 n-ki 569 }
364 n-ki 578 return count;
365 matthewc 432 }
366    
367 n-ki 569 NTSTATUS
368 astrand 580 serial_create(uint32 device_id, uint32 access, uint32 share_mode, uint32 disposition,
369     uint32 flags_and_attributes, char *filename, HANDLE * handle)
370 n-ki 569 {
371 astrand 580 HANDLE serial_fd;
372     SERIAL_DEVICE *pser_inf;
373     struct termios *ptermios;
374 n-ki 569
375 astrand 580 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 n-ki 569
379 astrand 580 if (serial_fd == -1)
380 n-ki 588 {
381     perror("open");
382 astrand 580 return STATUS_ACCESS_DENIED;
383 n-ki 588 }
384 n-ki 569
385 astrand 580 if (!get_termios(pser_inf, serial_fd))
386     return STATUS_ACCESS_DENIED;
387 n-ki 569
388 n-ki 578 // Store handle for later use
389 astrand 580 g_rdpdr_device[device_id].handle = serial_fd;
390 n-ki 569
391 n-ki 578 /* some sane information */
392 astrand 580 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 n-ki 569
395 n-ki 588 /* 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 n-ki 569
400 n-ki 588 tcsetattr(serial_fd, TCSANOW, ptermios);
401     */
402 astrand 580 *handle = serial_fd;
403     return STATUS_SUCCESS;
404 n-ki 569 }
405    
406 matthewc 432 static NTSTATUS
407     serial_close(HANDLE handle)
408     {
409 n-ki 588 g_rdpdr_device[get_device_index(handle)].handle = 0;
410     close(handle);
411 matthewc 432 return STATUS_SUCCESS;
412     }
413    
414 n-ki 569 NTSTATUS
415 astrand 580 serial_read(HANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
416 matthewc 432 {
417 astrand 580 long timeout;
418     SERIAL_DEVICE *pser_inf;
419     struct termios *ptermios;
420 n-ki 569
421 n-ki 588 // timeout = 90;
422 astrand 580 pser_inf = get_serial_info(handle);
423     ptermios = pser_inf->ptermios;
424 n-ki 569
425 n-ki 588 #if 0
426 astrand 580 // 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 n-ki 569
439 astrand 580 // 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 n-ki 588 #endif
454 astrand 580 *result = read(handle, data, length);
455     return STATUS_SUCCESS;
456 matthewc 432 }
457    
458 n-ki 569 NTSTATUS
459 astrand 580 serial_write(HANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
460 matthewc 432 {
461 astrand 580 *result = write(handle, data, length);
462     return STATUS_SUCCESS;
463 matthewc 432 }
464    
465     static NTSTATUS
466     serial_device_control(HANDLE handle, uint32 request, STREAM in, STREAM out)
467     {
468     uint32 result;
469     uint8 immediate;
470 n-ki 588 SERIAL_DEVICE *pser_inf;
471     struct termios *ptermios;
472 matthewc 432
473     if ((request >> 16) != FILE_DEVICE_SERIAL_PORT)
474     return STATUS_INVALID_PARAMETER;
475    
476 n-ki 588 pser_inf = get_serial_info(handle);
477     ptermios = pser_inf->ptermios;
478    
479 matthewc 432 /* 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 n-ki 588 in_uint32_le(in, pser_inf->baud_rate);
489     set_termios(pser_inf, handle);
490 matthewc 432 break;
491     case SERIAL_GET_BAUD_RATE:
492 n-ki 588 out_uint32_le(out, pser_inf->baud_rate);
493 matthewc 432 break;
494     case SERIAL_SET_QUEUE_SIZE:
495 n-ki 588 in_uint32_le(in, pser_inf->queue_in_size);
496     in_uint32_le(in, pser_inf->queue_out_size);
497 matthewc 432 break;
498     case SERIAL_SET_LINE_CONTROL:
499 n-ki 588 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 matthewc 432 break;
504     case SERIAL_GET_LINE_CONTROL:
505 n-ki 588 out_uint8(out, pser_inf->stop_bits);
506     out_uint8(out, pser_inf->parity);
507     out_uint8(out, pser_inf->word_length);
508 matthewc 432 break;
509     case SERIAL_IMMEDIATE_CHAR:
510     in_uint8(in, immediate);
511 n-ki 569 serial_write(handle, &immediate, 1, 0, &result);
512 matthewc 432 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 astrand 435 out_uint32_le(out, 3); /* Xon/Xoff */
525 matthewc 432 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 n-ki 588 out_uint32(out, pser_inf->wait_mask);
539 matthewc 432 break;
540     case SERIAL_SET_WAIT_MASK:
541 n-ki 588 in_uint32(in, pser_inf->wait_mask);
542 matthewc 432 break;
543     case SERIAL_SET_DTR:
544 n-ki 588 pser_inf->dtr = 1;
545     set_termios(pser_inf, handle);
546 matthewc 432 break;
547     case SERIAL_CLR_DTR:
548 n-ki 588 pser_inf->dtr = 0;
549     set_termios(pser_inf, handle);
550 matthewc 432 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 n-ki 569
560 astrand 580 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 n-ki 569
574 matthewc 432 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 n-ki 569 /* Read timeout for a given file descripter (device) when adding fd's to select() */
593     BOOL
594 n-ki 588 serial_get_timeout(HANDLE handle, uint32 length, uint32 * timeout, uint32 * itv_timeout)
595 n-ki 569 {
596 astrand 580 int index;
597     SERIAL_DEVICE *pser_inf;
598 n-ki 569
599 astrand 580 index = get_device_index(handle);
600 n-ki 569
601 astrand 580 if (g_rdpdr_device[index].device_type != DEVICE_TYPE_SERIAL)
602     {
603     return False;
604     }
605 n-ki 569
606 astrand 580 pser_inf = (SERIAL_DEVICE *) g_rdpdr_device[index].pdevice_data;
607 n-ki 569
608 astrand 580 *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 n-ki 569 }
614    
615 astrand 435 DEVICE_FNS serial_fns = {
616 matthewc 432 serial_create,
617     serial_close,
618     serial_read,
619     serial_write,
620     serial_device_control
621     };

  ViewVC Help
Powered by ViewVC 1.1.26