/[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 545 by stargo, Mon Nov 3 20:19:01 2003 UTC revision 569 by n-ki, Wed Jan 21 14:40:40 2004 UTC
# Line 52  Line 52 
52  #define ODD_PARITY                      1  #define ODD_PARITY                      1
53  #define EVEN_PARITY                     2  #define EVEN_PARITY                     2
54    
55    extern RDPDR_DEVICE    g_rdpdr_device[];
56    
57  int serial_fd;  int serial_fd;
58  struct termios termios;  struct termios termios;
59    
# Line 61  uint32 queue_in_size, queue_out_size; Line 63  uint32 queue_in_size, queue_out_size;
63  uint32 wait_mask;  uint32 wait_mask;
64  uint8 stop_bits, parity, word_length;  uint8 stop_bits, parity, word_length;
65    
66  static BOOL  SERIAL_DEVICE
67  get_termios(void)  *get_serial_info(HANDLE handle)
68  {  {
69          speed_t speed;          int     index;
70    
71          if (tcgetattr(serial_fd, &termios) == -1)          for (index = 0; index < RDPDR_MAX_DEVICES; index++)
72                  return False;          {
73                    if (handle == g_rdpdr_device[index].handle)
74                            return (SERIAL_DEVICE *) g_rdpdr_device[index].pdevice_data;
75            }
76            return NULL;
77    }
78    
79          speed = cfgetispeed(&termios);  BOOL
80          switch (speed)  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  #ifdef B75  #ifdef B75
94                  case B75:                  case B75:       pser_inf->baud_rate = 75; break;
                         baud_rate = 75;  
                         break;  
95  #endif  #endif
96  #ifdef B110  #ifdef B110
97                  case B110:                  case B110:      pser_inf->baud_rate = 110; break;
                         baud_rate = 110;  
                         break;  
98  #endif  #endif
99  #ifdef B134  #ifdef B134
100                  case B134:                  case B134:      pser_inf->baud_rate = 134; break;
                         baud_rate = 134;  
                         break;  
101  #endif  #endif
102  #ifdef B150  #ifdef B150
103                  case B150:                  case B150:      pser_inf->baud_rate = 150; break;
                         baud_rate = 150;  
                         break;  
104  #endif  #endif
105  #ifdef B300  #ifdef B300
106                  case B300:                  case B300:      pser_inf->baud_rate = 300; break;
                         baud_rate = 300;  
                         break;  
107  #endif  #endif
108  #ifdef B600  #ifdef B600
109                  case B600:                  case B600:      pser_inf->baud_rate = 600; break;
                         baud_rate = 600;  
                         break;  
110  #endif  #endif
111  #ifdef B1200  #ifdef B1200
112                  case B1200:                  case B1200:     pser_inf->baud_rate = 1200; break;
                         baud_rate = 1200;  
                         break;  
113  #endif  #endif
114  #ifdef B1800  #ifdef B1800
115                  case B1800:                  case B1800:     pser_inf->baud_rate = 1800; break;
                         baud_rate = 1800;  
                         break;  
116  #endif  #endif
117  #ifdef B2400  #ifdef B2400
118                  case B2400:                  case B2400:     pser_inf->baud_rate = 2400; break;
                         baud_rate = 2400;  
                         break;  
119  #endif  #endif
120  #ifdef B4800  #ifdef B4800
121                  case B4800:                  case B4800:     pser_inf->baud_rate = 4800; break;
                         baud_rate = 4800;  
                         break;  
122  #endif  #endif
123  #ifdef B9600  #ifdef B9600
124                  case B9600:                  case B9600:     pser_inf->baud_rate = 9600; break;
                         baud_rate = 9600;  
                         break;  
125  #endif  #endif
126  #ifdef B19200  #ifdef B19200
127                  case B19200:                  case B19200:    pser_inf->baud_rate = 19200; break;
                         baud_rate = 19200;  
                         break;  
128  #endif  #endif
129  #ifdef B38400  #ifdef B38400
130                  case B38400:                  case B38400:    pser_inf->baud_rate = 38400; break;
                         baud_rate = 38400;  
                         break;  
131  #endif  #endif
132  #ifdef B57600  #ifdef B57600
133                  case B57600:                  case B57600:    pser_inf->baud_rate = 57600; break;
                         baud_rate = 57600;  
                         break;  
134  #endif  #endif
135  #ifdef B115200  #ifdef B115200
136                  case B115200:                  case B115200:   pser_inf->baud_rate = 115200; break;
                         baud_rate = 115200;  
                         break;  
137  #endif  #endif
138                  default:                  default:        pser_inf->baud_rate = 0; break;
139                          baud_rate = 0;          }
                         break;  
         }  
