/[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 602 - (hide annotations)
Sat Feb 7 17:32:21 2004 UTC (20 years, 3 months ago) by stargo
File MIME type: text/plain
File size: 13501 byte(s)
Cleanup some warnings (from SUNWspro-compiler)

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

  ViewVC Help
Powered by ViewVC 1.1.26