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

Subversion Repositories w11

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

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

Line No. Rev Author Line
1 15 wfjm
// $Id: RlinkPortTerm.cpp 435 2011-12-04 20:15:25Z 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 15 wfjm
// 2011-12-04   435   1.0.2  Open(): add cts attr, hw flow control now optional
17 12 wfjm
// 2011-07-04   388   1.0.1  add termios readback and verification
18 10 wfjm
// 2011-03-27   374   1.0    Initial version
19
// ---------------------------------------------------------------------------
20
 
21
/*!
22
  \file
23 15 wfjm
  \version $Id: RlinkPortTerm.cpp 435 2011-12-04 20:15:25Z mueller $
24 10 wfjm
  \brief   Implemenation of RlinkPortTerm.
25
*/
26
 
27
#include <sys/types.h>
28
#include <sys/stat.h>
29
#include <fcntl.h>
30
#include <errno.h>
31
#include <unistd.h>
32
#include <termios.h>
33
 
34
#include "RlinkPortTerm.hpp"
35
 
36
#include "librtools/RosFill.hpp"
37
#include "librtools/RosPrintf.hpp"
38
 
39
using namespace std;
40
using namespace Retro;
41
 
42
/*!
43
  \class Retro::RlinkPortTerm
44
  \brief FIXME_text
45
*/
46
 
47
//------------------------------------------+-----------------------------------
48
//! Default constructor
49
 
50
RlinkPortTerm::RlinkPortTerm()
51
  : RlinkPort()
52
{}
53
 
54
//------------------------------------------+-----------------------------------
55
//! Destructor
56
 
57
RlinkPortTerm::~RlinkPortTerm()
58
{
59
  if (IsOpen()) RlinkPortTerm::Close();
60
}
61
 
62
//------------------------------------------+-----------------------------------
63
//! FIXME_text
64
 
