From d076ad3dbeac4bf7a58a335348c1560dd23799a7 Mon Sep 17 00:00:00 2001 From: Koen Kooi Date: Sat, 10 Jan 2009 10:44:13 +0100 Subject: gumstix utils: add char-driver, gpio-event, i2c and microwindows --- packages/i2c/files/Config.h | 41 +++ packages/i2c/files/Crc8.c | 149 +++++++++ packages/i2c/files/Crc8.h | 54 +++ packages/i2c/files/DumpMem.c | 93 ++++++ packages/i2c/files/DumpMem.h | 49 +++ packages/i2c/files/Log.c | 335 +++++++++++++++++++ packages/i2c/files/Log.h | 232 +++++++++++++ packages/i2c/files/i2c-api.c | 522 +++++++++++++++++++++++++++++ packages/i2c/files/i2c-api.h | 143 ++++++++ packages/i2c/files/i2c-dev.h | 365 +++++++++++++++++++++ packages/i2c/files/i2c-io-api.h | 52 +++ packages/i2c/files/i2c-io.h | 220 +++++++++++++ packages/i2c/files/i2c.c | 710 ++++++++++++++++++++++++++++++++++++++++ packages/i2c/files/i2c.h | 135 ++++++++ packages/i2c/files/i2c.init | 37 +++ packages/i2c/i2c.bb | 45 +++ 16 files changed, 3182 insertions(+) create mode 100644 packages/i2c/files/Config.h create mode 100644 packages/i2c/files/Crc8.c create mode 100644 packages/i2c/files/Crc8.h create mode 100644 packages/i2c/files/DumpMem.c create mode 100644 packages/i2c/files/DumpMem.h create mode 100644 packages/i2c/files/Log.c create mode 100644 packages/i2c/files/Log.h create mode 100644 packages/i2c/files/i2c-api.c create mode 100644 packages/i2c/files/i2c-api.h create mode 100644 packages/i2c/files/i2c-dev.h create mode 100644 packages/i2c/files/i2c-io-api.h create mode 100644 packages/i2c/files/i2c-io.h create mode 100644 packages/i2c/files/i2c.c create mode 100644 packages/i2c/files/i2c.h create mode 100755 packages/i2c/files/i2c.init create mode 100644 packages/i2c/i2c.bb (limited to 'packages/i2c') diff --git a/packages/i2c/files/Config.h b/packages/i2c/files/Config.h new file mode 100644 index 0000000000..83bb46de84 --- /dev/null +++ b/packages/i2c/files/Config.h @@ -0,0 +1,41 @@ +/**************************************************************************** +* +* Copyright (c) 2006 Dave Hylands +* +* 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 Config.h +* +* @brief Global Configuration information. +* +****************************************************************************/ + +#if !defined( CONFIG_H ) +#define CONFIG_H /**< Include Guard */ + +/* ---- Include Files ---------------------------------------------------- */ + +/* ---- Constants and Types ---------------------------------------------- */ + +/** + * Sets Logging parameters + */ + +#define CFG_LOG_TO_BUFFER 0 + +#define CFG_CRC8BLOCK 1 + +/** @} */ + +#endif // CONFIG_H + diff --git a/packages/i2c/files/Crc8.c b/packages/i2c/files/Crc8.c new file mode 100644 index 0000000000..87dcf5c2f4 --- /dev/null +++ b/packages/i2c/files/Crc8.c @@ -0,0 +1,149 @@ +/**************************************************************************** +* +* Copyright (c) 2006 Dave Hylands +* +* 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 Crc8.c +* +* @brief This file contains the definition of the CRC-8 algorithim +* used by SMBus +* +* +*****************************************************************************/ + +/* ---- Include Files ----------------------------------------------------- */ + +#include "Config.h" + +#include "Crc8.h" + +#include "Log.h" + +/* ---- Public Variables -------------------------------------------------- */ +/* ---- Private Constants and Types --------------------------------------- */ +/* ---- Private Variables ------------------------------------------------- */ +/* ---- Private Function Prototypes --------------------------------------- */ +/* ---- Functions --------------------------------------------------------- */ + +/****************************************************************************/ +/** +* Calculates the CRC-8 used as part of SMBus. +* +* CRC-8 is defined to be x^8 + x^2 + x + 1 +* +* To use this function use the following template: +* +* crc = Crc8( crc, data ); +*/ + +#if 0 // Traditional implementation + +#define POLYNOMIAL (0x1070U << 3) + +unsigned char Crc8( unsigned char inCrc, unsigned char inData ) +{ + int i; + unsigned short data; + + data = inCrc ^ inData; + data <<= 8; + + for ( i = 0; i < 8; i++ ) + { + if (( data & 0x8000 ) != 0 ) + { + data = data ^ POLYNOMIAL; + } + data = data << 1; + } + +#if 0 +#if defined( LogBuf2 ) + LogBuf2( "Crc8: data:0x%02x crc:0x%02x\n", inData, (unsigned char)( data >> 8 )); +#else + + Log( "Crc8: data:0x%02x crc:0x%02x\n", inData, (unsigned char)( data >> 8 )); +#endif + +#endif + + + return (unsigned char)( data >> 8 ); + +} // Crc8 + +#else // Optimized for 8 bit CPUs (0x22 bytes on ATMega128 versus 0x30 for above version) + +unsigned char Crc8( unsigned char inCrc, unsigned char inData ) +{ + unsigned char i; + unsigned char data; + + data = inCrc ^ inData; + + for ( i = 0; i < 8; i++ ) + { + if (( data & 0x80 ) != 0 ) + { + data <<= 1; + data ^= 0x07; + } + else + { + data <<= 1; + } + } + +#if 0 +#if defined( LogBuf2 ) + LogBuf2( "Crc8: data:0x%02x crc:0x%02x\n", inData, data ); +#else + + Log( "Crc8: data:0x%02x crc:0x%02x\n", inData, data ); +#endif + +#endif + + + return data; + +} // Crc8 + +#endif + + +#if defined( CFG_CRC8BLOCK ) + +/****************************************************************************/ +/** +* Calculates the CRC-8 used as part of SMBus over a block of memory. +*/ + +uint8_t Crc8Block( uint8_t crc, uint8_t *data, uint8_t len ) +{ + while ( len > 0 ) + { + crc = Crc8( crc, *data++ ); + len--; + } + + return crc; + +} // Crc8Block + +#endif // CFG_CRC8BLOCK + +/** @} */ + + diff --git a/packages/i2c/files/Crc8.h b/packages/i2c/files/Crc8.h new file mode 100644 index 0000000000..2d1f74b82c --- /dev/null +++ b/packages/i2c/files/Crc8.h @@ -0,0 +1,54 @@ +/**************************************************************************** +* +* Copyright (c) 2006 Dave Hylands +* +* 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 Crc8.h +* +* @brief This file contains the definition of the CRC-8 algorithim +* used by SMBus +* +****************************************************************************/ + +#if !defined( CRC8_H ) +#define CRC_H ///< Include Guard + +/* ---- Include Files ----------------------------------------------------- */ + +#include + +#if defined( __cplusplus ) +extern "C" +{ +#endif + + +/* ---- Constants and Types ---------------------------------------------- */ +/* ---- Variable Externs ------------------------------------------------- */ +/* ---- Function Prototypes ---------------------------------------------- */ + +uint8_t Crc8( uint8_t crc, uint8_t data ); + +uint8_t Crc8Block( uint8_t crc, uint8_t *data, uint8_t len ); + + +#if defined( __cplusplus ) +} +#endif + + +/** @} */ + +#endif // CRC8_H + diff --git a/packages/i2c/files/DumpMem.c b/packages/i2c/files/DumpMem.c new file mode 100644 index 0000000000..e13e94b0f8 --- /dev/null +++ b/packages/i2c/files/DumpMem.c @@ -0,0 +1,93 @@ +/**************************************************************************** +* +* Copyright (c) 2006 Dave Hylands +* +* 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 DumpMem.c +* +* @brief Memmory dump routine +* +****************************************************************************/ + +// ---- Include Files ------------------------------------------------------- + +#include +#include "DumpMem.h" +#include "Log.h" + +// ---- Public Variables ---------------------------------------------------- +// ---- Private Constants and Types ----------------------------------------- +// ---- Private Variables --------------------------------------------------- +// ---- Private Function Prototypes ----------------------------------------- +// ---- Functions ----------------------------------------------------------- + +/**************************************************************************/ +/** +* Dumps a page of output for debugging purposes. +*/ + +void DumpMem( const char *prefix, unsigned address, const void *inData, unsigned numBytes ) +{ + const uint8_t *data = (const uint8_t *)inData; + unsigned byteOffset; + + if ( numBytes == 0 ) + { + Log( "%s: No data\n", prefix ); + return; + } + +#define LINE_WIDTH 16 + + for ( byteOffset = 0; byteOffset < numBytes; byteOffset += LINE_WIDTH ) + { + unsigned i; + + Log( "%s: %04x: ", prefix, address + byteOffset ); + + for ( i = 0; i < LINE_WIDTH; i++ ) + { + if (( byteOffset + i ) < numBytes ) + { + Log( "%02.2X ", data[ byteOffset + i ] ); + } + else + { + Log( " " ); + } + } + for ( i = 0; i < LINE_WIDTH; i++ ) + { + if (( byteOffset + i ) < numBytes ) + { + unsigned char ch = data[ byteOffset + i ]; + if (( ch < ' ' ) || ( ch > '~' )) + { + Log( "." ); + } + else + { + Log( "%c", ch ); + } + } + else + { + break; + } + } + Log( "\n" ); + } + +} // DumpMem + diff --git a/packages/i2c/files/DumpMem.h b/packages/i2c/files/DumpMem.h new file mode 100644 index 0000000000..5d536f49e8 --- /dev/null +++ b/packages/i2c/files/DumpMem.h @@ -0,0 +1,49 @@ +/**************************************************************************** +* +* Copyright (c) 2006 Dave Hylands +* +* 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 DumpMem.h +* +* @brief Debug routine for dumping memory +* +****************************************************************************/ + +#if !defined( DUMPMEM_H ) +#define DUMPMEM_H ///< Include Guard + +// ---- Include Files ------------------------------------------------------- + +/** + * @addtogroup Log + * @{ + */ + +#if defined( __cplusplus ) +extern "C" +{ +#endif + + +void DumpMem( const char *prefix, unsigned address, const void *data, unsigned numBytes ); + +#if defined( __cplusplus ) +} +#endif + + +/** @} */ + +#endif // DUMPMEM_H + diff --git a/packages/i2c/files/Log.c b/packages/i2c/files/Log.c new file mode 100644 index 0000000000..e32783391b --- /dev/null +++ b/packages/i2c/files/Log.c @@ -0,0 +1,335 @@ +/**************************************************************************** +* +* Copyright (c) 2006 Dave Hylands +* +* 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 Log.cpp +* +* @brief This file contains the implementation of the logging functions. +* +****************************************************************************/ + +// ---- Include Files ------------------------------------------------------- + +#include "Log.h" + +#if CFG_LOG_USE_STDIO +# include +#else + +# include "Str.h" +# include "UART.h" +#endif + + +// ---- Public Variables ---------------------------------------------------- +// ---- Private Constants and Types ----------------------------------------- + +#if defined( AVR ) + +#undef Log +#undef LogError +#undef vLog + +#define Log Log_P +#define LogError LogError_P +#define vLog vLog_P +#define LogBuf LogBuf_P + +#define char prog_char + +#else + + +#define PSTR(str) str + +int gVerbose = 0; +int gDebug = 0; +int gQuiet = 0; + +#endif + + +#if CFG_LOG_TO_BUFFER + +volatile LOG_Buffer_t LOG_gBuffer; + +#endif + + +// ---- Private Variables --------------------------------------------------- + +#if CFG_LOG_USE_STDIO + +FILE *gLogFs = NULL; + +#endif + + +// ---- Private Function Prototypes ----------------------------------------- + +// ---- Functions ----------------------------------------------------------- + +/** + * @addtogroup Log + * @{ + */ + +#if !defined( AVR ) + +void DefaultLogFunc( int logLevel, const char *fmt, va_list args ) +{ + FILE *fs; + + if ( gQuiet && ( logLevel == LOG_LEVEL_NORMAL )) + { + return; + } + + if ( gLogFs == NULL ) + { + fs = stderr; + } + else + { + fs = gLogFs; + } + + if ( logLevel == LOG_LEVEL_ERROR ) + { + fprintf( fs, "ERROR: " ); + } + vfprintf( fs, fmt, args ); + fflush( fs ); + +} // DefaultLogFunc + +static LogFunc_t gLogFunc = DefaultLogFunc; + +void SetLogFunc( LogFunc_t logFunc ) +{ + + gLogFunc = logFunc; + +} // SetLogFunc + +#endif + + +//*************************************************************************** +/** +* Sets the logging stream +*/ + +#if CFG_LOG_USE_STDIO +void LogInit( FILE *logFs ) +{ + gLogFs = logFs; + +} // LogInit + +#else + + +static int LogToUartFunc( void *outParm, int ch ) +{ + UART0_PutChar( ch ); + + return 1; +} +#endif + + +//*************************************************************************** +/** +* Logs a string using printf like semantics +*/ + +void Log +( + const char *fmt, ///< printf style format specifier + ... ///< variable list of arguments +) +{ + va_list args; + + va_start( args, fmt ); + vLog( fmt, args ); + va_end( args ); +} + +//*************************************************************************** +/** +* Logs a string using printf like semantics +*/ + +void vLog +( + const char *fmt, ///< printf style format specified + va_list args ///< variable list of arguments +) +{ + // For now we call printf directly. A better way would be to install + // a callback which does the real work + +#if defined( AVR ) +# if CFG_LOG_USE_STDIO + if ( gLogFs != NULL ) + { + vfprintf_P( gLogFs, fmt, args ); + } +# else + + vStrXPrintf_P( LogToUartFunc, NULL, fmt, args ); +# endif + +#else + + if ( gLogFunc != NULL ) + { + gLogFunc( LOG_LEVEL_NORMAL, fmt, args ); + } +#endif + +} + +#if !defined( AVR ) + +//*************************************************************************** +/** +* Logs an error. +*/ + +void vLogError +( + const char *fmt, ///< printf style format specified + va_list args ///< variable list of arguments +) +{ + if ( gLogFunc != NULL ) + { + gLogFunc( LOG_LEVEL_ERROR, fmt, args ); + } +} + +#endif + + +/***************************************************************************/ +/** +* Logs an error +*/ + +void LogError +( + const char *fmt, ///< printf style format specifier + ... ///< variable list of arguments +) +{ + va_list args; + +#if defined( AVR ) + //Log( "ERROR: " ); + //Log_P( PSTR( "ERROR: " )); + + va_start( args, fmt ); + vLog( fmt, args ); + va_end( args ); +#else + + va_start( args, fmt ); + vLogError( fmt, args ); + va_end( args ); +#endif + + +} // LogError + +/***************************************************************************/ +/** +* Logs an entry to the log buffer +*/ + +#if CFG_LOG_TO_BUFFER + +void LogBuf( const char *fmt, uint8_t arg1, uint8_t arg2 LOG_EXTRA_PARAMS_DECL ) +{ +#if defined( AVR ) + uint8_t sreg = SREG; + cli(); +#endif + + + if ( CBUF_IsFull( LOG_gBuffer )) + { + volatile LOG_Entry_t *entry = CBUF_GetLastEntryPtr( LOG_gBuffer ); + + entry->fmt = PSTR( "*** Lost Messages ***\n" ); + } + else + { + volatile LOG_Entry_t *entry = CBUF_GetPushEntryPtr( LOG_gBuffer ); + + entry->fmt = fmt; + entry->param1 = arg1; + entry->param2 = arg2; + +#if CFG_LOG_EXTRA_PARAMS + entry->param3 = arg3; + entry->param4 = arg4; +#endif + + + CBUF_AdvancePushIdx( LOG_gBuffer ); + } + +#if defined( AVR ) + SREG = sreg; +#endif + + +} // LogBuf + +#endif // CFG_LOG_TO_BUFFER + +/***************************************************************************/ +/** +* Dumps any unlogged entries from the log buffer +*/ + +#if CFG_LOG_TO_BUFFER + +void LogBufDump( void ) +{ + while ( !CBUF_IsEmpty( LOG_gBuffer )) + { + volatile LOG_Entry_t *entry = CBUF_GetPopEntryPtr( LOG_gBuffer ); + +#if CFG_LOG_EXTRA_PARAMS + Log( entry->fmt, entry->param1, entry->param2, entry->param3, entry->param4 ); +#else + + Log( entry->fmt, entry->param1, entry->param2 ); +#endif + + + CBUF_AdvancePopIdx( LOG_gBuffer ); + } + +} // LogBufDump + +#endif // CFG_LOG_TO_BUFFER + +/** @} */ + diff --git a/packages/i2c/files/Log.h b/packages/i2c/files/Log.h new file mode 100644 index 0000000000..d12d482fc6 --- /dev/null +++ b/packages/i2c/files/Log.h @@ -0,0 +1,232 @@ +/**************************************************************************** +* +* Copyright (c) 2006 Dave Hylands +* +* 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 Log.h +* +* @brief Contains some logging macros. +* +****************************************************************************/ +/** +* @defgroup Log Logging +* +* @brief Provides a common interface for logging. +* +****************************************************************************/ + +#if !defined( LOG_H ) +#define LOG_H ///< Include Guard + +// ---- Include Files ------------------------------------------------------- + +#include +#include + +#if !defined( CONFIG_H ) +# include "Config.h" +#endif + +#if !defined( CFG_LOG_USE_STDIO ) +# define CFG_LOG_USE_STDIO 1 +#endif + + +#if defined( AVR ) +# include +# include +#endif + + +#if CFG_LOG_TO_BUFFER +# if !defined( CBUF_H ) +# include "CBUF.h" +# endif + +#endif + + + +/** + * @addtogroup Log + * @{ + */ + +#if !defined( CFG_LOG_ENABLED ) +# define CFG_LOG_ENABLED 1 +#endif + + +#if !CFG_LOG_ENABLED + +#define Log( fmt, args... ) +#define LogError( fmt, args... ) + +#else + + +#if defined( __cplusplus ) +extern "C" +{ +#endif + + +/*************************************************************************** +* +* Log Buffer support +*/ + +#if CFG_LOG_TO_BUFFER + +#if defined( AVR ) + +typedef struct +{ + const prog_char *fmt; + uint8_t param1; + uint8_t param2; +#if CFG_LOG_EXTRA_PARAMS + uint8_t param3; + uint8_t param4; +#endif + + +} LOG_Entry_t; + +#if CFG_LOG_EXTRA_PARAMS +# define LOG_EXTRA_PARAMS_DECL , uint8_t arg3, uint8_t arg4 +# define LOG_EXTRA_PARAMS , 0, 0 +#else + +# define LOG_EXTRA_PARAMS_DECL +# define LOG_EXTRA_PARAMS +#endif + + +void LogBuf_P( const prog_char *fmt, uint8_t arg1, uint8_t arg2 LOG_EXTRA_PARAMS_DECL ); + +#define LogBuf0( fmt ) LogBuf_P( PSTR( fmt ), 0, 0 LOG_EXTRA_PARAMS ) +#define LogBuf1( fmt, arg1 ) LogBuf_P( PSTR( fmt ), arg1, 0 LOG_EXTRA_PARAMS ) +#define LogBuf2( fmt, arg1, arg2 ) LogBuf_P( PSTR( fmt ), arg1, arg2 LOG_EXTRA_PARAMS ) + +#if CFG_LOG_EXTRA_PARAMS +#define LogBuf3( fmt, arg1, arg2, arg3 ) LogBuf_P( PSTR( fmt ), arg1, arg2, arg3, 0 ) +#define LogBuf4( fmt, arg1, arg2, arg3, arg4 ) LogBuf_P( PSTR( fmt ), arg1, arg2, arg3, arg4 ) +#endif + + +#else + + +typedef struct +{ + const char *fmt; + uint8_t param1; + uint8_t param2; + +} LOG_Entry_t; + +void LogBuf( const char *fmt, uint8_t arg1, uint8_t arg2 ); + +#define LogBuf0( fmt, arg1 ) LogBuf( fmt, 0, 0 ) +#define LogBuf1( fmt, arg1 ) LogBuf( fmt, arg1, 0 ) +#define LogBuf2( fmt, arg1, arg2 ) LogBuf( fmt, arg1, arg2 ) + +#endif // AVR + +#if ( CFG_LOG_NUM_BUFFER_ENTRIES > 128 ) +typedef uint16_t LOG_BufferIdx_t; +#else + +typedef uint8_t LOG_BufferIdx_t; +#endif + + +typedef struct +{ + LOG_BufferIdx_t m_getIdx; + LOG_BufferIdx_t m_putIdx; + LOG_Entry_t m_entry[ CFG_LOG_NUM_BUFFER_ENTRIES ]; + +} LOG_Buffer_t; + +extern volatile LOG_Buffer_t LOG_gBuffer; + +#define LOG_gBuffer_SIZE ( sizeof( LOG_gBuffer.m_entry ) / sizeof( LOG_gBuffer.m_entry[ 0 ] )) + +void LogBufDump( void ); + +#endif // CFG_LOG_TO_BUFFER + +/*************************************************************************** +* +* Regular logging support +*/ + +#if CFG_LOG_USE_STDIO +extern FILE *gLogFs; + +void LogInit( FILE *logFs ); +#endif + + +#if defined( AVR ) + +void Log_P( const prog_char *fmt, ... ); +void LogError_P( const prog_char *fmt, ... ); +void vLog_P( const prog_char *fmt, va_list args ); + +#define Log( fmt, args... ) Log_P( PSTR( fmt ), ## args ) +#define LogError( fmt, args... ) LogError_P( PSTR( fmt ), ## args ) +#define vLog( fmt, va_list, args ) vLog_P( PSTR( fmt ), args ) + +#else // AVR + +#define LOG_LEVEL_NORMAL 0 +#define LOG_LEVEL_ERROR 1 + +typedef void (*LogFunc_t)( int logLevel, const char *fmt, va_list args ); + +extern int gVerbose; +extern int gDebug; +extern int gQuiet; + +void Log( const char *fmt, ... ); +void LogError( const char *fmt, ... ); +void vLog( const char *fmt, va_list args ); +void vLogError( const char *fmt, va_list args ); + +#define Log_P( fmt, args... ) Log( fmt, ## args ) +#define LogError_P( fmt, args... ) LogError( fmt, ## args ) +#define vLog_P( fmt, args ) vLog( fmt, args ) + +#define LogDebug( fmt, args... ) do { if ( gDebug ) { Log( fmt, ## args ); }} while (0) +#define LogVerbose( fmt, args... ) do { if ( gVerbose ) { Log( fmt, ## args ); }} while (0) + +void SetLogFunc( LogFunc_t logFunc ); +void DefaultLogFunc( int logLevel, const char *fmt, va_list args ); + +#endif // AVR + +#if defined( __cplusplus ) +} +#endif + + +#endif // CFG_LOG_ENABLED + +/** @} */ + +#endif // LOG_H + diff --git a/packages/i2c/files/i2c-api.c b/packages/i2c/files/i2c-api.c new file mode 100644 index 0000000000..cfc41565a4 --- /dev/null +++ b/packages/i2c/files/i2c-api.c @@ -0,0 +1,522 @@ +/**************************************************************************** +* +* Copyright (c) 2006 Dave Hylands +* +* 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-api.c +* +* @brief This file contains the implementation for performing I2C operations +* on the gumstix. +* +****************************************************************************/ + +// ---- Include Files ------------------------------------------------------- + +#include +#include + +#include "i2c.h" +#include "i2c-dev.h" +#include "i2c-api.h" + +#include "Crc8.h" +#include "DumpMem.h" +#include "Log.h" + +// ---- Public Variables ---------------------------------------------------- + +// ---- Private Constants and Types ----------------------------------------- + +// ---- Private Variables --------------------------------------------------- + +static I2C_Addr_t gI2cAddr; +static int gUseCrc; + +// ---- Private Function Prototypes ----------------------------------------- + +// ---- Functions ----------------------------------------------------------- + +//*************************************************************************** +/** +* +* Sets the I2C address that we'll be communicating with, as well as whether +* the device uses smbus PEC (CRC). +*/ + +void I2cSetSlaveAddress( int i2cDev, I2C_Addr_t i2cAddr, int useCrc ) +{ + gI2cAddr = i2cAddr; + gUseCrc = useCrc; + + LogDebug( "----- I2cSetSlaveAddress i2cAddr:0x%02x useCrc:%d -----\n", + i2cAddr, useCrc ); + + // Indicate which slave we wish to speak to + + if ( ioctl( i2cDev, I2C_SLAVE, gI2cAddr ) < 0 ) + { + LogError( "I2cSetSlaveAddress: Error trying to set slave address to 0x%02x (%d %s)\n", + gI2cAddr, errno, strerror( errno )); + } + + // We do the CRC calculation ourself, so we don't need to tell the driver + // that we're using it. + +#if 0 + // Indicate that we use PEC (aka CRCs) + + if ( ioctl( i2cDev, I2C_PEC, 1 ) < 0 ) + { + LogError( "I2cSetSlaveAddress: Error trying to set PEC mode\n" ); + } +#endif + +} // I2cSetSlaveAddress + +//*************************************************************************** +/** +* Transfer data to/from an i2c device. +* +* This function implements the equivalent of the smbus functions using +* I2C_RDWR. +* +* The PXA driver doesn't support the smbus transfers. +* +* This function can perform the following SMBUS transactions: +* +* Write Byte: wrLen == 1, rdLen == 0 +* Read Byte: wrLen == 0, rdLen == 1 +* Write Word: wrLen == 2, rdLen == 0 +* Read Word: wrLen == 0, rdLen == 2 +* Process Call: wrLen == 2, rdLen == 2 +* Write Block: wrLen == 0x80 + numBytes, rdLen == 0 +* Read Block: wrLen == 0, rdLen == 0x80 + numBytes +* Process Block: wrLen == 0x80 + numBytes, rdLen == 0x80 + numBytes +*/ + +int I2cTransfer +( + int i2cDev, ///< Handle to i2c-dev file + uint8_t cmd, ///< Command to send + const void *wrData, ///< Data to write + uint8_t wrLen, ///< Number of bytes to write (or in 0x80 for a block write) + void *rdData, ///< Place to store data read + uint8_t rdLen, ///< Number of bytes to read (or in 0x80 for a block read) + uint8_t *bytesReadp ///< Place to store number of bytes read +) +{ + struct i2c_rdwr_ioctl_data rdwr; + struct i2c_msg msg[ 2 ]; + uint8_t wrBuf[ I2C_MAX_DATA_LEN + 3 ]; // +1 for cmd, +1 for len, +1 for CRC + uint8_t rdBuf[ I2C_MAX_DATA_LEN + 2 ]; // +1 for len, +1 for CRC + uint8_t crc = 0; + uint8_t wrBlock = (( wrLen & 0x80 ) != 0 ); + uint8_t rdBlock = (( rdLen & 0x80 ) != 0 ); + int rc = 0; + + LogDebug( "----- I2cTransfer: cmd:0x%02x wrLen:0x%02x rdLen:0x%02x wrBlock:%d rdBlock:%d -----\n", + cmd, wrLen, rdLen, wrBlock, rdBlock ); + if ( wrData != NULL ) + { + LogDebug( "----- wrData:0x%08x *wrData:0x%02x -----\n", wrData, *(const uint8_t *)wrData ); + } + + rdLen &= 0x7f; + wrLen &= 0x7f; + + if ( bytesReadp != NULL ) + { + *bytesReadp = 0; + } + + if ( wrLen > I2C_MAX_DATA_LEN ) + { + LogError( "I2cTransfer: wrLen too big: %d, max is %d\n", + wrLen, I2C_MAX_DATA_LEN ); + errno = ENOBUFS; + return -1; + } + + if ( rdLen > I2C_MAX_DATA_LEN ) + { + LogError( "I2cTransfer: rdLen too big: %d, max is %d\n", + rdLen, I2C_MAX_DATA_LEN ); + errno = ENOBUFS; + return -1; + } + + // Whether we're doing a read or a write, we always send + // the command. + + msg[ 0 ].addr = gI2cAddr; + msg[ 0 ].flags = 0; + msg[ 0 ].len = wrLen + 1 + wrBlock; // +1 for cmd + msg[ 0 ].buf = (char *)&wrBuf[ 0 ]; + + if ( gUseCrc ) + { + crc = Crc8( 0, gI2cAddr << 1 ); + crc = Crc8( crc, cmd ); + } + + wrBuf[ 0 ] = cmd; + + if ( wrLen > 0 ) + { + // We have some data to send down to the device + + if ( wrBlock ) + { + wrBuf[ 1 ] = wrLen; + memcpy( &wrBuf[ 2 ], wrData, wrLen ); + wrLen++; // Add in cmd to the length + } + else + { + memcpy( &wrBuf[ 1 ], wrData, wrLen ); + } + if ( gUseCrc ) + { + crc = Crc8Block( crc, &wrBuf[ 1 ], wrLen ); + + if ( rdLen == 0 ) + { + // This is a write-only, so we need to send the CRC + + wrBuf[ wrLen + 1 ] = crc; + msg[ 0 ].len++; + } + } + } + + if ( gDebug ) + { + Log( "msg[ 0 ].addr = 0x%02x\n", msg[ 0 ].addr ); + Log( "msg[ 0 ].flags = 0x%04x\n", msg[ 0 ].flags ); + Log( "msg[ 0 ].len = %d\n", msg[ 0 ].len ); + DumpMem( "I2cTransfer W", 0, &wrBuf[ 0 ], msg[ 0 ].len ); + } + + rdwr.msgs = msg; + rdwr.nmsgs = 1; + + if ( rdLen > 0 ) + { + // We're expecting some data to come back + + msg[ 1 ].addr = gI2cAddr; + msg[ 1 ].flags = I2C_M_RD; + msg[ 1 ].len = rdLen + rdBlock + gUseCrc; + msg[ 1 ].buf = (char *)&rdBuf[ 0 ]; + + rdwr.nmsgs = 2; + + if ( gUseCrc ) + { + crc = Crc8( crc, ( gI2cAddr << 1 ) | 1 ); + } + + if ( gDebug ) + { + Log( "msg[ 1 ].addr = 0x%02x\n", msg[ 1 ].addr ); + Log( "msg[ 1 ].flags = 0x%04x\n", msg[ 1 ].flags ); + Log( "msg[ 1 ].len = %d\n", msg[ 1 ].len ); + } + } + + if ( ioctl( i2cDev, I2C_RDWR, &rdwr ) < 0 ) + { + LogError( "I2cTransfer: ioctl failed: %s (%d)\n", strerror( errno ), errno ); + return -1; + } + + if ( rdLen > 0 ) + { + if ( rdBlock ) + { + if ( rdBuf[ 0 ] > rdLen ) + { + LogError( "I2cTransfer: length is too big: %d max: %d\n", rdBuf[ 0 ], rdLen ); + + rc = EMSGSIZE; + } + else + { + rdLen = rdBuf[ 0 ]; + } + } + + if ( gUseCrc ) + { + crc = Crc8Block( crc, &rdBuf[ 0 ], rdLen + rdBlock ); + + if ( crc != rdBuf[ rdLen + rdBlock ] ) + { + LogError( "I2cTransfer: CRC failed: Rcvd: 0x%02x, expecting: 0x%02x\n", + rdBuf[ rdLen + rdBlock ], crc ); + rc = EBADMSG; + } + } + + if ( gDebug ) + { + DumpMem( "I2cTransfer R", 0, &rdBuf[ 0 ], msg[ 1 ].len ); + } + memcpy( rdData, &rdBuf[ rdBlock ], rdLen ); + + if ( bytesReadp != NULL ) + { + *bytesReadp = rdLen; + } + } + return rc; + +} // I2cTransfer + +//*************************************************************************** +/** +* Uses the SMBUS Process-Block protocol to read data from a device. +*/ + +int I2cProcessBlock +( + int i2cDev, ///< Handle to i2c-dev file + uint8_t cmd, ///< Command to send + const void *wrData, ///< Data to write + uint8_t wrLen, ///< Number of bytes to write + void *rdData, ///< Place to store data read + uint8_t rdLen, ///< Number of bytes to read + uint8_t *bytesReadp ///< Place to store number of bytes read +) +{ + LogDebug( "----- I2cProcessBlock cmd: 0x%02x wrLen:0x%02x rdLen:0x%02x -----\n", cmd, wrLen, rdLen ); + + return I2cTransfer( i2cDev, cmd, wrData, 0x80 | wrLen, rdData, 0x80 | rdLen, bytesReadp ); + +} // I2cProcessBlock + +//*************************************************************************** +/** +* Uses the SMBUS Read-Block protocol to read data from a device. +*/ + +int I2cReadBlock +( + int i2cDev, ///< Handle to i2c-dev file + uint8_t cmd, ///< Command to send + void *rdData, ///< Place to store data read + uint8_t rdLen, ///< Number of bytes to read + uint8_t *bytesReadp ///< Place to store number of bytes read +) +{ + LogDebug( "----- I2cReadBlock cmd: 0x%02x rdLen:0x%02x -----\n", cmd, rdLen ); + + return I2cTransfer( i2cDev, cmd, NULL, 0, rdData, 0x80 | rdLen, bytesReadp ); + +} // I2cReadBlock + +//*************************************************************************** +/** +* Uses the SMBUS Read-Byte protocol to read a byte. +*/ + +int I2cReadByte +( + int i2cDev, ///< Handle to i2c-dev file + uint8_t cmd, ///< Command to send + uint8_t *rdByte ///< Place to store byte read +) +{ + LogDebug( "----- I2cReadByte cmd: 0x%02x -----\n", cmd ); + + return I2cTransfer( i2cDev, cmd, NULL, 0, rdByte, 1, NULL ); + +} // I2cReadByte + +//*************************************************************************** +/** +* Reads an array of bytes usinng i2c (not compatible with SMBUS) +*/ + +int I2cReadBytes +( + int i2cDev, ///< Handle to i2c-dev file + uint8_t cmd, ///< Command to send + void *rdByte, ///< Place to store bytes read + uint8_t rdLen ///< Number of bytes to read +) +{ + LogDebug( "----- I2cReadBytes cmd: 0x%02x rdLen: 0x%02x -----\n", cmd, rdLen ); + + return I2cTransfer( i2cDev, cmd, NULL, 0, rdByte, rdLen, NULL ); + +} // I2cReadBytes + +//*************************************************************************** +/** +* Uses the SMBUS Write-Block protocol to write data from a device. +*/ + +int I2cWriteBlock +( + int i2cDev, ///< Handle to i2c-dev file + uint8_t cmd, ///< Command to send + const void *wrData, ///< Data to write + uint8_t wrLen ///< Number of bytes to write +) +{ + LogDebug( "----- I2cWriteBlock cmd: 0x%02x wrLen:0x%02x -----\n", cmd, wrLen ); + + return I2cTransfer( i2cDev, cmd, wrData, 0x80 | wrLen, NULL, 0, NULL ); + +} // I2cWriteBlock + +//*************************************************************************** +/** +* Uses the SMBUS Write-Byte protocol to write a byte. +*/ + +int I2cWriteByte +( + int i2cDev, ///< Handle to i2c-dev file + uint8_t cmd, ///< Command to send + uint8_t wrByte ///< Byte to write +) +{ + LogDebug( "----- I2cWriteByte cmd: 0x%02x wrByte:0x%02x -----\n", cmd, wrByte ); + LogDebug( "----- &wrByte = 0x%08x wrByte = 0x%02x -----\n", &wrByte, *&wrByte ); + + return I2cTransfer( i2cDev, cmd, &wrByte, 1, NULL, 0, NULL ); + +} // I2cWriteByte + +//*************************************************************************** +/** +* Writes an array of bytes using i2c (not compatible with SMBUS) +*/ + +int I2cWriteBytes +( + int i2cDev, ///< Handle to i2c-dev file + uint8_t cmd, ///< Command to send + const void *wrByte, ///< Bytes to write + uint8_t wrLen ///< Number of bytes to write +) +{ + LogDebug( "----- I2cWriteBytes cmd: 0x%02x wrLen: 0x%02x -----\n", cmd, wrLen ); + + return I2cTransfer( i2cDev, cmd, wrByte, wrLen, NULL, 0, NULL ); + +} // I2cWriteBytes + +//*************************************************************************** +/** +* Uses the SMBUS Receive-Byte protocol to read a byte. +*/ + +int I2cReceiveByte +( + int i2cDev, ///< Handle to i2c-dev file + uint8_t *rdByte ///< Place to store byte read +) +{ + return I2cReceiveBytes( i2cDev, rdByte, 1 ); + +} // I2cReceiveByte + +//*************************************************************************** +/** +* Uses the SMBUS Receive-Byte protocol to read multiple (or one or zero) bytes. +*/ + +int I2cReceiveBytes +( + int i2cDev, ///< Handle to i2c-dev file + uint8_t *rdData, ///< Place to store data read + uint8_t rdLen ///< Number of bytes to read +) +{ + struct i2c_rdwr_ioctl_data rdwr; + struct i2c_msg msg; + + LogDebug( "----- I2cReceiveBytes -----\n" ); + + msg.addr = gI2cAddr; + msg.flags = I2C_M_RD; + msg.len = rdLen; + msg.buf = (char *)rdData; + + rdwr.msgs = &msg; + rdwr.nmsgs = 1; + + if ( ioctl( i2cDev, I2C_RDWR, &rdwr ) < 0 ) + { + LogError( "I2cReceiveBytes: ioctl failed: %s (%d)\n", strerror( errno ), errno ); + return -1; + } + + return 0; + +} // I2cReceiveBytes + +//*************************************************************************** +/** +* Uses the SMBUS Send-Byte protocol to write a byte. +*/ + +int I2cSendByte +( + int i2cDev, ///< Handle to i2c-dev file + uint8_t wrByte ///< Byte to write +) +{ + return I2cSendBytes( i2cDev, &wrByte, 1 ); + +} // I2cSendByte + +//*************************************************************************** +/** +* Uses the SMBUS Send-Byte protocol to write multiple (or zero or one) bytes. +*/ + +int I2cSendBytes +( + int i2cDev, ///< Handle to i2c-dev file + uint8_t *wrData, ///< Pointer to data to write + uint8_t wrLen ///< NUmber of bytes to write +) +{ + struct i2c_rdwr_ioctl_data rdwr; + struct i2c_msg msg; + + LogDebug( "----- I2cSendBytes wrLen = 0x%02x -----\n", wrLen ); + + msg.addr = gI2cAddr; + msg.flags = 0; + msg.len = wrLen; + msg.buf = (char *)wrData; + + rdwr.msgs = &msg; + rdwr.nmsgs = 1; + + if ( ioctl( i2cDev, I2C_RDWR, &rdwr ) < 0 ) + { + LogError( "I2cSendBytes: ioctl failed: %s (%d)\n", strerror( errno ), errno ); + return -1; + } + + return 0; + +} // I2cSendBytes + diff --git a/packages/i2c/files/i2c-api.h b/packages/i2c/files/i2c-api.h new file mode 100644 index 0000000000..73f9f20990 --- /dev/null +++ b/packages/i2c/files/i2c-api.h @@ -0,0 +1,143 @@ +/**************************************************************************** +* +* Copyright (c) 2006 Dave Hylands +* +* 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-api.h +* +* @brief This file contains definitions for performing i2c operations +* on the gumstix. +* +****************************************************************************/ + +#if !defined( I2C_API_H ) +#define I2C_API_H + +// ---- Include Files ------------------------------------------------------- + +#include +#include "i2c.h" + +// ---- Constants and Types ------------------------------------------------- + +#define I2C_USE_CRC 1 +#define I2C_NO_CRC 0 + +// ---- Variable Externs ---------------------------------------------------- + +// ---- Function Prototypes ------------------------------------------------- + +void I2cSetSlaveAddress +( + int i2cDev, ///< Handle to i2c-dev file + I2C_Addr_t i2cAddr, ///< 7 bit i2c address to use + int useCrc ); ///< Should CRC's be used? + +int I2cTransfer +( + int i2cDev, ///< Handle to i2c-dev file + uint8_t cmd, ///< Command to send + const void *wrData, ///< Data to write + uint8_t wrLen, ///< Number of bytes to write (or in 0x80 for a block write) + void *rdData, ///< Place to store data read + uint8_t rdLen, ///< Number of bytes to read (or in 0x80 for a block read) + uint8_t *bytesReadp ///< Place to store number of bytes read +); + +int I2cProcessBlock +( + int i2cDev, ///< Handle to i2c-dev file + uint8_t cmd, ///< Command to send + const void *wrData, ///< Data to write + uint8_t wrLen, ///< Number of bytes to write + void *rdData, ///< Place to store data read + uint8_t rdLen, ///< Number of bytes to read + uint8_t *bytesReadp ///< Place to store number of bytes read +); + +int I2cReadBlock +( + int i2cDev, ///< Handle to i2c-dev file + uint8_t cmd, ///< Command to send + void *rdData, ///< Place to store data read + uint8_t rdLen, ///< Number of bytes to read + uint8_t *bytesReadp ///< Place to store number of bytes read +); + +int I2cReadByte +( + int i2cDev, ///< Handle to i2c-dev file + uint8_t cmd, ///< Command to send + uint8_t *rdByte ///< Place to store byte to read +); + +int I2cReadBytes +( + int i2cDev, ///< Handle to i2c-dev file + uint8_t cmd, ///< Command to send + void *rdByte, ///< Place to store bytes read + uint8_t rdLen ///< Number of bytes to read +); + +int I2cWriteBlock +( + int i2cDev, ///< Handle to i2c-dev file + uint8_t cmd, ///< Command to send + const void *wrData, ///< Data to write + uint8_t wrLen ///< Number of bytes to write +); + +int I2cWriteByte +( + int i2cDev, ///< Handle to i2c-dev file + uint8_t cmd, ///< Command to send + uint8_t wrByte ///< Byte to write +); + +int I2cWriteBytes +( + int i2cDev, ///< Handle to i2c-dev file + uint8_t cmd, ///< Command to send + const void *wrByte, ///< Bytes to write + uint8_t wrLen ///< Number of bytes to write +); + +int I2cReceiveByte +( + int i2cDev, ///< Handle to i2c-dev file + uint8_t *rdByte ///< Place to store byte read +); + +int I2cReceiveBytes +( + int i2cDev, ///< Handle to i2c-dev file + uint8_t *rdData, ///< Place to store byte read + uint8_t rdLen ///< Number of bytes to read +); + +int I2cSendByte +( + int i2cDev, ///< Handle to i2c-dev file + uint8_t wrByte ///< Byte to write +); + +int I2cSendBytes +( + int i2cDev, ///< Handle to i2c-dev file + uint8_t *wrData, ///< Pointer to data to write. + uint8_t wrLen ///< Number of bytes to write. +); + +#endif // I2C_API_H + diff --git a/packages/i2c/files/i2c-dev.h b/packages/i2c/files/i2c-dev.h new file mode 100644 index 0000000000..cd20965ede --- /dev/null +++ b/packages/i2c/files/i2c-dev.h @@ -0,0 +1,365 @@ +/* + i2c-dev.h - i2c-bus driver, char device interface + + Copyright (C) 1995-97 Simon G. Vogl + Copyright (C) 1998-99 Frodo Looijaard + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* $Id: i2c-dev.h,v 1.4 2003/11/27 23:08:06 tat Exp $ */ + +#ifndef LIB_I2CDEV_H +#define LIB_I2CDEV_H + +#include +#include + + +/* -- i2c.h -- */ + + +/* + * I2C Message - used for pure i2c transaction, also from /dev interface + */ +struct i2c_msg { + __u16 addr; /* slave address */ + unsigned short flags; +#define I2C_M_TEN 0x10 /* we have a ten bit chip address */ +#define I2C_M_RD 0x01 +#define I2C_M_NOSTART 0x4000 +#define I2C_M_REV_DIR_ADDR 0x2000 +#define I2C_M_IGNORE_NAK 0x1000 +#define I2C_M_NO_RD_ACK 0x0800 + short len; /* msg length */ + char *buf; /* pointer to msg data */ +}; + +/* To determine what functionality is present */ + +#define I2C_FUNC_I2C 0x00000001 +#define I2C_FUNC_10BIT_ADDR 0x00000002 +#define I2C_FUNC_PROTOCOL_MANGLING 0x00000004 /* I2C_M_{REV_DIR_ADDR,NOSTART,..} */ +#define I2C_FUNC_SMBUS_HWPEC_CALC 0x00000008 /* SMBus 2.0 */ +#define I2C_FUNC_SMBUS_READ_WORD_DATA_PEC 0x00000800 /* SMBus 2.0 */ +#define I2C_FUNC_SMBUS_WRITE_WORD_DATA_PEC 0x00001000 /* SMBus 2.0 */ +#define I2C_FUNC_SMBUS_PROC_CALL_PEC 0x00002000 /* SMBus 2.0 */ +#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL_PEC 0x00004000 /* SMBus 2.0 */ +#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0x00008000 /* SMBus 2.0 */ +#define I2C_FUNC_SMBUS_QUICK 0x00010000 +#define I2C_FUNC_SMBUS_READ_BYTE 0x00020000 +#define I2C_FUNC_SMBUS_WRITE_BYTE 0x00040000 +#define I2C_FUNC_SMBUS_READ_BYTE_DATA 0x00080000 +#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA 0x00100000 +#define I2C_FUNC_SMBUS_READ_WORD_DATA 0x00200000 +#define I2C_FUNC_SMBUS_WRITE_WORD_DATA 0x00400000 +#define I2C_FUNC_SMBUS_PROC_CALL 0x00800000 +#define I2C_FUNC_SMBUS_READ_BLOCK_DATA 0x01000000 +#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000 +#define I2C_FUNC_SMBUS_READ_I2C_BLOCK 0x04000000 /* I2C-like block xfer */ +#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 /* w/ 1-byte reg. addr. */ +#define I2C_FUNC_SMBUS_READ_I2C_BLOCK_2 0x10000000 /* I2C-like block xfer */ +#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK_2 0x20000000 /* w/ 2-byte reg. addr. */ +#define I2C_FUNC_SMBUS_READ_BLOCK_DATA_PEC 0x40000000 /* SMBus 2.0 */ +#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC 0x80000000 /* SMBus 2.0 */ + +#define I2C_FUNC_SMBUS_BYTE I2C_FUNC_SMBUS_READ_BYTE | \ + I2C_FUNC_SMBUS_WRITE_BYTE +#define I2C_FUNC_SMBUS_BYTE_DATA I2C_FUNC_SMBUS_READ_BYTE_DATA | \ + I2C_FUNC_SMBUS_WRITE_BYTE_DATA +#define I2C_FUNC_SMBUS_WORD_DATA I2C_FUNC_SMBUS_READ_WORD_DATA | \ + I2C_FUNC_SMBUS_WRITE_WORD_DATA +#define I2C_FUNC_SMBUS_BLOCK_DATA I2C_FUNC_SMBUS_READ_BLOCK_DATA | \ + I2C_FUNC_SMBUS_WRITE_BLOCK_DATA +#define I2C_FUNC_SMBUS_I2C_BLOCK I2C_FUNC_SMBUS_READ_I2C_BLOCK | \ + I2C_FUNC_SMBUS_WRITE_I2C_BLOCK +#define I2C_FUNC_SMBUS_I2C_BLOCK_2 I2C_FUNC_SMBUS_READ_I2C_BLOCK_2 | \ + I2C_FUNC_SMBUS_WRITE_I2C_BLOCK_2 +#define I2C_FUNC_SMBUS_BLOCK_DATA_PEC I2C_FUNC_SMBUS_READ_BLOCK_DATA_PEC | \ + I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC +#define I2C_FUNC_SMBUS_WORD_DATA_PEC I2C_FUNC_SMBUS_READ_WORD_DATA_PEC | \ + I2C_FUNC_SMBUS_WRITE_WORD_DATA_PEC + +#define I2C_FUNC_SMBUS_READ_BYTE_PEC I2C_FUNC_SMBUS_READ_BYTE_DATA +#define I2C_FUNC_SMBUS_WRITE_BYTE_PEC I2C_FUNC_SMBUS_WRITE_BYTE_DATA +#define I2C_FUNC_SMBUS_READ_BYTE_DATA_PEC I2C_FUNC_SMBUS_READ_WORD_DATA +#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA_PEC I2C_FUNC_SMBUS_WRITE_WORD_DATA +#define I2C_FUNC_SMBUS_BYTE_PEC I2C_FUNC_SMBUS_BYTE_DATA +#define I2C_FUNC_SMBUS_BYTE_DATA_PEC I2C_FUNC_SMBUS_WORD_DATA + +#define I2C_FUNC_SMBUS_EMUL I2C_FUNC_SMBUS_QUICK | \ + I2C_FUNC_SMBUS_BYTE | \ + I2C_FUNC_SMBUS_BYTE_DATA | \ + I2C_FUNC_SMBUS_WORD_DATA | \ + I2C_FUNC_SMBUS_PROC_CALL | \ + I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | \ + I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC | \ + I2C_FUNC_SMBUS_I2C_BLOCK + +/* + * Data for SMBus Messages + */ +#define I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus standard */ +#define I2C_SMBUS_I2C_BLOCK_MAX 32 /* Not specified but we use same structure */ +union i2c_smbus_data { + __u8 byte; + __u16 word; + __u8 block[I2C_SMBUS_BLOCK_MAX + 3]; /* block[0] is used for length */ + /* one more for read length in block process call */ + /* and one more for PEC */ +}; + +/* smbus_access read or write markers */ +#define I2C_SMBUS_READ 1 +#define I2C_SMBUS_WRITE 0 + +/* SMBus transaction types (size parameter in the above functions) + Note: these no longer correspond to the (arbitrary) PIIX4 internal codes! */ +#define I2C_SMBUS_QUICK 0 +#define I2C_SMBUS_BYTE 1 +#define I2C_SMBUS_BYTE_DATA 2 +#define I2C_SMBUS_WORD_DATA 3 +#define I2C_SMBUS_PROC_CALL 4 +#define I2C_SMBUS_BLOCK_DATA 5 +#define I2C_SMBUS_I2C_BLOCK_DATA 6 +#define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */ +#define I2C_SMBUS_BLOCK_DATA_PEC 8 /* SMBus 2.0 */ +#define I2C_SMBUS_PROC_CALL_PEC 9 /* SMBus 2.0 */ +#define I2C_SMBUS_BLOCK_PROC_CALL_PEC 10 /* SMBus 2.0 */ +#define I2C_SMBUS_WORD_DATA_PEC 11 /* SMBus 2.0 */ + + +/* ----- commands for the ioctl like i2c_command call: + * note that additional calls are defined in the algorithm and hw + * dependent layers - these can be listed here, or see the + * corresponding header files. + */ + /* -> bit-adapter specific ioctls */ +#define I2C_RETRIES 0x0701 /* number of times a device address */ + /* should be polled when not */ + /* acknowledging */ +#define I2C_TIMEOUT 0x0702 /* set timeout - call with int */ + + +/* this is for i2c-dev.c */ +#define I2C_SLAVE 0x0703 /* Change slave address */ + /* Attn.: Slave address is 7 or 10 bits */ +#define I2C_SLAVE_FORCE 0x0706 /* Change slave address */ + /* Attn.: Slave address is 7 or 10 bits */ + /* This changes the address, even if it */ + /* is already taken! */ +#define I2C_TENBIT 0x0704 /* 0 for 7 bit addrs, != 0 for 10 bit */ + +#define I2C_FUNCS 0x0705 /* Get the adapter functionality */ +#define I2C_RDWR 0x0707 /* Combined R/W transfer (one stop only)*/ +#define I2C_PEC 0x0708 /* != 0 for SMBus PEC */ +#if 0 +#define I2C_ACK_TEST 0x0710 /* See if a slave is at a specific address */ +#endif + +#define I2C_SMBUS 0x0720 /* SMBus-level access */ + +/* -- i2c.h -- */ + + +/* Note: 10-bit addresses are NOT supported! */ + +/* This is the structure as used in the I2C_SMBUS ioctl call */ +struct i2c_smbus_ioctl_data { + char read_write; + __u8 command; + int size; + union i2c_smbus_data *data; +}; + +/* This is the structure as used in the I2C_RDWR ioctl call */ +struct i2c_rdwr_ioctl_data { + struct i2c_msg *msgs; /* pointers to i2c_msgs */ + int nmsgs; /* number of i2c_msgs */ +}; + + +static inline __s32 i2c_smbus_access(int file, char read_write, __u8 command, + int size, union i2c_smbus_data *data) +{ + struct i2c_smbus_ioctl_data args; + int rc; + + args.read_write = read_write; + args.command = command; + args.size = size; + args.data = data; + + rc = ioctl(file,I2C_SMBUS,&args); + + return rc; +} + + +static inline __s32 i2c_smbus_write_quick(int file, __u8 value) +{ + return i2c_smbus_access(file,value,0,I2C_SMBUS_QUICK,NULL); +} + +static inline __s32 i2c_smbus_read_byte(int file) +{ + union i2c_smbus_data data; + if (i2c_smbus_access(file,I2C_SMBUS_READ,0,I2C_SMBUS_BYTE,&data)) + return -1; + else + return 0x0FF & data.byte; +} + +static inline __s32 i2c_smbus_write_byte(int file, __u8 value) +{ + return i2c_smbus_access(file,I2C_SMBUS_WRITE,value, + I2C_SMBUS_BYTE,NULL); +} + +static inline __s32 i2c_smbus_read_byte_data(int file, __u8 command) +{ + union i2c_smbus_data data; + if (i2c_smbus_access(file,I2C_SMBUS_READ,command, + I2C_SMBUS_BYTE_DATA,&data)) + return -1; + else + return 0x0FF & data.byte; +} + +static inline __s32 i2c_smbus_write_byte_data(int file, __u8 command, + __u8 value) +{ + union i2c_smbus_data data; + data.byte = value; + return i2c_smbus_access(file,I2C_SMBUS_WRITE,command, + I2C_SMBUS_BYTE_DATA, &data); +} + +static inline __s32 i2c_smbus_read_word_data(int file, __u8 command) +{ + union i2c_smbus_data data; + if (i2c_smbus_access(file,I2C_SMBUS_READ,command, + I2C_SMBUS_WORD_DATA,&data)) + return -1; + else + return 0x0FFFF & data.word; +} + +static inline __s32 i2c_smbus_write_word_data(int file, __u8 command, + __u16 value) +{ + union i2c_smbus_data data; + data.word = value; + return i2c_smbus_access(file,I2C_SMBUS_WRITE,command, + I2C_SMBUS_WORD_DATA, &data); +} + +static inline __s32 i2c_smbus_process_call(int file, __u8 command, __u16 value) +{ + union i2c_smbus_data data; + data.word = value; + if (i2c_smbus_access(file,I2C_SMBUS_WRITE,command, + I2C_SMBUS_PROC_CALL,&data)) + return -1; + else + return 0x0FFFF & data.word; +} + + +/* Returns the number of read bytes */ +static inline __s32 i2c_smbus_read_block_data(int file, __u8 command, + __u8 *values) +{ + union i2c_smbus_data data; + int i; + if (i2c_smbus_access(file,I2C_SMBUS_READ,command, + I2C_SMBUS_BLOCK_DATA,&data)) + return -1; + else { + for (i = 1; i <= data.block[0]; i++) + values[i-1] = data.block[i]; + return data.block[0]; + } +} + +static inline __s32 i2c_smbus_write_block_data(int file, __u8 command, + __u8 length, __u8 *values) +{ + union i2c_smbus_data data; + int i; + if (length > 32) + length = 32; + for (i = 1; i <= length; i++) + data.block[i] = values[i-1]; + data.block[0] = length; + return i2c_smbus_access(file,I2C_SMBUS_WRITE,command, + I2C_SMBUS_BLOCK_DATA, &data); +} + +/* Returns the number of read bytes */ +static inline __s32 i2c_smbus_read_i2c_block_data(int file, __u8 command, + __u8 *values) +{ + union i2c_smbus_data data; + int i; + if (i2c_smbus_access(file,I2C_SMBUS_READ,command, + I2C_SMBUS_I2C_BLOCK_DATA,&data)) + return -1; + else { + for (i = 1; i <= data.block[0]; i++) + values[i-1] = data.block[i]; + return data.block[0]; + } +} + +static inline __s32 i2c_smbus_write_i2c_block_data(int file, __u8 command, + __u8 length, __u8 *values) +{ + union i2c_smbus_data data; + int i; + if (length > 32) + length = 32; + for (i = 1; i <= length; i++) + data.block[i] = values[i-1]; + data.block[0] = length; + return i2c_smbus_access(file,I2C_SMBUS_WRITE,command, + I2C_SMBUS_I2C_BLOCK_DATA, &data); +} + +/* Returns the number of read bytes */ +static inline __s32 i2c_smbus_block_process_call(int file, __u8 command, + __u8 length, __u8 *values) +{ + union i2c_smbus_data data; + int i; + if (length > 32) + length = 32; + for (i = 1; i <= length; i++) + data.block[i] = values[i-1]; + data.block[0] = length; + i = i2c_smbus_access(file,I2C_SMBUS_WRITE,command, + I2C_SMBUS_BLOCK_PROC_CALL,&data); + if ( i ) + return -1; + else { + for (i = 1; i <= data.block[0]; i++) + values[i-1] = data.block[i]; + return data.block[0]; + } +} + + +#endif /* LIB_I2CDEV_H */ + diff --git a/packages/i2c/files/i2c-io-api.h b/packages/i2c/files/i2c-io-api.h new file mode 100644 index 0000000000..35ab45865c --- /dev/null +++ b/packages/i2c/files/i2c-io-api.h @@ -0,0 +1,52 @@ +/**************************************************************************** +* +* Copyright (c) 2006 Dave Hylands +* +* 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-io-api.h +* +* @brief This file contains definitions for performing i2c-io operations +* on the gumstix. +* +****************************************************************************/ + +#if !defined( I2C_IO_API_H ) +#define I2C_IO_API_H + +// ---- Include Files ------------------------------------------------------- + +#include +#include "i2c-io.h" + +// ---- Constants and Types ------------------------------------------------- + +// ---- Variable Externs ---------------------------------------------------- + +// ---- Function Prototypes ------------------------------------------------- + +int I2C_IO_CheckVersion( const I2C_IO_Info_t *info ); + +int I2C_IO_GetInfo( int i2cDev, I2C_IO_Info_t *info ); +int I2C_IO_GetGPIO( int i2cDev, uint8_t portNum, uint8_t *pinVal ); +int I2C_IO_SetGPIO( int i2cDev, uint8_t portNum, uint8_t pinMask, uint8_t pinVal ); +int I2C_IO_GetGPIODir( int i2cDev, uint8_t portNum, uint8_t *pinVal ); +int I2C_IO_SetGPIODir( int i2cDev, uint8_t portNum, uint8_t pinMask, uint8_t pinVal ); +int I2C_IO_GetADC( int i2cDev, uint8_t mux, uint16_t *adcVal ); +int I2C_IO_ReadReg8( int i2cDev, uint8_t reg, uint8_t *regVal ); +int I2C_IO_ReadReg16( int i2cDev, uint8_t reg, uint16_t *regVal ); +int I2C_IO_WriteReg8( int i2cDev, uint8_t reg, uint8_t regVal ); +int I2C_IO_WriteReg16( int i2cDev, uint8_t reg, uint16_t regVal ); + +#endif // I2C_IO_API_H + diff --git a/packages/i2c/files/i2c-io.h b/packages/i2c/files/i2c-io.h new file mode 100644 index 0000000000..3ffb5e9c0e --- /dev/null +++ b/packages/i2c/files/i2c-io.h @@ -0,0 +1,220 @@ +/**************************************************************************** +* +* Copyright (c) 2006 Dave Hylands +* +* 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-io.h +* +* @brief This file defines the interface to the i2c-io program which +* runs on the robostix. +* +*****************************************************************************/ + +#if !defined( I2C_IO_H ) +#define I2C_IO_H /**< Include Guard */ + +/* ---- Include Files ---------------------------------------------------- */ + +/* ---- Constants and Types ---------------------------------------------- */ + +//--------------------------------------------------------------------------- +/** + * Defines the version of this API. This includes the layout of the + * various structures, along with the semantics associated with the + * protocol. Any changes require the version number to be incremented. + * + * Version 2 - Introduced READ/WRITE_REG_8/16 + */ + +#define I2C_IO_API_VERSION 2 + +//--------------------------------------------------------------------------- +/** + * The min version, determines the minimum version that this API is + * compatable with. This allows old host side programs to determine + * that they're not compatible. + */ + +#define I2C_IO_API_MIN_VERSION 1 + + +//--------------------------------------------------------------------------- +/** +* The I2C_IO_GET_INFO command retrieves information about the i2c-io +* program running on the robostix. +*/ + +#define I2C_IO_GET_INFO 0x01 + +typedef struct +{ + uint8_t version; + uint8_t minVersion; + uint16_t svnRevision; + +} I2C_IO_Info_t; + +//--------------------------------------------------------------------------- +/** +* The I2C_IO_GET_GPIO command retrieves the values of the pins indicated +* by portNum. +* +* The portNum is set such that 0 = A, 1 = B, etc. +* +* A block-reply with a single 8 bit value is returned. +*/ + +typedef struct +{ + uint8_t portNum; + +} I2C_IO_Get_GPIO_t; + +#define I2C_IO_GET_GPIO 0x02 + +//--------------------------------------------------------------------------- +/** +* The I2C_IO_SET_GPIO command sets the values of the pins specified +* by pinMask to the correponding bits in ponVal. +* +* Note: Setting a pin that's configured for input will enable a pullup +* resistor. +* +* The portNum is set such that 0 = A, 1 = B, etc. +*/ + +typedef struct +{ + uint8_t portNum; + uint8_t pinMask; + uint8_t pinVal; + +} I2C_IO_Set_GPIO_t; + +#define I2C_IO_SET_GPIO 0x03 + +//--------------------------------------------------------------------------- +/** +* The I2C_IO_GET_GPIO_DIR command retrieves the data direction +* register (DDR) for the indicated portNum. +* +* The I2C_IO_Get_GPIO_t structure is used for this command. +* +* Note: It's ok to read the values of pins which are set for output. +* +* The portNum is set such that 0 = A, 1 = B, etc. +* +* A block-reply with a single 8 bit value is returned. +* A 1 bit means that the pin is set for output and a 0 bit means that +* the pin is set for input. +*/ + +#define I2C_IO_GET_GPIO_DIR 0x04 + +//--------------------------------------------------------------------------- +/** +* The I2C_IO_SET_GPIO_DIR command sets the data direction +* register (DDR) for the indicated portNum. +* +* The I2C_IO_Set_GPIO_t structure is used for this command. +* +* The portNum is set such that 0 = A, 1 = B, etc. +*/ + +#define I2C_IO_SET_GPIO_DIR 0x05 + +//--------------------------------------------------------------------------- +/** +* The I2C_IO_GET_ADC command performs an ADC sample and returns the result. +* +* mux values 0 thru 7 read singled ended ADC values. Values 8 thru 31 +* return a variety of values. See the data sheet for specifics. +* +* A block-reply with a 16 bit value is returned, although only the +* lower 10 bits are significant. +*/ + +typedef struct +{ + uint8_t mux; + +} I2C_IO_Get_ADC_t; + +#define I2C_IO_GET_ADC 0x06 + +//--------------------------------------------------------------------------- +/** +* The I2C_IO_READ_REG_8 command reads a 8-bit register. +* +* A block reply with an 8 bit value is returned. +*/ + +typedef struct +{ + uint8_t reg; ///< Index of the register to be read. + +} I2C_IO_ReadReg8_t; + +#define I2C_IO_READ_REG_8 0x07 + +//--------------------------------------------------------------------------- +/** +* The I2C_IO_READ_REG_16 command reads a 16-bit register. +* +* A block reply with a 16 bit value is returned. +*/ + +typedef struct +{ + uint8_t reg; ///< Index of the register to be read. + +} I2C_IO_ReadReg16_t; + +#define I2C_IO_READ_REG_16 0x08 + +//--------------------------------------------------------------------------- +/** +* The I2C_IO_WRITE_REG_8 command writes an 8-bit register. +*/ + +typedef struct +{ + uint8_t reg; ///< Index of the register to be read. + uint8_t val; ///< Value to write into the register + +} I2C_IO_WriteReg8_t; + +#define I2C_IO_WRITE_REG_8 0x09 + +//--------------------------------------------------------------------------- +/** +* The I2C_IO_WRITE_REG_16 command writes a 16-bit register. +*/ + +typedef struct +{ + uint8_t reg; ///< Index of the register to be read. + uint8_t pad; ///< Pad for alignment on the host. + uint16_t val; ///< Value to write + +} I2C_IO_WriteReg16_t; + +#define I2C_IO_WRITE_REG_16 0x0A + +/* ---- Variable Externs ------------------------------------------------- */ + +/* ---- Function Prototypes ---------------------------------------------- */ + +#endif /* I2C_IO_H */ + 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 +* +* 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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" ); +} + diff --git a/packages/i2c/files/i2c.h b/packages/i2c/files/i2c.h new file mode 100644 index 0000000000..bbfd276cec --- /dev/null +++ b/packages/i2c/files/i2c.h @@ -0,0 +1,135 @@ +/**************************************************************************** +* +* Copyright (c) 2006 Dave Hylands +* +* 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.h +* +* @brief Global definitions for interfacing with the AVR TWI (aka I2C) +* hardware +* +****************************************************************************/ +/** +* @defgroup xxx Readable version of xxx. +* +* @brief Brief description of what xxx does. +* +* Longer description of what xxx does. +* +****************************************************************************/ + +#if !defined( I2C_H ) +#define I2C_H /**< Include Guard */ + +/* ---- Include Files ---------------------------------------------------- */ + +#include + +#if !defined( CONFIG_H ) +# include "Config.h" +#endif + + +/** + * @addtogroup I2C + * @{ + */ + +/* ---- Constants and Types ---------------------------------------------- */ + +/** + * Error Codes + */ + +#define I2C_ERROR_NONE 0 // No Error +#define I2C_ERROR_ADDR_NACK -1 // No response to SLA+R/W +#define I2C_ERROR_DATA_NACK -2 // NACK during data transmission +#define I2C_ERROR_ARBITRATION_LOST -3 // Lost arbitration +#define I2C_ERROR_BAD_LEN -4 // Length is wonky +#define I2C_ERROR_BAD_CRC -5 // CRC failed +#define I2C_ERROR_BUS_ERROR -6 // Someting weird on the i2c bus + +typedef int8_t I2C_Error_t; + +/** + * Since we're loosely following the SMBus spec, we restrict the amount + * of data in each transaction to 32 bytes. + */ + +#define I2C_MAX_DATA_LEN 32 + +/** + * I2C_Addr_t can contain the address of any device on the bus. This + * module only supports 7 bit addressing. + */ + +typedef uint8_t I2C_Addr_t; + +/** + * The I2C_CRC macro can be used to remove all CRC support at compile time. + */ + +#if CFG_I2C_USE_CRC +# define I2C_CRC(x) x +#else + +# define I2C_CRC(x) +#endif + + +/** + * I2C_Data_t encapsulates the data being read or written on the i2c bus. + * This module follows the SMBus spec, whihch specifies a maximum payload + * of 32 bytes. + */ + +typedef struct +{ +#if CFG_I2C_USE_CRC + uint8_t m_crc; +#endif + + + // For reads, m_len is the number of bytes actually read (doesn't include + // the CRC - if present). If a block transfer was performed which has a + // length byte, this length will include the length byte. + + uint8_t m_len; + + // Note: Under SMBus, a block write can consist of a command, a length, + // 32 bytes of payload, and a CRC. + // + // A read response can consist of a length, 32 bytes of data, and a CRC. + + uint8_t m_data[ I2C_MAX_DATA_LEN + 2]; // +1 for the command, +1 for length + +} I2C_Data_t; + +/* ---- Variable Externs ------------------------------------------------- */ + +/** + * Description of variable. + */ + +/* ---- Function Prototypes ---------------------------------------------- */ + +/* + * Just include prototypes here. Put full descriptions in the .c files. + */ + +/** @} */ + +#endif /* I2C_H */ + + diff --git a/packages/i2c/files/i2c.init b/packages/i2c/files/i2c.init new file mode 100755 index 0000000000..957ce68c7b --- /dev/null +++ b/packages/i2c/files/i2c.init @@ -0,0 +1,37 @@ +#!/bin/sh +# +# Start i2c support +# + +start() { + echo "Starting i2c..." + + /sbin/modprobe i2c-pxa + /sbin/modprobe i2c-dev +} +stop() { + echo "Stopping i2c..." + +} +restart() { + stop + start +} + +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart) + restart + ;; + *) + echo $"Usage: $0 {start|stop|restart}" + exit 1 +esac + +exit $? + diff --git a/packages/i2c/i2c.bb b/packages/i2c/i2c.bb new file mode 100644 index 0000000000..69b4c1cc32 --- /dev/null +++ b/packages/i2c/i2c.bb @@ -0,0 +1,45 @@ +DESCRIPTION = "i2c init file and command line tool" +SECTION = "base" +PRIORITY = "required" +PR = "r2" + +SRC_URI = " \ + file://Config.h \ + file://Crc8.h \ + file://Crc8.c \ + file://DumpMem.h \ + file://DumpMem.c \ + file://Log.h \ + file://Log.c \ + file://i2c-api.h \ + file://i2c-api.c \ + file://i2c-dev.h \ + file://i2c-io.h \ + file://i2c-io-api.h \ + file://i2c.h \ + file://i2c.c \ + file://i2c.init \ + " + +S = "${WORKDIR}" + +do_compile () { + ${CC} -o i2c *.c +} + +do_install () { + install -d ${D}${bindir}/ + install -m 0755 ${WORKDIR}/i2c ${D}${bindir}/ + + install -d ${D}${sysconfdir}/init.d/ + install -m 0755 ${WORKDIR}/i2c.init ${D}${sysconfdir}/init.d/i2c +} + +inherit update-rc.d +INITSCRIPT_NAME = "i2c" +INITSCRIPT_PARAMS = "defaults 90" + +PACKAGES = "${PN}" +FILES_${PN} = "${bindir}/*" +FILES_${PN} += "${sysconfdir}/*" + -- cgit v1.2.3