/[rdesktop]/jpeg/rdesktop/trunk/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 /jpeg/rdesktop/trunk/serial.c

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

revision 432 by matthewc, Tue Jul 1 09:31:25 2003 UTC revision 580 by astrand, Fri Jan 23 08:35:52 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 * get_serial_info(HANDLE handle)
68  get_termios(void)  {
69            int index;
70    
71            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    }
78    
79    BOOL
80    get_termios(SERIAL_DEVICE * pser_inf, HANDLE serial_fd)
81  {  {
82          speed_t speed;          speed_t speed;
83            struct termios *ptermios;
84    
85            ptermios = pser_inf->ptermios;
86    
87          if (tcgetattr(serial_fd, &termios) == -1)          if (tcgetattr(serial_fd, ptermios) == -1)
88                  return False;                  return False;
89    
90          speed = cfgetispeed(&termios);          speed = cfgetispeed(ptermios);
91          switch (speed)          switch (speed)
92          {          {
93                  case B75:       baud_rate = 75; break;  #ifdef B75
94                  case B110:      baud_rate = 110; break;                  case B75:
95                  case B134:      baud_rate = 134; break;                          pser_inf->baud_rate = 75;
96                  case B150:      baud_rate = 150; break;                          break;
97                  case B300:      baud_rate = 300; break;  #endif
98                  case B600:      baud_rate = 600; break;  #ifdef B110
99                  case B1200:     baud_rate = 1200; break;                  case B110:
100                  case B1800:     baud_rate = 1800; break;                          pser_inf->baud_rate = 110;
101                  case B2400:     baud_rate = 2400; break;                          break;
102                  case B4800:     baud_rate = 4800; break;  #endif
103                  case B9600:     baud_rate = 9600; break;  #ifdef B134
104                  case B19200:    baud_rate = 19200; break;                  case B134:
105                  case B38400:    baud_rate = 38400; break;                          pser_inf->baud_rate = 134;
106                  case B57600:    baud_rate = 57600; break;                          break;
107                  case B115200:   baud_rate = 115200; break;  #endif
108                  default:        baud_rate = 0; break;  #ifdef B150
109          }                  case B150:
110                            pser_inf->baud_rate = 150;
111          speed = cfgetospeed(&termios);                          break;
112          dtr = (speed == B0) ? 0 : 1;  #endif
113    #ifdef B300
114          stop_bits = (termios.c_cflag & CSTOPB) ? STOP_BITS_2 : STOP_BITS_1;                  case B300:
115          parity = (termios.c_cflag & PARENB) ? ((termios.c_cflag & PARODD) ? ODD_PARITY : EVEN_PARITY) : NO_PARITY;                          pser_inf->baud_rate = 300;
116          switch (termios.c_cflag & CSIZE)                          break;
117          {  #endif
118                  case CS5: word_length = 5; break;  #ifdef B600
119                  case CS6: word_length = 6; break;                  case B600:
120                  case CS7: word_length = 7; break;                          pser_inf->baud_rate = 600;
121                  default:  word_length = 8; break;                          break;
122    #endif
123    #ifdef B1200
124                    case B1200:
125                            pser_inf->baud_rate = 1200;
126                            break;
127    #endif
128    #ifdef B1800
129                    case B1800:
130                            pser_inf->baud_rate = 1800;
131                            break;
132    #endif
133    #ifdef B2400
134                    case B2400:
135                            pser_inf->baud_rate = 2400;
136                            break;
137    #endif
138    #ifdef B4800
139                    case B4800:
140                            pser_inf->baud_rate = 4800;
141                            break;
142    #endif
143    #ifdef B9600
144                    case B9600:
145                            pser_inf->baud_rate = 9600;
146                            break;
147    #endif
148    #ifdef B19200
149                    case B19200:
150                            pser_inf->baud_rate = 19200;
151                            break;
152    #endif
153    #ifdef B38400
154                    case B38400:
155                            pser_inf->baud_rate = 38400;
156                            break;
157    #endif
158    #ifdef B57600
159                    case B57600:
160                            pser_inf->baud_rate = 57600;
161                            break;
162    #endif
163    #ifdef B115200
164                    case B115200:
165                            pser_inf->baud_rate = 115200;
166                            break;
167    #endif
168                    default:
169                            pser_inf->baud_rate = 0;
170                            break;
171            }
172    
173            speed = cfgetospeed(ptermios);
174            pser_inf->dtr = (speed == B0) ? 0 : 1;
175    
176            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    
197          return True;          return True;
# Line 113  set_termios(void) Line 204  set_termios(void)
204    
205          switch (baud_rate)          switch (baud_rate)
206          {          {
207                  case 75:        speed = B75; break;  #ifdef B75
208                  case 110:       speed = B110; break;                  case 75:
209                  case 134:       speed = B134; break;                          speed = B75;
210                  case 150:       speed = B150; break;                          break;
211                  case 300:       speed = B300; break;  #endif
212                  case 600:       speed = B600; break;  #ifdef B110
213                  case 1200:      speed = B1200; break;                  case 110:
214                  case 1800:      speed = B1800; break;                          speed = B110;
215                  case 2400:      speed = B2400; break;                          break;
216                  case 4800:      speed = B4800; break;  #endif
217                  case 9600:      speed = B9600; break;  #ifdef B134
218                  case 19200:     speed = B19200; break;                  case 134:
219                  case 38400:     speed = B38400; break;                          speed = B134;
220                  case 57600:     speed = B57600; break;                          break;
221                  case 115200:    speed = B115200; break;  #endif
222                  default:        speed = B0; break;  #ifdef B150
223                    case 150:
224                            speed = B150;
225                            break;
226    #endif
227    #ifdef B300
228                    case 300:
229                            speed = B300;
230                            break;
231    #endif
232    #ifdef B600
233                    case 600:
234                            speed = B600;
235                            break;
236    #endif
237    #ifdef B1200
238                    case 1200:
239                            speed = B1200;
240                            break;
241    #endif
242    #ifdef B1800
243                    case 1800:
244                            speed = B1800;
245                            break;
246    #endif
247    #ifdef B2400
248                    case 2400:
249                            speed = B2400;
250                            break;
251    #endif
252    #ifdef B4800
253                    case 4800:
254                            speed = B4800;
255                            break;
256    #endif
257    #ifdef B9600
258                    case 9600:
259                            speed = B9600;
260                            break;
261    #endif
262    #ifdef B19200
263                    case 19200:
264                            speed = B19200;
265                            break;
266    #endif
267    #ifdef B38400
268                    case 38400:
269                            speed = B38400;
270                            break;
271    #endif
272    #ifdef B57600
273                    case 57600:
274                            speed = B57600;
275                            break;
276    #endif
277    #ifdef B115200
278                    case 115200:
279                            speed = B115200;
280                            break;
281    #endif
282                    default:
283                            speed = B0;
284                            break;
285          }          }
286    
287          /* 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 136  set_termios(void) Line 289  set_termios(void)
289          cfsetispeed(&termios, speed);          cfsetispeed(&termios, speed);
290          cfsetospeed(&termios, dtr ? speed : 0);          cfsetospeed(&termios, dtr ? speed : 0);
291    
292          termios.c_cflag &= ~(CSTOPB|PARENB|PARODD|CSIZE);          termios.c_cflag &= ~(CSTOPB | PARENB | PARODD | CSIZE);
293          switch (stop_bits)          switch (stop_bits)
294          {          {
295                  case STOP_BITS_2:                  case STOP_BITS_2:
# Line 149  set_termios(void) Line 302  set_termios(void)
302                          termios.c_cflag |= PARENB;                          termios.c_cflag |= PARENB;
303                          break;                          break;
304                  case ODD_PARITY:                  case ODD_PARITY:
305                          termios.c_cflag |= PARENB|PARODD;                          termios.c_cflag |= PARENB | PARODD;
306                          break;                          break;
307          }          }
308          switch (word_length)          switch (word_length)
309          {          {
310                  case 5:  termios.c_cflag |= CS5; break;                  case 5:
311                  case 6:  termios.c_cflag |= CS6; break;                          termios.c_cflag |= CS5;
312                  case 7:  termios.c_cflag |= CS7; break;                          break;
313                  default: termios.c_cflag |= CS8; break;                  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          }          }
323    
324          tcsetattr(serial_fd, TCSANOW, &termios);          tcsetattr(serial_fd, TCSANOW, &termios);
325  }  }
326    
327  static NTSTATUS  /* Enumeration of devices from rdesktop.c        */
328  serial_create(HANDLE *handle)  /* returns numer of units found and initialized. */
329    /* optarg looks like ':com1=/dev/ttyS0'           */
330    /* when it arrives to this function.              */
331    /* :com1=/dev/ttyS0,com2=/dev/ttyS1 */
332    int
333    serial_enum_devices(int *id, char *optarg)
334  {  {
335          /* XXX do we have to handle concurrent open attempts? */          SERIAL_DEVICE *pser_inf;
336          serial_fd = open("/dev/ttyS0", O_RDWR);  
337            char *pos = optarg;
338            char *pos2;
339            int count = 0;
340    
341            // skip the first colon
342            optarg++;
343            while ((pos = next_arg(optarg, ',')) && *id < RDPDR_MAX_DEVICES)
344            {
345                    // 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                    pos2 = next_arg(optarg, '=');
351                    strcpy(g_rdpdr_device[*id].name, optarg);
352    
353                    toupper_str(g_rdpdr_device[*id].name);
354    
355                    g_rdpdr_device[*id].local_path = xmalloc(strlen(pos2) + 1);
356                    strcpy(g_rdpdr_device[*id].local_path, pos2);
357                    printf("SERIAL %s to %s\n", g_rdpdr_device[*id].name,
358                           g_rdpdr_device[*id].local_path);
359                    // set device type
360                    g_rdpdr_device[*id].device_type = DEVICE_TYPE_SERIAL;
361                    g_rdpdr_device[*id].pdevice_data = (void *) pser_inf;
362                    count++;
363                    (*id)++;
364    
365                    optarg = pos;
366            }
367            return count;
368    }
369    
370    NTSTATUS
371    serial_create(uint32 device_id, uint32 access, uint32 share_mode, uint32 disposition,
372                  uint32 flags_and_attributes, char *filename, HANDLE * handle)
373    {
374            HANDLE serial_fd;
375            SERIAL_DEVICE *pser_inf;
376            struct termios *ptermios;
377    
378            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    
382          if (serial_fd == -1)          if (serial_fd == -1)
383                  return STATUS_ACCESS_DENIED;                  return STATUS_ACCESS_DENIED;
384    
385          if (!get_termios())          if (!get_termios(pser_inf, serial_fd))
386                  return STATUS_ACCESS_DENIED;                  return STATUS_ACCESS_DENIED;
387    
388          *handle = 0;          // Store handle for later use
389            g_rdpdr_device[device_id].handle = serial_fd;
390    
391            /* some sane information */
392            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    
395            //tcgetattr(serial_fd, pser_inf->ptermios);
396    
397            *handle = serial_fd;
398          return STATUS_SUCCESS;          return STATUS_SUCCESS;
399  }  }
400    
# Line 185  serial_close(HANDLE handle) Line 405  serial_close(HANDLE handle)
405          return STATUS_SUCCESS;          return STATUS_SUCCESS;
406  }  }
407    
408  static NTSTATUS  NTSTATUS
409  serial_read(HANDLE handle, uint8 *data, uint32 length, uint32 *result)  serial_read(HANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
410  {  {
411          *result = read(serial_fd, data, length);          long timeout;
412            SERIAL_DEVICE *pser_inf;
413            struct termios *ptermios;
414    
415            timeout = 0;
416            pser_inf = get_serial_info(handle);
417            ptermios = pser_inf->ptermios;
418    
419            // 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    
432            // 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    
447            *result = read(handle, data, length);
448          return STATUS_SUCCESS;          return STATUS_SUCCESS;
449  }  }
450    
451  static NTSTATUS  NTSTATUS
452  serial_write(HANDLE handle, uint8 *data, uint32 length, uint32 *result)  serial_write(HANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
453  {  {
454          *result = write(serial_fd, data, length);          *result = write(handle, data, length);
455          return STATUS_SUCCESS;          return STATUS_SUCCESS;
456  }  }
457    
# Line 240  serial_device_control(HANDLE handle, uin Line 496  serial_device_control(HANDLE handle, uin
496                          break;                          break;
497                  case SERIAL_IMMEDIATE_CHAR:                  case SERIAL_IMMEDIATE_CHAR:
498                          in_uint8(in, immediate);                          in_uint8(in, immediate);
499                          serial_write(handle, &immediate, 1, &result);                          serial_write(handle, &immediate, 1, 0, &result);
500                          break;                          break;
501                  case SERIAL_CONFIG_SIZE:                  case SERIAL_CONFIG_SIZE:
502                          out_uint32_le(out, 0);                          out_uint32_le(out, 0);
# Line 253  serial_device_control(HANDLE handle, uin Line 509  serial_device_control(HANDLE handle, uin
509                          break;                          break;
510                  case SERIAL_GET_HANDFLOW:                  case SERIAL_GET_HANDFLOW:
511                          out_uint32_le(out, 0);                          out_uint32_le(out, 0);
512                          out_uint32_le(out, 3); /* Xon/Xoff */                          out_uint32_le(out, 3);  /* Xon/Xoff */
513                          out_uint32_le(out, 0);                          out_uint32_le(out, 0);
514                          out_uint32_le(out, 0);                          out_uint32_le(out, 0);
515                          break;                          break;
# Line 288  serial_device_control(HANDLE handle, uin Line 544  serial_device_control(HANDLE handle, uin
544                          tcsendbreak(serial_fd, 0);                          tcsendbreak(serial_fd, 0);
545                          break;                          break;
546                  case SERIAL_PURGE:                  case SERIAL_PURGE:
547                          in_uint32(purge_mask);  
548                          /* tcflush */                          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;                          break;
561    
562                  case SERIAL_RESET_DEVICE:                  case SERIAL_RESET_DEVICE:
563                  case SERIAL_SET_BREAK_OFF:                  case SERIAL_SET_BREAK_OFF:
564                  case SERIAL_SET_RTS:                  case SERIAL_SET_RTS:
# Line 309  serial_device_control(HANDLE handle, uin Line 577  serial_device_control(HANDLE handle, uin
577          return STATUS_SUCCESS;          return STATUS_SUCCESS;
578  }  }
579    
580  DEVICE_FNS serial_fns =  /* Read timeout for a given file descripter (device) when adding fd's to select() */
581    BOOL
582    serial_get_timeout(uint32 handle, uint32 length, uint32 * timeout, uint32 * itv_timeout)
583  {  {
584            int index;
585            SERIAL_DEVICE *pser_inf;
586    
587            index = get_device_index(handle);
588    
589            if (g_rdpdr_device[index].device_type != DEVICE_TYPE_SERIAL)
590            {
591                    return False;
592            }
593    
594            pser_inf = (SERIAL_DEVICE *) g_rdpdr_device[index].pdevice_data;
595    
596            *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    }
602    
603    DEVICE_FNS serial_fns = {
604          serial_create,          serial_create,
605          serial_close,          serial_close,
606          serial_read,          serial_read,
607          serial_write,          serial_write,
608          serial_device_control          serial_device_control
609  };  };
   

Legend:
Removed from v.432  
changed lines
  Added in v.580

  ViewVC Help
Powered by ViewVC 1.1.26