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

Subversion Repositories w11

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

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

Line No. Rev Author Line
1 17 wfjm
// $Id: RlinkPort.cpp 466 2012-12-30 13:26:55Z mueller $
2 10 wfjm
//
3
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4
//
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 17 wfjm
// 2012-12-28   466   1.0.2  allow Close() even when not open
17
// 2012-12-26   465   1.0.1  add CloseFd() method
18 10 wfjm
// 2011-03-27   375   1.0    Initial version
19
// 2011-01-15   356   0.1    First draft
20
// ---------------------------------------------------------------------------
21
 
22
/*!
23
  \file
24 17 wfjm
  \version $Id: RlinkPort.cpp 466 2012-12-30 13:26:55Z mueller $
25 10 wfjm
  \brief   Implemenation of RlinkPort.
26
*/
27
 
28
#include <errno.h>
29
#include <unistd.h>
30
#include <poll.h>
31
 
32
#include <stdexcept>
33
#include <iostream>
34
 
35
#include "RlinkPort.hpp"
36
 
37
#include "librtools/RosFill.hpp"
38
#include "librtools/RosPrintf.hpp"
39
#include "librtools/RosPrintBvi.hpp"
40
 
41
using namespace std;
42
using namespace Retro;
43
 
44
/*!
45
  \class Retro::RlinkPort
46
  \brief FIXME_docs
47
*/
48
 
49
//------------------------------------------+-----------------------------------
50
//! Default constructor
51
 
52
RlinkPort::RlinkPort()
53
  : fIsOpen(false),
54
    fUrl(),
55
    fScheme(),
56
    fPath(),
57
    fOptMap(),
58
    fFdRead(-1),
59
    fFdWrite(-1),
60
    fpLogFile(0),
61
    fTraceLevel(0),
62
    fStats()
63
{
64
  fStats.Define(kStatNPortWrite, "NPortWrite", "Port::Write() calls");
65
  fStats.Define(kStatNPortRead,  "NPortRead",  "Port::Read() calls");
66
  fStats.Define(kStatNPortTxByt, "NPortTxByt", "Port Tx raw bytes send");
67
  fStats.Define(kStatNPortRxByt, "NPortRxByt", "Port Rx raw bytes rcvd");
68
}
69
 
70
//------------------------------------------+-----------------------------------
71
//! Destructor
72
 
73
RlinkPort::~RlinkPort()
74
{
75
  if (IsOpen()) RlinkPort::Close();
76
}
77
 
78
//------------------------------------------+-----------------------------------
79
//! FIXME_docs
80
 
81
void RlinkPort::Close()
82
{
83 17 wfjm
  if (!IsOpen()) return;
84 10 wfjm
 
85 17 wfjm
  if (fFdWrite == fFdRead) fFdWrite = -1;
86
  CloseFd(fFdWrite);
87
  CloseFd(fFdRead);
88 10 wfjm
 
89
  fIsOpen  = false;
90
  fUrl.clear();
91
  fScheme.clear();
92
  fPath.clear();
93
  fOptMap.clear();
94
 
95
  return;
96
}
97
 
98
//------------------------------------------+-----------------------------------
99
//! FIXME_docs
100
 
101
int RlinkPort::Read(uint8_t* buf, size_t size, double timeout, RerrMsg& emsg)
102
{
103
  if (!IsOpen())
104
    throw logic_error("RlinkPort::Read(): port not open");
105
  if (buf == 0)
106
    throw invalid_argument("RlinkPort::Read(): buf==NULL");
107
  if (size == 0)
108
    throw invalid_argument("RlinkPort::Read(): size==0");
109
 
110
  fStats.Inc(kStatNPortRead);
111
 
112
  bool rdpoll = PollRead(timeout);
113
  if (!rdpoll) return kTout;
114
 
115
  int irc = -1;
116
  while (irc < 0) {
117
    irc = read(fFdRead, (void*) buf, size);
118
    if (irc < 0 && errno != EINTR) {
119
      emsg.InitErrno("RlinkPort::Read()", "read() failed : ", errno);
120
      if (fpLogFile && fTraceLevel>0) (*fpLogFile)('E') << emsg << endl;
121
      return kErr;
122
    }
123
  }
124
 
125
  if (fpLogFile && fTraceLevel>0) {
126
    ostream& os = (*fpLogFile)();
127
    (*fpLogFile)('I') << "port  read nchar=" << RosPrintf(irc,"d",4);
128
    if (fTraceLevel>1) {
129
      size_t ncol = (80-5-6)/(2+1);
130
      for (int i=0; i<irc; i++) {
131
        if ((i%ncol)==0) os << "\n     " << RosPrintf(i,"d",4) << ": ";
132
        os << RosPrintBvi(buf[i],16) << " ";
133
      }
134
    }
135
    os << endl;
136
  }
137
 
138
  fStats.Inc(kStatNPortRxByt, double(irc));
139
 
140
  return irc;
141
}
142
 
