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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 435 by astrand, Wed Jul 9 09:18:20 2003 UTC revision 570 by stargo, Wed Jan 21 18:02:38 2004 UTC
# Line 1  Line 1 
1  #include <unistd.h>  #include <unistd.h>
2  #include <fcntl.h>  #include <fcntl.h>
3  #include <termios.h>  #include <termios.h>
4    #include <strings.h>
5  #include "rdesktop.h"  #include "rdesktop.h"
6    
7  #define FILE_DEVICE_SERIAL_PORT         0x1b  #define FILE_DEVICE_SERIAL_PORT         0x1b
# Line 52  Line 53 
53  #define ODD_PARITY                      1  #define ODD_PARITY                      1
54  #define EVEN_PARITY                     2  #define EVEN_PARITY                     2
55    
56    extern RDPDR_DEVICE    g_rdpdr_device[];
57    
58  int serial_fd;  int serial_fd;
59  struct termios termios;  struct termios termios;
60    
# Line 61  uint32 queue_in_size, queue_out_size; Line 64  uint32 queue_in_size, queue_out_size;
64  uint32 wait_mask;  uint32 wait_mask;
65  uint8 stop_bits, parity, word_length;  uint8 stop_bits, parity, word_length;
66    
67  static BOOL  SERIAL_DEVICE
68  get_termios(void)  *get_serial_info(HANDLE handle)
69  {  {
70          speed_t speed;          int     index;
71    
72          if (tcgetattr(serial_fd, &termios) == -1)          for (index = 0; index < RDPDR_MAX_DEVICES; index++)
73                  return False;          {
74                    if (handle == g_rdpdr_device[index].handle)
75                            return (SERIAL_DEVICE *) g_rdpdr_device[index].pdevice_data;
76            }
77            return NULL;
78    }
79    
80          speed = cfgetispeed(&termios);  BOOL
81          switch (speed)  get_termios(SERIAL_DEVICE *pser_inf, HANDLE serial_fd)
82          {  {
83                  case B75:          speed_t         speed;
84                          baud_rate = 75;          struct termios  *ptermios;
                         break;  
                 case B110:  
                         baud_rate = 110;  
                         break;  
                 case B134:  
                         baud_rate = 134;  
                         break;  
                 case B150:  
                         baud_rate = 150;  
                         break;  
                 case B300:  
                         baud_rate = 300;  
                         break;  
                 case B600:  
                         baud_rate = 600;  
                         break;  
                 case B1200:  
                         baud_rate = 1200;  
                         break;  
                 case B1800:  
                         baud_rate = 1800;  
                         break;  
                 case B2400:  
                         baud_rate = 2400;  
                         break;  
                 case B4800:  
                         baud_rate = 4800;  
                         break;  
                 case B9600:  
                         baud_rate = 9600;  
                         break;  
                 case B19200:  
                         baud_rate = 19200;  
                         break;  
                 case B38400:  
                         baud_rate = 38400;  
                         break;  
                 case B57600:  
                         baud_rate = 57600;  
                         break;  
                 case B115200:  
                         baud_rate = 115200;  
                         break;  
                 default:  
                         baud_rate = 0;  
                         break;  
         }  
85    
86          speed = cfgetospeed(&termios);          ptermios        = pser_inf->ptermios;
         dtr = (speed == B0) ? 0 : 1;  
87    
88          stop_bits = (termios.c_cflag & CSTOPB) ? STOP_BITS_2 : STOP_BITS_1;          if (tcgetattr(serial_fd, ptermios) == -1)
89          parity = (termios.                  return False;
90                    c_cflag & PARENB) ? ((termios.  
91                                          c_cflag & PARODD) ? ODD_PARITY : EVEN_PARITY) : NO_PARITY;          speed = cfgetispeed(ptermios);
92          switch (termios.c_cflag & CSIZE)          switch (speed)
93          {          {
94                  case CS5:  #ifdef B75
95                          word_length = 5;                  case B75:       pser_inf->baud_rate = 75; break;
96                          break;  #endif
97                  case CS6:  #ifdef B110
98                          word_length = 6;                  case B110:      pser_inf->baud_rate = 110; break;
99                          break;  #endif
100                  case CS7:  #ifdef B134
101                          word_length = 7;                  case B134:      pser_inf->baud_rate = 134; break;
102                          break;  #endif
103                  default:  #ifdef B150
104                          word_length = 8;                  case B150:      pser_inf->baud_rate = 150; break;
105                          break;  #endif
106          }  #ifdef B300
107                    case B300:      pser_inf->baud_rate = 300; break;
108    #endif
109    #ifdef B600
110                    case B600:      pser_inf->baud_rate = 600; break;
111    #endif
112    #ifdef B1200
113                    case B1200:     pser_inf->baud_rate = 1200; break;
114    #endif
115    #ifdef B1800
116                    case B1800:     pser_inf->baud_rate = 1800; break;
117    #endif
118    #ifdef B2400
119                    case B2400:     pser_inf->baud_rate = 2400; break;
120    #endif
121    #ifdef B4800
122                    case B4800:     pser_inf->baud_rate = 4800; break;
123    #endif
124    #ifdef B9600
125                    case B9600:     pser_inf->baud_rate = 9600; break;
126    #endif
127    #ifdef B19200
128                    case B19200:    pser_inf->baud_rate = 19200; break;
129    #endif
130    #ifdef B38400
131                    case B38400:    pser_inf->baud_rate = 38400; break;
132    #endif
133    #ifdef B57600
134                    case B57600:    pser_inf->baud_rate = 57600; break;
135    #endif
136    #ifdef B115200
137                    case B115200:   pser_inf->baud_rate = 115200; break;
138    #endif
139                    default:        pser_inf->baud_rate = 0; break;
140            }
141    
142          return True;          speed = cfgetospeed(ptermios);
143            pser_inf->dtr = (speed == B0) ? 0 : 1;
144    
145            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    
155            return True;
156  }  }
157    
158  static void  static void
# Line 155  set_termios(void) Line 162  set_termios(void)
162    
163          switch (baud_rate)          switch (baud_rate)
164          {          {
165                  case 75:  #ifdef B75
166                          speed = B75;                  case 75:        speed = B75;break;
167                          break;  #endif
168                  case 110:  #ifdef B110
169                          speed = B110;                  case 110:       speed = B110;break;
170                          break;  #endif
171                  case 134:  #ifdef B134
172                          speed = B134;                  case 134:       speed = B134;break;
173                          break;  #endif
174                  case 150:  #ifdef B150
175                          speed = B150;                  case 150:       speed = B150;break;
176                          break;  #endif
177                  case 300:  #ifdef B300
178                          speed = B300;                  case 300:       speed = B300;break;
179                          break;  #endif
180                  case 600:  #ifdef B600
181                          speed = B600;                  case 600:       speed = B600;break;
182                          break;  #endif
183                  case 1200:  #ifdef B1200
184                          speed = B1200;                  case 1200:      speed = B1200;break;
185                          break;  #endif
186                  case 1800:  #ifdef B1800
187                          speed = B1800;                  case 1800:      speed = B1800;break;
188                          break;  #endif
189                  case 2400:  #ifdef B2400
190                          speed = B2400;                  case 2400:      speed = B2400;break;
191                          break;  #endif
192                  case 4800:  #ifdef B4800
193                          speed = B4800;                  case 4800:      speed = B4800;break;
194                          break;  #endif
195                  case 9600:  #ifdef B9600
196                          speed = B9600;                  case 9600:      speed = B9600;break;
197                          break;  #endif
198                  case 19200:  #ifdef B19200
199                          speed = B19200;                  case 19200:     speed = B19200;break;
200                          break;  #endif
201                  case 38400:  #ifdef B38400
202                          speed = B38400;                  case 38400:     speed = B38400;break;
203                          break;  #endif
204                  case 57600:  #ifdef B57600
205                          speed = B57600;                  case 57600:     speed = B57600;break;
206                          break;  #endif
207                  case 115200:  #ifdef B115200
208                          speed = B115200;                  case 115200:    speed = B115200;break;
209                          break;  #endif
210                  default:                  default:        speed = B0;break;
                         speed = B0;  
                         break;  
211          }          }
212    
213          /* on systems with separate ispeed and ospeed, we can remember the speed          /* on systems with separate ispeed and ospeed, we can remember the speed
# Line 245  set_termios(void) Line 250  set_termios(void)
250          tcsetattr(serial_fd, TCSANOW, &termios);          tcsetattr(serial_fd, TCSANOW, &termios);
251  }  }
252    
253  static NTSTATUS  /* Enumeration of devices from rdesktop.c        */
254  serial_create(HANDLE * handle)  /* 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  {  {
262          /* XXX do we have to handle concurrent open attempts? */          SERIAL_DEVICE* pser_inf;
         serial_fd = open("/dev/ttyS0", O_RDWR);  
         if (serial_fd == -1)  
                 return STATUS_ACCESS_DENIED;  
