/[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 432 by matthewc, Tue Jul 1 09:31:25 2003 UTC revision 801 by astrand, Tue Nov 23 13:29:12 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 <sys/ioctl.h>
6    
7    #ifdef HAVE_SYS_MODEM_H
8    #include <sys/modem.h>
9    #endif
10    #ifdef HAVE_SYS_FILIO_H
11    #include <sys/filio.h>
12    #endif
13    #ifdef HAVE_SYS_STRTIO_H
14    #include <sys/strtio.h>
15    #endif
16    
17  #include "rdesktop.h"  #include "rdesktop.h"
18    
19    #ifdef WITH_DEBUG_SERIAL
20    #define DEBUG_SERIAL(args) printf args;
21    #else
22    #define DEBUG_SERIAL(args)
23    #endif
24    
25  #define FILE_DEVICE_SERIAL_PORT         0x1b  #define FILE_DEVICE_SERIAL_PORT         0x1b
26    
27  #define SERIAL_SET_BAUD_RATE            1  #define SERIAL_SET_BAUD_RATE            1
# Line 52  Line 71 
71  #define ODD_PARITY                      1  #define ODD_PARITY                      1
72  #define EVEN_PARITY                     2  #define EVEN_PARITY                     2
73    
74  int serial_fd;  #define SERIAL_PURGE_TXABORT 0x00000001
75  struct termios termios;  #define SERIAL_PURGE_RXABORT 0x00000002
76    #define SERIAL_PURGE_TXCLEAR 0x00000004
77    #define SERIAL_PURGE_RXCLEAR 0x00000008
78    
79    /* SERIAL_WAIT_ON_MASK */
80    #define SERIAL_EV_RXCHAR           0x0001       // Any Character received
81    #define SERIAL_EV_RXFLAG           0x0002       // Received certain character
82    #define SERIAL_EV_TXEMPTY          0x0004       // Transmitt Queue Empty
83    #define SERIAL_EV_CTS              0x0008       // CTS changed state
84    #define SERIAL_EV_DSR              0x0010       // DSR changed state
85    #define SERIAL_EV_RLSD             0x0020       // RLSD changed state
86    #define SERIAL_EV_BREAK            0x0040       // BREAK received
87    #define SERIAL_EV_ERR              0x0080       // Line status error occurred
88    #define SERIAL_EV_RING             0x0100       // Ring signal detected
89    #define SERIAL_EV_PERR             0x0200       // Printer error occured
90    #define SERIAL_EV_RX80FULL         0x0400       // Receive buffer is 80 percent full
91    #define SERIAL_EV_EVENT1           0x0800       // Provider specific event 1
92    #define SERIAL_EV_EVENT2           0x1000       // Provider specific event 2
93    
94    /* Modem Status */
95    #define SERIAL_MS_DTR 0x01
96    #define SERIAL_MS_RTS 0x02
97    #define SERIAL_MS_CTS 0x10
98    #define SERIAL_MS_DSR 0x20
99    #define SERIAL_MS_RNG 0x40
100    #define SERIAL_MS_CAR 0x80
101    
102    /* Handflow */
103    #define SERIAL_DTR_CONTROL      0x01
104    #define SERIAL_CTS_HANDSHAKE    0x08
105    #define SERIAL_ERROR_ABORT      0x80000000
106    
107    #define SERIAL_XON_HANDSHAKE    0x01
108    #define SERIAL_XOFF_HANDSHAKE   0x02
109    #define SERIAL_DSR_SENSITIVITY  0x40
110    
111    #define SERIAL_CHAR_EOF         0
112    #define SERIAL_CHAR_ERROR       1
113    #define SERIAL_CHAR_BREAK       2
114    #define SERIAL_CHAR_EVENT       3
115    #define SERIAL_CHAR_XON         4
116    #define SERIAL_CHAR_XOFF        5
117    
118  int dtr;  #ifndef CRTSCTS
119  uint32 baud_rate;  #define CRTSCTS 0
120  uint32 queue_in_size, queue_out_size;  #endif
121  uint32 wait_mask;  
122  uint8 stop_bits, parity, word_length;  /* FIONREAD should really do the same thing as TIOCINQ, where it is
123     * not available */
124    #ifndef TIOCINQ
125    #define TIOCINQ FIONREAD
126    #endif
127    
128    extern RDPDR_DEVICE g_rdpdr_device[];
129    
130    static SERIAL_DEVICE *
131    get_serial_info(NTHANDLE handle)
132    {
133            int index;
134    
135            for (index = 0; index < RDPDR_MAX_DEVICES; index++)
136            {
137                    if (handle == g_rdpdr_device[index].handle)
138                            return (SERIAL_DEVICE *) g_rdpdr_device[index].pdevice_data;
139            }
140            return NULL;
141    }
142    
143  static BOOL  static BOOL
144  get_termios(void)  get_termios(SERIAL_DEVICE * pser_inf, NTHANDLE serial_fd)
145  {  {
146          speed_t speed;          speed_t speed;
147            struct termios *ptermios;
148    
149          if (tcgetattr(serial_fd, &termios) == -1)          ptermios = pser_inf->ptermios;
150    
151            if (tcgetattr(serial_fd, ptermios) == -1)
152                  return False;                  return False;
153    
154          speed = cfgetispeed(&termios);          speed = cfgetispeed(ptermios);
155          switch (speed)          switch (speed)
156          {          {
157                  case B75:       baud_rate = 75; break;  #ifdef B75
158                  case B110:      baud_rate = 110; break;                  case B75:
159                  case B134:      baud_rate = 134; break;                          pser_inf->baud_rate = 75;
160                  case B150:      baud_rate = 150; break;                          break;
161                  case B300:      baud_rate = 300; break;  #endif
162                  case B600:      baud_rate = 600; break;  #ifdef B110
163                  case B1200:     baud_rate = 1200; break;                  case B110:
164                  case B1800:     baud_rate = 1800; break;                          pser_inf->baud_rate = 110;
165                  case B2400:     baud_rate = 2400; break;                          break;
166                  case B4800:     baud_rate = 4800; break;  #endif
167                  case B9600:     baud_rate = 9600; break;  #ifdef B134
168                  case B19200:    baud_rate = 19200; break;                  case B134:
169                  case B38400:    baud_rate = 38400; break;                          pser_inf->baud_rate = 134;
170                  case B57600:    baud_rate = 57600; break;                          break;
171                  case B115200:   baud_rate = 115200; break;  #endif
172                  default:        baud_rate = 0; break;  #ifdef B150
173          }                  case B150:
174                            pser_inf->baud_rate = 150;
175          speed = cfgetospeed(&termios);                          break;
176          dtr = (speed == B0) ? 0 : 1;  #endif
177    #ifdef B300
178          stop_bits = (termios.c_cflag & CSTOPB) ? STOP_BITS_2 : STOP_BITS_1;                  case B300:
179          parity = (termios.c_cflag & PARENB) ? ((termios.c_cflag & PARODD) ? ODD_PARITY : EVEN_PARITY) : NO_PARITY;                          pser_inf->baud_rate = 300;
180          switch (termios.c_cflag & CSIZE)                          break;
181          {  #endif
182                  case CS5: word_length = 5; break;  #ifdef B600
183                  case CS6: word_length = 6; break;                  case B600:
184                  case CS7: word_length = 7; break;                          pser_inf->baud_rate = 600;
185                  default:  word_length = 8; break;                          break;
186    #endif
187    #ifdef B1200
188                    case B1200:
189                            pser_inf->baud_rate = 1200;
190                            break;
191    #endif
192    #ifdef B1800
193                    case B1800:
194                            pser_inf->baud_rate = 1800;
195                            break;
196    #endif
197    #ifdef B2400
198                    case B2400:
199                            pser_inf->baud_rate = 2400;
200                            break;
201    #endif
202    #ifdef B4800
203                    case B4800:
204                            pser_inf->baud_rate = 4800;
205                            break;
206    #endif
207    #ifdef B9600
208                    case B9600:
209                            pser_inf->baud_rate = 9600;
210                            break;
211    #endif
212    #ifdef B19200
213                    case B19200:
214                            pser_inf->baud_rate = 19200;
215                            break;
216    #endif
217    #ifdef B38400
218                    case B38400:
219                            pser_inf->baud_rate = 38400;
220                            break;
221    #endif
222    #ifdef B57600
223                    case B57600:
224                            pser_inf->baud_rate = 57600;
225                            break;
226    #endif
227    #ifdef B115200
228                    case B115200:
229                            pser_inf->baud_rate = 115200;
230                            break;
231    #endif
232    #ifdef B230400
233                    case B230400:
234                            pser_inf->baud_rate = 230400;
235                            break;
236    #endif
237    #ifdef B460800
238                    case B460800:
239                            pser_inf->baud_rate = 460800;
240                            break;
241    #endif
242                    default:
243                            pser_inf->baud_rate = 9600;
244                            break;
245            }
246    
247            speed = cfgetospeed(ptermios);
248            pser_inf->dtr = (speed == B0) ? 0 : 1;
249    
250            pser_inf->stop_bits = (ptermios->c_cflag & CSTOPB) ? STOP_BITS_2 : STOP_BITS_1;
251            pser_inf->parity =
252                    (ptermios->
253                     c_cflag & PARENB) ? ((ptermios->
254                                           c_cflag & PARODD) ? ODD_PARITY : EVEN_PARITY) : NO_PARITY;
255            switch (ptermios->c_cflag & CSIZE)
256            {
257                    case CS5:
258                            pser_inf->word_length = 5;
259                            break;
260                    case CS6:
261                            pser_inf->word_length = 6;
262                            break;
263                    case CS7:
264                            pser_inf->word_length = 7;
265                            break;
266                    default:
267                            pser_inf->word_length = 8;
268                            break;
269            }
270    
271            if (ptermios->c_cflag & CRTSCTS)
272            {
273                    pser_inf->control = SERIAL_DTR_CONTROL | SERIAL_CTS_HANDSHAKE | SERIAL_ERROR_ABORT;
274            }
275            else
276            {
277                    pser_inf->control = SERIAL_DTR_CONTROL | SERIAL_ERROR_ABORT;
278          }          }
279    
280            pser_inf->xonoff = SERIAL_DSR_SENSITIVITY;
281            if (ptermios->c_iflag & IXON)
282                    pser_inf->xonoff |= SERIAL_XON_HANDSHAKE;
283    
284            if (ptermios->c_iflag & IXOFF)
285                    pser_inf->xonoff |= SERIAL_XOFF_HANDSHAKE;
286    
287            pser_inf->chars[SERIAL_CHAR_XON] = ptermios->c_cc[VSTART];
288            pser_inf->chars[SERIAL_CHAR_XOFF] = ptermios->c_cc[VSTOP];
289            pser_inf->chars[SERIAL_CHAR_EOF] = ptermios->c_cc[VEOF];
290            pser_inf->chars[SERIAL_CHAR_BREAK] = ptermios->c_cc[VINTR];
291            pser_inf->chars[SERIAL_CHAR_ERROR] = ptermios->c_cc[VKILL];
292    
293          return True;          return True;
294  }  }
295    
296  static void  static void
297  set_termios(void)  set_termios(SERIAL_DEVICE * pser_inf, NTHANDLE serial_fd)
298  {  {
299          speed_t speed;          speed_t speed;
300    
301          switch (baud_rate)          struct termios *ptermios;
302    
303            ptermios = pser_inf->ptermios;
304    
305    
306            switch (pser_inf->baud_rate)
307          {          {
308                  case 75:        speed = B75; break;  #ifdef B75
309                  case 110:       speed = B110; break;                  case 75:
310                  case 134:       speed = B134; break;                          speed = B75;
311                  case 150:       speed = B150; break;                          break;
312                  case 300:       speed = B300; break;  #endif
313                  case 600:       speed = B600; break;  #ifdef B110
314                  case 1200:      speed = B1200; break;                  case 110:
315                  case 1800:      speed = B1800; break;                          speed = B110;
316                  case 2400:      speed = B2400; break;                          break;
317                  case 4800:      speed = B4800; break;  #endif
318                  case 9600:      speed = B9600; break;  #ifdef B134
319                  case 19200:     speed = B19200; break;                  case 134:
320                  case 38400:     speed = B38400; break;                          speed = B134;
321                  case 57600:     speed = B57600; break;                          break;
322                  case 115200:    speed = B115200; break;  #endif
323                  default:        speed = B0; break;  #ifdef B150
324                    case 150:
325                            speed = B150;
326                            break;
327    #endif
328    #ifdef B300
329                    case 300:
330                            speed = B300;
331                            break;
332    #endif
333    #ifdef B600
334                    case 600:
335                            speed = B600;
336                            break;
337    #endif
338    #ifdef B1200
339                    case 1200:
340                            speed = B1200;
341                            break;
342    #endif
343    #ifdef B1800
344                    case 1800:
345                            speed = B1800;
346                            break;
347    #endif
348    #ifdef B2400
349                    case 2400:
350                            speed = B2400;
351                            break;
352    #endif
353    #ifdef B4800
354                    case 4800:
355                            speed = B4800;
356                            break;
357    #endif
358    #ifdef B9600
359                    case 9600:
360                            speed = B9600;
361                            break;
362    #endif
363    #ifdef B19200
364                    case 19200:
365                            speed = B19200;
366                            break;
367    #endif
368    #ifdef B38400
369                    case 38400:
370                            speed = B38400;
371                            break;
372    #endif
373    #ifdef B57600
374                    case 57600:
375                            speed = B57600;
376                            break;
377    #endif
378    #ifdef B115200
379                    case 115200:
380                            speed = B115200;
381                            break;
382    #endif
383    #ifdef B230400
384                    case 230400:
385                            speed = B115200;
386                            break;
387    #endif
388    #ifdef B460800
389                    case 460800:
390                            speed = B115200;
391                            break;
392    #endif
393                    default:
394                            speed = B9600;
395                            break;
396          }          }
397    
398    #ifdef CBAUD
399            ptermios->c_cflag &= ~CBAUD;
400            ptermios->c_cflag |= speed;
401    #else
402          /* on systems with separate ispeed and ospeed, we can remember the speed          /* on systems with separate ispeed and ospeed, we can remember the speed
403             in ispeed while changing DTR with ospeed */             in ispeed while changing DTR with ospeed */
404          cfsetispeed(&termios, speed);          cfsetispeed(pser_inf->ptermios, speed);
405          cfsetospeed(&termios, dtr ? speed : 0);          cfsetospeed(pser_inf->ptermios, pser_inf->dtr ? speed : 0);
406    #endif
407    
408          termios.c_cflag &= ~(CSTOPB|PARENB|PARODD|CSIZE);          ptermios->c_cflag &= ~(CSTOPB | PARENB | PARODD | CSIZE | CRTSCTS);
409          switch (stop_bits)          switch (pser_inf->stop_bits)
410          {          {
411                  case STOP_BITS_2:                  case STOP_BITS_2:
412                          termios.c_cflag |= CSTOPB;                          ptermios->c_cflag |= CSTOPB;
413                            break;
414                    default:
415                            ptermios->c_cflag &= ~CSTOPB;
416                          break;                          break;
417          }          }
418          switch (parity)  
419            switch (pser_inf->parity)
420          {          {
421                  case EVEN_PARITY:                  case EVEN_PARITY:
422                          termios.c_cflag |= PARENB;                          ptermios->c_cflag |= PARENB;
423                          break;                          break;
424                  case ODD_PARITY:                  case ODD_PARITY:
425                          termios.c_cflag |= PARENB|PARODD;                          ptermios->c_cflag |= PARENB | PARODD;
426                            break;
427                    case NO_PARITY:
428                            ptermios->c_cflag &= ~(PARENB | PARODD);
429                            break;
430            }
431    
432            switch (pser_inf->word_length)
433            {
434                    case 5:
435                            ptermios->c_cflag |= CS5;
436                            break;
437                    case 6:
438                            ptermios->c_cflag |= CS6;
439                            break;
440                    case 7:
441                            ptermios->c_cflag |= CS7;
442                            break;
443                    default:
444                            ptermios->c_cflag |= CS8;
445                          break;                          break;
446          }          }
447          switch (word_length)  
448    #if 0
449            if (pser_inf->rts)
450                    ptermios->c_cflag |= CRTSCTS;
451            else
452                    ptermios->c_cflag &= ~CRTSCTS;
453    #endif
454    
455            if (pser_inf->control & SERIAL_CTS_HANDSHAKE)
456            {
457                    ptermios->c_cflag |= CRTSCTS;
458            }
459            else
460            {
461                    ptermios->c_cflag &= ~CRTSCTS;
462            }
463    
464    
465            if (pser_inf->xonoff & SERIAL_XON_HANDSHAKE)
466            {
467                    ptermios->c_iflag |= IXON | IMAXBEL;
468            }
469            if (pser_inf->xonoff & SERIAL_XOFF_HANDSHAKE)
470            {
471                    ptermios->c_iflag |= IXOFF | IMAXBEL;
472            }
473    
474            if ((pser_inf->xonoff & (SERIAL_XOFF_HANDSHAKE | SERIAL_XON_HANDSHAKE)) == 0)
475          {          {
476                  case 5:  termios.c_cflag |= CS5; break;                  ptermios->c_iflag &= ~IXON;
477                  case 6:  termios.c_cflag |= CS6; break;                  ptermios->c_iflag &= ~IXOFF;
                 case 7:  termios.c_cflag |= CS7; break;  
                 default: termios.c_cflag |= CS8; break;  
478          }          }
479    
480          tcsetattr(serial_fd, TCSANOW, &termios);          ptermios->c_cc[VSTART] = pser_inf->chars[SERIAL_CHAR_XON];
481            ptermios->c_cc[VSTOP] = pser_inf->chars[SERIAL_CHAR_XOFF];
482            ptermios->c_cc[VEOF] = pser_inf->chars[SERIAL_CHAR_EOF];
483            ptermios->c_cc[VINTR] = pser_inf->chars[SERIAL_CHAR_BREAK];
484            ptermios->c_cc[VKILL] = pser_inf->chars[SERIAL_CHAR_ERROR];
485    
486            tcsetattr(serial_fd, TCSANOW, ptermios);
487    }
488    
489    /* Enumeration of devices from rdesktop.c        */
490    /* returns numer of units found and initialized. */
491    /* optarg looks like ':com1=/dev/ttyS0'           */
492    /* when it arrives to this function.              */
493    /* :com1=/dev/ttyS0,com2=/dev/ttyS1 */
494    int
495    serial_enum_devices(uint32 * id, char *optarg)
496    {
497            SERIAL_DEVICE *pser_inf;
498    
499            char *pos = optarg;
500            char *pos2;
501            int count = 0;
502    
503            // skip the first colon
504            optarg++;
505            while ((pos = next_arg(optarg, ',')) && *id < RDPDR_MAX_DEVICES)
506            {
507                    // Init data structures for device
508                    pser_inf = (SERIAL_DEVICE *) xmalloc(sizeof(SERIAL_DEVICE));
509                    pser_inf->ptermios = (struct termios *) xmalloc(sizeof(struct termios));
510                    memset(pser_inf->ptermios, 0, sizeof(struct termios));
511                    pser_inf->pold_termios = (struct termios *) xmalloc(sizeof(struct termios));
512                    memset(pser_inf->pold_termios, 0, sizeof(struct termios));
513    
514                    pos2 = next_arg(optarg, '=');
515                    strcpy(g_rdpdr_device[*id].name, optarg);
516    
517                    toupper_str(g_rdpdr_device[*id].name);
518    
519                    g_rdpdr_device[*id].local_path = xmalloc(strlen(pos2) + 1);
520                    strcpy(g_rdpdr_device[*id].local_path, pos2);
521                    printf("SERIAL %s to %s\n", g_rdpdr_device[*id].name,
522                           g_rdpdr_device[*id].local_path);
523                    // set device type
524                    g_rdpdr_device[*id].device_type = DEVICE_TYPE_SERIAL;
525                    g_rdpdr_device[*id].pdevice_data = (void *) pser_inf;
526                    count++;
527                    (*id)++;
528    
529                    optarg = pos;
530            }
531            return count;
532  }  }
533    
534  static NTSTATUS  static NTSTATUS
535  serial_create(HANDLE *handle)  serial_create(uint32 device_id, uint32 access, uint32 share_mode, uint32 disposition,
536                  uint32 flags_and_attributes, char *filename, NTHANDLE * handle)
537  {  {
538          /* XXX do we have to handle concurrent open attempts? */          NTHANDLE serial_fd;
539          serial_fd = open("/dev/ttyS0", O_RDWR);          SERIAL_DEVICE *pser_inf;
540            struct termios *ptermios;
541    
542            pser_inf = (SERIAL_DEVICE *) g_rdpdr_device[device_id].pdevice_data;
543            ptermios = pser_inf->ptermios;
544            serial_fd = open(g_rdpdr_device[device_id].local_path, O_RDWR | O_NOCTTY | O_NONBLOCK);
545    
546          if (serial_fd == -1)          if (serial_fd == -1)
547            {
548                    perror("open");
549                  return STATUS_ACCESS_DENIED;                  return STATUS_ACCESS_DENIED;
550            }
551    
552          if (!get_termios())          if (!get_termios(pser_inf, serial_fd))
553            {
554                    printf("INFO: SERIAL %s access denied\n", g_rdpdr_device[device_id].name);
555                    fflush(stdout);
556                  return STATUS_ACCESS_DENIED;                  return STATUS_ACCESS_DENIED;
557            }
558    
559            // Store handle for later use
560            g_rdpdr_device[device_id].handle = serial_fd;
561    
562            /* some sane information */
563            DEBUG_SERIAL(("INFO: SERIAL %s to %s\nINFO: speed %u baud, stop bits %u, parity %u, word length %u bits, dtr %u, rts %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, pser_inf->rts));
564    
565            pser_inf->ptermios->c_iflag &=
566                    ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
567            pser_inf->ptermios->c_oflag &= ~OPOST;
568            pser_inf->ptermios->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN | XCASE);
569            pser_inf->ptermios->c_cflag &= ~(CSIZE | PARENB);
570            pser_inf->ptermios->c_cflag |= CS8;
571    
572            tcsetattr(serial_fd, TCSANOW, pser_inf->ptermios);
573    
574            pser_inf->event_txempty = 0;
575            pser_inf->event_cts = 0;
576            pser_inf->event_dsr = 0;
577            pser_inf->event_rlsd = 0;
578            pser_inf->event_pending = 0;
579    
580            *handle = serial_fd;
581    
582            /* all read and writes should be non blocking */
583            if (fcntl(*handle, F_SETFL, O_NONBLOCK) == -1)
584                    perror("fcntl");
585    
586            pser_inf->read_total_timeout_constant = 5;
587    
         *handle = 0;  
588          return STATUS_SUCCESS;          return STATUS_SUCCESS;
589  }  }
590    
591  static NTSTATUS  static NTSTATUS
592  serial_close(HANDLE handle)  serial_close(NTHANDLE handle)
593  {  {
594          close(serial_fd);          int i = get_device_index(handle);
595            if (i >= 0)
596                    g_rdpdr_device[i].handle = 0;
597    
598            rdpdr_abort_io(handle, 0, STATUS_TIMEOUT);
599            close(handle);
600          return STATUS_SUCCESS;          return STATUS_SUCCESS;
601  }  }
602    
603  static NTSTATUS  static NTSTATUS
604  serial_read(HANDLE handle, uint8 *data, uint32 length, uint32 *result)  serial_read(NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
605  {  {
606          *result = read(serial_fd, data, length);          long timeout;
607            SERIAL_DEVICE *pser_inf;
608            struct termios *ptermios;
609    #ifdef WITH_DEBUG_SERIAL
610            int bytes_inqueue;
611    #endif
612    
613    
614            timeout = 90;
615            pser_inf = get_serial_info(handle);
616            ptermios = pser_inf->ptermios;
617    
618            // Set timeouts kind of like the windows serial timeout parameters. Multiply timeout
619            // with requested read size
620            if (pser_inf->read_total_timeout_multiplier | pser_inf->read_total_timeout_constant)
621            {
622                    timeout =
623                            (pser_inf->read_total_timeout_multiplier * length +
624                             pser_inf->read_total_timeout_constant + 99) / 100;
625            }
626            else if (pser_inf->read_interval_timeout)
627            {
628                    timeout = (pser_inf->read_interval_timeout * length + 99) / 100;
629            }
630    
631            // If a timeout is set, do a blocking read, which times out after some time.
632            // It will make rdesktop less responsive, but it will improve serial performance, by not
633            // reading one character at a time.
634            if (timeout == 0)
635            {
636                    ptermios->c_cc[VTIME] = 0;
637                    ptermios->c_cc[VMIN] = 0;
638            }
639            else
640            {
641                    ptermios->c_cc[VTIME] = timeout;
642                    ptermios->c_cc[VMIN] = 1;
643            }
644            tcsetattr(handle, TCSANOW, ptermios);
645    
646    #ifdef WITH_DEBUG_SERIAL
647            ioctl(handle, TIOCINQ, &bytes_inqueue);
648            DEBUG_SERIAL(("serial_read inqueue: %d expected %d\n", bytes_inqueue, length));
649    #endif
650    
651            *result = read(handle, data, length);
652    
653    #ifdef WITH_DEBUG_SERIAL
654            DEBUG_SERIAL(("serial_read Bytes %d\n", *result));
655            if (*result > 0)
656                    hexdump(data, *result);
657    #endif
658    
659          return STATUS_SUCCESS;          return STATUS_SUCCESS;
660  }  }
661    
662  static NTSTATUS  static NTSTATUS
663  serial_write(HANDLE handle, uint8 *data, uint32 length, uint32 *result)  serial_write(NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
664  {  {
665          *result = write(serial_fd, data, length);          SERIAL_DEVICE *pser_inf;
666    
667            pser_inf = get_serial_info(handle);
668    
669            *result = write(handle, data, length);
670    
671            if (*result > 0)
672                    pser_inf->event_txempty = *result;
673    
674            DEBUG_SERIAL(("serial_write length %d, offset %d result %d\n", length, offset, *result));
675    
676          return STATUS_SUCCESS;          return STATUS_SUCCESS;
677  }  }
678    
679  static NTSTATUS  static NTSTATUS
680  serial_device_control(HANDLE handle, uint32 request, STREAM in, STREAM out)  serial_device_control(NTHANDLE handle, uint32 request, STREAM in, STREAM out)
681  {  {
682          uint32 result;          int flush_mask, purge_mask;
683            uint32 result, modemstate;
684          uint8 immediate;          uint8 immediate;
685            SERIAL_DEVICE *pser_inf;
686            struct termios *ptermios;
687    
688          if ((request >> 16) != FILE_DEVICE_SERIAL_PORT)          if ((request >> 16) != FILE_DEVICE_SERIAL_PORT)
689                  return STATUS_INVALID_PARAMETER;                  return STATUS_INVALID_PARAMETER;
690    
691            pser_inf = get_serial_info(handle);
692            ptermios = pser_inf->ptermios;
693    
694          /* extract operation */          /* extract operation */
695          request >>= 2;          request >>= 2;
696          request &= 0xfff;          request &= 0xfff;
697    
         printf("SERIAL IOCTL %d\n", request);  
   
698          switch (request)          switch (request)
699          {          {
700                  case SERIAL_SET_BAUD_RATE:                  case SERIAL_SET_BAUD_RATE:
701                          in_uint32_le(in, baud_rate);                          in_uint32_le(in, pser_inf->baud_rate);
702                          set_termios();                          set_termios(pser_inf, handle);
703                            DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_BAUD_RATE %d\n",
704                                          pser_inf->baud_rate));
705                          break;                          break;
706                  case SERIAL_GET_BAUD_RATE:                  case SERIAL_GET_BAUD_RATE:
707                          out_uint32_le(out, baud_rate);                          out_uint32_le(out, pser_inf->baud_rate);
708                            DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_BAUD_RATE %d\n",
709                                          pser_inf->baud_rate));
710                          break;                          break;
711                  case SERIAL_SET_QUEUE_SIZE:                  case SERIAL_SET_QUEUE_SIZE:
712                          in_uint32_le(in, queue_in_size);                          in_uint32_le(in, pser_inf->queue_in_size);
713                          in_uint32_le(in, queue_out_size);                          in_uint32_le(in, pser_inf->queue_out_size);
714                            DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_QUEUE_SIZE in %d out %d\n",
715                                          pser_inf->queue_in_size, pser_inf->queue_out_size));
716                          break;                          break;
717                  case SERIAL_SET_LINE_CONTROL:                  case SERIAL_SET_LINE_CONTROL:
718                          in_uint8(in, stop_bits);                          in_uint8(in, pser_inf->stop_bits);
719                          in_uint8(in, parity);                          in_uint8(in, pser_inf->parity);
720                          in_uint8(in, word_length);                          in_uint8(in, pser_inf->word_length);
721                          set_termios();                          set_termios(pser_inf, handle);
722                            DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_LINE_CONTROL stop %d parity %d word %d\n", pser_inf->stop_bits, pser_inf->parity, pser_inf->word_length));
723                          break;                          break;
724                  case SERIAL_GET_LINE_CONTROL:                  case SERIAL_GET_LINE_CONTROL:
725                          out_uint8(out, stop_bits);                          DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_LINE_CONTROL\n"));
726                          out_uint8(out, parity);                          out_uint8(out, pser_inf->stop_bits);
727                          out_uint8(out, word_length);                          out_uint8(out, pser_inf->parity);
728                            out_uint8(out, pser_inf->word_length);
729                          break;                          break;
730                  case SERIAL_IMMEDIATE_CHAR:                  case SERIAL_IMMEDIATE_CHAR:
731                            DEBUG_SERIAL(("serial_ioctl -> SERIAL_IMMEDIATE_CHAR\n"));
732                          in_uint8(in, immediate);                          in_uint8(in, immediate);
733                          serial_write(handle, &immediate, 1, &result);                          serial_write(handle, &immediate, 1, 0, &result);
734                          break;                          break;
735                  case SERIAL_CONFIG_SIZE:                  case SERIAL_CONFIG_SIZE:
736                            DEBUG_SERIAL(("serial_ioctl -> SERIAL_CONFIG_SIZE\n"));
737                          out_uint32_le(out, 0);                          out_uint32_le(out, 0);
738                          break;                          break;
739                  case SERIAL_GET_CHARS:                  case SERIAL_GET_CHARS:
740                          out_uint8s(out, 6);                          DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_CHARS\n"));
741                            out_uint8a(out, pser_inf->chars, 6);
742                          break;                          break;
743                  case SERIAL_SET_CHARS:                  case SERIAL_SET_CHARS:
744                          in_uint8s(in, 6);                          DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_CHARS\n"));
745                            in_uint8a(in, pser_inf->chars, 6);
746    #ifdef WITH_DEBUG_SERIAL
747                            hexdump(pser_inf->chars, 6);
748    #endif
749                            set_termios(pser_inf, handle);
750                          break;                          break;
751                  case SERIAL_GET_HANDFLOW:                  case SERIAL_GET_HANDFLOW:
752                          out_uint32_le(out, 0);                          DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_HANDFLOW\n"));
753                          out_uint32_le(out, 3); /* Xon/Xoff */                          get_termios(pser_inf, handle);
754                          out_uint32_le(out, 0);                          out_uint32_le(out, pser_inf->control);
755                          out_uint32_le(out, 0);                          out_uint32_le(out, pser_inf->xonoff);   /* Xon/Xoff */
756                            out_uint32_le(out, pser_inf->onlimit);
757                            out_uint32_le(out, pser_inf->offlimit);
758                          break;                          break;
759                  case SERIAL_SET_HANDFLOW:                  case SERIAL_SET_HANDFLOW:
760                          in_uint8s(in, 16);                          in_uint32_le(in, pser_inf->control);
761                            in_uint32_le(in, pser_inf->xonoff);
762                            in_uint32_le(in, pser_inf->onlimit);
763                            in_uint32_le(in, pser_inf->offlimit);
764                            DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_HANDFLOW %x %x %x %x\n",
765                                          pser_inf->control, pser_inf->xonoff, pser_inf->onlimit,
766                                          pser_inf->onlimit));
767                            set_termios(pser_inf, handle);
768                          break;                          break;
769                  case SERIAL_SET_TIMEOUTS:                  case SERIAL_SET_TIMEOUTS:
770                          in_uint8s(in, 20);                          in_uint32(in, pser_inf->read_interval_timeout);
771                            in_uint32(in, pser_inf->read_total_timeout_multiplier);
772                            in_uint32(in, pser_inf->read_total_timeout_constant);
773                            in_uint32(in, pser_inf->write_total_timeout_multiplier);
774                            in_uint32(in, pser_inf->write_total_timeout_constant);
775                            DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_TIMEOUTS read timeout %d %d %d\n",
776                                          pser_inf->read_interval_timeout,
777                                          pser_inf->read_total_timeout_multiplier,
778                                          pser_inf->read_total_timeout_constant));
779                          break;                          break;
780                  case SERIAL_GET_TIMEOUTS:                  case SERIAL_GET_TIMEOUTS:
781                          out_uint8s(out, 20);                          DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_TIMEOUTS read timeout %d %d %d\n",
782                                          pser_inf->read_interval_timeout,
783                                          pser_inf->read_total_timeout_multiplier,
784                                          pser_inf->read_total_timeout_constant));
785    
786                            out_uint32(out, pser_inf->read_interval_timeout);
787                            out_uint32(out, pser_inf->read_total_timeout_multiplier);
788                            out_uint32(out, pser_inf->read_total_timeout_constant);
789                            out_uint32(out, pser_inf->write_total_timeout_multiplier);
790                            out_uint32(out, pser_inf->write_total_timeout_constant);
791                          break;                          break;
792                  case SERIAL_GET_WAIT_MASK:                  case SERIAL_GET_WAIT_MASK:
793                          out_uint32(out, wait_mask);                          DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_WAIT_MASK %X\n",
794                                          pser_inf->wait_mask); out_uint32(out, pser_inf->wait_mask));
795                          break;                          break;
796                  case SERIAL_SET_WAIT_MASK:                  case SERIAL_SET_WAIT_MASK:
797                          in_uint32(in, wait_mask);                          in_uint32(in, pser_inf->wait_mask);
798                            DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_WAIT_MASK %X\n",
799                                          pser_inf->wait_mask));
800                          break;                          break;
801                  case SERIAL_SET_DTR:                  case SERIAL_SET_DTR:
802                          dtr = 1;                          DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_DTR\n"));
803                          set_termios();                          ioctl(handle, TIOCMGET, &result);
804                            result |= TIOCM_DTR;
805                            ioctl(handle, TIOCMSET, &result);
806                            pser_inf->dtr = 1;
807                          break;                          break;
808                  case SERIAL_CLR_DTR:                  case SERIAL_CLR_DTR:
809                          dtr = 0;                          DEBUG_SERIAL(("serial_ioctl -> SERIAL_CLR_DTR\n"));
810                          set_termios();                          ioctl(handle, TIOCMGET, &result);
811                            result &= ~TIOCM_DTR;
812                            ioctl(handle, TIOCMSET, &result);
813                            pser_inf->dtr = 0;
814                          break;                          break;
815  #if 0                  case SERIAL_SET_RTS:
816                  case SERIAL_WAIT_ON_MASK:                          DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_RTS\n"));
817                          /* XXX implement me */                          ioctl(handle, TIOCMGET, &result);
818                            result |= TIOCM_RTS;
819                            ioctl(handle, TIOCMSET, &result);
820                            pser_inf->rts = 1;
821                          break;                          break;
822                  case SERIAL_SET_BREAK_ON:                  case SERIAL_CLR_RTS:
823                          tcsendbreak(serial_fd, 0);                          DEBUG_SERIAL(("serial_ioctl -> SERIAL_CLR_RTS\n"));
824                            ioctl(handle, TIOCMGET, &result);
825                            result &= ~TIOCM_RTS;
826                            ioctl(handle, TIOCMSET, &result);
827                            pser_inf->rts = 0;
828                            break;
829                    case SERIAL_GET_MODEMSTATUS:
830                            modemstate = 0;
831    #ifdef TIOCMGET
832                            ioctl(handle, TIOCMGET, &result);
833                            if (result & TIOCM_CTS)
834                                    modemstate |= SERIAL_MS_CTS;
835                            if (result & TIOCM_DSR)
836                                    modemstate |= SERIAL_MS_DSR;
837                            if (result & TIOCM_RNG)
838                                    modemstate |= SERIAL_MS_RNG;
839                            if (result & TIOCM_CAR)
840                                    modemstate |= SERIAL_MS_CAR;
841                            if (result & TIOCM_DTR)
842                                    modemstate |= SERIAL_MS_DTR;
843                            if (result & TIOCM_RTS)
844                                    modemstate |= SERIAL_MS_RTS;
845    #endif
846                            DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_MODEMSTATUS %X\n", modemstate));
847                            out_uint32_le(out, modemstate);
848                            break;
849                    case SERIAL_GET_COMMSTATUS:
850                            out_uint32_le(out, 0);  /* Errors */
851                            out_uint32_le(out, 0);  /* Hold reasons */
852    
853                            result = 0;
854                            ioctl(handle, TIOCINQ, &result);
855                            out_uint32_le(out, result);     /* Amount in in queue */
856                            if (result)
857                                    DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_COMMSTATUS in queue %d\n",
858                                                  result));
859    
860                            result = 0;
861                            ioctl(handle, TIOCOUTQ, &result);
862                            out_uint32_le(out, result);     /* Amount in out queue */
863                            if (result)
864                                    DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_COMMSTATUS out queue %d\n", result));
865    
866                            out_uint8(out, 0);      /* EofReceived */
867                            out_uint8(out, 0);      /* WaitForImmediate */
868                          break;                          break;
869                  case SERIAL_PURGE:                  case SERIAL_PURGE:
870                          in_uint32(purge_mask);                          in_uint32(in, purge_mask);
871                          /* tcflush */                          DEBUG_SERIAL(("serial_ioctl -> SERIAL_PURGE purge_mask %X\n", purge_mask));
872                            flush_mask = 0;
873                            if (purge_mask & SERIAL_PURGE_TXCLEAR)
874                                    flush_mask |= TCOFLUSH;
875                            if (purge_mask & SERIAL_PURGE_RXCLEAR)
876                                    flush_mask |= TCIFLUSH;
877                            if (flush_mask != 0)
878                                    tcflush(handle, flush_mask);
879                            if (purge_mask & SERIAL_PURGE_TXABORT)
880                                    rdpdr_abort_io(handle, 4, STATUS_CANCELLED);
881                            if (purge_mask & SERIAL_PURGE_RXABORT)
882                                    rdpdr_abort_io(handle, 3, STATUS_CANCELLED);
883                            break;
884                    case SERIAL_WAIT_ON_MASK:
885                            DEBUG_SERIAL(("serial_ioctl -> SERIAL_WAIT_ON_MASK %X\n",
886                                          pser_inf->wait_mask));
887                            pser_inf->event_pending = 1;
888                            if (serial_get_event(handle, &result))
889                            {
890                                    DEBUG_SERIAL(("WAIT end  event = %x\n", result));
891                                    out_uint32_le(out, result);
892                                    break;
893                            }
894                            return STATUS_PENDING;
895                            break;
896                    case SERIAL_SET_BREAK_ON:
897                            DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_BREAK_ON\n"));
898                            tcsendbreak(handle, 0);
899                          break;                          break;
900                  case SERIAL_RESET_DEVICE:                  case SERIAL_RESET_DEVICE:
901                            DEBUG_SERIAL(("serial_ioctl -> SERIAL_RESET_DEVICE\n"));
902                            break;
903                  case SERIAL_SET_BREAK_OFF:                  case SERIAL_SET_BREAK_OFF:
904                  case SERIAL_SET_RTS:                          DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_BREAK_OFF\n"));
905                  case SERIAL_CLR_RTS:                          break;
906                  case SERIAL_SET_XOFF:                  case SERIAL_SET_XOFF:
907                            DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_XOFF\n"));
908                            break;
909                  case SERIAL_SET_XON:                  case SERIAL_SET_XON:
910                          /* ignore */                          DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_XON\n"));
911                            tcflow(handle, TCION);
912                          break;                          break;
 #endif  
   
