//####COPYRIGHTBEGIN####
|
//####COPYRIGHTBEGIN####
|
//
|
//
|
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
|
// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
|
//
|
//
|
// This program is part of the eCos host tools.
|
// This program is part of the eCos host tools.
|
//
|
//
|
// This program is free software; you can redistribute it and/or modify it
|
// 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
|
// 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)
|
// Software Foundation; either version 2 of the License, or (at your option)
|
// any later version.
|
// any later version.
|
//
|
//
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
// more details.
|
// more details.
|
//
|
//
|
// You should have received a copy of the GNU General Public License along with
|
// 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.,
|
// this program; if not, write to the Free Software Foundation, Inc.,
|
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
//
|
//
|
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
//
|
//
|
//####COPYRIGHTEND####
|
//####COPYRIGHTEND####
|
//=================================================================
|
//=================================================================
|
//
|
//
|
// ser_filter.cxx
|
// ser_filter.cxx
|
//
|
//
|
// Serial test filter
|
// Serial test filter
|
//
|
//
|
//=================================================================
|
//=================================================================
|
//=================================================================
|
//=================================================================
|
//#####DESCRIPTIONBEGIN####
|
//#####DESCRIPTIONBEGIN####
|
//
|
//
|
// Author(s): jskov
|
// Author(s): jskov
|
// Contributors: jskov
|
// Contributors: jskov
|
// Date: 1999-03-01
|
// Date: 1999-03-01
|
// Description: This program acts as a filter between GDB and the test
|
// Description: This program acts as a filter between GDB and the test
|
// running on the target, allowing testing of the serial
|
// running on the target, allowing testing of the serial
|
// driver without confusing GDB.
|
// driver without confusing GDB.
|
// Usage: Run the program with one argument, the serial port
|
// Usage: Run the program with one argument, the serial port
|
// on with the target is connected.
|
// on with the target is connected.
|
// Run serial test in GDB, connecting to the target with
|
// Run serial test in GDB, connecting to the target with
|
// 'target remote localhost:5678'.
|
// 'target remote localhost:5678'.
|
//
|
//
|
// To Do:
|
// To Do:
|
// o Add timeout setup and handling for recovery, can rely on testing
|
// o Add timeout setup and handling for recovery, can rely on testing
|
// agent to control global timeout.
|
// agent to control global timeout.
|
// o Saving chunks that caused transfer failure?
|
// o Saving chunks that caused transfer failure?
|
// - In SEND with echo, do CRC on 32-byte sub-packets
|
// - In SEND with echo, do CRC on 32-byte sub-packets
|
// o Additional To Do items under each sub-protocol function.
|
// o Additional To Do items under each sub-protocol function.
|
// o Option to get all serial IO written (in hex, > and < prepends
|
// o Option to get all serial IO written (in hex, > and < prepends
|
// input/output lines) to a file.
|
// input/output lines) to a file.
|
// o Clean up the mess in this file....
|
// o Clean up the mess in this file....
|
// o Make main() listen on two ports - use one for ser filter, the other for
|
// o Make main() listen on two ports - use one for ser filter, the other for
|
// null filter connections.
|
// null filter connections.
|
// o Maybe use environment variable to find X10 reset command.
|
// o Maybe use environment variable to find X10 reset command.
|
//####DESCRIPTIONEND####
|
//####DESCRIPTIONEND####
|
|
|
#include "eCosTestSerialFilter.h"
|
#include "eCosTestSerialFilter.h"
|
#include "eCosTestDownloadFilter.h"
|
#include "eCosTestDownloadFilter.h"
|
#include "eCosTestMonitorFilter.h"
|
#include "eCosTestMonitorFilter.h"
|
#include "eCosTestUtils.h"
|
#include "eCosTestUtils.h"
|
#include "eCosThreadUtils.h"
|
#include "eCosThreadUtils.h"
|
#include "eCosTrace.h"
|
#include "eCosTrace.h"
|
|
|
bool opt_ser_debug = false;
|
bool opt_ser_debug = false;
|
bool opt_null_filter = false;
|
bool opt_null_filter = false;
|
bool opt_console_output = false;
|
bool opt_console_output = false;
|
bool opt_X10_reset = false;
|
bool opt_X10_reset = false;
|
bool opt_filter_trace = false;
|
bool opt_filter_trace = false;
|
char opt_X10_port[2];
|
char opt_X10_port[2];
|
bool opt_monitor = false;
|
bool opt_monitor = false;
|
|
|
void
|
void
|
no_gdb(const char* pszPort, int nBaud,
|
no_gdb(const char* pszPort, int nBaud,
|
CeCosSocket::FilterFunc *pSerialToSocketFilterFunc,
|
CeCosSocket::FilterFunc *pSerialToSocketFilterFunc,
|
void *pParam, bool *pbStop)
|
void *pParam, bool *pbStop)
|
{
|
{
|
fprintf(stderr, "no_gdb, listening on %s\n",pszPort);
|
fprintf(stderr, "no_gdb, listening on %s\n",pszPort);
|
|
|
CeCosSocket dummy_socket;
|
CeCosSocket dummy_socket;
|
CeCosSerial serial;
|
CeCosSerial serial;
|
serial.SetBlockingReads(false);
|
serial.SetBlockingReads(false);
|
bool rc=false;
|
bool rc=false;
|
|
|
// Open serial device.
|
// Open serial device.
|
if (!serial.Open(pszPort,nBaud)){
|
if (!serial.Open(pszPort,nBaud)){
|
ERROR("Couldn't open port %s\n",pszPort);
|
ERROR("Couldn't open port %s\n",pszPort);
|
} else {
|
} else {
|
// Flush the serial buffer.
|
// Flush the serial buffer.
|
serial.Flush();
|
serial.Flush();
|
|
|
serial.ClearError();
|
serial.ClearError();
|
enum {BUFSIZE=8192};
|
enum {BUFSIZE=8192};
|
void *pBuf=malloc(BUFSIZE);
|
void *pBuf=malloc(BUFSIZE);
|
rc=true;
|
rc=true;
|
while(rc && (0==pbStop || !(*pbStop))){
|
while(rc && (0==pbStop || !(*pbStop))){
|
unsigned int nRead=0;
|
unsigned int nRead=0;
|
|
|
for(;;) {
|
for(;;) {
|
if(serial.Read(pBuf,BUFSIZE,nRead)){
|
if(serial.Read(pBuf,BUFSIZE,nRead)){
|
if(nRead>0){
|
if(nRead>0){
|
break;
|
break;
|
}
|
}
|
CeCosThreadUtils::Sleep(1);
|
CeCosThreadUtils::Sleep(1);
|
} else {
|
} else {
|
fprintf(stderr, "Serial read failed (%d)\n", errno);
|
fprintf(stderr, "Serial read failed (%d)\n", errno);
|
}
|
}
|
}
|
}
|
|
|
if(pSerialToSocketFilterFunc){
|
if(pSerialToSocketFilterFunc){
|
rc=pSerialToSocketFilterFunc(pBuf,nRead,serial,dummy_socket,
|
rc=pSerialToSocketFilterFunc(pBuf,nRead,serial,dummy_socket,
|
pParam);
|
pParam);
|
}
|
}
|
}
|
}
|
free(pBuf);
|
free(pBuf);
|
}
|
}
|
}
|
}
|
|
|
int
|
int
|
main(int argc, char** argv)
|
main(int argc, char** argv)
|
{
|
{
|
int nSock = 0;
|
int nSock = 0;
|
int baud_rate, nTcpPort;
|
int baud_rate, nTcpPort;
|
|
|
bool opt_no_gdb = false;
|
bool opt_no_gdb = false;
|
char* ser_port;
|
char* ser_port;
|
int i=1;
|
int i=1;
|
if(!CeCosTestUtils::CommandLine(argc, argv, false)){
|
if(!CeCosTestUtils::CommandLine(argc, argv, false)){
|
goto Usage;
|
goto Usage;
|
}
|
}
|
|
|
while(i<argc){
|
while(i<argc){
|
if(argv[i][0]=='-'){
|
if(argv[i][0]=='-'){
|
switch(argv[i][1]){
|
switch(argv[i][1]){
|
case 't':
|
case 't':
|
// redundant - -v does this
|
// redundant - -v does this
|
CeCosTrace ::EnableTracing(CeCosTrace::TRACE_LEVEL_TRACE);
|
CeCosTrace ::EnableTracing(CeCosTrace::TRACE_LEVEL_TRACE);
|
break;
|
break;
|
case 'f':
|
case 'f':
|
opt_filter_trace = true;
|
opt_filter_trace = true;
|
break;
|
break;
|
case 'S':
|
case 'S':
|
opt_ser_debug = true;
|
opt_ser_debug = true;
|
break;
|
break;
|
case 'm':
|
case 'm':
|
opt_monitor = true;
|
opt_monitor = true;
|
break;
|
break;
|
case 'n':
|
case 'n':
|
opt_no_gdb = true;
|
opt_no_gdb = true;
|
// fall through! Output on console when no GDB.
|
// fall through! Output on console when no GDB.
|
case 'c':
|
case 'c':
|
opt_console_output = true;
|
opt_console_output = true;
|
break;
|
break;
|
case '0':
|
case '0':
|
opt_null_filter = true;
|
opt_null_filter = true;
|
break;
|
break;
|
case 'X':
|
case 'X':
|
// X-10 port to reset when connection drops
|
// X-10 port to reset when connection drops
|
opt_X10_reset = true;
|
opt_X10_reset = true;
|
opt_X10_port[0] = argv[i][2];
|
opt_X10_port[0] = argv[i][2];
|
opt_X10_port[1] = argv[i][3];
|
opt_X10_port[1] = argv[i][3];
|
break;
|
break;
|
default:
|
default:
|
fprintf(stderr,"Unrecognized switch %s\n",argv[i]);
|
fprintf(stderr,"Unrecognized switch %s\n",argv[i]);
|
goto Usage;
|
goto Usage;
|
break;
|
break;
|
}
|
}
|
for(int j=i;j<argc;j++){
|
for(int j=i;j<argc;j++){
|
argv[j]=argv[j+1];
|
argv[j]=argv[j+1];
|
}
|
}
|
argc--;
|
argc--;
|
argv[argc]=0;
|
argv[argc]=0;
|
} else {
|
} else {
|
i++;
|
i++;
|
}
|
}
|
}
|
}
|
|
|
if(!((3==argc && opt_no_gdb) || (4==argc && !opt_no_gdb)))
|
if(!((3==argc && opt_no_gdb) || (4==argc && !opt_no_gdb)))
|
{
|
{
|
goto Usage;
|
goto Usage;
|
}
|
}
|
|
|
if (opt_no_gdb) {
|
if (opt_no_gdb) {
|
ser_port = argv[1];
|
ser_port = argv[1];
|
baud_rate=atoi(argv[2]);
|
baud_rate=atoi(argv[2]);
|
} else {
|
} else {
|
nTcpPort=atoi(argv[1]);
|
nTcpPort=atoi(argv[1]);
|
if(0==nTcpPort){
|
if(0==nTcpPort){
|
fprintf(stderr,"Invalid port %s\n",argv[1]);
|
fprintf(stderr,"Invalid port %s\n",argv[1]);
|
return main(0,argv); // Provoke usage message
|
return main(0,argv); // Provoke usage message
|
}
|
}
|
|
|
ser_port = argv[2];
|
ser_port = argv[2];
|
baud_rate=atoi(argv[3]);
|
baud_rate=atoi(argv[3]);
|
|
|
nSock = CeCosSocket::Listen(nTcpPort);
|
nSock = CeCosSocket::Listen(nTcpPort);
|
if (-1 == nSock) {
|
if (-1 == nSock) {
|
fprintf(stderr, "Couldn't access socket.\n");
|
fprintf(stderr, "Couldn't access socket.\n");
|
throw "listen failed";
|
throw "listen failed";
|
}
|
}
|
}
|
}
|
|
|
|
|
if (opt_monitor) {
|
if (opt_monitor) {
|
fprintf(stdout, "Monitor mode - will not interact with data streams...\n");
|
fprintf(stdout, "Monitor mode - will not interact with data streams...\n");
|
|
|
for(;;) {
|
for(;;) {
|
|
|
CeCosTestMonitorFilter* host_filter =
|
CeCosTestMonitorFilter* host_filter =
|
new CeCosTestMonitorFilter();
|
new CeCosTestMonitorFilter();
|
CeCosTestMonitorFilter* target_filter =
|
CeCosTestMonitorFilter* target_filter =
|
new CeCosTestMonitorFilter();
|
new CeCosTestMonitorFilter();
|
|
|
// Set filter directions
|
// Set filter directions
|
host_filter->SetOrigin(CeCosTestMonitorFilter::MF_HOST);
|
host_filter->SetOrigin(CeCosTestMonitorFilter::MF_HOST);
|
target_filter->SetOrigin(CeCosTestMonitorFilter::MF_TARGET);
|
target_filter->SetOrigin(CeCosTestMonitorFilter::MF_TARGET);
|
|
|
// Enable filters
|
// Enable filters
|
host_filter->SetVerbose(true);
|
host_filter->SetVerbose(true);
|
target_filter->SetVerbose(true);
|
target_filter->SetVerbose(true);
|
|
|
// Set filter functions
|
// Set filter functions
|
CeCosSocket::FilterFunc *host_filter_function =
|
CeCosSocket::FilterFunc *host_filter_function =
|
&SerialMonitorFunction;
|
&SerialMonitorFunction;
|
CeCosSocket::FilterFunc *target_filter_function =
|
CeCosSocket::FilterFunc *target_filter_function =
|
&SerialMonitorFunction;
|
&SerialMonitorFunction;
|
|
|
try {
|
try {
|
CeCosSocket::ConnectSocketToSerial(nSock, ser_port,
|
CeCosSocket::ConnectSocketToSerial(nSock, ser_port,
|
baud_rate,
|
baud_rate,
|
target_filter_function,
|
target_filter_function,
|
(void*)target_filter,
|
(void*)target_filter,
|
host_filter_function,
|
host_filter_function,
|
(void*)host_filter,
|
(void*)host_filter,
|
NULL);
|
NULL);
|
}
|
}
|
catch (const char* p) {
|
catch (const char* p) {
|
fprintf(stderr, "Caught filter crash: %s\n", p);
|
fprintf(stderr, "Caught filter crash: %s\n", p);
|
}
|
}
|
|
|
delete target_filter;
|
delete target_filter;
|
delete host_filter;
|
delete host_filter;
|
}
|
}
|
}
|
}
|
|
|
for(;;) {
|
for(;;) {
|
CeCosTestSerialFilter* serial_filter =
|
CeCosTestSerialFilter* serial_filter =
|
new CeCosTestSerialFilter();
|
new CeCosTestSerialFilter();
|
CeCosTestDownloadFilter* download_filter =
|
CeCosTestDownloadFilter* download_filter =
|
new CeCosTestDownloadFilter();
|
new CeCosTestDownloadFilter();
|
|
|
// Set filter configuration
|
// Set filter configuration
|
serial_filter->SetFilterTrace(opt_filter_trace);
|
serial_filter->SetFilterTrace(opt_filter_trace);
|
serial_filter->SetSerialDebug(opt_ser_debug);
|
serial_filter->SetSerialDebug(opt_ser_debug);
|
serial_filter->SetConsoleOutput(opt_console_output);
|
serial_filter->SetConsoleOutput(opt_console_output);
|
|
|
// Set download filter configuration
|
// Set download filter configuration
|
download_filter->SetFilterTrace(opt_filter_trace);
|
download_filter->SetFilterTrace(opt_filter_trace);
|
download_filter->SetSerialDebug(opt_ser_debug);
|
download_filter->SetSerialDebug(opt_ser_debug);
|
|
|
// Set serial side filter
|
// Set serial side filter
|
CeCosSocket::FilterFunc *ser_filter_function =
|
CeCosSocket::FilterFunc *ser_filter_function =
|
&SerialFilterFunction;
|
&SerialFilterFunction;
|
if (opt_null_filter)
|
if (opt_null_filter)
|
ser_filter_function = NULL;
|
ser_filter_function = NULL;
|
|
|
// Set socket side filter
|
// Set socket side filter
|
CeCosSocket::FilterFunc *sock_filter_function =
|
CeCosSocket::FilterFunc *sock_filter_function =
|
&DownloadFilterFunction;
|
&DownloadFilterFunction;
|
|
|
try {
|
try {
|
if (opt_no_gdb)
|
if (opt_no_gdb)
|
no_gdb(ser_port, baud_rate, ser_filter_function,
|
no_gdb(ser_port, baud_rate, ser_filter_function,
|
(void*)serial_filter, NULL);
|
(void*)serial_filter, NULL);
|
else
|
else
|
CeCosSocket::ConnectSocketToSerial(nSock, ser_port,
|
CeCosSocket::ConnectSocketToSerial(nSock, ser_port,
|
baud_rate,
|
baud_rate,
|
ser_filter_function,
|
ser_filter_function,
|
(void*)serial_filter,
|
(void*)serial_filter,
|
sock_filter_function,
|
sock_filter_function,
|
(void*)download_filter,
|
(void*)download_filter,
|
NULL);
|
NULL);
|
}
|
}
|
catch (const char* p) {
|
catch (const char* p) {
|
fprintf(stderr, "Caught filter crash: %s\n", p);
|
fprintf(stderr, "Caught filter crash: %s\n", p);
|
}
|
}
|
|
|
if (opt_X10_reset) {
|
if (opt_X10_reset) {
|
char X10_cmd[80];
|
char X10_cmd[80];
|
sprintf(X10_cmd, "/usr/unsupported/bin/x10cli x10 5000 %c %c",
|
sprintf(X10_cmd, "/usr/unsupported/bin/x10cli x10 5000 %c %c",
|
opt_X10_port[0], opt_X10_port[1]);
|
opt_X10_port[0], opt_X10_port[1]);
|
system(X10_cmd);
|
system(X10_cmd);
|
}
|
}
|
|
|
delete serial_filter;
|
delete serial_filter;
|
delete download_filter;
|
delete download_filter;
|
}
|
}
|
|
|
// return 0;
|
// return 0;
|
|
|
Usage:
|
Usage:
|
const char *pszMe="ser_filter";
|
const char *pszMe="ser_filter";
|
fprintf(stderr,"Usage: %s [-c -S -0 -Xab] TcpIPport SerialPort BaudRate\n"
|
fprintf(stderr,"Usage: %s [-c -S -0 -Xab] TcpIPport SerialPort BaudRate\n"
|
" or: %s -n [-c -S -0 -Xab] SerialPort BaudRate\n"
|
" or: %s -n [-c -S -0 -Xab] SerialPort BaudRate\n"
|
" Switches:\n"
|
" Switches:\n"
|
" -f: Enable filter output tracing.\n"
|
" -f: Enable filter output tracing.\n"
|
" -S: Output data read from serial line.\n"
|
" -S: Output data read from serial line.\n"
|
" -c: Output data on console instead of via GDB.\n"
|
" -c: Output data on console instead of via GDB.\n"
|
" -m: Work only as a monitor filter. Implies -c.\n"
|
" -m: Work only as a monitor filter. Implies -c.\n"
|
" -n: No GDB.\n"
|
" -n: No GDB.\n"
|
" -0: Use null filter.\n"
|
" -0: Use null filter.\n"
|
" -Xab: Reset X-10 Port 'a b' when TCP connection breaks\n",pszMe,pszMe);
|
" -Xab: Reset X-10 Port 'a b' when TCP connection breaks\n",pszMe,pszMe);
|
CeCosTestUtils::UsageMessage();
|
CeCosTestUtils::UsageMessage();
|
|
|
return 1;
|
return 1;
|
}
|
}
|
|
|