/[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 580 - (hide annotations)
Fri Jan 23 08:35:52 2004 UTC (20 years, 5 months ago) by astrand
File MIME type: text/plain
File size: 12788 byte(s)
Ran indent-all.sh

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 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 astrand 580 SERIAL_DEVICE * get_serial_info(HANDLE handle)
68 matthewc 432 {
69 astrand 580 int index;
70 matthewc 432
71 astrand 580 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 n-ki 569 }
78 matthewc 432
79 n-ki 569 BOOL
80 astrand 580 get_termios(SERIAL_DEVICE * pser_inf, HANDLE serial_fd)
81 n-ki 569 {
82 astrand 580 speed_t speed;
83     struct termios *ptermios;
84 n-ki 569
85 astrand 580 ptermios = pser_inf->ptermios;
86 n-ki 569
87 astrand 580 if (tcgetattr(serial_fd, ptermios) == -1)
88     return False;
89 n-ki 569
90 astrand 580 speed = cfgetispeed(ptermios);
91     switch (speed)
92     {
93 stargo 545 #ifdef B75
94 astrand 580 case B75:
95     pser_inf->baud_rate = 75;
96     break;
97 stargo 545 #endif
98     #ifdef B110
99 astrand 580 case B110:
100     pser_inf->baud_rate = 110;
101     break;
102 stargo 545 #endif
103     #ifdef B134
104 astrand 580 case B134:
105     pser_inf->baud_rate = 134;
106     break;
107 stargo 545 #endif
108     #ifdef B150
109 astrand 580 case B150:
110     pser_inf->baud_rate = 150;
111     break;
112 stargo 545 #endif
113     #ifdef B300
114 astrand 580 case B300:
115     pser_inf->baud_rate = 300;
116     break;
117 stargo 545 #endif
118     #ifdef B600
119 astrand 580 case B600:
120     pser_inf->baud_rate = 600;
121     break;
122 stargo 545 #endif
123     #ifdef B1200
124 astrand 580 case B1200:
125     pser_inf->baud_rate = 1200;
126     break;
127 stargo 545 #endif
128     #ifdef B1800
129 astrand 580 case B1800:
130     pser_inf->baud_rate = 1800;
131     break;
132 stargo 545 #endif
133     #ifdef B2400
134 astrand 580 case B2400:
135     pser_inf->baud_rate = 2400;
136     break;
137 stargo 545 #endif
138     #ifdef B4800
139 astrand 580 case B4800:
140     pser_inf->baud_rate = 4800;
141     break;
142 stargo 545 #endif
143     #ifdef B9600
144 astrand 580 case B9600:
145     pser_inf->baud_rate = 9600;
146     break;
147 stargo 545 #endif
148     #ifdef B19200
149 astrand 580 case B19200:
150     pser_inf->baud_rate = 19200;
151     break;
152 stargo 545 #endif
153     #ifdef B38400
154 astrand 580 case B38400:
155     pser_inf->baud_rate = 38400;
156     break;
157 stargo 545 #endif
158     #ifdef B57600
159 astrand 580 case B57600:
160     pser_inf->baud_rate = 57600;
161     break;
162 stargo 545 #endif
163     #ifdef B115200
164 astrand 580 case B115200:
165     pser_inf->baud_rate = 115200;
166     break;
167 stargo 545 #endif
168 astrand 580 default:
169     pser_inf->baud_rate = 0;
170     break;
171     }
172 matthewc 432
173 astrand 580 speed = cfgetospeed(ptermios);
174     pser_inf->dtr = (speed == B0) ? 0 : 1;
175 matthewc 432
176 astrand 580 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 matthewc 432
197 astrand 580 return True;
198 matthewc 432 }
199    
200     static void
201     set_termios(void)
202     {
203     speed_t speed;
204    
205     switch (baud_rate)
206     {
207 stargo 545 #ifdef B75
208 astrand 580 case 75:
209     speed = B75;
210     break;
211 stargo 545 #endif
212     #ifdef B110
213 astrand 580 case 110:
214     speed = B110;
215     break;
216 stargo 545 #endif
217     #ifdef B134
218 astrand 580 case 134:
219     speed = B134;
220     break;
221 stargo 545 #endif
222     #ifdef B150
223 astrand 580 case 150:
224     speed = B150;
225     break;
226 stargo 545 #endif
227     #ifdef B300
228 astrand 580 case 300:
229     speed = B300;
230     break;
231 stargo 545 #endif
232     #ifdef B600
233 astrand 580 case 600:
234     speed = B600;
235     break;
236 stargo 545 #endif
237     #ifdef B1200
238 astrand 580 case 1200:
239     speed = B1200;
240     break;
241 stargo 545 #endif
242     #ifdef B1800
243 astrand 580 case 1800:
244     speed = B1800;
245     break;
246 stargo 545 #endif
247     #ifdef B2400
248 astrand 580 case 2400:
249     speed = B2400;
250     break;
251 stargo 545 #endif
252     #ifdef B4800
253 astrand 580 case 4800:
254     speed = B4800;
255     break;
256 stargo 545 #endif
257     #ifdef B9600
258 astrand 580 case 9600:
259     speed = B9600;
260     break;
261 stargo 545 #endif
262     #ifdef B19200
263 astrand 580 case 19200:
264     speed = B19200;
265     break;
266 stargo 545 #endif
267     #ifdef B38400
268 astrand 580 case 38400:
269     speed = B38400;
270     break;
271 stargo 545 #endif
272     #ifdef B57600
273 astrand 580 case 57600:
274     speed = B57600;
275     break;
276 stargo 545 #endif
277     #ifdef B115200
278 astrand 580 case 115200:
279     speed = B115200;
280     break;
281 stargo 545 #endif
282 astrand 580 default:
283     speed = B0;
284     break;
285 matthewc 432 }
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 astrand 435 termios.c_cflag &= ~(CSTOPB | PARENB | PARODD | CSIZE);
293 matthewc 432 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 astrand 435 termios.c_cflag |= PARENB | PARODD;
306 matthewc 432 break;
307     }
308     switch (word_length)
309     {
310 astrand 435 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 matthewc 432 }
323    
324     tcsetattr(serial_fd, TCSANOW, &termios);
325     }
326    
327 n-ki 569 /* 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 n-ki 578 /* :com1=/dev/ttyS0,com2=/dev/ttyS1 */
332 n-ki 569 int
333 astrand 580 serial_enum_devices(int *id, char *optarg)
334 matthewc 432 {
335 astrand 580 SERIAL_DEVICE *pser_inf;
336 matthewc 432
337 n-ki 578 char *pos = optarg;
338     char *pos2;
339     int count = 0;
340 matthewc 432
341 n-ki 578 // skip the first colon
342     optarg++;
343     while ((pos = next_arg(optarg, ',')) && *id < RDPDR_MAX_DEVICES)
344     {
345 n-ki 569 // 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 n-ki 578 pos2 = next_arg(optarg, '=');
351     strcpy(g_rdpdr_device[*id].name, optarg);
352 n-ki 569
353 n-ki 578 toupper_str(g_rdpdr_device[*id].name);
354 n-ki 569
355 n-ki 578 g_rdpdr_device[*id].local_path = xmalloc(strlen(pos2) + 1);
356     strcpy(g_rdpdr_device[*id].local_path, pos2);
357 astrand 580 printf("SERIAL %s to %s\n", g_rdpdr_device[*id].name,
358     g_rdpdr_device[*id].local_path);
359 n-ki 569 // set device type
360     g_rdpdr_device[*id].device_type = DEVICE_TYPE_SERIAL;
361     g_rdpdr_device[*id].pdevice_data = (void *) pser_inf;
362 n-ki 578 count++;
363 n-ki 569 (*id)++;
364    
365 n-ki 578 optarg = pos;
366 n-ki 569 }
367 n-ki 578 return count;
368 matthewc 432 }
369    
370 n-ki 569 NTSTATUS
371 astrand 580 serial_create(uint32 device_id, uint32 access, uint32 share_mode, uint32 disposition,
372     uint32 flags_and_attributes, char *filename, HANDLE * handle)
373 n-ki 569 {
374 astrand 580 HANDLE serial_fd;
375     SERIAL_DEVICE *pser_inf;
376     struct termios *ptermios;
377 n-ki 569
378 astrand 580 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 n-ki 569
382 astrand 580 if (serial_fd == -1)
383     return STATUS_ACCESS_DENIED;
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 578 //tcgetattr(serial_fd, pser_inf->ptermios);
396 n-ki 569
397 astrand 580 *handle = serial_fd;
398     return STATUS_SUCCESS;
399 n-ki 569 }
400    
401 matthewc 432 static NTSTATUS
402     serial_close(HANDLE handle)
403     {
404     close(serial_fd);
405     return STATUS_SUCCESS;
406     }
407    
408 n-ki 569 NTSTATUS
409 astrand 580 serial_read(HANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
410 matthewc 432 {
411 astrand 580 long timeout;
412     SERIAL_DEVICE *pser_inf;
413     struct termios *ptermios;
414 n-ki 569
415 astrand 580 timeout = 0;
416     pser_inf = get_serial_info(handle);
417     ptermios = pser_inf->ptermios;
418 n-ki 569
419 astrand 580 // 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 n-ki 569
432 astrand 580 // 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 n-ki 569
447 astrand 580 *result = read(handle, data, length);
448     return STATUS_SUCCESS;
449 matthewc 432 }
450    
451 n-ki 569 NTSTATUS
452 astrand 580 serial_write(HANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
453 matthewc 432 {
454 astrand 580 *result = write(handle, data, length);
455     return STATUS_SUCCESS;
456 matthewc 432 }
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 n-ki 569 serial_write(handle, &immediate, 1, 0, &result);
500 matthewc 432 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 astrand 435 out_uint32_le(out, 3); /* Xon/Xoff */
513 matthewc 432 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 n-ki 569
548 astrand 580 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 n-ki 569
562 matthewc 432 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 n-ki 569 /* Read timeout for a given file descripter (device) when adding fd's to select() */
581     BOOL
582 astrand 580 serial_get_timeout(uint32 handle, uint32 length, uint32 * timeout, uint32 * itv_timeout)
583 n-ki 569 {
584 astrand 580 int index;
585     SERIAL_DEVICE *pser_inf;
586 n-ki 569
587 astrand 580 index = get_device_index(handle);
588 n-ki 569
589 astrand 580 if (g_rdpdr_device[index].device_type != DEVICE_TYPE_SERIAL)
590     {
591     return False;
592     }
593 n-ki 569
594 astrand 580 pser_inf = (SERIAL_DEVICE *) g_rdpdr_device[index].pdevice_data;
595 n-ki 569
596 astrand 580 *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 n-ki 569 }
602    
603 astrand 435 DEVICE_FNS serial_fns = {
604 matthewc 432 serial_create,
605     serial_close,
606     serial_read,
607     serial_write,
608     serial_device_control
609     };

  ViewVC Help
Powered by ViewVC 1.1.26