913                  default:                  default:
914                          unimpl("SERIAL IOCTL %d\n", request);                          unimpl("SERIAL IOCTL %d\n", request);
915                          return STATUS_INVALID_PARAMETER;                          return STATUS_INVALID_PARAMETER;
# Line 309  serial_device_control(HANDLE handle, uin Line 918  serial_device_control(HANDLE handle, uin
918          return STATUS_SUCCESS;          return STATUS_SUCCESS;
919  }  }
920    
921  DEVICE_FNS serial_fns =  BOOL
922    serial_get_event(NTHANDLE handle, uint32 * result)
923    {
924            int index;
925            SERIAL_DEVICE *pser_inf;
926            int bytes;
927            BOOL ret = False;
928    
929            *result = 0;
930            index = get_device_index(handle);
931            if (index < 0)
932                    return False;
933    
934            pser_inf = (SERIAL_DEVICE *) g_rdpdr_device[index].pdevice_data;
935    
936    
937            ioctl(handle, TIOCINQ, &bytes);
938    
939            if (bytes > 0)
940            {
941                    DEBUG_SERIAL(("serial_get_event Bytes %d\n", bytes));
942                    if (bytes > pser_inf->event_rlsd)
943                    {
944                            pser_inf->event_rlsd = bytes;
945                            if (pser_inf->wait_mask & SERIAL_EV_RLSD)
946                            {
947                                    DEBUG_SERIAL(("Event -> SERIAL_EV_RLSD \n"));
948                                    *result |= SERIAL_EV_RLSD;
949                                    ret = True;
950                            }
951    
952                    }
953    
954                    if ((bytes > 1) && (pser_inf->wait_mask & SERIAL_EV_RXFLAG))
955                    {
956                            DEBUG_SERIAL(("Event -> SERIAL_EV_RXFLAG Bytes %d\n", bytes));
957                            *result |= SERIAL_EV_RXFLAG;
958                            ret = True;
959                    }
960                    if ((pser_inf->wait_mask & SERIAL_EV_RXCHAR))
961                    {
962                            DEBUG_SERIAL(("Event -> SERIAL_EV_RXCHAR Bytes %d\n", bytes));
963                            *result |= SERIAL_EV_RXCHAR;
964                            ret = True;
965                    }
966    
967            }
968            else
969            {
970                    pser_inf->event_rlsd = 0;
971            }
972    
973    
974            ioctl(handle, TIOCOUTQ, &bytes);
975            if ((bytes == 0)
976                && (pser_inf->event_txempty > 0) && (pser_inf->wait_mask & SERIAL_EV_TXEMPTY))
977            {
978    
979                    DEBUG_SERIAL(("Event -> SERIAL_EV_TXEMPTY\n"));
980                    *result |= SERIAL_EV_TXEMPTY;
981                    ret = True;
982            }
983            pser_inf->event_txempty = bytes;
984    
985    
986            ioctl(handle, TIOCMGET, &bytes);
987            if ((bytes & TIOCM_DSR) != pser_inf->event_dsr)
988            {
989                    pser_inf->event_dsr = bytes & TIOCM_DSR;
990                    if (pser_inf->wait_mask & SERIAL_EV_DSR)
991                    {
992                            DEBUG_SERIAL(("event -> SERIAL_EV_DSR %s\n",
993                                          (bytes & TIOCM_DSR) ? "ON" : "OFF"));
994                            *result |= SERIAL_EV_DSR;
995                            ret = True;
996                    }
997            }
998    
999            if ((bytes & TIOCM_CTS) != pser_inf->event_cts)
1000            {
1001                    pser_inf->event_cts = bytes & TIOCM_CTS;
1002                    if (pser_inf->wait_mask & SERIAL_EV_CTS)
1003                    {
1004                            DEBUG_SERIAL((" EVENT-> SERIAL_EV_CTS %s\n",
1005                                          (bytes & TIOCM_CTS) ? "ON" : "OFF"));
1006                            *result |= SERIAL_EV_CTS;
1007                            ret = True;
1008                    }
1009            }
1010    
1011            if (ret)
1012                    pser_inf->event_pending = 0;
1013    
1014            return ret;
1015    }
1016    
1017    /* Read timeout for a given file descripter (device) when adding fd's to select() */
1018    BOOL
1019    serial_get_timeout(NTHANDLE handle, uint32 length, uint32 * timeout, uint32 * itv_timeout)
1020  {  {
1021            int index;
1022            SERIAL_DEVICE *pser_inf;
1023    
1024            index = get_device_index(handle);
1025            if (index < 0)
1026                    return True;
1027    
1028            if (g_rdpdr_device[index].device_type != DEVICE_TYPE_SERIAL)
1029            {
1030                    return False;
1031            }
1032    
1033            pser_inf = (SERIAL_DEVICE *) g_rdpdr_device[index].pdevice_data;
1034    
1035            *timeout =
1036                    pser_inf->read_total_timeout_multiplier * length +
1037                    pser_inf->read_total_timeout_constant;
1038            *itv_timeout = pser_inf->read_interval_timeout;
1039            return True;
1040    }
1041    
1042    DEVICE_FNS serial_fns = {
1043          serial_create,          serial_create,
1044          serial_close,          serial_close,
1045          serial_read,          serial_read,
1046          serial_write,          serial_write,
1047          serial_device_control          serial_device_control
1048  };  };
   

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

  ViewVC Help
Powered by ViewVC 1.1.26