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 }