diff options
author | Koen Kooi <koen@openembedded.org> | 2009-01-10 10:44:13 +0100 |
---|---|---|
committer | Koen Kooi <koen@openembedded.org> | 2009-01-10 10:44:13 +0100 |
commit | d076ad3dbeac4bf7a58a335348c1560dd23799a7 (patch) | |
tree | f402fe30741bb8ea76d0f411a1179c6ac937be76 /packages/robostix-utils | |
parent | 06af67f2e653d6b0d45117f9aaad0b25db1eaa67 (diff) |
gumstix utils: add char-driver, gpio-event, i2c and microwindows
Diffstat (limited to 'packages/robostix-utils')
-rw-r--r-- | packages/robostix-utils/robostix-cmdline.bb | 28 | ||||
-rw-r--r-- | packages/robostix-utils/robostix-cmdline/robostix.c | 278 | ||||
-rw-r--r-- | packages/robostix-utils/robostix-cmdline/robostix.h | 114 | ||||
-rw-r--r-- | packages/robostix-utils/robostix-sertest.bb | 28 | ||||
-rw-r--r-- | packages/robostix-utils/robostix-sertest/sertest.c | 443 |
5 files changed, 891 insertions, 0 deletions
diff --git a/packages/robostix-utils/robostix-cmdline.bb b/packages/robostix-utils/robostix-cmdline.bb new file mode 100644 index 0000000000..0eecfc2e14 --- /dev/null +++ b/packages/robostix-utils/robostix-cmdline.bb @@ -0,0 +1,28 @@ +DESCRIPTION = "robostix programs" +SECTION = "base" +PRIORITY = "required" +PR = "r1" + +DEPENDS = robostix-module + +SRC_URI = " \ + file://robostix.h \ + file://robostix.c \ + " + +CMD_NAME=robostix + +S = "${WORKDIR}" + +do_compile () { + ${CC} -o ${CMD_NAME} *.c +} + +do_install () { + install -d ${D}${bindir}/ + install -m 0755 ${WORKDIR}/${CMD_NAME} ${D}${bindir}/ +} + +PACKAGES = "${PN}" +FILES_${PN} = "${bindir}/*" + diff --git a/packages/robostix-utils/robostix-cmdline/robostix.c b/packages/robostix-utils/robostix-cmdline/robostix.c new file mode 100644 index 0000000000..be47b5c5a9 --- /dev/null +++ b/packages/robostix-utils/robostix-cmdline/robostix.c @@ -0,0 +1,278 @@ +/**************************************************************************** +* +* Copyright (c) 2006 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. +* +****************************************************************************/ +/** +* +* robostix.c +* +* PURPOSE: +* +* This implements the usermode program for talking to the robostix. +* +*****************************************************************************/ + +/* ---- Include Files ---------------------------------------------------- */ + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <errno.h> + +#include "robostix.h" + +/* ---- Public Variables ------------------------------------------------- */ + +int gFd = -1; + +int gVal; + +/* ---- Private Constants and Types -------------------------------------- */ +/* ---- Private Variables ------------------------------------------------ */ + +typedef struct +{ + const char *cmdStr; + const char *argStr; + const char *helpStr; + int (*parseArgs)( int argc, char **argv ); + void (*execFunc)( int cmd ); + int cmd; + +} Cmd; + +int ParseNone( int argc, char **argv ); +int ParseOnOffArg( int argc, char **argv ); +int ParseOnOffPulseArg( int argc, char **argv ); +void Usage( void ); + +void Power( int cmd ); +void ReadIOctl( int cmd ); +void SimpleIOctl( int cmd ); + +Cmd gCmd[] = +{ + { "power", "on|off", "Controls the robostix voltage regulators", ParseOnOffArg, Power, -1 }, + { "reset", "on|off|pulse", "Resets the robostix", ParseOnOffPulseArg, SimpleIOctl, ROBOSTIX_IOCTL_RESET }, + { "245", "on|off", "Controls the 245 buffer chip", ParseOnOffArg, SimpleIOctl, ROBOSTIX_IOCTL_245_ENABLE }, + + { "sck", "on|off", "Sets/clears the SCK line", ParseOnOffArg, SimpleIOctl, ROBOSTIX_IOCTL_SET_SCK }, + { "ss", "on|off", "Sets/clears the SS line", ParseOnOffArg, SimpleIOctl, ROBOSTIX_IOCTL_SET_SS }, + { "txd", "on|off", "Sets/clears the IR-TXD line", ParseOnOffArg, SimpleIOctl, ROBOSTIX_IOCTL_SET_IR_TXD }, + { "mosi", "on|off", "Sets/clears the MOSI line", ParseOnOffArg, SimpleIOctl, ROBOSTIX_IOCTL_SET_MOSI }, + + { "rxd", "", "Reads the IR-RXD line", ParseNone, ReadIOctl, ROBOSTIX_IOCTL_GET_IR_RXD }, + { "irq", "", "Reads the TM-IRQ line", ParseNone, ReadIOctl, ROBOSTIX_IOCTL_GET_IRQ }, + { "miso", "", "Reads the MISO line", ParseNone, ReadIOctl, ROBOSTIX_IOCTL_GET_MISO }, + + { NULL } +}; + +/* ---- Private Function Prototypes -------------------------------------- */ +/* ---- Functions -------------------------------------------------------- */ + + +/**************************************************************************** +* +* main +* +***************************************************************************/ + +int main( int argc, char **argv ) +{ + char *cmdStr; + int argIdx; + Cmd *cmd; + + if ( argc == 1 ) + { + Usage( ); + exit( 0 ); + } + + if (( gFd = open( "/dev/robostix", O_RDWR )) < 0 ) + { + perror( "Unable to open /dev/robostix" ); + exit( 1 ); + } + + argIdx = 1; + cmdStr = argv[ argIdx++ ]; + + for ( cmd = gCmd; cmd->cmdStr != NULL; cmd++ ) + { + if ( strcasecmp( cmdStr, cmd->cmdStr ) == 0 ) + { + break; + } + } + if ( cmd->cmdStr == NULL ) + { + fprintf( stderr, "Unrecognized command: '%s'\n", cmdStr ); + exit( 1 ); + } + + if ( cmd->parseArgs( argc - argIdx, &argv[ argIdx ] )) + { + cmd->execFunc( cmd->cmd ); + } + + close( gFd ); + + exit( 0 ); + return 0; + +} // main + +/**************************************************************************** +* +* Checks to see if the argument is on/off (or equivalent) +* +***************************************************************************/ + +int IsOnOffArg( int argc, char **argv ) +{ + if (( strcasecmp( *argv, "on" ) == 0 ) + || ( strcasecmp( *argv, "t" ) == 0 ) + || ( strcasecmp( *argv, "1" ) == 0 )) + { + gVal = 1; + return 1; + } + + if (( strcasecmp( *argv, "off" ) == 0 ) + || ( strcasecmp( *argv, "f" ) == 0 ) + || ( strcasecmp( *argv, "0" ) == 0 )) + { + gVal = 0; + return 1; + } + + return 0; + +} // IsOnOffArg + +/**************************************************************************** +* +* Parses no arguments +* +***************************************************************************/ + +int ParseNone( int argc, char **argv ) +{ + return 1; + +} // ParseNone + +/**************************************************************************** +* +* Parses a command line argument for legel on/off values +* +***************************************************************************/ + +int ParseOnOffArg( int argc, char **argv ) +{ + if ( IsOnOffArg( argc, argv )) + { + return 1; + } + + fprintf( stderr, "Expecting on/off, found: '%s'\n", *argv ); + return 0; + +} // ParseOnOffArg + +/**************************************************************************** +* +* Parses a command line argument for legel on/off values +* +***************************************************************************/ + +int ParseOnOffPulseArg( int argc, char **argv ) +{ + if (( strcasecmp( *argv, "pulse" ) == 0 ) + || ( strcasecmp( *argv, "2" ) == 0 )) + { + gVal = 2; + return 1; + } + + if ( IsOnOffArg( argc, argv )) + { + return 1; + } + + fprintf( stderr, "Expecting on/off/pulse, found: '%s'\n", *argv ); + return 0; + +} // ParseOnoffPulseArg + +/**************************************************************************** +* +* Power +* +***************************************************************************/ + +void Power( int cmd ) +{ + SimpleIOctl( ROBOSTIX_IOCTL_POWER_VCC5 ); + +} // Power + +/**************************************************************************** +* +* SimpleIOctl +* +***************************************************************************/ + +void SimpleIOctl( int cmd ) +{ + if ( ioctl( gFd, cmd, gVal ) != 0 ) + { + fprintf( stderr, "ioctl call failed: %d\n", errno ); + } + +} // SimpleIOctl + +/**************************************************************************** +* +* SimpleIOctl +* +***************************************************************************/ + +void ReadIOctl( int cmd ) +{ + if ( ioctl( gFd, cmd, &gVal ) != 0 ) + { + fprintf( stderr, "ioctl call failed: %d\n", errno ); + } + +} // ReadIOctl + +/**************************************************************************** +* +* Usage +* +***************************************************************************/ + +void Usage( void ) +{ + Cmd *cmd; + + for ( cmd = gCmd; cmd->cmdStr != NULL; cmd++ ) + { + printf( "%-12s %-12s %s\n", cmd->cmdStr, cmd->argStr, cmd->helpStr ); + } + +} // Usage + diff --git a/packages/robostix-utils/robostix-cmdline/robostix.h b/packages/robostix-utils/robostix-cmdline/robostix.h new file mode 100644 index 0000000000..0d860bc7a4 --- /dev/null +++ b/packages/robostix-utils/robostix-cmdline/robostix.h @@ -0,0 +1,114 @@ +/**************************************************************************** +* +* Copyright (c) 2006 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. +* +****************************************************************************/ +/** +* +* robostix_drv.h +* +* PURPOSE: +* +* This implements a driver for using the robostix from the gumstix +* +* Initially, this contains the required support to emulate enough of the +* parallel port interface to allow avrdude to program the ATMega128. +* +*****************************************************************************/ + +#if !defined( LINUX_ROBOSTIX_H ) +#define LINUX_ROBOSTIX_H ) + +/* ---- Include Files ----------------------------------------------------- */ + +#include <linux/ioctl.h> + +/* ---- Constants and Types ----------------------------------------------- */ + +#define ROBOSTIX_MAJOR 240 + +#define ROBOSTIX_IOCTL_MAGIC 'R' + +/** + * Deefines for each of the commands. Note that since we want to reduce + * the possibility that a user mode program gets out of sync with a given + * driver, we explicitly assign a value to each enumeration. This makes + * it more difficult to stick new ioctl's in the middle of the list. + */ + +typedef enum +{ + ROBOSTIX_CMD_FIRST = 0x80, + + ROBOSTIX_CMD_POWER_VCC5 = 0x80, + ROBOSTIX_CMD_RESET = 0x81, + ROBOSTIX_CMD_245_ENABLE = 0x82, + ROBOSTIX_CMD_SET_SCK = 0x83, + ROBOSTIX_CMD_SET_SS = 0x84, + ROBOSTIX_CMD_SET_IR_TXD = 0x85, + ROBOSTIX_CMD_GET_IR_RXD = 0x86, + ROBOSTIX_CMD_SET_MOSI = 0x87, + ROBOSTIX_CMD_GET_MISO = 0x88, + ROBOSTIX_CMD_GET_IRQ = 0x89, + ROBOSTIX_CMD_DELAY_USEC = 0x8A, // value is hardocded in uisp DAPA.C + + /* Insert new ioctls here */ + + ROBOSTIX_CMD_LAST, + +} ROBOSTIX_CMD; + +/* + * The following are arguments to the various ioctl's + */ + +#define ROBOSTIX_PIN_OFF 0 +#define ROBOSTIX_PIN_ON 1 +#define ROBOSTIX_PIN_PULSE 2 // only used or Reset + +/* + * Definitions for the actual ioctl commands + */ + +#define ROBOSTIX_IOCTL_POWER_VCC5 _IO( ROBOSTIX_IOCTL_MAGIC, ROBOSTIX_CMD_POWER_VCC5 ) // arg is int +#define ROBOSTIX_IOCTL_RESET _IO( ROBOSTIX_IOCTL_MAGIC, ROBOSTIX_CMD_RESET ) // arg is int +#define ROBOSTIX_IOCTL_245_ENABLE _IO( ROBOSTIX_IOCTL_MAGIC, ROBOSTIX_CMD_245_ENABLE ) // arg is int +#define ROBOSTIX_IOCTL_SET_SCK _IO( ROBOSTIX_IOCTL_MAGIC, ROBOSTIX_CMD_SET_SCK ) // arg is int +#define ROBOSTIX_IOCTL_SET_SS _IO( ROBOSTIX_IOCTL_MAGIC, ROBOSTIX_CMD_SET_SS ) // arg is int +#define ROBOSTIX_IOCTL_SET_IR_TXD _IO( ROBOSTIX_IOCTL_MAGIC, ROBOSTIX_CMD_SET_IR_TXD ) // arg is int +#define ROBOSTIX_IOCTL_GET_IR_RXD _IOR( ROBOSTIX_IOCTL_MAGIC, ROBOSTIX_CMD_GET_IR_RXD, int ) // arg is int * +#define ROBOSTIX_IOCTL_SET_MOSI _IO( ROBOSTIX_IOCTL_MAGIC, ROBOSTIX_CMD_SET_MOSI ) // arg is int +#define ROBOSTIX_IOCTL_GET_MISO _IOR( ROBOSTIX_IOCTL_MAGIC, ROBOSTIX_CMD_GET_MISO, int ) // arg is int * +#define ROBOSTIX_IOCTL_GET_IRQ _IOR( ROBOSTIX_IOCTL_MAGIC, ROBOSTIX_CMD_GET_IRQ, int ) // arg is int * +#define ROBOSTIX_IOCTL_DELAY_USEC _IO( ROBOSTIX_IOCTL_MAGIC, ROBOSTIX_CMD_DELAY_USEC ) // arg is int + + +/* + * Definitions for sysctl. The top level define has to be unique system wide. + * The kernel defines values 1 thru about 10 (see include/linunx/sysctl.h) + */ + +#define CTL_ROBOSTIX 0x526F626F /* 'Robo' in hex form */ + +/* + * The following are for entries in /proc/sys/robostix + */ + +enum +{ + CTL_ROBOSTIX_DEBUG_TRACE = 101, + CTL_ROBOSTIX_DEBUG_IOCTL = 102, + CTL_ROBOSTIX_DEBUG_ERROR = 103 +}; + +#endif // LINUX_ROBOSTIX_H + diff --git a/packages/robostix-utils/robostix-sertest.bb b/packages/robostix-utils/robostix-sertest.bb new file mode 100644 index 0000000000..0196f6c8f3 --- /dev/null +++ b/packages/robostix-utils/robostix-sertest.bb @@ -0,0 +1,28 @@ +DESCRIPTION = "robostix programs" +SECTION = "base" +PRIORITY = "required" +PR = "r1" + +DEPENDS = robostix-module + +SRC_URI = " \ + file://sertest.c \ + " + +CMD_NAME=sertest +LDLIBS = -lpthread + +S = "${WORKDIR}" + +do_compile () { + ${CC} ${LDLIBS} -o ${CMD_NAME} *.c +} + +do_install () { + install -d ${D}${bindir}/ + install -m 0755 ${WORKDIR}/${CMD_NAME} ${D}${bindir}/ +} + +PACKAGES = "${PN}" +FILES_${PN} = "${bindir}/*" + diff --git a/packages/robostix-utils/robostix-sertest/sertest.c b/packages/robostix-utils/robostix-sertest/sertest.c new file mode 100644 index 0000000000..3f0cf7a6fc --- /dev/null +++ b/packages/robostix-utils/robostix-sertest/sertest.c @@ -0,0 +1,443 @@ +/**************************************************************************** +* +* Copyright (c) 2006 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. +* +****************************************************************************/ +/** +* +* sertest.c +* +* PURPOSE: +* +* This implements a sample program for accessing the serial port. +* +*****************************************************************************/ + +/* ---- Include Files ---------------------------------------------------- */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/unistd.h> +#include <pthread.h> +#include <getopt.h> +#include <termios.h> + +/* ---- Public Variables ------------------------------------------------- */ + +int gFd = -1; + +int gVal; + +/* ---- Private Constants and Types -------------------------------------- */ +/* ---- Private Variables ------------------------------------------------ */ + +struct option gLongOption[] = +{ + // option A Flag V (has_arg, flag, val) + // ----------- - ---- --- + { "baud", 1, NULL, 'b' }, + { "debug", 0, NULL, 'd' }, + { "help", 0, NULL, 'h' }, + { "port", 1, NULL, 'p' }, + { "verbose", 0, NULL, 'v' }, + { 0 }, + +}; + +struct +{ + speed_t speed; + unsigned baudRate; +} gBaudTable[] = +{ + { B50, 50 }, + { B75, 75 }, + { B110, 110 }, + { B134, 134 }, + { B150, 150 }, + { B200, 200 }, + { B300, 300 }, + { B600, 600 }, + { B1200, 1200 }, + { B1800, 1800 }, + { B2400, 2400 }, + { B4800, 4800 }, + { B9600, 9600 }, + { B19200, 19200 }, + { B38400, 38400 }, + { B57600, 57600 }, + { B115200, 115200 }, + { B230400, 230400 } +}; + +#define ARRAY_LEN(x) ( sizeof( x ) / sizeof( x[ 0 ])) + +int gVerbose = 0; +int gDebug = 0; + +int gPortFd = -1; + +/* ---- Private Function Prototypes -------------------------------------- */ + +void *ReaderThread( void *param ); +char *StrMaxCpy( char *dst, const char *src, size_t maxLen ); +char *StrMaxCat( char *dst, const char *src, size_t maxLen ); +void Usage( void ); + +/* ---- Functions -------------------------------------------------------- */ + + +/*************************************************************************** +* +* main +* +****************************************************************************/ + +int main( int argc, char **argv ) +{ + int rc; + int opt; + char devName[ 40 ]; + const char *baudStr = NULL; + const char *portStr = "ttyS2"; + speed_t baudRate; + pthread_t readerThreadId; + + struct termios attr; + + // Parse the command line options + + while (( opt = getopt_long( argc, argv, "b:dhp:v", gLongOption, NULL )) > 0 ) + { + switch ( opt ) + { + case 'b': + { + baudStr = optarg; + break; + } + + case 'd': + { + gDebug = 1; + break; + } + + case 'p': + { + portStr = optarg; + break; + } + + case 'v': + { + gVerbose = 1; + break; + } + case '?': + case 'h': + { + Usage(); + return 1; + } + } + } + + devName[ 0 ] = '\0'; + if ( portStr[ 0 ] != '/' ) + { + StrMaxCpy( devName, "/dev/", sizeof( devName )); + } + StrMaxCat( devName, portStr, sizeof( devName )); + + + baudRate = B0; + if ( baudStr == NULL ) + { + baudRate = B9600; + } + else + { + int baudIdx; + int testBaud = atoi( baudStr ); + + for ( baudIdx = 0; baudIdx < ARRAY_LEN( gBaudTable ); baudIdx++ ) + { + if ( gBaudTable[ baudIdx ].baudRate == testBaud ) + { + baudRate = gBaudTable[ baudIdx ].speed; + break; + } + } + + if ( baudRate == B0 ) + { + fprintf( stderr, "Unrecognized baud rate: '%s'\n", baudStr ); + exit( 1 ); + } + } + + if (( gPortFd = open( devName, O_RDWR | O_EXCL )) < 0 ) + { + fprintf( stderr, "Unable to open serial port '%s': %s\n", devName, strerror( errno )); + exit( 2 ); + } + + if ( tcgetattr( gPortFd, &attr ) < 0 ) + { + fprintf( stderr, "Call to tcgetattr failed: %s\n", strerror( errno )); + exit( 3 ); + } + + attr.c_iflag = 0; + attr.c_oflag = 0; + attr.c_cflag = CLOCAL | CREAD | CS8; + attr.c_lflag = 0; + attr.c_cc[ VTIME ] = 0; // timeout in tenths of a second + attr.c_cc[ VMIN ] = 1; // Only wait for a single char + + cfsetispeed( &attr, baudRate ); + cfsetospeed( &attr, baudRate ); + + if ( tcsetattr( gPortFd, TCSAFLUSH, &attr ) < 0 ) + { + fprintf( stderr, "Call to tcsetattr failed: %s\n", strerror( errno )); + exit( 4 ); + } + + // Put stdin & stdout in unbuffered mode. + + setbuf( stdin, NULL ); + setbuf( stdout, NULL ); + + // Put stdin in raw mode (i.e. turn off canonical mode). Canonical mode + // causes the driver to wait for the RETURN character so that line editing + // can take place. We also want to turn off ECHO. + + { + struct termios tio; + + if ( tcgetattr( fileno( stdin ), &tio ) < 0 ) + { + fprintf( stderr, "Unable to retrieve terminal settings: %s\n", strerror( errno )); + exit( 5 ); + } + + tio.c_lflag &= ~( ICANON | ECHO ); + tio.c_cc[VTIME] = 0; + tio.c_cc[VMIN] = 1; + + if ( tcsetattr( fileno( stdin ), TCSANOW, &tio ) < 0 ) + { + fprintf( stderr, "Unable to update terminal settings: %s\n", strerror( errno )); + exit( 6 ); + } + } + + // Kick off the serial port reader thread. + + rc = pthread_create( &readerThreadId, NULL, ReaderThread, NULL ); + if ( rc != 0 ) + { + fprintf( stderr, "Error creating ReaderThread: %s\n", strerror( rc )); + exit( 7 ); + } + + // Read stdin and send rcvd chars to the serial port + + while ( 1 ) + { + char ch; + int chInt = fgetc( stdin ); + if ( chInt < 0 ) + { + fprintf( stderr, "Exiting...\n" ); + break; + } + ch = (char)chInt; + + if ( gDebug ) + { + if (( ch < ' ' ) || ( ch > '~' )) + { + fprintf( stderr, "stdin Read: 0x%02x '.'\n", ch ); + } + else + { + fprintf( stderr, "stdin Read: 0x%02x '%c'\n", ch, ch ); + } + + } + + if ( write( gPortFd, &ch, 1 ) != 1 ) + { + fprintf( stderr, "write to serial port failed: %s\n", strerror( errno )); + break; + } + } + + + close( gPortFd ); + + exit( 0 ); + return 0; // Get rid of warning about not returning anything +} + +/***************************************************************************/ +/** +* Thread which processes the incoming serial data. +*/ + +void *ReaderThread( void *param ) +{ + while ( 1 ) + { + char ch; + int bytesRead; + + if (( bytesRead = read( gPortFd, &ch, 1 )) < 0 ) + { + fprintf( stderr, "Serial port read failed: %s\n", strerror( errno )); + exit( 1 ); + } + + if ( gDebug ) + { + if (( ch < ' ' ) || ( ch > '~' )) + { + fprintf( stderr, "Serial Read: 0x%02x '.'\n", ch ); + } + else + { + fprintf( stderr, "Serial Read: 0x%02x '%c'\n", ch, ch ); + } + + } + + putc( ch, stdout ); + } + + return 0; + +} // ReaderThread + +/***************************************************************************/ +/** +* Concatenates source to the destination, but makes sure that the +* destination string (including terminating null), doesn't exceed maxLen. +* +* @param dst (mod) String to concatnate onto. +* @param src (in) String to being added to the end of @a dst. +* @param maxLen (in) Maximum length that @a dst is allowed to be. +* +* @return A pointer to the destination string. +*/ + +char *StrMaxCat( char *dst, const char *src, size_t maxLen ) +{ + size_t dstLen = strlen( dst ); + + if ( dstLen < maxLen ) + { + StrMaxCpy( &dst[ dstLen ], src, maxLen - dstLen ); + } + + return dst; + +} /* StrMaxCat */ + +/***************************************************************************/ +/** +* Copies the source to the destination, but makes sure that the +* destination string (including terminating null), doesn't exceed +* maxLen. +* +* @param dst (out) Place to store the string copy. +* @param src (in) String to copy. +* @param maxLen (in) Maximum number of characters to copy into @a dst. +* +* @return A pointer to the destination string. +*/ + +char *StrMaxCpy( char *dst, const char *src, size_t maxLen ) +{ + if ( maxLen < 1 ) + { + /* + * There's no room in the buffer? + */ + + return ""; + } + + if ( maxLen == 1 ) + { + /* + * There's only room for the terminating null character + */ + + dst[ 0 ] = '\0'; + return dst; + } + + /* + * The Visual C++ version of strncpy writes to every single character + * of the destination buffer, so we use a length one character smaller + * and write in our own null (if required). + * + * This allows the caller to store a sentinel in the last byte of the + * buffer to detect overflows (if desired). + */ + + strncpy( dst, src, maxLen - 1 ); + if (( strlen( src ) + 1 ) >= maxLen ) + { + /* + * The string exactly fits, or probably overflows the buffer. + * Write in the terminating null character since strncpy doesn't in + * this particular case. + * + * We don't do this arbitrarily so that the caller can use a sentinel + * in the very end of the buffer to detect buffer overflows. + */ + + dst[ maxLen - 1 ] = '\0'; + } + + return dst; + +} /* StrMaxCpy */ + +/*************************************************************************** +* +* Usage +* +****************************************************************************/ + +void Usage() +{ + fprintf( stderr, "Usage: sertest [option(s)]\n" ); + fprintf( stderr, " Download a program via serial/i2c\n" ); + fprintf( stderr, "\n" ); + fprintf( stderr, " -b, --baud=baud Set the baudrate used\n" ); + fprintf( stderr, " -d, --debug Turn on debug output\n" ); + fprintf( stderr, " -h, --help Display this message\n" ); + fprintf( stderr, " -p, --port=port Set the I/O port\n" ); + fprintf( stderr, " -v, --verbose Turn on verbose messages\n" ); + +} // Usage + + |