Subversion Repositories Projects

Compare Revisions

Ignore whitespace Rev 226 → Rev 227

/bioloid/cli/NetBus.cpp
0,0 → 1,418
/****************************************************************************
*
* Copyright (c) 2009 Dave Hylands <dhylands@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*
****************************************************************************/
/**
*
* @file NetBus.cpp
*
* @brief This file implements the NetBus class, which talks to the
* bioloid bus using a network interface.
*
****************************************************************************/
 
// ---- Include Files -------------------------------------------------------
 
#include "Log.h"
#include "DumpMem.h"
#include "NetBus.h"
#include "Str.h"
#include "StrToken.h"
#include "Error.h"
 
#if defined( WIN32 )
#include <WinSock2.h>
#endif
 
// ---- Public Variables ----------------------------------------------------
// ---- Private Constants and Types -----------------------------------------
// ---- Private Variables ---------------------------------------------------
// ---- Private Function Prototypes -----------------------------------------
// ---- Functions -----------------------------------------------------------
 
/**
* @addtogroup bioloid
* @{
*/
 
//***************************************************************************
/**
* Constructor
*/
 
NetBus::NetBus()
: m_dataBytes( 0 ),
m_debug( false ),
m_initialized( false )
{
}
 
//***************************************************************************
/**
* Destructor
*
* virtual
*/
 
NetBus::~NetBus()
{
}
 
//***************************************************************************
/**
* Adds a byte to the buffer of data to send.
*/
 
void NetBus::BufferByte( uint8_t data )
{
m_data[ m_dataBytes++ ] = data;
 
if ( m_dataBytes >= sizeof( m_data ))
{
WriteBuffer();
}
}
 
//***************************************************************************
/**
* Sets the serial port that will be used for talking with the bioloid
* devices.
*/
 
