Line 1... |
Line 1... |
// $Id: Rw11UnitTerm.cpp 504 2013-04-13 15:37:24Z mueller $
|
// $Id: Rw11UnitTerm.cpp 508 2013-04-20 18:43:28Z mueller $
|
//
|
//
|
// Copyright 2013- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
// Copyright 2013- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
//
|
//
|
// This program is free software; you may redistribute and/or modify it under
|
// This program is free software; you may redistribute and/or modify it under
|
// the terms of the GNU General Public License as published by the Free
|
// the terms of the GNU General Public License as published by the Free
|
Line 17... |
Line 17... |
// 2013-02-19 490 0.1 First draft
|
// 2013-02-19 490 0.1 First draft
|
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
|
|
/*!
|
/*!
|
\file
|
\file
|
\version $Id: Rw11UnitTerm.cpp 504 2013-04-13 15:37:24Z mueller $
|
\version $Id: Rw11UnitTerm.cpp 508 2013-04-20 18:43:28Z mueller $
|
\brief Implemenation of Rw11UnitTerm.
|
\brief Implemenation of Rw11UnitTerm.
|
*/
|
*/
|
|
|
#include "boost/thread/locks.hpp"
|
#include "boost/thread/locks.hpp"
|
#include "boost/bind.hpp"
|
#include "boost/bind.hpp"
|
|
|
|
#include "librtools/RparseUrl.hpp"
|
#include "librtools/RosPrintf.hpp"
|
#include "librtools/RosPrintf.hpp"
|
|
#include "librtools/Rexception.hpp"
|
|
|
#include "Rw11UnitTerm.hpp"
|
#include "Rw11UnitTerm.hpp"
|
|
|
using namespace std;
|
using namespace std;
|
|
|
Line 43... |
Line 45... |
//------------------------------------------+-----------------------------------
|
//------------------------------------------+-----------------------------------
|
//! Constructor
|
//! Constructor
|
|
|
Rw11UnitTerm::Rw11UnitTerm(Rw11Cntl* pcntl, size_t index)
|
Rw11UnitTerm::Rw11UnitTerm(Rw11Cntl* pcntl, size_t index)
|
: Rw11UnitVirt<Rw11VirtTerm>(pcntl, index),
|
: Rw11UnitVirt<Rw11VirtTerm>(pcntl, index),
|
fRcv7bit(false),
|
fTo7bit(false),
|
fRcvQueue()
|
fToEnpc(false),
|
{}
|
fTi7bit(false),
|
|
fRcvQueue(),
|
|
fLogFname(),
|
|
fLogStream(),
|
|
fLogOptCrlf(false),
|
|
fLogCrPend(false),
|
|
fLogLfLast(false)
|
|
{
|
|
fStats.Define(kStatNPreAttDrop, "NPreAttDrop",
|
|
"snd bytes dropped prior attach");
|
|
}
|
|
|
//------------------------------------------+-----------------------------------
|
//------------------------------------------+-----------------------------------
|
//! Destructor
|
//! Destructor
|
|
|
Rw11UnitTerm::~Rw11UnitTerm()
|
Rw11UnitTerm::~Rw11UnitTerm()
|
Line 66... |
Line 78... |
}
|
}
|
|
|
//------------------------------------------+-----------------------------------
|
//------------------------------------------+-----------------------------------
|
//! FIXME_docs
|
//! FIXME_docs
|
|
|
|
void Rw11UnitTerm::SetLog(const std::string& fname)
|
|
{
|
|
if (fLogStream.is_open()) {
|
|
if (fLogCrPend) fLogStream << "\r";
|
|
fLogCrPend = false;
|
|
fLogStream.close();
|
|
}
|
|
|
|
fLogFname.clear();
|
|
if (fname.length() == 0) return;
|
|
|
|
RparseUrl purl;
|
|
RerrMsg emsg;
|
|
if (!purl.Set(fname, "|app|crlf|", emsg))
|
|
throw Rexception(emsg);
|
|
|
|
ios_base::openmode mode = ios_base::out;
|
|
if (purl.FindOpt("app")) mode |= ios_base::app;
|
|
|
|
fLogStream.open(purl.Path(), mode);
|
|
if (!fLogStream.is_open()) {
|
|
throw Rexception("Rw11UnitTerm::SetLog",
|
|
string("failed to open '")+purl.Path()+"'");
|
|
}
|
|
|
|
fLogFname = fname;
|
|
fLogOptCrlf = purl.FindOpt("crlf");
|
|
fLogCrPend = false;
|
|
fLogLfLast = false;
|
|
|
|
return;
|
|
}
|
|
|
|
//------------------------------------------+-----------------------------------
|
|
//! FIXME_docs
|
|
|
bool Rw11UnitTerm::RcvQueueEmpty()
|
bool Rw11UnitTerm::RcvQueueEmpty()
|
{
|
{
|
return fRcvQueue.empty();
|
return fRcvQueue.empty();
|
}
|
}
|
|
|
Line 109... |
Line 157... |
//! FIXME_docs
|
//! FIXME_docs
|
|
|
bool Rw11UnitTerm::Snd(const uint8_t* buf, size_t count)
|
bool Rw11UnitTerm::Snd(const uint8_t* buf, size_t count)
|
{
|
{
|
bool ok = true;
|
bool ok = true;
|
if (fpVirt) {
|
vector<uint8_t> bufmod;
|
|
const uint8_t* bufout = buf;
|
|
size_t bufcnt = count;
|
|
|
|
if (fTo7bit || fToEnpc) {
|
|
for (size_t i=0; i<count; i++) {
|
|
uint8_t ochr = buf[i];
|
|
if (fTo7bit) ochr &= 0177;
|
|
if (fToEnpc) {
|
|
if ((ochr>=040 && ochr<177) ||
|
|
ochr=='\t' || ochr=='\n' || ochr=='\r') {
|
|
bufmod.push_back(ochr);
|
|
} else {
|
|
if (ochr != 0) {
|
|
bufmod.push_back('<');
|
|
bufmod.push_back('0' + ((ochr>>6)&07) );
|
|
bufmod.push_back('0' + ((ochr>>3)&07) );
|
|
bufmod.push_back('0' + (ochr &07) );
|
|
bufmod.push_back('>');
|
|
}
|
|
}
|
|
|
|
} else {
|
|
bufmod.push_back(ochr);
|
|
}
|
|
}
|
|
bufout = bufmod.data();
|
|
bufcnt = bufmod.size();
|
|
}
|
|
|
|
if (fLogStream.is_open()) {
|
|
for (size_t i=0; i<bufcnt; i++) {
|
|
uint8_t ochr = bufout[i];
|
|
// the purpose of the 'crlf' filter is to map
|
|
// \r\n -> \n
|
|
// \r\r\n -> \n (any number of \r)
|
|
// \n\r -> \n
|
|
// \n\r\r -> \n (any number of \r)
|
|
// and to ignore \0 chars
|
|
if (fLogOptCrlf) { // crlf filtering on
|
|
if (ochr == 0) continue; // ignore \0 chars
|
|
if (fLogCrPend) {
|
|
if (ochr == '\r') continue; // collapes multiple \r
|
|
if (ochr != '\n') fLogStream << '\r'; // log \r if not followed by \n
|
|
fLogCrPend = false;
|
|
}
|
|
if (ochr == '\r') { // \r seen
|
|
fLogCrPend = !fLogLfLast; // remember \r if last wasn't \n
|
|
continue;
|
|
}
|
|
}
|
|
fLogStream << char(ochr);
|
|
fLogLfLast = (ochr == '\n');
|
|
}
|
|
}
|
|
|
|
if (fpVirt) { // if virtual device attached
|
RerrMsg emsg;
|
RerrMsg emsg;
|
ok = fpVirt->Snd(buf, count, emsg);
|
ok = fpVirt->Snd(bufout, bufcnt, emsg);
|
// FIXME_code: handler errors
|
// FIXME_code: handler errors
|
} else {
|
|
for (size_t i=0; i<count; i++) cout << buf[i] << flush;
|
} else { // no virtual device attached
|
|
if (Name() == "tta0") { // is it main console ?
|
|
for (size_t i=0; i<bufcnt; i++) { // than print to stdout
|
|
cout << char(bufout[i]) << flush;
|
|
}
|
|
} else { // otherwise discard
|
|
fStats.Inc(kStatNPreAttDrop); // and count at least...
|
|
}
|
}
|
}
|
return ok;
|
return ok;
|
}
|
}
|
|
|
|
|
Line 129... |
Line 240... |
{
|
{
|
// lock connect to protect rxqueue
|
// lock connect to protect rxqueue
|
boost::lock_guard<RlinkConnect> lock(Connect());
|
boost::lock_guard<RlinkConnect> lock(Connect());
|
|
|
bool que_empty_old = fRcvQueue.empty();
|
bool que_empty_old = fRcvQueue.empty();
|
for (size_t i=0; i<count; i++) fRcvQueue.push_back(buf[i]);
|
for (size_t i=0; i<count; i++) {
|
|
uint8_t ichr = buf[i];
|
|
if (fTi7bit) ichr &= 0177;
|
|
fRcvQueue.push_back(ichr);
|
|
}
|
bool que_empty_new = fRcvQueue.empty();
|
bool que_empty_new = fRcvQueue.empty();
|
if (que_empty_old && !que_empty_new) WakeupCntl();
|
if (que_empty_old && !que_empty_new) WakeupCntl();
|
return true;
|
return true;
|
}
|
}
|
|
|
Line 151... |
Line 266... |
void Rw11UnitTerm::Dump(std::ostream& os, int ind, const char* text) const
|
void Rw11UnitTerm::Dump(std::ostream& os, int ind, const char* text) const
|
{
|
{
|
RosFill bl(ind);
|
RosFill bl(ind);
|
os << bl << (text?text:"--") << "Rw11UnitTerm @ " << this << endl;
|
os << bl << (text?text:"--") << "Rw11UnitTerm @ " << this << endl;
|
|
|
os << bl << " fRcv7bit: " << fRcv7bit << endl;
|
os << bl << " fTo7bit: " << fTo7bit << endl;
|
|
os << bl << " fToEnpc: " << fToEnpc << endl;
|
|
os << bl << " fTi7bit: " << fTi7bit << endl;
|
{
|
{
|
boost::lock_guard<RlinkConnect> lock(Connect());
|
boost::lock_guard<RlinkConnect> lock(Connect());
|
size_t size = fRcvQueue.size();
|
size_t size = fRcvQueue.size();
|
os << bl << " fRcvQueue.size: " << fRcvQueue.size() << endl;
|
os << bl << " fRcvQueue.size: " << fRcvQueue.size() << endl;
|
if (size > 0) {
|
if (size > 0) {
|
Line 177... |
Line 294... |
}
|
}
|
os << "\"" << endl;
|
os << "\"" << endl;
|
}
|
}
|
}
|
}
|
|
|
|
os << bl << " fLogFname: " << fLogFname << endl;
|
|
os << bl << " fLogStream.is_open: " << fLogStream.is_open() << endl;
|
|
os << bl << " fLogOptCrlf: " << fLogOptCrlf << endl;
|
|
os << bl << " fLogCrPend: " << fLogCrPend << endl;
|
|
os << bl << " fLogLfLast: " << fLogLfLast << endl;
|
|
|
Rw11UnitVirt<Rw11VirtTerm>::Dump(os, ind, " ^");
|
Rw11UnitVirt<Rw11VirtTerm>::Dump(os, ind, " ^");
|
return;
|
return;
|
}
|
}
|
|
|
//------------------------------------------+-----------------------------------
|
//------------------------------------------+-----------------------------------
|