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

Annotation of /sourceforge.net/trunk/rdesktop/serial.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 569 - (hide annotations)
Wed Jan 21 14:40:40 2004 UTC (20 years, 4 months ago) by n-ki
File MIME type: text/plain
File size: 15780 byte(s)
redirection of disk, lptport, printer, comport.

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

  ViewVC Help
Powered by ViewVC 1.1.26