140    
141          speed = cfgetospeed(&termios);          speed = cfgetospeed(ptermios);
142          dtr = (speed == B0) ? 0 : 1;          pser_inf->dtr = (speed == B0) ? 0 : 1;
143    
144          stop_bits = (termios.c_cflag & CSTOPB) ? STOP_BITS_2 : STOP_BITS_1;          pser_inf->stop_bits = (ptermios->c_cflag & CSTOPB) ? STOP_BITS_2 : STOP_BITS_1;
145          parity = (termios.          pser_inf->parity = (ptermios->c_cflag & PARENB) ? ((ptermios->c_cflag & PARODD) ? ODD_PARITY : EVEN_PARITY) : NO_PARITY;
146                    c_cflag & PARENB) ? ((termios.          switch (ptermios->c_cflag & CSIZE)
147                                          c_cflag & PARODD) ? ODD_PARITY : EVEN_PARITY) : NO_PARITY;          {
148          switch (termios.c_cflag & CSIZE)                  case CS5: pser_inf->word_length = 5; break;
149          {                  case CS6: pser_inf->word_length = 6; break;
150                  case CS5:                  case CS7: pser_inf->word_length = 7; break;
151                          word_length = 5;                  default:  pser_inf->word_length = 8; break;
152                          break;          }
                 case CS6:  
                         word_length = 6;  
                         break;  
                 case CS7:  
                         word_length = 7;  
                         break;  
                 default:  
                         word_length = 8;  
                         break;  
         }  
