aboutsummaryrefslogtreecommitdiffstats
path: root/packages/i2c/files/i2c.c
diff options
context:
space:
mode:
Diffstat (limited to 'packages/i2c/files/i2c.c')
-rw-r--r--packages/i2c/files/i2c.c710
1 files changed, 710 insertions, 0 deletions
diff --git a/packages/i2c/files/i2c.c b/packages/i2c/files/i2c.c
new file mode 100644
index 0000000000..9f0bafdba1
--- /dev/null
+++ b/packages/i2c/files/i2c.c
@@ -0,0 +1,710 @@
+/****************************************************************************
+*
+* 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.
+*
+****************************************************************************/
+/**
+*
+* @file i2c.c
+*
+* @brief This program allows basic i2c commands to be sent out the i2c
+* bus,
+*
+****************************************************************************/
+
+// ---- Include Files -------------------------------------------------------
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/timeb.h>
+
+#include "i2c-dev.h"
+#include "i2c-api.h"
+#include "i2c-io-api.h"
+#include "Log.h"
+
+// #include "svn-version.h"
+
+// ---- Public Variables ----------------------------------------------------
+// ---- Private Constants and Types -----------------------------------------
+
+// ---- Private Variables ---------------------------------------------------
+
+enum
+{
+ OPT_MEM_DEFAULT = 0,
+
+ // Options assigned a single character code can use that charater code
+ // as a short option.
+
+ OPT_COUNT = 'c',
+
+ // Options from this point onwards don't have any short option equivalents
+
+ OPT_FIRST_LONG_OPT = 0x80,
+
+ OPT_HELP,
+ OPT_VERSION,
+};
+
+enum
+{
+ CMD_DEFAULT,
+
+ CMD_READ_BYTE,
+ CMD_READ_BYTE_2,
+ CMD_READ_BYTE_4,
+
+ CMD_WRITE_BYTE,
+ CMD_WRITE_BYTE_2,
+ CMD_WRITE_BYTE_4,
+
+ CMD_RECV_BYTE,
+ CMD_RECV_BYTE_2,
+ CMD_RECV_BYTE_4,
+
+ CMD_SEND_BYTE,
+ CMD_SEND_BYTE_2,
+ CMD_SEND_BYTE_4,
+};
+
+struct
+{
+ int cmd;
+ const char *cmdStr;
+
+} gCmdMap[] =
+{
+ { CMD_READ_BYTE, "ReadByte" },
+ { CMD_READ_BYTE, "rb" },
+ { CMD_READ_BYTE_2, "ReadByte2" },
+ { CMD_READ_BYTE_2, "rb2" },
+ { CMD_READ_BYTE_4, "ReadByte4" },
+ { CMD_READ_BYTE_4, "rb4" },
+
+ { CMD_WRITE_BYTE, "WriteByte" },
+ { CMD_WRITE_BYTE, "wb" },
+ { CMD_WRITE_BYTE_2, "WriteByte2" },
+ { CMD_WRITE_BYTE_2, "wb2" },
+ { CMD_WRITE_BYTE_4, "WriteByte4" },
+ { CMD_WRITE_BYTE_4, "wb4" },
+
+ { CMD_RECV_BYTE, "RecvByte" },
+ { CMD_RECV_BYTE, "vb" },
+ { CMD_RECV_BYTE_2, "RecvByte2" },
+ { CMD_RECV_BYTE_2, "vb2" },
+ { CMD_RECV_BYTE_4, "RecvByte4" },
+ { CMD_RECV_BYTE_4, "vb4" },
+
+ { CMD_SEND_BYTE, "SendByte" },
+ { CMD_SEND_BYTE, "sb" },
+ { CMD_SEND_BYTE_2, "SendByte2" },
+ { CMD_SEND_BYTE_2, "sb2" },
+ { CMD_SEND_BYTE_4, "SendByte4" },
+ { CMD_SEND_BYTE_4, "sb4" },
+};
+
+int gNumCmds = sizeof( gCmdMap ) / sizeof( gCmdMap[ 0 ]);
+
+int gI2cAddr = -1;
+int gByteCount = 1;
+
+const char *gCmdStr;
+int gCmd = CMD_DEFAULT;
+const char *gAddrStr = NULL;
+const char *gDataStr = NULL;
+
+struct option gOption[] =
+{
+ { "count", required_argument, NULL, OPT_COUNT },
+ { "version", no_argument, NULL, OPT_VERSION },
+ { "verbose", no_argument, &gVerbose, 1 },
+ { "debug", no_argument, &gDebug, 1 },
+ { "help", no_argument, NULL, OPT_HELP },
+ { NULL }
+};
+
+#define TRUE 1
+#define FALSE 0
+
+typedef enum
+{
+ NoADC,
+ AllowADC,
+
+} AllowADC_t;
+
+#define ADC_PORT 8
+
+// ---- Private Function Prototypes -----------------------------------------
+
+static int ParseByte( const char *byteStr, uint8_t *byte );
+static int ParseBytes( const char *byteStr, uint8_t *byte, uint8_t maxBytes, uint8_t *bytesParsed );
+
+static void ProcessReadByteCommand( int i2cDev, const char *addrStr );
+static void ProcessWriteByteCommand( int i2cDev, const char *addrStr, const char *dataStr );
+static void ProcessRecvByteCommand( int i2cDev );
+static void ProcessSendByteCommand( int i2cDev, const char *dataStr );
+static void Usage( void );
+
+// ---- Functions -----------------------------------------------------------
+
+//***************************************************************************
+/**
+* Main entry point
+*/
+
+int main( int argc, char **argv )
+{
+ char shortOptsStr[ sizeof( gOption ) / sizeof( gOption[ 0 ] ) + 1 ];
+ char *shortOpts = shortOptsStr;
+ struct option *scanOpt;
+ int opt;
+ const char *i2cDevName = "/dev/i2c-0";
+ int i2cDev;
+ int cmdIdx;
+
+ LogInit( stdout );
+
+ // Figure out the short options from our options structure
+
+ for ( scanOpt = gOption; scanOpt->name != NULL; scanOpt++ )
+ {
+ if (( scanOpt->flag == NULL ) && ( scanOpt->val < OPT_FIRST_LONG_OPT ))
+ {
+ *shortOpts++ = (char)scanOpt->val;
+
+ if ( scanOpt->has_arg != no_argument )
+ {
+ *shortOpts++ = ':';
+ }
+ }
+ }
+ *shortOpts++ = '\0';
+
+ // Parse the command line options
+
+ while (( opt = getopt_long( argc, argv, shortOptsStr, gOption, NULL )) != -1 )
+ {
+ switch ( opt )
+ {
+ case 0:
+ {
+ // getopt_long returns 0 for entries where flag is non-NULL
+
+ break;
+ }
+
+ case OPT_COUNT:
+ {
+ gByteCount = (int)strtol( optarg, NULL, 0 );
+ if ( gByteCount <= 0 )
+ {
+ LogError( "Expecting byte count >= 0, found: '%s'\n", optarg );
+ Usage();
+ exit( 1 );
+ }
+ if ( gByteCount > I2C_MAX_DATA_LEN )
+ {
+ LogError( "Max byte count supported: %d, found %d\n", I2C_MAX_DATA_LEN, gByteCount );
+ Usage();
+ exit( 1 );
+ }
+ break;
+ }
+
+// case OPT_VERSION:
+// {
+// Log( "i2c SVN Revision: %d\n", SVN_REVISION );
+// exit( 0 );
+// break;
+// }
+
+ case '?':
+ case OPT_HELP:
+ default:
+ {
+ LogError( "opt:%d\n", opt );
+ Usage();
+ exit( 1 );
+ }
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ // Verify that an i2c-address was specified
+
+ if ( argc < 1 )
+ {
+ LogError( "Must specify an i2c address\n\n" );
+ Usage();
+ exit( 1 );
+ }
+ gI2cAddr = strtol( argv[ 0 ], NULL, 0 );
+ if (( gI2cAddr <= 0 ) || ( gI2cAddr > 127 ))
+ {
+ LogError( "Expecting i2c address in the range of 1-127, Found: %d\n", gI2cAddr );
+ Usage();
+ exit( 1 );
+ }
+
+ // Verify that a command has been specified
+
+ if ( argc < 2 )
+ {
+ LogError( "Must specify a command\n" );
+ Usage();
+ exit( 1 );
+ }
+ gCmdStr = argv[ 1 ];
+ for ( cmdIdx = 0; cmdIdx < gNumCmds; cmdIdx++ )
+ {
+ if ( strcasecmp( gCmdStr, gCmdMap[ cmdIdx ].cmdStr ) == 0 )
+ {
+ gCmd = gCmdMap[ cmdIdx ].cmd;
+ break;
+ }
+ }
+ if ( gCmd == CMD_DEFAULT )
+ {
+ LogError( "Unrecognized command '%s'\n", gCmdStr );
+ exit( 1 );
+ }
+
+ // Process command specific arguments
+
+ if (( gCmd == CMD_READ_BYTE_2 )
+ || ( gCmd == CMD_WRITE_BYTE_2 )
+ || ( gCmd == CMD_RECV_BYTE_2 )
+ || ( gCmd == CMD_SEND_BYTE_2 ))
+ {
+ gByteCount = 2;
+ }
+ else
+ if (( gCmd == CMD_READ_BYTE_4 )
+ || ( gCmd == CMD_WRITE_BYTE_4 )
+ || ( gCmd == CMD_RECV_BYTE_4 )
+ || ( gCmd == CMD_SEND_BYTE_4 ))
+ {
+ gByteCount = 4;
+ }
+
+ if (( gCmd == CMD_READ_BYTE )
+ || ( gCmd == CMD_READ_BYTE_2 )
+ || ( gCmd == CMD_READ_BYTE_4 ))
+ {
+ if ( argc < 3 )
+ {
+ LogError( "Expecting address\n" );
+ Usage();
+ exit( 1 );
+ }
+ if ( argc > 3 )
+ {
+ LogError( "Unexpected extra parameters\n" );
+ Usage();
+ exit( 1 );
+ }
+
+ gAddrStr = argv[ 2 ];
+ }
+ else
+ if (( gCmd == CMD_WRITE_BYTE )
+ || ( gCmd == CMD_WRITE_BYTE_2 )
+ || ( gCmd == CMD_WRITE_BYTE_4 ))
+ {
+ if ( argc < 4 )
+ {
+ LogError( "Expecting address and data\n" );
+ Usage();
+ exit( 1 );
+ }
+ if ( argc > 4 )
+ {
+ LogError( "Unexpected extra parameters\n" );
+ Usage();
+ exit( 1 );
+ }
+
+ gAddrStr = argv[ 2 ];
+ gDataStr = argv[ 3 ];
+ }
+ else
+ if (( gCmd == CMD_RECV_BYTE )
+ || ( gCmd == CMD_RECV_BYTE_2 )
+ || ( gCmd == CMD_RECV_BYTE_4 ))
+ {
+ if ( argc > 2 )
+ {
+ LogError( "Unexpected extra parameters\n" );
+ Usage();
+ exit( 1 );
+ }
+ }
+ else
+ if (( gCmd == CMD_SEND_BYTE )
+ || ( gCmd == CMD_SEND_BYTE_2 )
+ || ( gCmd == CMD_SEND_BYTE_4 ))
+ {
+ if ( argc < 3 )
+ {
+ LogError( "Expecting data\n" );
+ Usage();
+ exit( 1 );
+ }
+ if ( argc > 3 )
+ {
+ LogError( "Unexpected extra parameters\n" );
+ Usage();
+ exit( 1 );
+ }
+ gDataStr = argv[ 2 ];
+ }
+
+ if ( gDebug )
+ {
+ Log( "i2cAddr:0x%02x Cmd: %s (%d)", gI2cAddr, gCmdStr, gCmd );
+ if ( gAddrStr != NULL )
+ {
+ Log( " Addr: %s", gAddrStr );
+ }
+ if ( gDataStr != NULL )
+ {
+ Log( " Data: %s", gDataStr );
+ }
+ Log( "\n" );
+ }
+
+ // Try to open the i2c device
+
+ if (( i2cDev = open( i2cDevName, O_RDWR )) < 0 )
+ {
+ LogError( "Error opening '%s': %s\n", i2cDevName, strerror( errno ));
+ exit( 1 );
+ }
+
+ // Indicate which slave we wish to speak to
+
+ I2cSetSlaveAddress( i2cDev, gI2cAddr, I2C_NO_CRC );
+
+ switch ( gCmd )
+ {
+ case CMD_READ_BYTE:
+ case CMD_READ_BYTE_2:
+ case CMD_READ_BYTE_4:
+ {
+ ProcessReadByteCommand( i2cDev, gAddrStr );
+ break;
+ }
+
+ case CMD_WRITE_BYTE:
+ case CMD_WRITE_BYTE_2:
+ case CMD_WRITE_BYTE_4:
+ {
+ ProcessWriteByteCommand( i2cDev, gAddrStr, gDataStr );
+ break;
+ }
+
+ case CMD_RECV_BYTE:
+ case CMD_RECV_BYTE_2:
+ case CMD_RECV_BYTE_4:
+ {
+ ProcessRecvByteCommand( i2cDev );
+ break;
+ }
+
+ case CMD_SEND_BYTE:
+ case CMD_SEND_BYTE_2:
+ case CMD_SEND_BYTE_4:
+ {
+ ProcessSendByteCommand( i2cDev, gDataStr );
+ break;
+ }
+ }
+
+ close( i2cDev );
+
+ return 0;
+
+} // main
+
+//***************************************************************************
+/**
+* Parse a string looking for a single byte.
+*/
+
+int ParseByte( const char *byteStr, uint8_t *byte )
+{
+ char *endPtr;
+
+ *byte = (uint8_t)strtol( byteStr, &endPtr, 0 );
+
+ if ( *endPtr != '\0' )
+ {
+ LogError( "Expecting numeric value, found '%s'\n", byteStr );
+ return FALSE;
+ }
+
+ return TRUE;
+
+} // ParseByte
+
+//***************************************************************************
+/**
+* Parse a string looking for an array of bytes.
+*/
+
+int ParseBytes( const char *byteStr, uint8_t *byte, uint8_t maxBytes, uint8_t *bytesParsed )
+{
+ char *endPtr;
+
+ if (( byteStr[ 0 ] == '0' ) && ( byteStr[ 1 ] == 'x' ))
+ {
+ const char *s = &byteStr[ 2 ];
+ *bytesParsed = 0;
+
+ // Could be a multi-byte hex string
+
+ while ( *s != '\0' )
+ {
+ if ( *bytesParsed >= maxBytes )
+ {
+ LogError( "Too many bytes, max: %d\n", maxBytes );
+ return FALSE;
+ }
+
+ (*bytesParsed)++;
+ *byte = 0;
+
+ if (( *s >= 'A' ) && ( *s <= 'F' ))
+ {
+ *byte = *s - 'A' + 10;
+ }
+ else
+ if (( *s >= 'a' ) && ( *s <= 'f' ))
+ {
+ *byte = *s - 'a' + 10;
+ }
+ else
+ if (( *s >= '0' ) && ( *s <= '9' ))
+ {
+ *byte = *s - '0';
+ }
+ else
+ {
+ LogError( "Expecting hex digit, found '%c'\n", *s );
+ return FALSE;
+ }
+ s++;
+
+ if ( *s == '\0' )
+ {
+ break;
+ }
+
+ *byte <<= 4;
+ if (( *s >= 'A' ) && ( *s <= 'F' ))
+ {
+ *byte |= *s - 'A' + 10;
+ }
+ else
+ if (( *s >= 'a' ) && ( *s <= 'f' ))
+ {
+ *byte |= *s - 'a' + 10;
+ }
+ else
+ if (( *s >= '0' ) && ( *s <= '9' ))
+ {
+ *byte |= *s - '0';
+ }
+ else
+ {
+ LogError( "Expecting hex digit, found '%c'\n", *s );
+ return FALSE;
+ }
+ s++;
+ byte++;
+ }
+ }
+ else
+ {
+ // It's decimal or octal - only a single byte
+
+ *byte = (uint8_t)strtol( byteStr, &endPtr, 0 );
+
+ if ( *endPtr != '\0' )
+ {
+ LogError( "Expecting numeric value, found '%s'\n", byteStr );
+ return FALSE;
+ }
+ *bytesParsed = 1;
+ }
+
+ return TRUE;
+
+} // ParseBytes
+
+//***************************************************************************
+/**
+* Issues a read byte command to read a byte from a particular address.
+*/
+
+void ProcessReadByteCommand( int i2cDev, const char *addrStr )
+{
+ uint8_t addr;
+ uint8_t dataByte[ I2C_MAX_DATA_LEN ];
+ int rc;
+ int i;
+
+ if ( !ParseByte( addrStr, &addr ))
+ {
+ return;
+ }
+
+ if (( rc = I2cReadBytes( i2cDev, addr, dataByte, gByteCount )) != 0 )
+ {
+ LogError( "I2cReadByte failed: %d\n", rc );
+ return;
+ }
+
+ Log( "0x", dataByte[0] );
+
+ for ( i = 0; i < gByteCount; i++ )
+ {
+ Log( "%02x", dataByte[i] );
+ }
+ Log( "\n" );
+
+} // ProcessReadByteCommand
+
+//***************************************************************************
+/**
+* Issues a recv byte command to read bytes with no address.
+*/
+
+void ProcessRecvByteCommand( int i2cDev )
+{
+ uint8_t dataByte[ I2C_MAX_DATA_LEN ];
+ int rc;
+ int i;
+
+ if (( rc = I2cReceiveBytes( i2cDev, dataByte, gByteCount )) != 0 )
+ {
+ LogError( "I2cRecvBytes failed: %d\n", rc );
+ return;
+ }
+
+ Log( "0x", dataByte[0] );
+
+ for ( i = 0; i < gByteCount; i++ )
+ {
+ Log( "%02x", dataByte[i] );
+ }
+ Log( "\n" );
+
+} // ProcessRecvByteCommand
+
+//***************************************************************************
+/**
+* Issues a write byte command to write a byte to a particular address.
+*/
+
+void ProcessWriteByteCommand( int i2cDev, const char *addrStr, const char *dataStr )
+{
+ uint8_t addr;
+ uint8_t dataByte[ I2C_MAX_DATA_LEN ];
+ uint8_t bytesParsed;
+ int rc;
+
+ if ( !ParseByte( addrStr, &addr ))
+ {
+ return;
+ }
+
+ if ( !ParseBytes( dataStr, dataByte, sizeof( dataByte ), &bytesParsed ))
+ {
+ return;
+ }
+
+ if (( rc = I2cWriteBytes( i2cDev, addr, dataByte, bytesParsed )) != 0 )
+ {
+ LogError( "I2cWriteBytes failed: %d\n", rc );
+ return;
+ }
+
+} // ProcessWriteByteCommand
+
+//***************************************************************************
+/**
+* Issues a send byte command to write bytes with no address specified.
+*/
+
+void ProcessSendByteCommand( int i2cDev, const char *dataStr )
+{
+ uint8_t dataByte[ I2C_MAX_DATA_LEN ];
+ uint8_t bytesParsed;
+ int rc;
+
+ if ( !ParseBytes( dataStr, dataByte, sizeof( dataByte ), &bytesParsed ))
+ {
+ return;
+ }
+
+ if (( rc = I2cSendBytes( i2cDev, dataByte, bytesParsed )) != 0 )
+ {
+ LogError( "I2cSendBytes failed: %d\n", rc );
+ return;
+ }
+
+} // ProcessSendByteCommand
+
+//***************************************************************************
+/**
+* Usage
+*/
+
+void Usage( void )
+{
+ fprintf( stderr, "Usage: i2c [options] i2c-addr cmd [cmd-arguments]\n" );
+ fprintf( stderr, "Send I2C commands\n" );
+ fprintf( stderr, "\n" );
+ fprintf( stderr, "The following commands are supported:\n" );
+ fprintf( stderr, "ReadByte addr Retrieves byte(s) starting at the indicated address\n" );
+ fprintf( stderr, "WriteByte addr data Write byte(s) starting at the indicated address\n" );
+ fprintf( stderr, "ReadByte2 addr Retrieves two bytes from the indicated address\n" );
+ fprintf( stderr, "WriteByte2 addr data Writes two bytes into the indicated address\n" );
+ fprintf( stderr, "ReadByte4 addr Retrieves four bytes from the indicated address\n" );
+ fprintf( stderr, "WriteByte4 addr data Writes four bytes into the indicated address\n" );
+ fprintf( stderr, "RecvByte Retrieves byte(s)(no address specified)\n" );
+ fprintf( stderr, "SendByte data Writes byte(s)(no address specified)\n" );
+ fprintf( stderr, "RecvByte2 Retrieves 2 bytes (no address specified)\n" );
+ fprintf( stderr, "SendByte2 data Writes 2 bytes(no address specified)\n" );
+ fprintf( stderr, "RecvByte4 Retrieves 4 bytes (no address specified)\n" );
+ fprintf( stderr, "SendByte4 data Writes 4 bytes(no address specified)\n" );
+ fprintf( stderr, "\n" );
+ fprintf( stderr, "The above commands can be shortened to rb, wb, rb2, wb2, rb4, wb4, vb, sd, vb2 sb2 vb4, and sb4 \n" );
+ fprintf( stderr, "respectively.\n" );
+ fprintf( stderr, "\n" );
+ fprintf( stderr, "The following options may be used:\n" );
+ fprintf( stderr, "--count=n Specifies how many bytes to read for ReadByte or RecvByte\n" );
+ fprintf( stderr, "--version Prints the SVN version of this program\n" );
+ fprintf( stderr, "--verbose Print additional information\n" );
+ fprintf( stderr, "--help Prints this information\n" );
+}
+