OpenCores
URL https://opencores.org/ocsvn/w11/w11/trunk

Subversion Repositories w11

[/] [w11/] [tags/] [w11a_V0.7/] [tools/] [src/] [librlink/] [RlinkPort.cpp] - Blame information for rev 27

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 wfjm
// $Id: RlinkPort.cpp 611 2014-12-10 23:23:58Z mueller $
2 10 wfjm
//
3 27 wfjm
// Copyright 2011-2014 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4 10 wfjm
//
5
// This program is free software; you may redistribute and/or modify it under
6
// the terms of the GNU General Public License as published by the Free
7
// Software Foundation, either version 2, or at your option any later version.
8
//
9
// This program is distributed in the hope that it will be useful, but
10
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
11
// or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12
// for complete details.
13
// 
14
// Revision History: 
15
// Date         Rev Version  Comment
16 27 wfjm
// 2014-12-10   611   1.2.4  add time stamps for Read/Write for logs
17
// 2014-11-29   607   1.2.3  BUGFIX: fix time handling on RawRead()
18
// 2014-11-23   606   1.2.2  use Rtools::TimeOfDayAsDouble()
19
// 2014-08-22   584   1.2.1  use nullptr
20 19 wfjm
// 2013-02-23   492   1.2    use RparseUrl
21
// 2013-02-22   491   1.1    use new RlogFile/RlogMsg interfaces
22
// 2013-02-10   485   1.0.5  add static const defs
23
// 2013-02-03   481   1.0.4  use Rexception
24
// 2013-01-27   477   1.0.3  add RawRead(),RawWrite() methods
25 17 wfjm
// 2012-12-28   466   1.0.2  allow Close() even when not open
26
// 2012-12-26   465   1.0.1  add CloseFd() method
27 10 wfjm
// 2011-03-27   375   1.0    Initial version
28
// 2011-01-15   356   0.1    First draft
29
// ---------------------------------------------------------------------------
30
 
31
/*!
32
  \file
33 27 wfjm
  \version $Id: RlinkPort.cpp 611 2014-12-10 23:23:58Z mueller $
34 10 wfjm
  \brief   Implemenation of RlinkPort.
35
*/
36
 
37
#include <errno.h>
38
#include <unistd.h>
39
#include <poll.h>
40
 
41
#include <iostream>
42
 
43
#include "librtools/RosFill.hpp"
44
#include "librtools/RosPrintf.hpp"
45
#include "librtools/RosPrintBvi.hpp"
46 19 wfjm
#include "librtools/Rexception.hpp"
47
#include "librtools/RlogMsg.hpp"
48 27 wfjm
#include "librtools/Rtools.hpp"
49 10 wfjm
 
50 19 wfjm
#include "RlinkPort.hpp"
51
 
52 10 wfjm
using namespace std;
53
 
54
/*!
55
  \class Retro::RlinkPort
56
  \brief FIXME_docs
57
*/
58
 