65
bool RlinkPortTerm::Open(const std::string& url, RerrMsg& emsg)
66
{
67
  if (IsOpen()) Close();
68
 
69 15 wfjm
  if (!ParseUrl(url, "|baud=|break|cts|", emsg)) return false;
70 10 wfjm
 
71
  speed_t speed = B115200;
72
  string baud;
73
  if (UrlFindOpt("baud", baud)) {
74
    speed = B0;
75
    if (baud=="9600")                     speed = B9600;
76
    if (baud=="19200"   || baud=="19k")   speed = B19200;
77
    if (baud=="38400"   || baud=="38k")   speed = B38400;
78
    if (baud=="57600"   || baud=="57k")   speed = B57600;
79
    if (baud=="115200"  || baud=="115k")  speed = B115200;
80
    if (baud=="230400"  || baud=="230k")  speed = B230400;
81
    if (baud=="460800"  || baud=="460k")  speed = B460800;
82
    if (baud=="500000"  || baud=="500k")  speed = B500000;
83
    if (baud=="921600"  || baud=="921k")  speed = B921600;
84
    if (baud=="1000000" || baud=="1M")    speed = B1000000;
85
    if (baud=="2000000" || baud=="2M")    speed = B2000000;
86
    if (baud=="3000000" || baud=="3M")    speed = B3000000;
87
    if (speed == B0) {
88
      emsg.Init("RlinkPortTerm::Open()",
89
                string("invalid baud rate \"") + baud + string("\" specified"));
90
      return false;
91
    }
92
  }
93
 
94
  int fd;
95
 
96
  fd = open(fPath.c_str(), O_RDWR|O_NOCTTY);
97
  if (fd < 0) {
98
    emsg.InitErrno("RlinkPortTerm::Open()",
99
                   string("open() for \"") + fPath + string("\" failed: "),
100
                   errno);
101
    return false;
102
  }
103
 
104
  if (!isatty(fd)) {
105
    emsg.Init("RlinkPortTerm::Open()",
106
              string("isatty() check for \"") + fPath +
107
              string("\" failed: not a TTY"));
108
    close(fd);
109
    return false;
110
  }
111
 
112
  if (tcgetattr(fd, &fTiosOld) != 0) {
113
    emsg.InitErrno("RlinkPortTerm::Open()",
114
                   string("tcgetattr() for \"") + fPath + string("\" failed: "),
115
                   errno);
116
    close(fd);
117
    return false;
118
  }
119
 
120
  fTiosNew = fTiosOld;
121
 
122
  fTiosNew.c_iflag = IGNBRK |               // ignore breaks on input
123
                     IGNPAR;                // ignore parity errors
124 15 wfjm
 
125 10 wfjm
  fTiosNew.c_oflag = 0;
126 15 wfjm
 
127 10 wfjm
  fTiosNew.c_cflag = CS8 |                  // 8 bit chars
128
                     CSTOPB |               // 2 stop bits
129
                     CREAD |                // enable receiver
130 15 wfjm
                     CLOCAL;                // ignore modem control
131
  if (UrlFindOpt("cts")) {
132
    fTiosNew.c_cflag |= CRTSCTS;            // enable hardware flow control
133
  }
134
 
135 10 wfjm
  fTiosNew.c_lflag = 0;
136
 
137
  if (cfsetspeed(&fTiosNew, speed) != 0) {
138
    emsg.InitErrno("RlinkPortTerm::Open()",
139
                   string("cfsetspeed() for \"") + baud + string("\" failed: "),
140
                   errno);
141
    close(fd);
142
    return false;
143
  }
144
 
145
  fTiosNew.c_cc[VEOF]   = 0;                // undef
146
  fTiosNew.c_cc[VEOL]   = 0;                // undef
147
  fTiosNew.c_cc[VERASE] = 0;                // undef
148
  fTiosNew.c_cc[VINTR]  = 0;                // undef
149
  fTiosNew.c_cc[VKILL]  = 0;                // undef
150
  fTiosNew.c_cc[VQUIT]  = 0;                // undef
151
  fTiosNew.c_cc[VSUSP]  = 0;                // undef
152
  fTiosNew.c_cc[VSTART] = 0;                // undef
153
  fTiosNew.c_cc[VSTOP]  = 0;                // undef
154
  fTiosNew.c_cc[VMIN]   = 1;                // wait for 1 char
155
  fTiosNew.c_cc[VTIME]  = 0;                // 
156
 
157
  if (tcsetattr(fd, TCSANOW, &fTiosNew) != 0) {
158
    emsg.InitErrno("RlinkPortTerm::Open()",
159
                   string("tcsetattr() for \"") + fPath + string("\" failed: "),
160
                   errno);
161
    close(fd);
162
    return false;
163
  }
164
 
165 12 wfjm
  // tcsetattr() returns success if any of the requested changes could be
166
  // successfully carried out. Therefore the termios structure is read back
167
  // and verified.
168
 
169
  struct termios tios;
170
  if (tcgetattr(fd, &tios) != 0) {
171
    emsg.InitErrno("RlinkPortTerm::Open()",
172
                   string("2nd tcgetattr() for \"") + fPath +
173
                     string("\" failed: "),
174
                   errno);
175
    close(fd);
176
    return false;
177
  }
178
 
179
  const char* pmsg = 0;
180
  if (tios.c_iflag != fTiosNew.c_iflag) pmsg = "c_iflag";
181
  if (tios.c_oflag != fTiosNew.c_oflag) pmsg = "c_oflag";
182
  if (tios.c_cflag != fTiosNew.c_cflag) pmsg = "c_cflag";
183
  if (tios.c_lflag != fTiosNew.c_lflag) pmsg = "c_lflag";
184
  if (cfgetispeed(&tios) != speed)      pmsg = "ispeed";
185
  if (cfgetospeed(&tios) != speed)      pmsg = "ospeed";
186
  for (int i=0; i<NCCS; i++) {
187
    if (tios.c_cc[i] != fTiosNew.c_cc[i]) pmsg = "c_cc char";
188
  }
189
 
190
  if (pmsg) {
191
    emsg.Init("RlinkPortTerm::Open()",
192
              string("tcsetattr() failed to set") +
193
                string(pmsg));
194
    close(fd);
195
    return false;
196
  }
197
 
198 10 wfjm
  fFdWrite = fd;
199
  fFdRead  = fd;
200
  fIsOpen  = true;
201
 
202
  if (UrlFindOpt("break")) {
203
    if (tcsendbreak(fd, 0) != 0) {
204
      emsg.InitErrno("RlinkPortTerm::Open()",
205
                     string("tcsendbreak() for \"") + fPath +
206
                     string("\" failed: "), errno);
207
      Close();
208
      return false;
209
    }
210
    uint8_t buf[1];
211
    buf[0] = 0x80;
212
    if (Write(buf, 1, emsg) != 1) {
213
      Close();
214
      return false;
215
    }
216
  }
217
 
218
  return true;
219
}
220
 