bool NetBus::Open( const char *hostStr )
{
uint32_t err;
char errStr[ 200 ];
 
if ( !m_initialized )
{
#if defined( WIN32 )
WSADATA wsaData;
 
if (( err = WSAStartup( 0x0202, &wsaData )) != 0 )
{
LogError( "Error initializing Windows Sockets: %s\n", GetErrorStr( err, errStr, sizeof( errStr )));
return false;
}
#endif
m_initialized = true;
}
 
char *endPtr;
 
// Extract the hostname and portname.
 
char token[ 200 ];
 
char *hostName = NULL;
 
// NextToken parses skips leading delimiters
 
if ( *hostStr == ':' )
{
hostName = "";
hostStr++;
}
 
// If it's all digits, then assume it's a port number
 
if ( strspn( hostStr, "0123456789" ) == strlen( hostStr ))
{
hostName = "";
}
 
StrTokenizer tokenizer( hostStr, token, sizeof( token ));
 
if ( hostName == NULL )
{
hostName = tokenizer.NextToken( ":" );
}
 
if ( hostName == NULL )
{
LogError( "No hostname specified" );
return false;
}
 
// Check to see if the servername is only made up of numbers and dots.
 
if ( strspn( hostName, ".0123456789" ) == strlen( hostName ))
{
int seg;
char *segStr = hostName;
char *endPtr;
 
// The hostname is only made up of numbers and dots. We'll parse
// it ourselves.
//
// We expect it to be of the form a.b.c.d, where a, b, c, and d are
// all positive integers in the range 0 thru 255.
 
for ( seg = 0; seg < 4; seg++ )
{
long longByte = strtol( segStr, &endPtr, 10 );
 
if (( longByte < 0 ) || ( longByte > 255 ))
{
LogError( "Expecting a positive number between 0 and 255, found: '%s'\n", segStr );
return false;
}
if (( endPtr == segStr )
|| (( *endPtr == '.' ) && ( seg == 3 ))
|| (( *endPtr != '.' ) && ( seg < 3 )))
{
LogError( "Expecting IP address of the form a.b.c.d, found: '%s'\n", hostName );
return false;
}
 
m_sockAddr.sin_addr.S_un.S_addr <<= 8;
m_sockAddr.sin_addr.S_un.S_addr += (unsigned char)longByte;
 
segStr = endPtr + 1;
}
m_sockAddr.sin_addr.S_un.S_addr = htonl( m_sockAddr.sin_addr.S_un.S_addr );
}
else
{
// The server name was specified symbolically, see if we can translate it
 
struct hostent *hostent;
 
hostent = gethostbyname( hostName );
if ( hostent == NULL )
{
LogError( "Unable to translate hostname '%s' into an IP address.\n", hostName );
return false;
}
m_sockAddr.sin_addr.S_un.S_addr = *((long *)hostent->h_addr_list[ 0 ]);
}
 
// Now parse the port (if present)
 
const char *portStr = tokenizer.Remainder();
 
if ( *portStr == '\0' )
{
// No port specified
 
m_sockAddr.sin_port = htons( m_defaultPort );
}
else
{
long longPort;
 
if ( strspn( portStr, "0123456789" ) == strlen( portStr ))
{
// The port string is all numeric
 
longPort = strtol( portStr, &endPtr, 0 );
if ( *endPtr != '\0' )
{
LogError( "Expecting a positive numeric port specifier; Found '%s'.\n", portStr );
return false;
}
}
else
{
struct servent *servent;
 
servent = getservbyname( portStr, "tcp" );
if ( servent == NULL )
{
LogError( "Unable to translate service '%s' into a port number.", portStr );
return false;
}
longPort = ntohs( servent->s_port );
}
 
if (( longPort <= 0 ) || ( longPort > 65535 ))
{
LogError( "Expecting port to be between 1 and 65535; Found: %ld\n", longPort );
return false;
}
m_sockAddr.sin_port = htons( (short)longPort );
}
m_sockAddr.sin_family = AF_INET;
 
// We now have an IP address and port number
 
// Open a socket
 
m_socket = socket( AF_INET, SOCK_STREAM, 0 );
if ( m_socket == INVALID_SOCKET )
{
err = WSAGetLastError();
LogError( "Error calling socket: %s\n", GetErrorStr( err, errStr, sizeof( errStr )));
return false;
}
 
// Connect to the server
 
if ( connect( m_socket, (struct sockaddr *)&m_sockAddr, sizeof( m_sockAddr )) != 0 )
{
err = WSAGetLastError();
LogError( "Error calling connect: %s\n", GetErrorStr( err, errStr, sizeof( errStr )));
return false;
}
 
StrPrintf( m_connectionInfo, sizeof( m_connectionInfo ),
"%s (%d.%d.%d.%d:%d)", hostStr,
m_sockAddr.sin_addr.S_un.S_un_b.s_b1,
m_sockAddr.sin_addr.S_un.S_un_b.s_b2,
m_sockAddr.sin_addr.S_un.S_un_b.s_b3,
m_sockAddr.sin_addr.S_un.S_un_b.s_b4,
ntohs( m_sockAddr.sin_port ));
 
Log( "Connected to %s\n", m_connectionInfo );
}
 
//***************************************************************************
/**
* Writes all of the buffered bytes to the serial port.
*/
 
void NetBus::WriteBuffer()
{
size_t bytesWritten;
 
if ( m_debug )
{
DumpMem( "W", 0, m_data, m_dataBytes );
}
 
#if 0
if (( bytesWritten = m_serialPort->Write( m_data, m_dataBytes )) != m_dataBytes )
{
LogError( "Error writing %d bytes to serial port", m_dataBytes );
}
#endif
 
m_dataBytes = 0;
}
 
//***************************************************************************
/**
* Reads a byte.
*
* virtual
*/
 
bool NetBus::ReadByte( uint8_t *ch )
{
bool rc;
 
#if 1
rc = true;
#else
rc = m_serialPort->Read( ch, 1 ) == 1;
#endif
 
if ( rc )
{
if ( m_dataBytes < sizeof( m_data ))
{
m_data[ m_dataBytes++ ] = *ch;
}
}
 
return rc;
}
 
