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

Subversion Repositories w11

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

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

Line No. Rev Author Line
1 29 wfjm
// $Id: RlinkPortTerm.cpp 641 2015-02-01 22:12:15Z mueller $
2 10 wfjm
//
3 29 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 29 wfjm
// 2015-02-01   641   1.2    support custom baud rates (5M,6M,10M,12M)
17 19 wfjm
// 2013-02-23   492   1.1    use RparseUrl
18 16 wfjm
// 2011-12-18   440   1.0.4  add kStatNPort stats; Open(): autoadd /dev/tty,
19
//                           BUGFIX: Open(): set VSTART, VSTOP
20
// 2011-12-11   438   1.0.3  Read(),Write(): added for xon handling, tcdrain();
21
//                           Open(): add more baud rates, support xon attribute
22 15 wfjm
// 2011-12-04   435   1.0.2  Open(): add cts attr, hw flow control now optional
23 12 wfjm
// 2011-07-04   388   1.0.1  add termios readback and verification
24 10 wfjm
// 2011-03-27   374   1.0    Initial version
25
// ---------------------------------------------------------------------------
26
 
27
/*!
28
  \file
29 29 wfjm
  \version $Id: RlinkPortTerm.cpp 641 2015-02-01 22:12:15Z mueller $
30 10 wfjm
  \brief   Implemenation of RlinkPortTerm.
31
*/
32
 
33
#include <sys/types.h>
34
#include <sys/stat.h>
35
#include <fcntl.h>
36
#include <errno.h>
37
#include <unistd.h>
38
#include <termios.h>
39 29 wfjm
#include <sys/ioctl.h>
40
#include <linux/serial.h>
41 10 wfjm
 
42
#include "RlinkPortTerm.hpp"
43
 
44
#include "librtools/RosFill.hpp"
45
#include "librtools/RosPrintf.hpp"
46
 
47
using namespace std;
48
 
49
/*!
50
  \class Retro::RlinkPortTerm
51 19 wfjm
  \brief FIXME_docs
52 10 wfjm
*/
53
 
