/ src / libserver / lowlevel.cpp
lowlevel.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 "lowlevel.h"
 21  
 22  #include <cerrno>
 23  #include <fcntl.h>
 24  #include <unistd.h>
 25  
 26  LowLevelAdapter::~LowLevelAdapter()
 27  {
 28    delete iface;
 29  }
 30  
 31  LowLevelIface::~LowLevelIface()
 32  {
 33    local_timeout.stop();
 34  }
 35  
 36  LowLevelIface::LowLevelIface()
 37  {
 38    sendLocal_done.set<LowLevelIface,&LowLevelIface::sendLocal_done_cb>(this);
 39    local_timeout.set<LowLevelIface,&LowLevelIface::local_timeout_cb>(this);
 40  }
 41  
 42  LowLevelFilter::~LowLevelFilter()
 43  {
 44    delete iface;
 45  }
 46  
 47  void
 48  LowLevelIface::sendLocal_done_cb(bool success)
 49  {
 50    if (!success)
 51      stopped(true);
 52  }
 53  
 54  void
 55  LowLevelIface::send_Local(CArray &d, int raw)
 56  {
 57    assert(!is_local);
 58    is_local = true;
 59    local_timeout.start(1.5, 0);
 60    TRACEPRINTF (tr(), 0, "starting send_Local");
 61  
 62    do_send_Local(d, raw);
 63  }
 64  
 65  LowLevelFilter::LowLevelFilter (LowLevelIface* parent, IniSectionPtr& s, LowLevelDriver* i)
 66    : LowLevelDriver(parent,s)
 67  {
 68    t->setAuxName("LowF");
 69    if (i != nullptr)
 70      {
 71        i->resetMaster(this);
 72        iface = i;
 73        inserted = true;
 74      }
 75  }
 76  
 77  bool LowLevelFilter::setup()
 78  {
 79    if (iface == nullptr)
 80      return false;
 81    if (!LowLevelDriver::setup())
 82      return false;
 83    if (inserted)
 84      return true;
 85    return iface->setup();
 86  }
 87  
 88  void
 89  LowLevelFilter::do_send_Local(CArray &d, int raw)
 90  {
 91    if (raw)
 92      iface->do_send_Local(d, raw-1);
 93    else
 94      send_Data(d);
 95  }
 96  
 97  void
 98  LowLevelAdapter::do_send_Local(CArray &d, int raw)
 99  {
100    if (raw)
101      iface->do_send_Local(d, raw-1);
102    else
103      send_Data(d);
104  }
105  
106  void
107  LowLevelIface::local_timeout_cb(ev::timer &, int)
108  {
109    ERRORPRINTF (tr(), E_ERROR | 75, "send_Local timed out!");
110    is_local = false;
111    sendLocal_done(false);
112  }
113  
114  void
115  LowLevelIface::send_Next()
116  {
117    if (is_local)
118      {
119        TRACEPRINTF (tr(), 0, "send_Local done");
120        local_timeout.stop();
121        is_local = false;
122        sendLocal_done(true);
123      }
124    else
125      do_send_Next();
126  }
127  
128  void
129  LowLevelAdapter::send_L_Data(LDataPtr l)
130  {
131    if (!iface)
132      {
133        ERRORPRINTF (t, E_ERROR | 76, "Send: not running??");
134        stop(true);
135        return;
136      }
137    iface->send_L_Data(std::move(l));
138  }
139  
140  FDdriver::FDdriver (LowLevelIface* p, IniSectionPtr& s)
141    : sendbuf(), recvbuf(), LowLevelDriver (p,s)
142  {
143    t->setAuxName("FD");
144  }
145  
146  bool
147  FDdriver::setup()
148  {
149    if(!LowLevelDriver::setup())
150      return false;
151  
152    return true;
153  }
154  
155  void
156  FDdriver::setup_buffers()
157  {
158    TRACEPRINTF (t, 2, "Buffer Setup on fd %d", fd);
159    sendbuf.init(fd);
160    recvbuf.init(fd);
161    recvbuf.low_latency();
162  
163    recvbuf.on_read.set<FDdriver,&FDdriver::read_cb>(this);
164    recvbuf.on_error.set<FDdriver,&FDdriver::error_cb>(this);
165    sendbuf.on_error.set<FDdriver,&FDdriver::error_cb>(this);
166  
167    sendbuf.start();
168    recvbuf.start();
169  }
170  
171  void
172  FDdriver::error_cb()
173  {
174    ERRORPRINTF (t, E_ERROR | 77, "Communication error: %s", strerror(errno));
175    stop(true);
176  }
177  
178  FDdriver::~FDdriver ()
179  {
180    TRACEPRINTF (t, 2, "Close F");
181  
182    if (fd != -1)
183      {
184        sendbuf.stop(true);
185        recvbuf.stop(true);
186        close (fd);
187      }
188  }
189  
190  void
191  FDdriver::send_Data(CArray &c)
192  {
193    CArray *cp = new CArray(c);
194    sendbuf.write(cp);
195  }
196  
197  void
198  FDdriver::start()
199  {
200    setup_buffers();
201    LowLevelDriver::start();
202  }
203  
204  void
205  FDdriver::stop(bool err)
206  {
207    if (fd >= -1)
208      {
209        sendbuf.stop(true);
210        recvbuf.stop(true);
211  
212        close(fd);
213        fd = -1;
214      }
215    LowLevelDriver::stop(err);
216  }
217  
218  size_t
219  FDdriver::read_cb(uint8_t *buf, size_t len)
220  {
221    CArray c(buf,len);
222    recv_Data(c);
223    return len;
224  }
225  
226  bool
227  HWBusDriver::setup()
228  {
229    if (! BusDriver::setup())
230      return false;
231    if (! assureFilter("retry"))
232      return false;
233    return true;
234  }