//***************************************************************************
/**
* Reads a packet. Returns true if a packet was read successfully,
* false if a timeout or error occurred.
*
* virtual
*/
 
bool NetBus::ReadStatusPacket( BioloidPacket *pkt )
{
bool rc;
 
m_dataBytes = 0;
 
rc = BioloidBus::ReadStatusPacket( pkt );
 
if ( m_debug )
{
if ( m_dataBytes > 0 )
{
DumpMem( "R", 0, m_data, m_dataBytes );
}
#if 0
if ( !rc )
{
LogError( "Packet Error\n" );
}
#endif
}
 
return rc;
}
 
//***************************************************************************
/**
* Sends a byte. This will automatically accumulate the byte into
* the checksum)
*
* virtual
*/
 
void NetBus::SendByte( uint8_t data )
{
m_checksum += data;
 
BufferByte( data );
}
 
//***************************************************************************
/**
* Send the checksum. Since the checksum byte is the last byte of the
* packet, this function is made virtual to allow bus drivers to
* buffer the packet bytes until the entire packet is ready to send.
*
* virtual
*/
 
void NetBus::SendCheckSum()
{
SendByte( ~m_checksum );
 
WriteBuffer();
}
 
//***************************************************************************
/**
* Sends the command header, which is common to all of the commands.
* 2 is added to paramLen (to cover the length and cmd bytes). This
* way the caller is only responsible for figuring out how many extra
* parameter bytes are being sent.
*
* virtual
*/
 
void NetBus::SendCmdHeader
(
Bioloid::ID_t id,
uint8_t paramLen,
Bioloid::Command cmd
)
{
m_dataBytes = 0;
 
BioloidBus::SendCmdHeader( id, paramLen, cmd );
}
 
/** @} */
 
