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

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

  ViewVC Help
Powered by ViewVC 1.1.26