w11 - cpp 0.794
Backend server for Rlink and w11
Loading...
Searching...
No Matches
RlinkPacketBufRcv.cpp
Go to the documentation of this file.
1// $Id: RlinkPacketBufRcv.cpp 1198 2019-07-27 19:08:31Z mueller $
2// SPDX-License-Identifier: GPL-3.0-or-later
3// Copyright 2014-2019 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4//
5// Revision History:
6// Date Rev Version Comment
7// 2019-07-27 1198 1.2.3 add Nak handling
8// 2019-06-14 1163 1.2.2 ReadData(): coverity fixup (logically dead code)
9// 2018-12-23 1091 1.2.1 ReadData(): remove port open check, done at caller
10// 2018-12-08 1079 1.2 use ref not ptr for RlinkPort
11// 2017-04-07 868 1.1.1 Dump(): add detail arg
12// 2017-02-19 853 1.1 use Rtime
13// 2014-12-25 621 1.0.1 Reorganize packet send/revd stats
14// 2014-11-30 607 1.0 Initial version
15// 2014-11-02 600 0.1 First draft (re-organize PacketBuf for rlink v4)
16// ---------------------------------------------------------------------------
17
22#include <sys/time.h>
23
24#include <iostream>
25
26#include "RlinkPacketBufRcv.hpp"
27
28#include "librtools/RosFill.hpp"
32
33using namespace std;
34
40// all method definitions in namespace Retro
41namespace Retro {
42
43//------------------------------------------+-----------------------------------
45
47 : fRawBufSize(0),
48 fRawBufDone(0),
49 fRcvState(kRcvIdle),
50 fNDone(0),
51 fEscSeen(false),
52 fNakIndex(-1),
53 fNakCode(0),
54 fDropData()
55{
56 // Statistic setup
57 fStats.Define(kStatNRxPktByt, "NRxPktByt", "Rx packet bytes rcvd");
58 fStats.Define(kStatNRxDrop, "NRxDrop", "Rx bytes dropped");
59 fStats.Define(kStatNRxSop, "NRxSop", "Rx SOP commas seen");
60 fStats.Define(kStatNRxEop, "NRxEop", "Rx EOP commas seen");
61 fStats.Define(kStatNRxNak, "NRxNak", "Rx NAK commas seen");
62 fStats.Define(kStatNRxAttn, "NRxAttn", "Rx ATTN commas seen");
63 fStats.Define(kStatNRxEsc, "NRxEsc", "Rx data escapes");
64 fStats.Define(kStatNRxClobber, "NRxClobber", "Rx clobbered escapes");
65 fStats.Define(kStatNRxNakCcrc, "NRxNakCcrc", "Rx NAK Ccrc seen");
66 fStats.Define(kStatNRxNakDcrc, "NRxNakDcrc", "Rx NAK Dcrc seen");
67 fStats.Define(kStatNRxNakFrame, "NRxNakFrame", "Rx NAK Frame seen");
68 fStats.Define(kStatNRxNakUnused, "NRxNakUnused", "Rx NAK Unused seen");
69 fStats.Define(kStatNRxNakCmd, "NRxNakCmd", "Rx NAK Cmd seen");
70 fStats.Define(kStatNRxNakCnt, "NRxNakCnt", "Rx NAK Cnt seen");
71 fStats.Define(kStatNRxNakRtOvlf, "NRxNakRtOvlf", "Rx NAK RtOvlf seen");
72 fStats.Define(kStatNRxNakRtWblk, "NRxNakRtWblk", "Rx NAK RtWblk seen");
73 fStats.Define(kStatNRxNakInval, "NRxNakInval", "Rx NAK invalid seen");
74}
75
76//------------------------------------------+-----------------------------------
78
80{}
81
82//------------------------------------------+-----------------------------------
84
85int RlinkPacketBufRcv::ReadData(RlinkPort& port, const Rtime& timeout,
86 RerrMsg& emsg)
87{
89 throw Rexception("RlinkPacketBufRcv::ReadData()",
90 "Bad state: called while data pending in buffer");
91
92 fRawBufDone = 0;
93 fRawBufSize = 0;
94
95 int irc = port.Read(fRawBuf, sizeof(fRawBuf), timeout, emsg);
96
97 if (timeout.IsZero() && irc == RlinkPort::kTout) return 0;
98
99 if (irc <= 0) {
100 if (irc == RlinkPort::kTout) {
102 } else {
104 if (irc == RlinkPort::kEof) {
105 emsg.Init("RlinkPacketBuf::ReadData()", "eof on read");
106 }
107 }
108 } else {
109 fRawBufSize = size_t(irc);
110 }
111
112 return irc;
113}
114
115//------------------------------------------+-----------------------------------
117
119{
120 if (fRawBufDone ==fRawBufSize) return false;
121
122 while (fRawBufDone < fRawBufSize) {
123 switch (fRcvState) {
124 case kRcvIdle:
126 break;
127
128 case kRcvFill:
130 break;
131
132 default:
133 return true;
134 }
135 }
136 return true;
137}
138
139//------------------------------------------+-----------------------------------
141
143{
144 fPktBuf.clear();
145 fCrc.Clear();
146 fFlags = 0;
148 fNDone = 0;
149 fNakIndex = -1;
150 fNakCode = 0;
151 fDropData.clear();
152 return;
153}
154
155//------------------------------------------+-----------------------------------
157
159{
160 fRawBufSize = 0;
161 fRawBufDone = 0;
162 fEscSeen = false;
163 return;
164}
165
166//------------------------------------------+-----------------------------------
168
170{
173 return kPktError;
174}
175
176//------------------------------------------+-----------------------------------
178
179void RlinkPacketBufRcv::GetWithCrc(uint16_t* pdata, size_t count)
180{
181 uint16_t* pend = pdata + count;
182 while (pdata < pend) GetWithCrc(*pdata++);
183 return;
184}
185
186//------------------------------------------+-----------------------------------
188
189void RlinkPacketBufRcv::Dump(std::ostream& os, int ind, const char* text,
190 int detail) const
191{
192 RosFill bl(ind);
193 os << bl << (text?text:"--") << "RlinkPacketBufRcv @ " << this << endl;
194 os << bl << " fRawBufSize: " << RosPrintf(fRawBufSize,"d",4) << endl;
195 os << bl << " fRawBufDone: " << RosPrintf(fRawBufDone,"d",4) << endl;
196 if (fRawBufDone > 0) {
197 os << bl << " fRawBuf[last]: "
198 << RosPrintBvi(fRawBuf[fRawBufDone-1],16) << endl;
199 }
200 os << bl << " fRcvState: " << RosPrintf(fRcvState,"d",4) << endl;
201 os << bl << " fNDone: " << RosPrintf(fNDone,"d",4) << endl;
202 os << bl << " fEscSeen: " << RosPrintf(fEscSeen) << endl;
203 os << bl << " fNakIndex: " << RosPrintf(fNakIndex,"d",4) << endl;
204 os << bl << " fNakCode: " << RosPrintf(fNakCode,"d",4) << endl;
205
206 os << bl << " fDropData.size:" << RosPrintf(fDropData.size(),"d",4);
207 size_t ncol = max(1, (80-ind-4-6)/(2+1));
208 for (size_t i=0; i<fDropData.size(); i++) {
209 if (i%ncol == 0) os << "\n" << bl << " " << RosPrintf(i,"d",4) << ": ";
210 os << RosPrintBvi(fDropData[i],16) << " ";
211 }
212 os << endl;
213
214 RlinkPacketBuf::Dump(os, ind, " ^", detail);
215 return;
216}
217
218//------------------------------------------+-----------------------------------
220
222{
223 // loop over buffer
224 while (fRawBufDone < fRawBufSize) {
225
226 // handle escapes
227 if (fEscSeen) {
228 uint8_t ec = GetEcode();
229 switch (ec) {
230
231 case kEcSop:
234 return;
235
236 case kEcAttn:
239 return;
240
241 default:
242 fDropData.push_back(kSymEsc);
243 fDropData.push_back(fRawBuf[fRawBufDone-1]);
245 break;
246 }
247 } //if (fEscSeen)
248
249 // handle plain data (till next escape)
250 uint8_t* pi = fRawBuf+fRawBufDone;
251 uint8_t* pend = fRawBuf+fRawBufSize;
252
253 while (pi < pend) {
254 uint8_t c = *pi++;
255 if (c == kSymEsc) {
256 fEscSeen = true;
257 break;
258 }
259 fDropData.push_back(c);
261 }
262 fRawBufDone = pi - fRawBuf;
263
264 } // while (fRawBufDone < fRawBufSize)
265
266 return;
267}
268
269//------------------------------------------+-----------------------------------
271
273{
274 // loop over buffer
275 while (fRawBufDone < fRawBufSize) {
276
277 // handle escapes
278 if (fEscSeen) {
279 uint8_t ec = GetEcode();
280 switch (ec) {
281
282 case kEcEop: // EOP seen
283 SetFlagBit(kFlagEopSeen); // -> set eop and return
285 fStats.Inc(kStatNRxPktByt, double(PktSize()));
286 return;
287
288 case kEcNak: // NAK seen
289 if (TestFlag(kFlagAttnSeen|kFlagNakSeen)) { // NAK after ATTN or NAK
290 SetFlagBit(kFlagErrFrame); // -> set frame error and return
292 return;
293 } // else 1st NAK
294
295 SetFlagBit(kFlagNakSeen); // -> set flag and index; continue
296 fNakIndex = fPktBuf.size();
297 if (fRawBufDone+1 < fRawBufSize) {
298 uint8_t nc = fRawBuf[fRawBufDone];
299 uint8_t ncpre = nc & 0xc0;
300 uint8_t ncneg = ((~nc)>>3) & 0x07;
301 uint8_t ncpos = nc & 0x07;
302 fNakCode = (ncpre == 0x80 && ncneg == ncpos) ? ncpos : kNcInval;
303 } else {
305 }
306 switch (fNakCode) {
307 case kNcCcrc: fStats.Inc(kStatNRxNakCcrc); break; // NAK Ccrc seen
308 case kNcDcrc: fStats.Inc(kStatNRxNakDcrc); break; // NAK Dcrc seen
309 case kNcFrame: fStats.Inc(kStatNRxNakFrame); break; // NAK Frame seen
310 case kNcUnused: fStats.Inc(kStatNRxNakUnused); break; // NAK Unused seen
311 case kNcCmd: fStats.Inc(kStatNRxNakCmd); break; // NAK Cmd seen
312 case kNcCnt: fStats.Inc(kStatNRxNakCnt); break; // NAK Cnt seen
313 case kNcRtOvlf: fStats.Inc(kStatNRxNakRtOvlf); break; // NAK RtOvlf seen
314 case kNcRtWblk: fStats.Inc(kStatNRxNakRtWblk); break; // NAK RtWblk seen
315 case kNcInval: fStats.Inc(kStatNRxNakInval); break; // NAK invalid seen
316 }
317
318 break;
319
320 // data escapes seen: add escaped char and continue
321 case kEcXon: fPktBuf.push_back(kSymXon); break;
322 case kEcXoff: fPktBuf.push_back(kSymXoff); break;
323 case kEcFill: fPktBuf.push_back(kSymFill); break;
324 case kEcEsc: fPktBuf.push_back(kSymEsc); break;
325
326 case kEcClobber: // Clobber(ed) escape seen
327 SetFlagBit(kFlagErrClobber); // -> set clobber error and return
329 return;
330
331 default: // unexpected escape (SOP,ATTN)
332 SetFlagBit(kFlagErrFrame); // -> set frame error and return
334 return;
335 }
336 } // if (fEscSeen)
337
338 // handle plain data (till next escape)
339 uint8_t* pi = fRawBuf+fRawBufDone;
340 uint8_t* pend = fRawBuf+fRawBufSize;
341
342 while (pi < pend) {
343 uint8_t c = *pi++;
344 if (c == kSymEsc) {
345 fEscSeen = true;
346 break;
347 }
348 fPktBuf.push_back(c);
349 }
350 fRawBufDone = pi - fRawBuf;
351
352 } // while (fRawBufDone < fRawBufSize)
353
354 return;
355}
356
357//------------------------------------------+-----------------------------------
359
361{
363 throw Rexception("RlinkPacketBufRcv::GetEcode()", "Bad state");
364
365 fEscSeen = false;
366
367 uint8_t c = fRawBuf[fRawBufDone++];
368 uint8_t ec = c & 0x7;
369 if ((c & 0xC0) != kSymEdPref || (((~c)>>3)&0x7) != ec) ec = kEcClobber;
370
371 switch (ec) {
372 case kEcSop: fStats.Inc(kStatNRxSop); break; // SOP comma seen
373 case kEcEop: fStats.Inc(kStatNRxEop); break; // EOP comma seen
374 case kEcNak: fStats.Inc(kStatNRxNak); break; // NAK comma seen
375 case kEcAttn: fStats.Inc(kStatNRxAttn); break; // ATTN comma seen
376 case kEcClobber: fStats.Inc(kStatNRxClobber); break; // clobbered esc seen
377 default: fStats.Inc(kStatNRxEsc); break; // escaped data seen
378 }
379
380 return ec;
381}
382
383} // end namespace Retro
FIXME_docs.
Definition: RerrMsg.hpp:25
void Init(const std::string &meth, const std::string &text)
FIXME_docs.
Definition: RerrMsg.cpp:74
FIXME_docs.
Definition: Rexception.hpp:29
void Clear()
FIXME_docs.
Definition: RlinkCrc16.ipp:29
uint8_t GetEcode()
FIXME_docs.
uint8_t fNakCode
code of active nak
void GetWithCrc(uint8_t &data)
FIXME_docs.
@ kPktAttn
attn notify packet (ATTN+EOP)
@ kPktPend
pending, still being filled
@ kPktResp
response packet (SOP+EOP)
int fNakIndex
index of active nak (-1 if no)
enum rcv_state fRcvState
receive FSM state
@ kStatNRxNak
Rx NAK commas seen.
@ kStatNRxNakCnt
Rx NAK Cnt seen.
@ kStatNRxNakDcrc
Rx NAK Dcrc seen.
@ kStatNRxNakRtOvlf
Rx NAK RtOvlf seen.
@ kStatNRxDrop
Rx bytes dropped.
@ kStatNRxEsc
Rx data escapes.
@ kStatNRxNakRtWblk
Rx NAK RtWblk seen.
@ kStatNRxEop
Rx EOP commas seen.
@ kStatNRxNakCcrc
Rx NAK Ccrc seen.
@ kStatNRxNakFrame
Rx NAK Frame seen.
@ kStatNRxPktByt
Rx packet bytes rcvd.
@ kStatNRxSop
Rx SOP commas seen.
@ kStatNRxNakCmd
Rx NAK Cmd seen.
@ kStatNRxNakUnused
Rx NAK Unused seen.
@ kStatNRxNakInval
Rx NAK invalid seen.
@ kStatNRxAttn
Rx ATTN commas seen.
@ kStatNRxClobber
Rx clobbered escapes.
std::vector< uint8_t > fDropData
dropped data buffer
RlinkPacketBufRcv()
Default constructor.
void ProcessDataIdle()
FIXME_docs.
uint8_t fRawBuf[4096]
raw data buffer
void ProcessDataFill()
FIXME_docs.
bool fEscSeen
last char was Escape
void AcceptPacket()
FIXME_docs.
pkt_state PacketState()
FIXME_docs.
@ kRcvIdle
wait for SOP or ATTN
@ kRcvError
packet framing error
@ kRcvFill
fill packet till EOP seen
@ kRcvDone
packet ok, EOP seen
size_t fNDone
number of pkt bytes processed
int ReadData(RlinkPort &port, const Rtime &timeout, RerrMsg &emsg)
FIXME_docs.
void Dump(std::ostream &os, int ind=0, const char *text=0, int detail=0) const
FIXME_docs.
static const uint8_t kEcXon
VHDL def ec_xon 100.
static const uint8_t kNcCnt
VHDL def nak_cnt 101.
static const uint8_t kNcRtWblk
VHDL def nak_rtwblk 111.
static const uint8_t kNcUnused
VHDL def nak_unused 011.
static const uint8_t kNcFrame
VHDL def nak_frame 010.
static const uint32_t kFlagErrTout
err: timeout on read
static const uint8_t kSymEsc
VHDL def escape 1100 1010.
static const uint8_t kEcClobber
invalid Ecode
size_t PktSize() const
FIXME_docs.
static const uint8_t kEcEsc
VHDL def ec_esc 111.
void SetFlagBit(uint32_t mask)
FIXME_docs.
static const uint8_t kNcCmd
VHDL def nak_cmd 100.
static const uint32_t kFlagSopSeen
sop was seen
static const uint8_t kSymFill
VHDL def fill 1101 0101.
static const uint8_t kNcRtOvlf
VHDL def nak_rtovfl 110.
RlinkCrc16 fCrc
crc accumulator
static const uint8_t kEcSop
VHDL def ec_sop 000.
static const uint32_t kFlagEopSeen
eop was seen
static const uint8_t kNcDcrc
VHDL def nak_dcrc 001.
static const uint32_t kFlagErrFrame
err: frame error
static const uint8_t kEcFill
VHDL def ec_fill 110.
static const uint8_t kNcInval
invalid NAK
std::vector< uint8_t > fPktBuf
packet buffer
static const uint32_t kFlagErrClobber
err: clobbered esc
static const uint32_t kFlagNakSeen
nak was seen
Rstats fStats
statistics
static const uint8_t kEcNak
VHDL def ec_nak 010.
static const uint8_t kEcAttn
VHDL def ec_attn 011.
static const uint8_t kSymEdPref
VHDL def ed_pref 0100 0000.
uint32_t fFlags
request/response flags
static const uint8_t kEcXoff
VHDL def ec_xoff 101.
static const uint8_t kSymXon
VHDL def xon 0001 0001.
static const uint8_t kEcEop
VHDL def ec_eop 001.
static const uint8_t kSymXoff
VHDL def xoff 0001 0011.
static const uint8_t kNcCcrc
VHDL def nak_ccrc 000.
void Dump(std::ostream &os, int ind=0, const char *text=0, int detail=0) const
FIXME_docs.
bool TestFlag(uint32_t mask) const
FIXME_docs.
static const uint32_t kFlagErrIO
err: IO error on read
static const uint32_t kFlagAttnSeen
attn was seen
FIXME_docs.
Definition: RlinkPort.hpp:45
static const int kEof
return code: end-of-file
Definition: RlinkPort.hpp:86
static const int kTout
return code: time out
Definition: RlinkPort.hpp:87
virtual int Read(uint8_t *buf, size_t size, const Rtime &timeout, RerrMsg &emsg)
FIXME_docs.
Definition: RlinkPort.cpp:115
I/O appicator to generate fill characters.
Definition: RosFill.hpp:24
void Inc(size_t ind, double val=1.)
FIXME_docs.
Definition: Rstats.ipp:29
void Define(size_t ind, const std::string &name, const std::string &text)
FIXME_docs.
Definition: Rstats.cpp:72
FIXME_docs.
Definition: Rtime.hpp:25
bool IsZero() const
FIXME_docs.
Definition: Rtime.ipp:85
RosPrintfS< bool > RosPrintf(bool value, const char *form=0, int width=0, int prec=0)
Creates a print object for the formatted output of a bool value.
Definition: RosPrintf.ipp:38
Declaration of class ReventLoop.
Definition: ReventLoop.cpp:47