143
//------------------------------------------+-----------------------------------
144
//! FIXME_docs
145
 
146
int RlinkPort::Write(const uint8_t* buf, size_t size, RerrMsg& emsg)
147
{
148
  if (!IsOpen())
149
    throw logic_error("RlinkPort::Write(): port not open");
150
  if (buf == 0)
151
    throw invalid_argument("RlinkPort::Write(): buf==NULL");
152
  if (size == 0)
153
    throw invalid_argument("RlinkPort::Write(): size==0");
154
 
155
  fStats.Inc(kStatNPortWrite);
156
 
157
  if (fpLogFile && fTraceLevel>0) {
158
    ostream& os = (*fpLogFile)();
159
    (*fpLogFile)('I') << "port write nchar=" << RosPrintf(size,"d",4);
160
    if (fTraceLevel>1) {
161
      size_t ncol = (80-5-6)/(2+1);
162
      for (size_t i=0; i<size; i++) {
163
        if ((i%ncol)==0) os << "\n     " << RosPrintf(i,"d",4) << ": ";
164
        os << RosPrintBvi(buf[i],16) << " ";
165
      }
166
    }
167
    os << endl;
168
  }
169
 
170
  size_t ndone = 0;
171
  while (ndone < size) {
172
    int irc = -1;
173
    while (irc < 0) {
174
      irc = write(fFdWrite, (void*) (buf+ndone), size-ndone);
175
      if (irc < 0 && errno != EINTR) {
176
        emsg.InitErrno("RlinkPort::Write()", "write() failed : ", errno);
177
        if (fpLogFile && fTraceLevel>0) (*fpLogFile)('E') << emsg << endl;
178
        return kErr;
179
      }
180
    }
181
    // FIXME_code: handle eof ??
182
    ndone += irc;
183
  }
184
 
185
  fStats.Inc(kStatNPortTxByt, double(ndone));
186
 
187
  return ndone;
188
}
189
 
190
//------------------------------------------+-----------------------------------
191
//! FIXME_docs
192
 
193
bool RlinkPort::PollRead(double timeout)
194
{
195
  if (! IsOpen())
196
    throw logic_error("RlinkPort::PollRead(): port not open");
197
  if (timeout < 0.)
198
    throw invalid_argument("RlinkPort::PollRead(): timeout < 0");
199
 
200
  int ito = 1000.*timeout + 0.1;
201
 
202
  struct pollfd fds[1] = {{fFdRead,         // fd
203
                           POLLIN,          // events
204
                           0}};             // revents
205
 
206
 
207
  int irc = -1;
208
  while (irc < 0) {
209
    irc = poll(fds, 1, ito);
210
    if (irc < 0 && errno != EINTR)
211
      throw logic_error("RlinkPort::PollRead(): poll failed: rc<0");
212
  }
213
 
214
  if (irc == 0) return false;
215
 
216
  if (fds[0].revents == POLLERR)
217
    throw logic_error("RlinkPort::PollRead(): poll failed: POLLERR");
218
 
219
  return true;
220
}
221
 
222
//------------------------------------------+-----------------------------------
223
//! FIXME_docs
224
 
225
bool RlinkPort::UrlFindOpt(const std::string& name) const
226
{
227
  omap_cit_t it = fOptMap.find(name);
228
  if (it == fOptMap.end()) return false;
229
  return true;
230
}
231
 
232
//------------------------------------------+-----------------------------------
233
//! FIXME_docs
234
 
235
bool RlinkPort::UrlFindOpt(const std::string& name, std::string& value) const
236
{
237
  omap_cit_t it = fOptMap.find(name);
238
  if (it == fOptMap.end()) return false;
239
 
240
  value = it->second;
241
 
242
  return true;
243
}
244
 
245
//------------------------------------------+-----------------------------------
246
//! FIXME_docs
247
 