153    
154          return True;          return True;
155  }  }
156    
157  static void  static void
# Line 186  set_termios(void) Line 162  set_termios(void)
162          switch (baud_rate)          switch (baud_rate)
163          {          {
164  #ifdef B75  #ifdef B75
165                  case 75:                  case 75:        speed = B75;break;
                         speed = B75;  
                         break;  
166  #endif  #endif
167  #ifdef B110  #ifdef B110
168                  case 110:                  case 110:       speed = B110;break;
                         speed = B110;  
                         break;  
169  #endif  #endif
170  #ifdef B134  #ifdef B134
171                  case 134:                  case 134:       speed = B134;break;
                         speed = B134;  
                         break;  
172  #endif  #endif
173  #ifdef B150  #ifdef B150
174                  case 150:                  case 150:       speed = B150;break;
                         speed = B150;  
                         break;  
175  #endif  #endif
176  #ifdef B300  #ifdef B300
177                  case 300:                  case 300:       speed = B300;break;
                         speed = B300;  
                         break;  
178  #endif  #endif
179  #ifdef B600  #ifdef B600
180                  case 600:                  case 600:       speed = B600;break;
                         speed = B600;  
                         break;  
181  #endif  #endif
182  #ifdef B1200  #ifdef B1200
183                  case 1200:                  case 1200:      speed = B1200;break;
                         speed = B1200;  
                         break;  
184  #endif  #endif
185  #ifdef B1800  #ifdef B1800
186                  case 1800:                  case 1800:      speed = B1800;break;
                         speed = B1800;  
                         break;  
187  #endif  #endif
188  #ifdef B2400  #ifdef B2400
189                  case 2400:                  case 2400:      speed = B2400;break;
                         speed = B2400;  
                         break;  
190  #endif  #endif
191  #ifdef B4800  #ifdef B4800
192                  case 4800:                  case 4800:      speed = B4800;break;
                         speed = B4800;  
                         break;  
193  #endif  #endif
194  #ifdef B9600  #ifdef B9600
195                  case 9600:                  case 9600:      speed = B9600;break;
                         speed = B9600;  
                         break;  
196  #endif  #endif
197  #ifdef B19200  #ifdef B19200
198                  case 19200:                  case 19200:     speed = B19200;break;
                         speed = B19200;  
                         break;  
199  #endif  #endif
200  #ifdef B38400  #ifdef B38400
201                  case 38400:                  case 38400:     speed = B38400;break;
                         speed = B38400;  
                         break;  
202  #endif  #endif
203  #ifdef B57600  #ifdef B57600
204                  case 57600:                  case 57600:     speed = B57600;break;
                         speed = B57600;  
                         break;  
205  #endif  #endif
206  #ifdef B115200  #ifdef B115200
207                  case 115200:                  case 115200:    speed = B115200;break;
                         speed = B115200;  
                         break;  
208  #endif  #endif
209                  default:                  default:        speed = B0;break;
                         speed = B0;  
                         break;  
210          }          }
211    
212          /* 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 305  set_termios(void) Line 249  set_termios(void)
249          tcsetattr(serial_fd, TCSANOW, &termios);          tcsetattr(serial_fd, TCSANOW, &termios);
250  }  }
251    
252  static NTSTATUS  /* Enumeration of devices from rdesktop.c        */
253  serial_create(HANDLE * handle)  /* 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  {  {
261          /* 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;  
262    
263          if (!get_termios())          int argcount=0;
264                  return STATUS_ACCESS_DENIED;          char* pos = optarg;
265            char* pos2;
266            char* pos3;
267    
268            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          *handle = 0;                  return 1;
345          return STATUS_SUCCESS;          }
346            return 0;
347    }
348    
349    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  static NTSTATUS  static NTSTATUS
# Line 327  serial_close(HANDLE handle) Line 403  serial_close(HANDLE handle)
403          return STATUS_SUCCESS;          return STATUS_SUCCESS;
404  }  }
405    
406  static NTSTATUS  NTSTATUS
407  serial_read(HANDLE handle, uint8 * data, uint32 length, uint32 * result)  serial_read(HANDLE handle, uint8 *data, uint32 length, uint32 offset, uint32 *result)
408  {  {
409          *result = read(serial_fd, data, length);          long            timeout;
410          return STATUS_SUCCESS;          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  }  }
446    
447  static NTSTATUS  NTSTATUS
448  serial_write(HANDLE handle, uint8 * data, uint32 length, uint32 * result)  serial_write(HANDLE handle, uint8 *data, uint32 length, uint32 offset, uint32 *result)
449  {  {
450          *result = write(serial_fd, data, length);          *result = write(handle, data, length);
451          return STATUS_SUCCESS;          return STATUS_SUCCESS;
452  }  }
453    
454  static NTSTATUS  static NTSTATUS
# Line 382  serial_device_control(HANDLE handle, uin Line 492  serial_device_control(HANDLE handle, uin
492                          break;                          break;
493                  case SERIAL_IMMEDIATE_CHAR:                  case SERIAL_IMMEDIATE_CHAR:
494                          in_uint8(in, immediate);                          in_uint8(in, immediate);
495                          serial_write(handle, &immediate, 1, &result);                          serial_write(handle, &immediate, 1, 0, &result);
496                          break;                          break;
497                  case SERIAL_CONFIG_SIZE:                  case SERIAL_CONFIG_SIZE:
498                          out_uint32_le(out, 0);                          out_uint32_le(out, 0);
# Line 430  serial_device_control(HANDLE handle, uin Line 540  serial_device_control(HANDLE handle, uin
540                          tcsendbreak(serial_fd, 0);                          tcsendbreak(serial_fd, 0);
541                          break;                          break;
542                  case SERIAL_PURGE:                  case SERIAL_PURGE:
543                          in_uint32(purge_mask);  
544                          /* tcflush */                          printf("SERIAL_PURGE\n");
545                          break;                          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                  case SERIAL_RESET_DEVICE:                  case SERIAL_RESET_DEVICE:
554                  case SERIAL_SET_BREAK_OFF:                  case SERIAL_SET_BREAK_OFF:
555                  case SERIAL_SET_RTS:                  case SERIAL_SET_RTS:
# Line 451  serial_device_control(HANDLE handle, uin Line 568  serial_device_control(HANDLE handle, uin
568          return STATUS_SUCCESS;          return STATUS_SUCCESS;
569  }  }
570    
571    /* 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  DEVICE_FNS serial_fns = {  DEVICE_FNS serial_fns = {
593          serial_create,          serial_create,
594          serial_close,          serial_close,

Legend:
Removed from v.545  
changed lines
  Added in v.569

  ViewVC Help
Powered by ViewVC 1.1.26