/[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 570 - (hide annotations)
Wed Jan 21 18:02:38 2004 UTC (20 years, 5 months ago) by stargo
File MIME type: text/plain
File size: 15805 byte(s)
some fixes for solaris compiles.
toupper was redefined to handle strings, now renamed to toupper_str
disk.c has some more problems (it uses statfs and dirfd)

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

  ViewVC Help
Powered by ViewVC 1.1.26