221
//------------------------------------------+-----------------------------------
222
//! FIXME_text
223
 
224
void RlinkPortTerm::Close()
225
{
226
  if (fIsOpen) {
227
    if (fFdWrite >= 0) {
228
      tcflush(fFdWrite, TCIOFLUSH);
229
      tcsetattr(fFdWrite, TCSANOW, &fTiosOld);
230
    }
231
    RlinkPort::Close();
232
  }
233
  return;
234
}
235
 
236
//------------------------------------------+-----------------------------------
237
//! FIXME_text
238
 
239
void RlinkPortTerm::Dump(std::ostream& os, int ind, const char* text) const
240
{
241
  RosFill bl(ind);
242
  os << bl << (text?text:"--") << "RlinkPortTerm @ " << this << endl;
243
  DumpTios(os, ind, "fTiosOld", fTiosOld);
244
  DumpTios(os, ind, "fTiosNew", fTiosNew);
245
  RlinkPort::Dump(os, ind+2, "");
246
  return;
247
}
248
 
249
 
250
//------------------------------------------+-----------------------------------
251
//! FIXME_text
252
 
253
void RlinkPortTerm::DumpTios(std::ostream& os, int ind, const std::string& name,
254
                             const struct termios& tios) const
255
{
256
  RosFill bl(ind+2);
257
  os << bl << name << ":" << endl;
258
  os << bl << "  c_iflag : " << RosPrintf(tios.c_iflag,"x0",8);
259
  if (tios.c_iflag & BRKINT) os << " BRKINT";
260
  if (tios.c_iflag & ICRNL)  os << " ICRNL ";
261
  if (tios.c_iflag & IGNBRK) os << " IGNBRK";
262
  if (tios.c_iflag & IGNCR)  os << " IGNCR ";
263
  if (tios.c_iflag & IGNPAR) os << " IGNPAR";
264
  if (tios.c_iflag & INLCR)  os << " INLCR ";
265
  if (tios.c_iflag & INPCK)  os << " INPCK ";
266
  if (tios.c_iflag & ISTRIP) os << " ISTRIP";
267
  if (tios.c_iflag & IXOFF)  os << " IXOFF ";
268
  if (tios.c_iflag & IXON)   os << " IXON  ";
269
  if (tios.c_iflag & PARMRK) os << " PARMRK";
270
  os << endl;
271
 
272
  os << bl << "  c_oflag : " << RosPrintf(tios.c_oflag,"x0",8);
273
  if (tios.c_oflag & OPOST)  os << " OPOST ";
274
  os << endl;
275
 
276
  os << bl << "  c_cflag : " << RosPrintf(tios.c_cflag,"x0",8);
277
  if (tios.c_cflag & CLOCAL) os << " CLOCAL";
278
  if (tios.c_cflag & CREAD)  os << " CREAD ";
279
  if ((tios.c_cflag & CSIZE) == CS5)  os << " CS5   ";
280
  if ((tios.c_cflag & CSIZE) == CS6)  os << " CS6   ";
281
  if ((tios.c_cflag & CSIZE) == CS7)  os << " CS7   ";
282
  if ((tios.c_cflag & CSIZE) == CS8)  os << " CS8   ";
283
  if (tios.c_cflag & CSTOPB) os << " CSTOPB";
284
  if (tios.c_cflag & HUPCL)  os << " HUPCL ";
285
  if (tios.c_cflag & PARENB) os << " PARENB";
286
  if (tios.c_cflag & PARODD) os << " PARODD";
287
  speed_t speed = cfgetispeed(&tios);
288
  int baud = 0;
289
  if (speed == B9600)    baud =    9600;
290
  if (speed == B19200)   baud =   19200;
291
  if (speed == B38400)   baud =   38400;
292
  if (speed == B57600)   baud =   57600;
293
  if (speed == B115200)  baud =  115200;
294
  if (speed == B230400)  baud =  230400;
295
  if (speed == B460800)  baud =  460800;
296
  if (speed == B500000)  baud =  500000;
297
  if (speed == B921600)  baud =  921600;
298
  if (speed == B1000000) baud = 1000000;
299
  if (speed == B2000000) baud = 2000000;
300
  if (speed == B3000000) baud = 3000000;
301
  os << " speed: " << RosPrintf(baud, "d", 7);
302
  os << endl;
303
 
304
  os << bl << "  c_lflag : " << RosPrintf(tios.c_lflag,"x0",8);
305
  if (tios.c_lflag & ECHO)   os << " ECHO  ";
306
  if (tios.c_lflag & ECHOE)  os << " ECHOE ";
307
  if (tios.c_lflag & ECHOK)  os << " ECHOK ";
308
  if (tios.c_lflag & ECHONL) os << " ECHONL";
309
  if (tios.c_lflag & ICANON) os << " ICANON";
310
  if (tios.c_lflag & IEXTEN) os << " IEXTEN";
311
  if (tios.c_lflag & ISIG)   os << " ISIG  ";
312
  if (tios.c_lflag & NOFLSH) os << " NOFLSH";
313
  if (tios.c_lflag & TOSTOP) os << " TOSTOP";
314
  os << endl;
315
 
316
  os << bl << "  c_cc    : " << endl;
317
  os << bl << "    [VEOF]  : " << RosPrintf(tios.c_cc[VEOF],"o",3);
318
  os       << "    [VEOL]  : " << RosPrintf(tios.c_cc[VEOL],"o",3);
319
  os       << "    [VERASE]: " << RosPrintf(tios.c_cc[VERASE],"o",3);
320
  os       << "    [VINTR] : " << RosPrintf(tios.c_cc[VINTR],"o",3)  << endl;
321
  os << bl << "    [VKILL] : " << RosPrintf(tios.c_cc[VKILL],"o",3);
322
  os       << "    [VQUIT] : " << RosPrintf(tios.c_cc[VQUIT],"o",3);
323
  os       << "    [VSUSP] : " << RosPrintf(tios.c_cc[VSUSP],"o",3);
324
  os       << "    [VSTART]: " << RosPrintf(tios.c_cc[VSTART],"o",3) << endl;
325
  os << bl << "    [VSTOP] : " << RosPrintf(tios.c_cc[VSTOP],"o",3);
326
  os       << "    [VMIN]  : " << RosPrintf(tios.c_cc[VMIN],"o",3);
327
  os       << "    [VTIME] : " << RosPrintf(tios.c_cc[VTIME],"o",3)  << endl;
328
 
329
  return;
330
}
331
 
332
//------------------------------------------+-----------------------------------
333
#if (defined(Retro_NoInline) || defined(Retro_RlinkPortTerm_NoInline))
334
#define inline
335
//#include "RlinkPortTerm.ipp"
336
#undef  inline
337
#endif

powered by: WebSVN 2.1.0

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