📄 ecostestserialfilter.cpp
字号:
//####COPYRIGHTBEGIN####// // ----------------------------------------------------------------------------// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.//// This program is part of the eCos host tools.//// This program is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 of the License, or (at your option) // any later version.// // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for // more details.// // You should have received a copy of the GNU General Public License along with// this program; if not, write to the Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.//// ----------------------------------------------------------------------------// //####COPYRIGHTEND####//=================================================================//// eCosTestSerialFilter.cpp//// Serial test filter class////=================================================================//=================================================================//#####DESCRIPTIONBEGIN####//// Author(s): jskov// Contributors: jskov// Date: 1999-03-01// Description: This filter sits between GDB and the test running on// the target, allowing testing of the serial driver // without confusing GDB.// To Do:// o Add timeout setup and handling for recovery, can rely on testing// agent to control global timeout.// o Saving chunks that caused transfer failure?// - In SEND with echo, do CRC on 32-byte sub-packets// o Additional To Do items under each sub-protocol function.// o Option to get all serial IO written (in hex, > and < prepends // input/output lines) to a file.// o Clean up the mess in this file....//####DESCRIPTIONEND#####include "eCosStd.h"#define SER_FILTER_VER "$Id: eCosTestSerialFilter.cpp,v 1.9 2000/03/07 16:01:03 sdf Exp $"#include "eCosTestSerialFilter.h"char msg_ok[] = "OK";char msg_er[] = "ER";CeCosTestSerialFilter::CeCosTestSerialFilter(): m_bOptConsoleOutput(false), m_bOptSerDebug(false), m_bOptFilterTrace(false), m_xUnreadBuffer(NULL), m_nUnreadBufferIndex(0), m_nUnreadBufferSize(0), m_bNullFilter(false), m_nCmdIndex(0), m_bCmdFlag(false), m_bFirstCommandSeen(false), m_cGDBSocket(NULL){}CeCosTestSerialFilter::~CeCosTestSerialFilter(){}//------------------------// Output helpers.// Encode string in an O-packet and send it to GDB.void CeCosTestSerialFilter::GDBWrite(const char* pszStr){ if (m_cGDBSocket) { static const char hexchars[] = "0123456789abcdef"; char* packet = new char[strlen(pszStr)*2+6]; char* p = packet; *p++ = '$'; *p++ = 'O'; unsigned char crc = 'O'; char c; for (;;) { c = *pszStr++; if (0 == c) break; char h = hexchars[(c >> 4) & 0x0f]; char l = hexchars[c & 0x0f]; *p++ = h; *p++ = l; crc = (unsigned char) (crc + h + l); }; *p++ = '#'; *p++ = hexchars[(crc >> 4) & 0x0f]; *p++ = hexchars[crc & 0x0f]; // Only try to send once. If it fails, it's probably because // GDB has disconnected. m_cGDBSocket->send(packet, p - packet); m_cGDBSocket->recv(&c, 1); delete [] packet; }}voidCeCosTestSerialFilter::ConsoleWrite(const char* pszStr){ fputs(pszStr, stderr); fflush(stderr);}voidCeCosTestSerialFilter::Trace(const char* pszFormat, ...){ va_list marker; va_start (marker, pszFormat); for(int nLength=100;nLength;) { char *buf=new char[1+nLength]; int n=vsnprintf(buf+4, nLength-4, pszFormat, marker ); if(-1==n){ nLength*=2; // NT behavior } else if (n<nLength){ memcpy(buf,"[f] ",4); if (m_bOptConsoleOutput) { ConsoleWrite(buf); } else { GDBWrite(buf); } nLength=0; // trigger exit from loop } else { nLength=n+1; // UNIX behavior generally, or NT behavior when buffer size exactly matches required length } delete [] buf; } va_end (marker); }voidCeCosTestSerialFilter::Log(const char* pszFormat, ...){ va_list marker; va_start (marker, pszFormat); for(int nLength=100;nLength;) { char *buf=new char[1+nLength]; int n=vsnprintf(buf, nLength, pszFormat, marker ); if(-1==n){ nLength*=2; // NT behavior } else if (n<nLength){ if (m_bOptConsoleOutput) { ConsoleWrite(buf); } else { GDBWrite(buf); } nLength=0; // trigger exit from loop } else { nLength=n+1; // UNIX behavior generally, or NT behavior when buffer size exactly matches required length } delete [] buf; } va_end (marker);}voidCeCosTestSerialFilter::PrintHex(const unsigned char* d1, int len, data_origin_t origin/*=SF_TARGET*/){ int offset = 0; int i; char buf[128]; int width = 8; while (len) { int count = MIN(width, len); char* p = buf; switch (origin) { case SF_TARGET: p += sprintf(p, "T"); break; case SF_FILTER: p += sprintf(p, "F"); break; } p += sprintf(p, ":%04x ", offset); // Print hex values. for (i = 0; i < count; i++) p += sprintf(p, "%02x ", d1[i]); for ( ; i < width ; i++) p += sprintf(p, ".. "); // Print ASCII string p += sprintf(p, "'"); for (i = 0; i < count; i++) { int c = d1[i]; if (' ' >= c || 'z' <= c) c = '.'; p += sprintf(p, "%c", c); } sprintf(p, "'\n"); Trace("%s", buf); len -= count; offset += count; d1 += count; }}voidCeCosTestSerialFilter::TargetWrite(CeCosTestSerial &pSer, const unsigned char* buffer, int len){ unsigned int __written; if (m_bOptFilterTrace) PrintHex(buffer, len, SF_FILTER); do { if (!(pSer.Write((void*) buffer, len, __written))) { fprintf(stderr, "Writing %d bytes to serial failed\n", len); fprintf(stderr, "%s", (LPCTSTR)pSer.ErrString()); throw "serial write failed"; } buffer += __written; len -= __written; } while (len);}boolCeCosTestSerialFilter::TargetRead(CeCosTestSerial &pSer, unsigned char* buffer, int len){ unsigned int __read; int __total_read = 0; unsigned char* __buffer_base = buffer; int __timeouts = 0; int __timeout_failure = 0; int __orig_len = len; do { // First check for unread data. if (m_nUnreadBufferSize) { int i = 0; __read = 0; while (i < len && m_nUnreadBufferIndex < m_nUnreadBufferSize) { buffer[i++] = m_xUnreadBuffer[m_nUnreadBufferIndex++]; __read++; } if (m_nUnreadBufferIndex == m_nUnreadBufferSize) { free(m_xUnreadBuffer); m_nUnreadBufferSize = 0; m_nUnreadBufferIndex = 0; } } else { // Then read directly from serial. if (!(pSer.Read((void*) buffer, len, __read))) { fprintf(stderr,"Reading %d bytes from serial failed (read %d).\n", len, __read); char *pszErr=pSer.ErrString().GetCString(); fprintf(stderr, "%s", pszErr); delete [] pszErr; throw "serial read failed"; } } __total_read += __read; unsigned int i; for (i = 0; i < __read; i++) { if ('$' == buffer[i]) { Log("FAIL:<target crashed>\n"); Trace("**** Detected $ -- resuming as null filter ****\n"); Trace("Data received %d bytes (of %d) from target:\n", __total_read, __orig_len); PrintHex(__buffer_base, __total_read); Trace("<end>\n"); filter_abort_t* msg = new filter_abort_t(); msg->data_ptr = &buffer[i]; msg->data_len = __read - i; throw msg; } } if (0 == __read) { Sleep(20); __timeouts++; if (25 == __timeouts) { __timeouts = 0; if (5 == __timeout_failure++) { Log("FAIL:<target timed out>\n"); Trace("**** Timed out while reading -- resuming as null filter\n"); Trace("Data received %d bytes (of %d) from target:\n", __total_read, __orig_len); PrintHex(__buffer_base, __total_read); Trace("<end>\n"); static const char kill_msg[] = "$X00#b8"; filter_abort_t* msg = new filter_abort_t(); msg->data_len = strlen(kill_msg); msg->data_ptr = (const unsigned char *)kill_msg; throw msg; } } } else { __timeouts = 0; __timeout_failure = 0; } buffer += __read; len -= __read; } while (len); return true;}// Send C ASCII string to target.void CeCosTestSerialFilter::TargetASCIIWrite(CeCosTestSerial &pSer, const char* s) { TargetWrite(pSer, (const unsigned char*) s, strlen(s)); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -