/[rdesktop]/jpeg/rdesktop/trunk/serial.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /jpeg/rdesktop/trunk/serial.c

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

revision 580 by astrand, Fri Jan 23 08:35:52 2004 UTC revision 1475 by jsorg71, Fri Jul 11 03:51:23 2008 UTC
# Line 1  Line 1 
1    /* -*- c-basic-offset: 8 -*-
2       rdesktop: A Remote Desktop Protocol client.
3    
4       Copyright (C) Matthew Chapman 1999-2008
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>  #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 53  Line 90 
90  #define ODD_PARITY                      1  #define ODD_PARITY                      1
91  #define EVEN_PARITY                     2  #define EVEN_PARITY                     2
92    
93  extern RDPDR_DEVICE g_rdpdr_device[];  #define SERIAL_PURGE_TXABORT 0x00000001
94    #define SERIAL_PURGE_RXABORT 0x00000002
95  int serial_fd;  #define SERIAL_PURGE_TXCLEAR 0x00000004
96  struct termios termios;  #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[];
 uint32 baud_rate;  
 uint32 queue_in_size, queue_out_size;  
 uint32 wait_mask;  
 uint8 stop_bits, parity, word_length;  
151    
152  SERIAL_DEVICE * get_serial_info(HANDLE handle)  static SERIAL_DEVICE *
153    get_serial_info(RD_NTHANDLE handle)
154  {  {
155          int index;          int index;
156    
# Line 76  SERIAL_DEVICE * get_serial_info(HANDLE h Line 162  SERIAL_DEVICE * get_serial_info(HANDLE h
162          return NULL;          return NULL;
163  }  }
164    
165  BOOL  static RD_BOOL
166  get_termios(SERIAL_DEVICE * pser_inf, HANDLE serial_fd)  get_termios(SERIAL_DEVICE * pser_inf, RD_NTHANDLE serial_fd)
167  {  {
168          speed_t speed;          speed_t speed;
169          struct termios *ptermios;          struct termios *ptermios;
# Line 165  get_termios(SERIAL_DEVICE * pser_inf, HA Line 251  get_termios(SERIAL_DEVICE * pser_inf, HA
251                          pser_inf->baud_rate = 115200;                          pser_inf->baud_rate = 115200;
252                          break;                          break;
253  #endif  #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;
263    #endif
264                  default:                  default:
265                          pser_inf->baud_rate = 0;                          pser_inf->baud_rate = 9600;
266                          break;                          break;
267          }          }
268    
# Line 194  get_termios(SERIAL_DEVICE * pser_inf, HA Line 290  get_termios(SERIAL_DEVICE * pser_inf, HA
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, RD_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 279  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        */  /* Enumeration of devices from rdesktop.c        */
# Line 330  set_termios(void) Line 514  set_termios(void)
514  /* when it arrives to this function.              */  /* when it arrives to this function.              */
515  /* :com1=/dev/ttyS0,com2=/dev/ttyS1 */  /* :com1=/dev/ttyS0,com2=/dev/ttyS1 */
516  int  int
517  serial_enum_devices(int *id, char *optarg)  serial_enum_devices(uint32 * id, char *optarg)
518  {  {
519          SERIAL_DEVICE *pser_inf;          SERIAL_DEVICE *pser_inf;
520    
# Line 338  serial_enum_devices(int *id, char *optar Line 522  serial_enum_devices(int *id, char *optar
522          char *pos2;          char *pos2;
523          int count = 0;          int count = 0;
524    
525          // skip the first colon          /* skip the first colon */
526          optarg++;          optarg++;
527          while ((pos = next_arg(optarg, ',')) && *id < RDPDR_MAX_DEVICES)          while ((pos = next_arg(optarg, ',')) && *id < RDPDR_MAX_DEVICES)
528          {          {
529                  // Init data structures for device                  /* Init data structures for device */
530                  pser_inf = (SERIAL_DEVICE *) xmalloc(sizeof(SERIAL_DEVICE));                  pser_inf = (SERIAL_DEVICE *) xmalloc(sizeof(SERIAL_DEVICE));
531                  pser_inf->ptermios = (struct termios *) xmalloc(sizeof(struct termios));                  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));                  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, '=');                  pos2 = next_arg(optarg, '=');
537                  strcpy(g_rdpdr_device[*id].name, optarg);                  strcpy(g_rdpdr_device[*id].name, optarg);
# Line 356  serial_enum_devices(int *id, char *optar Line 542  serial_enum_devices(int *id, char *optar
542                  strcpy(g_rdpdr_device[*id].local_path, pos2);                  strcpy(g_rdpdr_device[*id].local_path, pos2);
543                  printf("SERIAL %s to %s\n", g_rdpdr_device[*id].name,                  printf("SERIAL %s to %s\n", g_rdpdr_device[*id].name,
544                         g_rdpdr_device[*id].local_path);                         g_rdpdr_device[*id].local_path);
545                  // set device type                  /* set device type */
546                  g_rdpdr_device[*id].device_type = DEVICE_TYPE_SERIAL;                  g_rdpdr_device[*id].device_type = DEVICE_TYPE_SERIAL;
547                  g_rdpdr_device[*id].pdevice_data = (void *) pser_inf;                  g_rdpdr_device[*id].pdevice_data = (void *) pser_inf;
548                  count++;                  count++;
# Line 367  serial_enum_devices(int *id, char *optar Line 553  serial_enum_devices(int *id, char *optar
553          return count;          return count;
554  }  }
555    
556  NTSTATUS  static RD_NTSTATUS
557  serial_create(uint32 device_id, uint32 access, uint32 share_mode, uint32 disposition,  serial_create(uint32 device_id, uint32 access, uint32 share_mode, uint32 disposition,
558                uint32 flags_and_attributes, char *filename, HANDLE * handle)                uint32 flags_and_attributes, char *filename, RD_NTHANDLE * handle)
559  {  {
560          HANDLE serial_fd;          RD_NTHANDLE serial_fd;
561          SERIAL_DEVICE *pser_inf;          SERIAL_DEVICE *pser_inf;
562          struct termios *ptermios;          struct termios *ptermios;
563    
564          pser_inf = (SERIAL_DEVICE *) g_rdpdr_device[device_id].pdevice_data;          pser_inf = (SERIAL_DEVICE *) g_rdpdr_device[device_id].pdevice_data;
565          ptermios = pser_inf->ptermios;          ptermios = pser_inf->ptermios;
566          serial_fd = open(g_rdpdr_device[device_id].local_path, O_RDWR | O_NOCTTY);          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                  return STATUS_ACCESS_DENIED;          {
570                    perror("open");
571                    return RD_STATUS_ACCESS_DENIED;
572            }
573    
574          if (!get_termios(pser_inf, serial_fd))          if (!get_termios(pser_inf, serial_fd))
575                  return STATUS_ACCESS_DENIED;          {
576                    printf("INFO: SERIAL %s access denied\n", g_rdpdr_device[device_id].name);
577                    fflush(stdout);
578                    return RD_STATUS_ACCESS_DENIED;
579            }
580    
581          // Store handle for later use          /* Store handle for later use */
582          g_rdpdr_device[device_id].handle = serial_fd;          g_rdpdr_device[device_id].handle = serial_fd;
583    
584          /* some sane information */          /* some sane information */
585          printf("INFO: SERIAL %s to %s\nINFO: speed %u baud, stop bits %u, parity %u, word length %u bits, dtr %u\n", g_rdpdr_device[device_id].name, g_rdpdr_device[device_id].local_path, pser_inf->baud_rate, pser_inf->stop_bits, pser_inf->parity, pser_inf->word_length, pser_inf->dtr);          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));
         printf("INFO: use stty to change settings\n");  