Property changes:
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: cli/NetBus.h
===================================================================
--- cli/NetBus.h (nonexistent)
+++ cli/NetBus.h (revision 227)
@@ -0,0 +1,125 @@
+/****************************************************************************
+*
+* Copyright (c) 2009 Dave Hylands <dhylands@gmail.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* Alternatively, this software may be distributed under the terms of BSD
+* license.
+*
+* See README and COPYING for more details.
+*
+****************************************************************************/
+/**
+*
+* @file SerialBus.h
+*
+* @brief Implements a bioloid bus using posix serial. This typically
+* assumes that an FTDI USB-to-serial adapter is being used
+* to do the RS-485 management.
+*
+****************************************************************************/
+
+#if !defined( NETBUS_H )
+#define NETBUS_H /**< Include Guard */
+
+// ---- Include Files -------------------------------------------------------
+
+#include "BioloidBus.h"
+
+#if defined( WIN32 )
+#include <windows.h>
+#endif
+
+/**
+ * @addtogroup bioloid
+ * @{
+ */
+
+class NetBus : public BioloidBus
+{
+public:
+ //------------------------------------------------------------------------
+ // Default constructor
+
+ NetBus();
+
+ //------------------------------------------------------------------------
+ // Destructor
+
+ virtual ~NetBus();
+
+ //------------------------------------------------------------------------
+ // Sets the serial port which will be used for communications
+
+ bool Open( const char *hostStr );
+
+ //------------------------------------------------------------------------
+ // Reads a byte.
+
+ virtual bool ReadByte( uint8_t *ch );
+
+ //------------------------------------------------------------------------
+ // Reads a packet. Returns true if a packet was read successfully,
+ // false if a timeout or error occurred.
+
+ virtual bool ReadStatusPacket( BioloidPacket *pkt );
+
+ //------------------------------------------------------------------------
+ // Sends a byte. This will automatically accumulate the byte into
+ // the checksum
+
+ virtual void SendByte( uint8_t data );
+
+ //------------------------------------------------------------------------
+ // Send the checksum. Since the checksum byte is the last byte of the
+ // packet, this function is made virtual to allow bus drivers to
+ // buffer the packet bytes until the entire packet is ready to send.
+
+ virtual void SendCheckSum();
+
+ //------------------------------------------------------------------------
+ // Sends the command header, which is common to all of the commands.
+ // 2 is added to paramLen (to cover the length and cmd bytes). This
+ // way the caller is only responsible for figuring out how many extra
+ // parameter bytes are being sent.
+
+ virtual void SendCmdHeader( Bioloid::ID_t id, uint8_t paramLen, Bioloid::Command cmd );
+
+ //------------------------------------------------------------------------
+ // Sets the debug mode
+
+ void SetDebug( bool debug ) { m_debug = debug; }
+
+private:
+
+ //------------------------------------------------------------------------
+ // Adds a byte to the buffer of data to send.
+
+ void BufferByte( uint8_t data );
+
+ //------------------------------------------------------------------------
+ // Writes all of the buffered bytes to the serial port.
+
+ void WriteBuffer();
+
+ //------------------------------------------------------------------------
+
+ bool m_debug;
+
+ bool m_initialized;
+
+ int m_socket; ///< Socket handle
+ int m_dataBytes;
+ uint8_t m_data[ 128 ];
+ unsigned short m_defaultPort; ///< Default Port number (if none specified)
+ struct sockaddr_in m_sockAddr; ///< Socket address for the remote end
+ char m_connectionInfo[ 100 ]; ///< Describes the hostname etc.
+};
+
+/** @} */
+
+#endif /* NETBUS_H */
+
/cli/NetBus.h
Property changes:
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: cli/bioloid.cpp
===================================================================
--- cli/bioloid.cpp (revision 226)
+++ cli/bioloid.cpp (revision 227)
@@ -24,8 +24,10 @@
#if defined( AVR )
#define USE_COMMAND_LINE 0
+#define USE_NETBUS 0
#else
#define USE_COMMAND_LINE 1
+#define USE_NETBUS 1
#endif
// ---- Include Files -------------------------------------------------------
@@ -48,6 +50,10 @@
#include "SerialBus.h"
#include "DevTypeParser.h"
+#if USE_NETBUS
+# include "NetBus.h"
+#endif
+
#if defined( WIN32 )
# include <windows.h>
#else
@@ -76,6 +82,7 @@
OPT_BAUD = 'b',
OPT_DEBUG = 'd',
OPT_PORT = 'p',
+ OPT_NET = 'n',
OPT_VERBOSE = 'v',
OPT_HELP = 'h',
@@ -92,6 +99,7 @@
{ "debug", no_argument, NULL, OPT_DEBUG },
{ "help", no_argument, NULL, OPT_HELP },
{ "port", required_argument, NULL, OPT_PORT },
+ { "net", required_argument, NULL, OPT_NET },
{ "verbose", no_argument, NULL, OPT_VERBOSE },
{ NULL }
};
@@ -99,8 +107,14 @@
SerialPort gSerialPort;
SerialBus gSerialBus;
-BioloidDevice gDev( &gSerialBus, 1 );
+bool gUseSerial = false;
+
+#if USE_NETBUS
+NetBus gNetBus;
+bool gUseNet = false;
+#endif
+
#define MAX_DEV_TYPES 20
static unsigned gNumDevTypes;
@@ -209,6 +223,7 @@
fprintf( stderr, "\n" );
fprintf( stderr, " -b, --baud=baud Set the baudrate used\n" );
fprintf( stderr, " -p, --port=name Set the serial port to use\n" );
+ fprintf( stderr, " -n, --net=name[:port] Set the network host to use\n" );
fprintf( stderr, " -d, --debug Enable debug features\n" );
fprintf( stderr, " -h, --help Display this message\n" );
fprintf( stderr, " -v, --verbose Turn on verbose messages\n" );
@@ -232,6 +247,9 @@
const char *baudStr = DEFAULT_BAUD;
const char *portStr = DEFAULT_PORT;
#endif
+#if USE_NETBUS
+ const char *hostStr = NULL;
+#endif
char line[ 80 ];
BioloidCommandLine cmdLine;
@@ -285,9 +303,19 @@
case OPT_PORT:
{
portStr = optarg;
+ gUseSerial = true;
break;
}
+#if USE_NETBUS
+ case OPT_NET:
+ {
+ hostStr = optarg;
+ gUseNet = true;
+ break;
+ }
+#endif
+
case OPT_VERBOSE:
{
gVerbose = 1;
@@ -313,19 +341,41 @@
LogVerbose( "Verbose enabled\n" );
#endif
+ if ( gUseSerial && gUseNet )
+ {
+ LogError( "Only specify network or serial, not both\n" );
+ exit( 1 );
+ }
+
// Read in all of the reg-*.bld files
ReadRegisterFiles( exeDir );
- if ( !gSerialPort.Open( portStr, baudStr ))
+#if USE_NETBUS
+ if ( gUseNet )
{
- exit( 1 );
+ if ( !gNetBus.Open( hostStr ))
+ {
+ exit( 1 );
+ }
+ gNetBus.SetDebug( gDebug != 0 );
+ cmdLine.SetBus( &gNetBus );
}
- gSerialBus.SetSerialPort( &gSerialPort );
- gSerialBus.SetDebug( gDebug != 0 );
+ else
+#endif
+ {
+ // Default to serial if no network specified
+ if ( !gSerialPort.Open( portStr, baudStr ))
+ {
+ exit( 1 );
+ }
+ gSerialBus.SetSerialPort( &gSerialPort );
+ gSerialBus.SetDebug( gDebug != 0 );
+ cmdLine.SetBus( &gSerialBus );
+ }
+
cmdLine.RegisterDeviceTypes( gNumDevTypes, gDevType );
- cmdLine.SetBus( &gSerialBus );
printf( "> " );
while ( fgets( line, sizeof( line ), stdin ) != NULL )
@@ -343,4 +393,3 @@
return 0;
}
-
/bioloid/cli/SerialBus.cpp
27,6 → 27,7
#include "Log.h"
#include "DumpMem.h"
#include "SerialBus.h"
#include "Error.h"
 