59 19 wfjm
// all method definitions in namespace Retro
60
namespace Retro {
61
 
62 10 wfjm
//------------------------------------------+-----------------------------------
63 19 wfjm
// constants definitions
64
 
65
const int  RlinkPort::kEof;
66
const int  RlinkPort::kTout;
67
const int  RlinkPort::kErr;
68
 
69
//------------------------------------------+-----------------------------------
70 10 wfjm
//! Default constructor
71
 
72
RlinkPort::RlinkPort()
73
  : fIsOpen(false),
74
    fUrl(),
75
    fFdRead(-1),
76
    fFdWrite(-1),
77 19 wfjm
    fspLog(),
78 10 wfjm
    fTraceLevel(0),
79 27 wfjm
    fTsLastRead(-1.),
80
    fTsLastWrite(-1.),
81 10 wfjm
    fStats()
82
{
83 19 wfjm
  fStats.Define(kStatNPortWrite,    "NPortWrite", "Port::Write() calls");
84
  fStats.Define(kStatNPortRead,     "NPortRead",  "Port::Read() calls");
85
  fStats.Define(kStatNPortTxByt,    "NPortTxByt", "Port Tx bytes send");
86
  fStats.Define(kStatNPortRxByt,    "NPortRxByt", "Port Rx bytes rcvd");
87
  fStats.Define(kStatNPortRawWrite, "NPortRawWrite", "Port::RawWrite() calls");
88
  fStats.Define(kStatNPortRawRead,  "NPortRawRead",  "Port::RawRead() calls");
89 10 wfjm
}
90
 
91
//------------------------------------------+-----------------------------------
92
//! Destructor
93
 
94
RlinkPort::~RlinkPort()
95
{
96
  if (IsOpen()) RlinkPort::Close();
97
}
98
 
99
//------------------------------------------+-----------------------------------
100
//! FIXME_docs
101
 
102
void RlinkPort::Close()
103
{
104 17 wfjm
  if (!IsOpen()) return;
105 10 wfjm
 
106 17 wfjm
  if (fFdWrite == fFdRead) fFdWrite = -1;
107
  CloseFd(fFdWrite);
108
  CloseFd(fFdRead);
109 10 wfjm
 
110
  fIsOpen  = false;
111 19 wfjm
  fUrl.Clear();
112 10 wfjm
 
113
  return;
114
}
115
 
116
//------------------------------------------+-----------------------------------
117
//! FIXME_docs
118
 
119
int RlinkPort::Read(uint8_t* buf, size_t size, double timeout, RerrMsg& emsg)
120
{
121
  if (!IsOpen())
122 19 wfjm
    throw Rexception("RlinkPort::Read()","Bad state: port not open");
123 10 wfjm
  if (buf == 0)
124 27 wfjm
    throw Rexception("RlinkPort::Read()","Bad args: buf==nullptr");
125 10 wfjm
  if (size == 0)
126 19 wfjm
    throw Rexception("RlinkPort::Read()","Bad args: size==0");
127 10 wfjm
 
128
  fStats.Inc(kStatNPortRead);
129
 
130
  bool rdpoll = PollRead(timeout);
131
  if (!rdpoll) return kTout;
132
 
133
  int irc = -1;
134
  while (irc < 0) {
135 27 wfjm
    irc = ::read(fFdRead, (void*) buf, size);
136 10 wfjm
    if (irc < 0 && errno != EINTR) {
137
      emsg.InitErrno("RlinkPort::Read()", "read() failed : ", errno);
138 19 wfjm
      if (fspLog && fTraceLevel>0) fspLog->Write(emsg.Message(), 'E');
139 10 wfjm
      return kErr;
140
    }
141
  }
142
 
143 19 wfjm
  if (fspLog && fTraceLevel>0) {
144
    RlogMsg lmsg(*fspLog, 'I');
145
    lmsg << "port  read nchar=" << RosPrintf(irc,"d",4);
146 27 wfjm
    double now = Rtools::TimeOfDayAsDouble();
147
    if (fTsLastRead  > 0.)
148
      lmsg << "  dt_rd=" << RosPrintf(now-fTsLastRead,"f",8,6);
149
    if (fTsLastWrite > 0.)
150
      lmsg << "  dt_wr=" << RosPrintf(now-fTsLastWrite,"f",8,6);
151
    fTsLastRead = now;
152 10 wfjm
    if (fTraceLevel>1) {
153
      size_t ncol = (80-5-6)/(2+1);
154
      for (int i=0; i<irc; i++) {
155 19 wfjm
        if ((i%ncol)==0) lmsg << "\n     " << RosPrintf(i,"d",4) << ": ";
156
        lmsg << RosPrintBvi(buf[i],16) << " ";
157 10 wfjm
      }
158
    }
159
  }
160
 
161
  fStats.Inc(kStatNPortRxByt, double(irc));
162
 
163
  return irc;
164
}
165
 
166
//------------------------------------------+-----------------------------------
167
//! FIXME_docs
168
 
169
int RlinkPort::Write(const uint8_t* buf, size_t size, RerrMsg& emsg)
170
{
171
  if (!IsOpen())
172 19 wfjm
    throw Rexception("RlinkPort::Write()","Bad state: port not open");
173 10 wfjm
  if (buf == 0)
174 27 wfjm
    throw Rexception("RlinkPort::Write()","Bad args: buf==nullptr");
175 10 wfjm
  if (size == 0)
176 19 wfjm
    throw Rexception("RlinkPort::Write()","Bad args: size==0");
177 10 wfjm
 
178
  fStats.Inc(kStatNPortWrite);
179
 
180 19 wfjm
  if (fspLog && fTraceLevel>0) {
181
    RlogMsg lmsg(*fspLog, 'I');
182
    lmsg << "port write nchar=" << RosPrintf(size,"d",4);
183 27 wfjm
    double now = Rtools::TimeOfDayAsDouble();
184
    if (fTsLastRead  > 0.)
185
      lmsg << "  dt_rd=" << RosPrintf(now-fTsLastRead,"f",8,6);
186
    if (fTsLastWrite > 0.)
187
      lmsg << "  dt_wr=" << RosPrintf(now-fTsLastWrite,"f",8,6);
188
    fTsLastWrite = now;
189 10 wfjm
    if (fTraceLevel>1) {
190
      size_t ncol = (80-5-6)/(2+1);
191
      for (size_t i=0; i<size; i++) {
192 19 wfjm
        if ((i%ncol)==0) lmsg << "\n     " << RosPrintf(i,"d",4) << ": ";
193
        lmsg << RosPrintBvi(buf[i],16) << " ";
194 10 wfjm
      }
195
    }
196
  }
197
 
198
  size_t ndone = 0;
199
  while (ndone < size) {
200
    int irc = -1;
201
    while (irc < 0) {
202 27 wfjm
      irc = ::write(fFdWrite, (void*) (buf+ndone), size-ndone);
203 10 wfjm
      if (irc < 0 && errno != EINTR) {
204
        emsg.InitErrno("RlinkPort::Write()", "write() failed : ", errno);
205 19 wfjm
        if (fspLog && fTraceLevel>0) fspLog->Write(emsg.Message(), 'E');
206 10 wfjm
        return kErr;
207
      }
208
    }
209
    // FIXME_code: handle eof ??
210
    ndone += irc;
211
  }
212
 
213
  fStats.Inc(kStatNPortTxByt, double(ndone));
214
 
215
  return ndone;
216
}
217
 
218
//------------------------------------------+-----------------------------------
219
//! FIXME_docs
220
 
221
bool RlinkPort::PollRead(double timeout)
222
{
223
  if (! IsOpen())
224 19 wfjm
    throw Rexception("RlinkPort::PollRead()","Bad state: port not open");
225 10 wfjm
  if (timeout < 0.)
226 19 wfjm
    throw Rexception("RlinkPort::PollRead()","Bad args: timeout < 0");
227 10 wfjm
 
228
  int ito = 1000.*timeout + 0.1;
229
 
230
  struct pollfd fds[1] = {{fFdRead,         // fd
231
                           POLLIN,          // events
232
                           0}};             // revents
233
 
234
 
235
  int irc = -1;
236
  while (irc < 0) {
237 27 wfjm
    irc = ::poll(fds, 1, ito);
238 10 wfjm
    if (irc < 0 && errno != EINTR)
239 19 wfjm
      throw Rexception("RlinkPort::PollRead()","poll() failed: rc<0: ", errno);
240 10 wfjm
  }
241
 
242
  if (irc == 0) return false;
243
 
244
  if (fds[0].revents == POLLERR)
245 19 wfjm
    throw Rexception("RlinkPort::PollRead()", "poll() failed: POLLERR");
246 10 wfjm
 
247
  return true;
248
}
249
 
250
//------------------------------------------+-----------------------------------
251
//! FIXME_docs
252 19 wfjm
int RlinkPort::RawRead(uint8_t* buf, size_t size, bool exactsize,
253
                       double timeout, double& tused, RerrMsg& emsg)
254
{
255
  if (timeout <= 0.)
256
    throw Rexception("RlinkPort::RawRead()", "Bad args: timeout <= 0.");
257
  if (size <= 0)
258
    throw Rexception("RlinkPort::RawRead()", "Bad args: size <= 0");
259 10 wfjm
 
260 19 wfjm
  fStats.Inc(kStatNPortRawRead);
261
  tused = 0.;
262
 
263 27 wfjm
  double tnow = Rtools::TimeOfDayAsDouble();
264
  double tend = tnow + timeout;
265
  double tbeg = tnow;
266 19 wfjm
 
267
  size_t ndone = 0;
268 27 wfjm
  while (tnow < tend && ndone<size) {
269
    int irc = Read(buf+ndone, size-ndone, tend-tnow, emsg);
270
    tnow  = Rtools::TimeOfDayAsDouble();
271
    tused = tnow - tbeg;
272 19 wfjm
    if (irc <= 0) return irc;
273
    if (!exactsize) break;
274
    ndone += irc;
275
  }
276
 
277
  return (int)ndone;
278 10 wfjm
}
279
 
280
//------------------------------------------+-----------------------------------
281
//! FIXME_docs
282 19 wfjm
int RlinkPort::RawWrite(const uint8_t* buf, size_t size, RerrMsg& emsg)
283 10 wfjm
{
284 19 wfjm
  fStats.Inc(kStatNPortRawWrite);
285
  return Write(buf, size, emsg);
286 10 wfjm
}
287
 
288
//------------------------------------------+-----------------------------------
289
//! FIXME_docs
290
 
291
void RlinkPort::Dump(std::ostream& os, int ind, const char* text) const
292
{
293
  RosFill bl(ind);
294
  os << bl << (text?text:"--") << "RlinkPort @ " << this << endl;
295
 
296
  os << bl << "  fIsOpen:         " << (int)fIsOpen << endl;
297 19 wfjm
  fUrl.Dump(os, ind+2, "fUrl: ");
298 10 wfjm
  os << bl << "  fFdRead:         " << fFdRead << endl;
299
  os << bl << "  fFdWrite:        " << fFdWrite << endl;
300 19 wfjm
  os << bl << "  fspLog:          " << fspLog.get() << endl;
301
  os << bl << "  fTraceLevel:     " << fTraceLevel << endl;
302 27 wfjm
  //FIXME_code: fTsLastRead, fTsLastWrite not yet in Dump (get formatter...)
303 10 wfjm
  fStats.Dump(os, ind+2, "fStats: ");
304
  return;
305
}
306
 
307
//------------------------------------------+-----------------------------------
308
//! FIXME_docs
309
 
310 17 wfjm
void RlinkPort::CloseFd(int& fd)
311
{
312
  if (fd >= 0) {
313 27 wfjm
    ::close(fd);
314 17 wfjm
    fd  = -1;
315
  }
316
  return;
317
}
318
 
319 19 wfjm
} // end namespace Retro

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.