54 19 wfjm
// all method definitions in namespace Retro
55
namespace Retro {
56
 
57 10 wfjm
//------------------------------------------+-----------------------------------
58 16 wfjm
// constants definitions
59
const uint8_t RlinkPortTerm::kc_xon;
60
const uint8_t RlinkPortTerm::kc_xoff;
61
const uint8_t RlinkPortTerm::kc_xesc;
62
 
63
//------------------------------------------+-----------------------------------
64 10 wfjm
//! Default constructor
65
 
66
RlinkPortTerm::RlinkPortTerm()
67
  : RlinkPort()
68 16 wfjm
{
69
  fStats.Define(kStatNPortTxXesc, "NPortTxXesc", "Tx XESC escapes");
70
  fStats.Define(kStatNPortRxXesc, "NPortRxXesc", "Rx XESC escapes");
71
}
72 10 wfjm
 
73
//------------------------------------------+-----------------------------------
74
//! Destructor
75
 
76
RlinkPortTerm::~RlinkPortTerm()
77
{
78 19 wfjm
  RlinkPortTerm::Close();
79 10 wfjm
}
80
 
81
//------------------------------------------+-----------------------------------
82 19 wfjm
//! FIXME_docs
83 10 wfjm
 
84
bool RlinkPortTerm::Open(const std::string& url, RerrMsg& emsg)
85
{
86 19 wfjm
  Close();
87 10 wfjm
 
88 19 wfjm
  if (!fUrl.Set(url, "|baud=|break|cts|xon|", emsg)) return false;
89 10 wfjm
 
90 16 wfjm
  // if path doesn't start with a '/' prepend a '/dev/tty'
91 19 wfjm
  if (fUrl.Path().substr(0,1) != "/") {
92
    fUrl.SetPath(string("/dev/tty" + fUrl.Path()));
93 16 wfjm
  }
94
 
95 10 wfjm
  speed_t speed = B115200;
96 29 wfjm
  unsigned long nsbaud = 0;
97 10 wfjm
  string baud;
98 19 wfjm
  if (fUrl.FindOpt("baud", baud)) {
99 10 wfjm
    speed = B0;
100 16 wfjm
    if (baud=="2400")                     speed = B2400;
101
    if (baud=="4800")                     speed = B4800;
102 10 wfjm
    if (baud=="9600")                     speed = B9600;
103
    if (baud=="19200"   || baud=="19k")   speed = B19200;
104
    if (baud=="38400"   || baud=="38k")   speed = B38400;
105
    if (baud=="57600"   || baud=="57k")   speed = B57600;
106
    if (baud=="115200"  || baud=="115k")  speed = B115200;
107
    if (baud=="230400"  || baud=="230k")  speed = B230400;
108
    if (baud=="460800"  || baud=="460k")  speed = B460800;
109
    if (baud=="500000"  || baud=="500k")  speed = B500000;
110
    if (baud=="921600"  || baud=="921k")  speed = B921600;
111 16 wfjm
    if (baud=="1000000" || baud=="1000k" || baud=="1M") speed = B1000000;
112
    if (baud=="1152000" || baud=="1152k")               speed = B1152000;
113
    if (baud=="1500000" || baud=="1500k")               speed = B1500000;
114
    if (baud=="2000000" || baud=="2000k" || baud=="2M") speed = B2000000;
115
    if (baud=="2500000" || baud=="2500k")               speed = B2500000;
116
    if (baud=="3000000" || baud=="3000k" || baud=="3M") speed = B3000000;
117
    if (baud=="3500000" || baud=="3500k")               speed = B3500000;
118
    if (baud=="4000000" || baud=="4000k" || baud=="4M") speed = B4000000;
119 29 wfjm
 
120
    // now handle non-standart baud rates
121 10 wfjm
    if (speed == B0) {
122 29 wfjm
      if (baud== "5000000" || baud== "5000k" || baud== "5M") nsbaud =  5000000;
123
      if (baud== "6000000" || baud== "6000k" || baud== "6M") nsbaud =  6000000;
124
      if (baud== "6666666" || baud== "6666k")                nsbaud =  6666666;
125
      if (baud=="10000000" || baud=="10000k" || baud=="10M") nsbaud = 10000000;
126
      if (baud=="12000000" || baud=="12000k" || baud=="12M") nsbaud = 12000000;
127
      if (nsbaud == 0) {
128
        emsg.Init("RlinkPortTerm::Open()",
129
                  string("invalid baud rate '") + baud + "' specified");
130
        return false;
131
      }
132 10 wfjm
    }
133
  }
134
 
135
  int fd;
136
 
137 19 wfjm
  fd = open(fUrl.Path().c_str(), O_RDWR|O_NOCTTY);
138 10 wfjm
  if (fd < 0) {
139
    emsg.InitErrno("RlinkPortTerm::Open()",
140 21 wfjm
                   string("open() for '") + fUrl.Path() + "' failed: ",
141 10 wfjm
                   errno);
142
    return false;
143
  }
144
 
145
  if (!isatty(fd)) {
146
    emsg.Init("RlinkPortTerm::Open()",
147 21 wfjm
              string("isatty() check for '") + fUrl.Path() +
148
              "' failed: not a TTY");
149 10 wfjm
    close(fd);
150
    return false;
151
  }
152
 
153 27 wfjm
  if (::tcgetattr(fd, &fTiosOld) != 0) {
154 10 wfjm
    emsg.InitErrno("RlinkPortTerm::Open()",
155 21 wfjm
                   string("tcgetattr() for '") + fUrl.Path() + "' failed: ",
156 10 wfjm
                   errno);
157 27 wfjm
    ::close(fd);
158 10 wfjm
    return false;
159
  }
160
 
161 29 wfjm
  struct serial_struct sioctl;
162
  int cdivisor = 0;
163
 
164
  if (nsbaud != 0) {
165
    if (::ioctl(fd, TIOCGSERIAL, &sioctl) < 0) {
166
      emsg.InitErrno("RlinkPortTerm::Open()",
167
                     string("ioctl(TIOCGSERIAL) for '")+fUrl.Path()+"' failed: ",
168
                     errno);
169
      ::close(fd);
170
      return false;
171
    }
172
    double fcdivisor = double(sioctl.baud_base) / double(nsbaud);
173
    cdivisor = fcdivisor + 0.5;
174
    speed    = B38400;
175
  }
176
 
177 19 wfjm
  bool use_cts = fUrl.FindOpt("cts");
178
  bool use_xon = fUrl.FindOpt("xon");
179 16 wfjm
  fUseXon = use_xon;
180
  fPendXesc = false;
181
 
182 10 wfjm
  fTiosNew = fTiosOld;
183
 
184
  fTiosNew.c_iflag = IGNBRK |               // ignore breaks on input
185
                     IGNPAR;                // ignore parity errors
186 16 wfjm
  if (use_xon) {
187
    fTiosNew.c_iflag |= IXON|               // XON/XOFF flow control output
188
                        IXOFF;              // XON/XOFF flow control input
189
  }
190 15 wfjm
 
191 10 wfjm
  fTiosNew.c_oflag = 0;
192 15 wfjm
 
193 10 wfjm
  fTiosNew.c_cflag = CS8 |                  // 8 bit chars
194
                     CSTOPB |               // 2 stop bits
195
                     CREAD |                // enable receiver
196 15 wfjm
                     CLOCAL;                // ignore modem control
197 16 wfjm
  if (use_cts) {
198 15 wfjm
    fTiosNew.c_cflag |= CRTSCTS;            // enable hardware flow control
199
  }
200
 
201 10 wfjm
  fTiosNew.c_lflag = 0;
202
 
203 27 wfjm
  if (::cfsetspeed(&fTiosNew, speed) != 0) {
204 10 wfjm
    emsg.InitErrno("RlinkPortTerm::Open()",
205 21 wfjm
                   string("cfsetspeed() for '") + baud + "' failed: ",
206 10 wfjm
                   errno);
207
    close(fd);
208
    return false;
209
  }
210
 
211 29 wfjm
  if (cdivisor != 0) {
212
    sioctl.flags          |= ASYNC_SPD_CUST;
213
    sioctl.custom_divisor  = cdivisor;
214
    if (::ioctl(fd, TIOCSSERIAL, &sioctl) < 0) {
215
      emsg.InitErrno("RlinkPortTerm::Open()",
216
                     string("ioctl(TIOCSSERIAL) for '")+fUrl.Path()+"' failed: ",
217
                     errno);
218
      ::close(fd);
219
      return false;
220
    }
221
  }
222
 
223 10 wfjm
  fTiosNew.c_cc[VEOF]   = 0;                // undef
224
  fTiosNew.c_cc[VEOL]   = 0;                // undef
225
  fTiosNew.c_cc[VERASE] = 0;                // undef
226
  fTiosNew.c_cc[VINTR]  = 0;                // undef
227
  fTiosNew.c_cc[VKILL]  = 0;                // undef
228
  fTiosNew.c_cc[VQUIT]  = 0;                // undef
229
  fTiosNew.c_cc[VSUSP]  = 0;                // undef
230
  fTiosNew.c_cc[VSTART] = 0;                // undef
231
  fTiosNew.c_cc[VSTOP]  = 0;                // undef
232
  fTiosNew.c_cc[VMIN]   = 1;                // wait for 1 char
233
  fTiosNew.c_cc[VTIME]  = 0;                // 
234 16 wfjm
  if (use_xon) {
235
    fTiosNew.c_cc[VSTART] = kc_xon;         // setup XON  -> ^Q
236
    fTiosNew.c_cc[VSTOP]  = kc_xoff;        // setup XOFF -> ^S   
237
  }
238 10 wfjm
 
239 27 wfjm
  if (::tcsetattr(fd, TCSANOW, &fTiosNew) != 0) {
240 10 wfjm
    emsg.InitErrno("RlinkPortTerm::Open()",
241 21 wfjm
                   string("tcsetattr() for '") + fUrl.Path() + "' failed: ",
242 10 wfjm
                   errno);
243 27 wfjm
    ::close(fd);
244 10 wfjm
    return false;
245
  }
246
 
247 12 wfjm
  // tcsetattr() returns success if any of the requested changes could be
248
  // successfully carried out. Therefore the termios structure is read back
249
  // and verified.
250
 
251
  struct termios tios;
252 27 wfjm
  if (::tcgetattr(fd, &tios) != 0) {
253 12 wfjm
    emsg.InitErrno("RlinkPortTerm::Open()",
254 21 wfjm
                   string("2nd tcgetattr() for '") + fUrl.Path() +
255
                   "' failed: ", errno);
256 27 wfjm
    ::close(fd);
257 12 wfjm
    return false;
258
  }
259
 
260
  const char* pmsg = 0;
261
  if (tios.c_iflag != fTiosNew.c_iflag) pmsg = "c_iflag";
262
  if (tios.c_oflag != fTiosNew.c_oflag) pmsg = "c_oflag";
263
  if (tios.c_cflag != fTiosNew.c_cflag) pmsg = "c_cflag";
264
  if (tios.c_lflag != fTiosNew.c_lflag) pmsg = "c_lflag";
265 27 wfjm
  if (::cfgetispeed(&tios) != speed)      pmsg = "ispeed";
266
  if (::cfgetospeed(&tios) != speed)      pmsg = "ospeed";
267 12 wfjm
  for (int i=0; i<NCCS; i++) {
268
    if (tios.c_cc[i] != fTiosNew.c_cc[i]) pmsg = "c_cc char";
269
  }
270
 
271 29 wfjm
  // FIXME_code: why does readback fail for 38400 ?
272
  if (speed != B38400 && pmsg) {
273 12 wfjm
    emsg.Init("RlinkPortTerm::Open()",
274 21 wfjm
              string("tcsetattr() failed to set") + string(pmsg));
275 27 wfjm
    ::close(fd);
276 12 wfjm
    return false;
277
  }
278
 
279 10 wfjm
  fFdWrite = fd;
280
  fFdRead  = fd;
281
  fIsOpen  = true;
282
 
283 19 wfjm
  if (fUrl.FindOpt("break")) {
284 10 wfjm
    if (tcsendbreak(fd, 0) != 0) {
285
      emsg.InitErrno("RlinkPortTerm::Open()",
286 19 wfjm
                     string("tcsendbreak() for '") + fUrl.Path() +
287 21 wfjm
                     "' failed: ", errno);
288 10 wfjm
      Close();
289
      return false;
290
    }
291
    uint8_t buf[1];
292
    buf[0] = 0x80;
293
    if (Write(buf, 1, emsg) != 1) {
294
      Close();
295
      return false;
296
    }
297
  }
298
 
299
  return true;
300
}
301
 
302
//------------------------------------------+-----------------------------------
303 19 wfjm
//! FIXME_docs
304 10 wfjm
 
305
void RlinkPortTerm::Close()
306
{
307 17 wfjm
  if (!IsOpen()) return;
308
 
309
  if (fFdWrite >= 0) {
310 27 wfjm
    ::tcflush(fFdWrite, TCIOFLUSH);
311
    ::tcsetattr(fFdWrite, TCSANOW, &fTiosOld);
312 10 wfjm
  }
313 17 wfjm
  RlinkPort::Close();
314
 
315 10 wfjm
  return;
316
}
317
 
318
//------------------------------------------+-----------------------------------
319 16 wfjm
//! FIXME_docs
320
 
321
int RlinkPortTerm::Read(uint8_t* buf, size_t size, double timeout,
322
                        RerrMsg& emsg)
323
{
324
  int irc;
325
  if (fUseXon) {
326
    uint8_t* po = buf;
327
    if (fRxBuf.size() < size) fRxBuf.resize(size);
328
 
329 17 wfjm
    // repeat read until at least one byte returned (or an error occurs)
330 16 wfjm
    // this avoids that the Read() returns with 0 in case only one byte is
331
    // seen and this is a kc_xesc. At most two iterations possible because
332
    // in 2nd iteration fPendXesc must be set and thus po pushed.
333
    while (po == buf) {
334
      irc = RlinkPort::Read(fRxBuf.data(), size, timeout, emsg);
335
      if (irc <= 0) break;
336
      uint8_t* pi = fRxBuf.data();
337
      for (int i=0; i<irc; i++) {
338
        uint8_t c = *pi++;
339
        if (fPendXesc) {
340
          *po++ = ~c;
341
          fPendXesc = false;
342
        } else if (c == kc_xesc) {
343
          fStats.Inc(kStatNPortRxXesc);
344
          fPendXesc = true;
345
        } else {
346
          *po++ = c;
347
        }
348
      }
349
      irc = po - buf;                       // set irc to # of unescaped bytes
350
    }
351
 
352
  } else {
353
    irc = RlinkPort::Read(buf, size, timeout, emsg);
354
  }
355
 
356
  return irc;
357
}
358
 
359
//------------------------------------------+-----------------------------------
360
//! FIXME_docs
361
 
362
int RlinkPortTerm::Write(const uint8_t* buf, size_t size, RerrMsg& emsg)
363
{
364
  int irc = 0;
365
 
366
  if (fUseXon) {
367
    fTxBuf.clear();
368
    const uint8_t* pc = buf;
369
 
370
    for (size_t i=0; i<size; i++) {
371
      uint8_t c = *pc++;
372
      if (c==kc_xon || c==kc_xoff || c==kc_xesc) {
373
        fStats.Inc(kStatNPortTxXesc);
374
        fTxBuf.push_back(kc_xesc);
375
        fTxBuf.push_back(~c);
376
      } else {
377
        fTxBuf.push_back(c);
378
      }
379
    }
380
    int irce = RlinkPort::Write(fTxBuf.data(), fTxBuf.size(), emsg);
381
    if (irce == (int)fTxBuf.size()) irc = size;
382
  } else {
383
    irc = RlinkPort::Write(buf, size, emsg);
384
  }
385
 
386
  /* tcdrain(fFdWrite);*/
387
  return irc;
388
}
389
 
390
//------------------------------------------+-----------------------------------
391 19 wfjm
//! FIXME_docs
392 10 wfjm
 
393
void RlinkPortTerm::Dump(std::ostream& os, int ind, const char* text) const
394
{
395
  RosFill bl(ind);
396
  os << bl << (text?text:"--") << "RlinkPortTerm @ " << this << endl;
397
  DumpTios(os, ind, "fTiosOld", fTiosOld);
398
  DumpTios(os, ind, "fTiosNew", fTiosNew);
399 19 wfjm
  RlinkPort::Dump(os, ind, " ^");
400 10 wfjm
  return;
401 19 wfjm
}
402 10 wfjm
 
403
//------------------------------------------+-----------------------------------
404 19 wfjm
//! FIXME_docs
405 10 wfjm
 
406
void RlinkPortTerm::DumpTios(std::ostream& os, int ind, const std::string& name,
407
                             const struct termios& tios) const
408
{
409
  RosFill bl(ind+2);
410
  os << bl << name << ":" << endl;
411
  os << bl << "  c_iflag : " << RosPrintf(tios.c_iflag,"x0",8);
412
  if (tios.c_iflag & BRKINT) os << " BRKINT";
413
  if (tios.c_iflag & ICRNL)  os << " ICRNL ";
414
  if (tios.c_iflag & IGNBRK) os << " IGNBRK";
415
  if (tios.c_iflag & IGNCR)  os << " IGNCR ";
416
  if (tios.c_iflag & IGNPAR) os << " IGNPAR";
417
  if (tios.c_iflag & INLCR)  os << " INLCR ";
418
  if (tios.c_iflag & INPCK)  os << " INPCK ";
419
  if (tios.c_iflag & ISTRIP) os << " ISTRIP";
420
  if (tios.c_iflag & IXOFF)  os << " IXOFF ";
421
  if (tios.c_iflag & IXON)   os << " IXON  ";
422
  if (tios.c_iflag & PARMRK) os << " PARMRK";
423
  os << endl;
424
 
425
  os << bl << "  c_oflag : " << RosPrintf(tios.c_oflag,"x0",8);
426
  if (tios.c_oflag & OPOST)  os << " OPOST ";
427
  os << endl;
428
 
429
  os << bl << "  c_cflag : " << RosPrintf(tios.c_cflag,"x0",8);
430
  if (tios.c_cflag & CLOCAL) os << " CLOCAL";
431
  if (tios.c_cflag & CREAD)  os << " CREAD ";
432
  if ((tios.c_cflag & CSIZE) == CS5)  os << " CS5   ";
433
  if ((tios.c_cflag & CSIZE) == CS6)  os << " CS6   ";
434
  if ((tios.c_cflag & CSIZE) == CS7)  os << " CS7   ";
435
  if ((tios.c_cflag & CSIZE) == CS8)  os << " CS8   ";
436
  if (tios.c_cflag & CSTOPB) os << " CSTOPB";
437
  if (tios.c_cflag & HUPCL)  os << " HUPCL ";
438
  if (tios.c_cflag & PARENB) os << " PARENB";
439
  if (tios.c_cflag & PARODD) os << " PARODD";
440
  speed_t speed = cfgetispeed(&tios);
441
  int baud = 0;
442 16 wfjm
  if (speed == B2400)    baud =    2400;
443
  if (speed == B4800)    baud =    4800;
444 10 wfjm
  if (speed == B9600)    baud =    9600;
445
  if (speed == B19200)   baud =   19200;
446
  if (speed == B38400)   baud =   38400;
447
  if (speed == B57600)   baud =   57600;
448
  if (speed == B115200)  baud =  115200;
449
  if (speed == B230400)  baud =  230400;
450
  if (speed == B460800)  baud =  460800;
451
  if (speed == B500000)  baud =  500000;
452
  if (speed == B921600)  baud =  921600;
453
  if (speed == B1000000) baud = 1000000;
454 16 wfjm
  if (speed == B1152000) baud = 1152000;
455
  if (speed == B1500000) baud = 1500000;
456 10 wfjm
  if (speed == B2000000) baud = 2000000;
457 16 wfjm
  if (speed == B2500000) baud = 2500000;
458 10 wfjm
  if (speed == B3000000) baud = 3000000;
459 16 wfjm
  if (speed == B3500000) baud = 3500000;
460
  if (speed == B4000000) baud = 4000000;
461 10 wfjm
  os << " speed: " << RosPrintf(baud, "d", 7);
462
  os << endl;
463
 
464
  os << bl << "  c_lflag : " << RosPrintf(tios.c_lflag,"x0",8);
465
  if (tios.c_lflag & ECHO)   os << " ECHO  ";
466
  if (tios.c_lflag & ECHOE)  os << " ECHOE ";
467
  if (tios.c_lflag & ECHOK)  os << " ECHOK ";
468
  if (tios.c_lflag & ECHONL) os << " ECHONL";
469
  if (tios.c_lflag & ICANON) os << " ICANON";
470
  if (tios.c_lflag & IEXTEN) os << " IEXTEN";
471
  if (tios.c_lflag & ISIG)   os << " ISIG  ";
472
  if (tios.c_lflag & NOFLSH) os << " NOFLSH";
473
  if (tios.c_lflag & TOSTOP) os << " TOSTOP";
474
  os << endl;
475
 
476
  os << bl << "  c_cc    : " << endl;
477
  os << bl << "    [VEOF]  : " << RosPrintf(tios.c_cc[VEOF],"o",3);
478
  os       << "    [VEOL]  : " << RosPrintf(tios.c_cc[VEOL],"o",3);
479
  os       << "    [VERASE]: " << RosPrintf(tios.c_cc[VERASE],"o",3);
480
  os       << "    [VINTR] : " << RosPrintf(tios.c_cc[VINTR],"o",3)  << endl;
481
  os << bl << "    [VKILL] : " << RosPrintf(tios.c_cc[VKILL],"o",3);
482
  os       << "    [VQUIT] : " << RosPrintf(tios.c_cc[VQUIT],"o",3);
483
  os       << "    [VSUSP] : " << RosPrintf(tios.c_cc[VSUSP],"o",3);
484
  os       << "    [VSTART]: " << RosPrintf(tios.c_cc[VSTART],"o",3) << endl;
485
  os << bl << "    [VSTOP] : " << RosPrintf(tios.c_cc[VSTOP],"o",3);
486
  os       << "    [VMIN]  : " << RosPrintf(tios.c_cc[VMIN],"o",3);
487
  os       << "    [VTIME] : " << RosPrintf(tios.c_cc[VTIME],"o",3)  << endl;
488
 
489
  return;
490
}
491
 
492 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.