263    
264          if (!get_termios())          int argcount=0;
265                  return STATUS_ACCESS_DENIED;          char* pos = optarg;
266            char* pos2;
267            char* pos3;
268    
269            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                                            toupper_str(g_rdpdr_device[*id].name);
291    
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          *handle = 0;                  return 1;
346          return STATUS_SUCCESS;          }
347            return 0;
348    }
349    
350    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  static NTSTATUS  static NTSTATUS
# Line 267  serial_close(HANDLE handle) Line 404  serial_close(HANDLE handle)
404          return STATUS_SUCCESS;          return STATUS_SUCCESS;
405  }  }
406    
407  static NTSTATUS  NTSTATUS
408  serial_read(HANDLE handle, uint8 * data, uint32 length, uint32 * result)  serial_read(HANDLE handle, uint8 *data, uint32 length, uint32 offset, uint32 *result)
409  {  {
410          *result = read(serial_fd, data, length);          long            timeout;
411          return STATUS_SUCCESS;          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  }  }
447    
448  static NTSTATUS  NTSTATUS
449  serial_write(HANDLE handle, uint8 * data, uint32 length, uint32 * result)  serial_write(HANDLE handle, uint8 *data, uint32 length, uint32 offset, uint32 *result)
450  {  {
451          *result = write(serial_fd, data, length);          *result = write(handle, data, length);
452          return STATUS_SUCCESS;          return STATUS_SUCCESS;
453  }  }
454    
455  static NTSTATUS  static NTSTATUS
# Line 322  serial_device_control(HANDLE handle, uin Line 493  serial_device_control(HANDLE handle, uin
493                          break;                          break;
494                  case SERIAL_IMMEDIATE_CHAR:                  case SERIAL_IMMEDIATE_CHAR:
495                          in_uint8(in, immediate);                          in_uint8(in, immediate);
496                          serial_write(handle, &immediate, 1, &result);                          serial_write(handle, &immediate, 1, 0, &result);
497                          break;                          break;
498                  case SERIAL_CONFIG_SIZE:                  case SERIAL_CONFIG_SIZE:
499                          out_uint32_le(out, 0);                          out_uint32_le(out, 0);
# Line 370  serial_device_control(HANDLE handle, uin Line 541  serial_device_control(HANDLE handle, uin
541                          tcsendbreak(serial_fd, 0);                          tcsendbreak(serial_fd, 0);
542                          break;                          break;
543                  case SERIAL_PURGE:                  case SERIAL_PURGE:
544                          in_uint32(purge_mask);  
545                          /* tcflush */                          printf("SERIAL_PURGE\n");
546                          break;                          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                  case SERIAL_RESET_DEVICE:                  case SERIAL_RESET_DEVICE:
555                  case SERIAL_SET_BREAK_OFF:                  case SERIAL_SET_BREAK_OFF:
556                  case SERIAL_SET_RTS:                  case SERIAL_SET_RTS:
# Line 391  serial_device_control(HANDLE handle, uin Line 569  serial_device_control(HANDLE handle, uin
569          return STATUS_SUCCESS;          return STATUS_SUCCESS;
570  }  }
571    
572    /* 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  DEVICE_FNS serial_fns = {  DEVICE_FNS serial_fns = {
594          serial_create,          serial_create,
595          serial_close,          serial_close,

Legend:
Removed from v.435  
changed lines
  Added in v.570

  ViewVC Help
Powered by ViewVC 1.1.26