248
void RlinkPort::Dump(std::ostream& os, int ind, const char* text) const
249
{
250
  RosFill bl(ind);
251
  os << bl << (text?text:"--") << "RlinkPort @ " << this << endl;
252
 
253
  os << bl << "  fIsOpen:         " << (int)fIsOpen << endl;
254
  os << bl << "  fUrl:            " << fUrl << endl;
255
  os << bl << "  fScheme:         " << fScheme << endl;
256
  os << bl << "  fPath:           " << fPath << endl;
257
  os << bl << "  fOptMap:         " << endl;
258
  for (omap_cit_t it=fOptMap.begin(); it!=fOptMap.end(); it++) {
259
    os << bl << "    " << RosPrintf((it->first).c_str(), "-s",8)
260
       << " : " << it->second << endl;
261
  }
262
  os << bl << "  fFdRead:         " << fFdRead << endl;
263
  os << bl << "  fFdWrite:        " << fFdWrite << endl;
264
  fStats.Dump(os, ind+2, "fStats: ");
265
  return;
266
}
267
 
268
//------------------------------------------+-----------------------------------
269
//! FIXME_docs
270
 
271
bool RlinkPort::ParseUrl(const std::string& url, const std::string& optlist,
272
                         RerrMsg& emsg)
273
{
274
  fUrl.clear();
275
  fScheme.clear();
276
  fPath.clear();
277
  fOptMap.clear();
278
 
279
  size_t pdel = url.find_first_of(':');
280
  if (pdel == string::npos) {
281
    emsg.Init("RlinkPort::ParseUrl()",
282
              string("no scheme specified in url \"") + url + string("\""));
283
    return false;
284
  }
285
 
286
  fUrl = url;
287
  fScheme = url.substr(0, pdel);
288
 
289
  size_t odel = url.find_first_of('?', pdel);
290
  if (odel == string::npos) {               // no options
291
    if (url.length() > pdel+1) fPath = url.substr(pdel+1);
292
 
293
  } else {                                  // options to process
294
    fPath = url.substr(pdel+1,odel-(pdel+1));
295
    string key;
296
    string val;
297
    bool   hasval = false;
298
 
299
    for (size_t i=odel+1; i<url.length(); i++) {
300
      char c = url[i];
301
      if (c == ';') {
302
        if (!AddOpt(key, val, hasval, optlist, emsg)) return false;
303
        key.clear();
304
        val.clear();
305
        hasval = false;
306
      } else {
307
        if (!hasval) {
308
          if (c == '=') {
309
            hasval = true;
310
          } else
311
            key.push_back(c);
312
        } else {
313
          if (c == '\\') {
314
            if (i+1 >= url.length()) {
315
              emsg.Init("RlinkPort::ParseUrl()",
316
                        string("invalid trailing \\ in url \"") + url +
317
                        string("\""));
318
              return false;
319
            }
320
            i += 1;
321
            switch (url[i]) {
322
              case '\\' : c = '\\'; break;
323
              case ';'  : c = ';';  break;
324
              default   : emsg.Init("RlinkPort::ParseUrl()",
325
                                    string("invalid \\ escape in url \"") +
326
                                    url + string("\""));
327
                          return false;
328
            }
329
          }
330
          val.push_back(c);
331
        }
332
      }
333
    }
334
    if (key.length() || hasval) {
335
      if (!AddOpt(key, val, hasval, optlist, emsg)) return false;
336
    }
337
  }
338
 
339
  return true;
340
}
341 17 wfjm
//
342 10 wfjm
//------------------------------------------+-----------------------------------
343
//! FIXME_docs
344
 
345
bool RlinkPort::AddOpt(const std::string& key, const std::string& val,
346
                       bool hasval, const std::string& optlist, RerrMsg& emsg)
347
{
348
  string lkey = "|";
349
  lkey += key;
350
  if (hasval) lkey += "=";
351
  lkey += "|";
352
  if (optlist.find(lkey) == string::npos) {
353
    emsg.Init("RlinkPort::AddOpt()",
354
              string("invalid field name \"") + lkey + string("\""));
355
  }
356
 
357
  fOptMap.insert(omap_val_t(key, hasval ? val : "1"));
358
  return true;
359
}
360
 
361
//------------------------------------------+-----------------------------------
362 17 wfjm
//! FIXME_docs
363
 
364
void RlinkPort::CloseFd(int& fd)
365
{
366
  if (fd >= 0) {
367
    close(fd);
368
    fd  = -1;
369
  }
370
  return;
371
}
372
 
373
//------------------------------------------+-----------------------------------
374 10 wfjm
#if (defined(Retro_NoInline) || defined(Retro_RlinkPort_NoInline))
375
#define inline
376
#include "RlinkPort.ipp"
377
#undef  inline
378
#endif

powered by: WebSVN 2.1.0

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