/ src / libserver / llserial.cpp
llserial.cpp
  1  /*
  2      EIBD eib bus access and management daemon
  3      Copyright (C) 2005-2011 Martin Koegler <mkoegler@auto.tuwien.ac.at>
  4  
  5      This program is free software; you can redistribute it and/or modify
  6      it under the terms of the GNU General Public License as published by
  7      the Free Software Foundation; either version 2 of the License, or
  8      (at your option) any later version.
  9  
 10      This program is distributed in the hope that it will be useful,
 11      but WITHOUT ANY WARRANTY; without even the implied warranty of
 12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13      GNU General Public License for more details.
 14  
 15      You should have received a copy of the GNU General Public License
 16      along with this program; if not, write to the Free Software
 17      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 18  */
 19  
 20  #include "llserial.h"
 21  #include "config.h"
 22  
 23  #include <cerrno>
 24  #include <fcntl.h>
 25  #include <sys/ioctl.h>
 26  #include <termios.h>
 27  #include <unistd.h>
 28  #ifdef HAVE_LINUX_LOWLATENCY
 29  #include <cstring> // memcpy
 30  #include <sys/ioctl.h>
 31  #endif
 32  
 33  
 34  static speed_t getbaud(int baud)
 35  {
 36    switch(baud)
 37      {
 38      case 9600:
 39        return B9600;
 40      case 19200:
 41        return B19200;
 42      case 38400:
 43        return B38400;
 44      case 115200:
 45        return B115200;
 46      default:
 47        return 0;
 48      }
 49  }
 50  
 51  bool
 52  LLserial::setup()
 53  {
 54    if(!FDdriver::setup())
 55      return false;
 56  
 57    dev = cfg->value("device","");
 58    if(dev.size() == 0)
 59      {
 60        ERRORPRINTF (t, E_ERROR | 22, "Missing device= config");
 61        return false;
 62      }
 63    baudrate = cfg->value("baudrate", (int)default_baudrate());
 64    if (getbaud(baudrate) == 0)
 65      {
 66        ERRORPRINTF (t, E_ERROR | 66, "Wrong baudrate= config");
 67        return false;
 68      }
 69    low_latency = cfg->value("low-latency",false);
 70  
 71    return true;
 72  }
 73  
 74  void
 75  LLserial::start()
 76  {
 77    struct termios t1;
 78    int term_baudrate;
 79  
 80    fd = open (dev.c_str(), O_RDWR | O_NOCTTY | O_NDELAY | O_SYNC);
 81    if (fd == -1)
 82      {
 83        ERRORPRINTF (t, E_ERROR | 67, "Opening %s failed: %s", dev, strerror(errno));
 84        goto ex1;
 85      }
 86  
 87    if (!set_low_latency (fd, &sold, low_latency))
 88      {
 89        ERRORPRINTF (t, E_ERROR | 68, "low_latency %s failed: %s", dev, strerror(errno));
 90        goto ex2;
 91      }
 92  
 93    close (fd);
 94  
 95    fd = open (dev.c_str(), O_RDWR | O_NOCTTY | O_SYNC);
 96    if (fd == -1)
 97      {
 98        ERRORPRINTF (t, E_ERROR | 69, "Opening %s failed: %s", dev, strerror(errno));
 99        goto ex1;
100      }
101  
102    if (tcgetattr (fd, &old))
103      {
104        ERRORPRINTF (t, E_ERROR | 24, "tcgetattr %s failed: %s", dev, strerror(errno));
105        goto ex3;
106      }
107  
108    if (tcgetattr (fd, &t1))
109      {
110        ERRORPRINTF (t, E_ERROR | 70, "tcgetattr %s failed: %s", dev, strerror(errno));
111        goto ex3;
112      }
113  
114    termios_settings(t1);
115    term_baudrate = getbaud(baudrate);
116    if (term_baudrate == -1)
117      {
118        ERRORPRINTF (t, E_ERROR | 71, "baudrate %d not recognized", baudrate);
119        goto ex3;
120      }
121    TRACEPRINTF(t, 0, "Opened %s with baud %d", dev, baudrate);
122    cfsetospeed (&t1, term_baudrate);
123    cfsetispeed (&t1, 0);
124  
125    if (tcsetattr (fd, TCSAFLUSH, &t1))
126      {
127        ERRORPRINTF (t, E_ERROR | 26, "tcsetattr %s failed: %s", dev, strerror(errno));
128        goto ex3;
129      }
130  
131    TRACEPRINTF (t, 2, "Opened");
132    FDdriver::start();
133    return;
134  
135  ex3:
136    restore_low_latency (fd, &sold, low_latency);
137  ex2:
138    close (fd);
139    fd = -1;
140  ex1:
141    stopped(true);
142  }
143  
144  void
145  LLserial::stop(bool err)
146  {
147    if (fd >= 0)
148      restore_low_latency (fd, &sold, low_latency);
149    FDdriver::stop(err);
150  }
151  
152  int
153  LLserial::enable_input_parity_check()
154  {
155    struct termios t1;
156  
157    TRACEPRINTF (t, 8, "Enabling input parity check on fd %d\n", fd);
158  
159    if (tcgetattr (fd, &t1))
160    {
161      ERRORPRINTF (t, E_ERROR | 70, "tcgetattr failed: %s", strerror(errno));
162      return -1;
163    }
164  
165    t1.c_iflag = t1.c_iflag | INPCK;
166  
167    if (tcsetattr (fd, TCSANOW, &t1))
168    {
169      ERRORPRINTF (t, E_ERROR | 70, "tcsetattr failed: %s", strerror(errno));
170      return -2;
171    }
172  
173    return 0;
174  }