// ---- Public Variables ----------------------------------------------------
// ---- Private Constants and Types -----------------------------------------
/bioloid/cli/Makefile
26,6 → 26,8
BioloidPacket.cpp \
SerialPort.cpp \
SerialBus.cpp \
Error.cpp \
NetBus.cpp \
bioloid-reg.cpp \
StrPrintf.c \
BioloidCommandLine.cpp \
35,10 → 37,6
Str.c \
StrToken.cpp
 
ifeq ($(MK_HOST_OS),mingw)
MK_SRC_FILES += Error.cpp
endif
 
ifeq ($(MK_OS),avr)
MK_SRC_FILES += c++-support.cpp
endif
48,7 → 46,9
#CFLAGS += $(OPTS)
#CXXFLAGS += $(OPTS)
 
#LDLIBS += -lpthread
ifeq ($(MK_HOST_OS),mingw)
LDLIBS += -lwsock32
endif
 
include ../../rules/mkRules.mk
 
69,6 → 69,8
$(MK_COPY_FILES) : $(MK_BIN_DIR)/% : %
@echo "Copying $< to $@ ..."
cp $< $@
 
copy-files: $(MK_COPY_FILES)
#
# Now go and build an installer.
81,7 → 83,7
MK_INSTALL_FILES += $(MK_HTM_FILES)
MK_INSTALL_FILES += $(MK_DEVICE_TYPE_FILES)
 
installer : $(MK_COPY_FILES)
installer : copy-files
@$(ECHO) -e "file $(subst $(space),\nfile ,$(MK_INSTALL_FILES))" > $(MK_BIN_DIR)/file-list.nsh
@$(ECHO) -e "delete \$$INSTDIR\\\\$(subst $(space),\ndelete \$$INSTDIR\\\\,$(MK_INSTALL_FILES))" > $(MK_BIN_DIR)/file-delete.nsh
(cd $(MK_BIN_DIR); makensis installer.nsi)