586    
587          //tcgetattr(serial_fd, pser_inf->ptermios);          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;          *handle = serial_fd;
603          return STATUS_SUCCESS;  
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    
610            return RD_STATUS_SUCCESS;
611  }  }
612    
613  static NTSTATUS  static RD_NTSTATUS
614  serial_close(HANDLE handle)  serial_close(RD_NTHANDLE handle)
615  {  {
616          close(serial_fd);          int i = get_device_index(handle);
617          return STATUS_SUCCESS;          if (i >= 0)
618                    g_rdpdr_device[i].handle = 0;
619    
620            rdpdr_abort_io(handle, 0, RD_STATUS_TIMEOUT);
621            close(handle);
622            return RD_STATUS_SUCCESS;
623  }  }
624    
625  NTSTATUS  static RD_NTSTATUS
626  serial_read(HANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)  serial_read(RD_NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
627  {  {
628          long timeout;          long timeout;
629          SERIAL_DEVICE *pser_inf;          SERIAL_DEVICE *pser_inf;
630          struct termios *ptermios;          struct termios *ptermios;
631    #ifdef WITH_DEBUG_SERIAL
632            int bytes_inqueue;
633    #endif
634    
635    
636          timeout = 0;          timeout = 90;
637          pser_inf = get_serial_info(handle);          pser_inf = get_serial_info(handle);
638          ptermios = pser_inf->ptermios;          ptermios = pser_inf->ptermios;
639    
640          // Set timeouts kind of like the windows serial timeout parameters. Multiply timeout          /* Set timeouts kind of like the windows serial timeout parameters. Multiply timeout
641          // with requested read size             with requested read size */
642          if (pser_inf->read_total_timeout_multiplier | pser_inf->read_total_timeout_constant)          if (pser_inf->read_total_timeout_multiplier | pser_inf->read_total_timeout_constant)
643          {          {
644                  timeout =                  timeout =
# Line 429  serial_read(HANDLE handle, uint8 * data, Line 650  serial_read(HANDLE handle, uint8 * data,
650                  timeout = (pser_inf->read_interval_timeout * length + 99) / 100;                  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.          /* 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             It will make rdesktop less responsive, but it will improve serial performance, by not
655          // reading one character at a time.             reading one character at a time. */
656          if (timeout == 0)          if (timeout == 0)
657          {          {
658                  ptermios->c_cc[VTIME] = 0;                  ptermios->c_cc[VTIME] = 0;
# Line 444  serial_read(HANDLE handle, uint8 * data, Line 665  serial_read(HANDLE handle, uint8 * data,
665          }          }
666          tcsetattr(handle, TCSANOW, ptermios);          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);          *result = read(handle, data, length);
674          return STATUS_SUCCESS;  
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 RD_STATUS_SUCCESS;
682  }  }
683    
684  NTSTATUS  static RD_NTSTATUS
685  serial_write(HANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)  serial_write(RD_NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
686  {  {
687            SERIAL_DEVICE *pser_inf;
688    
689            pser_inf = get_serial_info(handle);
690    
691          *result = write(handle, data, length);          *result = write(handle, data, length);
692          return STATUS_SUCCESS;  
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 RD_STATUS_SUCCESS;
699  }  }
700    
701  static NTSTATUS  static RD_NTSTATUS
702  serial_device_control(HANDLE handle, uint32 request, STREAM in, STREAM out)  serial_device_control(RD_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 RD_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, 0, &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:
   
                         printf("SERIAL_PURGE\n");  
897                          in_uint32(in, purge_mask);                          in_uint32(in, purge_mask);
898                          if (purge_mask & 0x04)                          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;                                  flush_mask |= TCOFLUSH;
902                          if (purge_mask & 0x08)                          if (purge_mask & SERIAL_PURGE_RXCLEAR)
903                                  flush_mask |= TCIFLUSH;                                  flush_mask |= TCIFLUSH;
904                          if (flush_mask != 0)                          if (flush_mask != 0)
905                                  tcflush(handle, flush_mask);                                  tcflush(handle, flush_mask);
906                          if (purge_mask & 0x01)                          if (purge_mask & SERIAL_PURGE_TXABORT)
907                                  rdpdr_abort_io(handle, 4, STATUS_CANCELLED);                                  rdpdr_abort_io(handle, 4, RD_STATUS_CANCELLED);
908                          if (purge_mask & 0x02)                          if (purge_mask & SERIAL_PURGE_RXABORT)
909                                  rdpdr_abort_io(handle, 3, STATUS_CANCELLED);                                  rdpdr_abort_io(handle, 3, RD_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 RD_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 RD_STATUS_INVALID_PARAMETER;
943            }
944    
945            return RD_STATUS_SUCCESS;
946    }
947    
948    RD_BOOL
949    serial_get_event(RD_NTHANDLE handle, uint32 * result)
950    {
951            int index;
952            SERIAL_DEVICE *pser_inf;
953            int bytes;
954            RD_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          return STATUS_SUCCESS;          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() */  /* Read timeout for a given file descripter (device) when adding fd's to select() */
1046  BOOL  RD_BOOL
1047  serial_get_timeout(uint32 handle, uint32 length, uint32 * timeout, uint32 * itv_timeout)  serial_get_timeout(RD_NTHANDLE handle, uint32 length, uint32 * timeout, uint32 * itv_timeout)
1048  {  {
1049          int index;          int index;
1050          SERIAL_DEVICE *pser_inf;          SERIAL_DEVICE *pser_inf;
1051    
1052          index = get_device_index(handle);          index = get_device_index(handle);
1053            if (index < 0)
1054                    return True;
1055    
1056          if (g_rdpdr_device[index].device_type != DEVICE_TYPE_SERIAL)          if (g_rdpdr_device[index].device_type != DEVICE_TYPE_SERIAL)
1057          {          {

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

  ViewVC Help
Powered by ViewVC 1.1.26