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 36

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

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