1 /****************************************************************************
3 * Copyright (c) 2006 Dave Hylands <dhylands@gmail.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
14 ****************************************************************************/
19 * @brief This program allows basic i2c commands to be sent out the i2c
22 ****************************************************************************/
24 // ---- Include Files -------------------------------------------------------
34 #include <sys/timeb.h>
38 #include "i2c-io-api.h"
41 // #include "svn-version.h"
43 // ---- Public Variables ----------------------------------------------------
44 // ---- Private Constants and Types -----------------------------------------
46 // ---- Private Variables ---------------------------------------------------
52 // Options assigned a single character code can use that charater code
57 // Options from this point onwards don't have any short option equivalents
59 OPT_FIRST_LONG_OPT
= 0x80,
93 { CMD_READ_BYTE
, "ReadByte" },
94 { CMD_READ_BYTE
, "rb" },
95 { CMD_READ_BYTE_2
, "ReadByte2" },
96 { CMD_READ_BYTE_2
, "rb2" },
97 { CMD_READ_BYTE_4
, "ReadByte4" },
98 { CMD_READ_BYTE_4
, "rb4" },
100 { CMD_WRITE_BYTE
, "WriteByte" },
101 { CMD_WRITE_BYTE
, "wb" },
102 { CMD_WRITE_BYTE_2
, "WriteByte2" },
103 { CMD_WRITE_BYTE_2
, "wb2" },
104 { CMD_WRITE_BYTE_4
, "WriteByte4" },
105 { CMD_WRITE_BYTE_4
, "wb4" },
107 { CMD_RECV_BYTE
, "RecvByte" },
108 { CMD_RECV_BYTE
, "vb" },
109 { CMD_RECV_BYTE_2
, "RecvByte2" },
110 { CMD_RECV_BYTE_2
, "vb2" },
111 { CMD_RECV_BYTE_4
, "RecvByte4" },
112 { CMD_RECV_BYTE_4
, "vb4" },
114 { CMD_SEND_BYTE
, "SendByte" },
115 { CMD_SEND_BYTE
, "sb" },
116 { CMD_SEND_BYTE_2
, "SendByte2" },
117 { CMD_SEND_BYTE_2
, "sb2" },
118 { CMD_SEND_BYTE_4
, "SendByte4" },
119 { CMD_SEND_BYTE_4
, "sb4" },
122 int gNumCmds
= sizeof( gCmdMap
) / sizeof( gCmdMap
[ 0 ]);
128 int gCmd
= CMD_DEFAULT
;
129 const char *gAddrStr
= NULL
;
130 const char *gDataStr
= NULL
;
132 struct option gOption
[] =
134 { "count", required_argument
, NULL
, OPT_COUNT
},
135 { "version", no_argument
, NULL
, OPT_VERSION
},
136 { "verbose", no_argument
, &gVerbose
, 1 },
137 { "debug", no_argument
, &gDebug
, 1 },
138 { "help", no_argument
, NULL
, OPT_HELP
},
154 // ---- Private Function Prototypes -----------------------------------------
156 static int ParseByte( const char *byteStr
, uint8_t *byte
);
157 static int ParseBytes( const char *byteStr
, uint8_t *byte
, uint8_t maxBytes
, uint8_t *bytesParsed
);
159 static void ProcessReadByteCommand( int i2cDev
, const char *addrStr
);
160 static void ProcessWriteByteCommand( int i2cDev
, const char *addrStr
, const char *dataStr
);
161 static void ProcessRecvByteCommand( int i2cDev
);
162 static void ProcessSendByteCommand( int i2cDev
, const char *dataStr
);
163 static void Usage( void );
165 // ---- Functions -----------------------------------------------------------
167 //***************************************************************************
172 int main( int argc
, char **argv
)
174 char shortOptsStr
[ sizeof( gOption
) / sizeof( gOption
[ 0 ] ) + 1 ];
175 char *shortOpts
= shortOptsStr
;
176 struct option
*scanOpt
;
178 const char *i2cDevName
= "/dev/i2c-0";
184 // Figure out the short options from our options structure
186 for ( scanOpt
= gOption
; scanOpt
->name
!= NULL
; scanOpt
++ )
188 if (( scanOpt
->flag
== NULL
) && ( scanOpt
->val
< OPT_FIRST_LONG_OPT
))
190 *shortOpts
++ = (char)scanOpt
->val
;
192 if ( scanOpt
->has_arg
!= no_argument
)
200 // Parse the command line options
202 while (( opt
= getopt_long( argc
, argv
, shortOptsStr
, gOption
, NULL
)) != -1 )
208 // getopt_long returns 0 for entries where flag is non-NULL
215 gByteCount
= (int)strtol( optarg
, NULL
, 0 );
216 if ( gByteCount
<= 0 )
218 LogError( "Expecting byte count >= 0, found: '%s'\n", optarg
);
222 if ( gByteCount
> I2C_MAX_DATA_LEN
)
224 LogError( "Max byte count supported: %d, found %d\n", I2C_MAX_DATA_LEN
, gByteCount
);
233 // Log( "i2c SVN Revision: %d\n", SVN_REVISION );
242 LogError( "opt:%d\n", opt
);
251 // Verify that an i2c-address was specified
255 LogError( "Must specify an i2c address\n\n" );
259 gI2cAddr
= strtol( argv
[ 0 ], NULL
, 0 );
260 if (( gI2cAddr
<= 0 ) || ( gI2cAddr
> 127 ))
262 LogError( "Expecting i2c address in the range of 1-127, Found: %d\n", gI2cAddr
);
267 // Verify that a command has been specified
271 LogError( "Must specify a command\n" );
276 for ( cmdIdx
= 0; cmdIdx
< gNumCmds
; cmdIdx
++ )
278 if ( strcasecmp( gCmdStr
, gCmdMap
[ cmdIdx
].cmdStr
) == 0 )
280 gCmd
= gCmdMap
[ cmdIdx
].cmd
;
284 if ( gCmd
== CMD_DEFAULT
)
286 LogError( "Unrecognized command '%s'\n", gCmdStr
);
290 // Process command specific arguments
292 if (( gCmd
== CMD_READ_BYTE_2
)
293 || ( gCmd
== CMD_WRITE_BYTE_2
)
294 || ( gCmd
== CMD_RECV_BYTE_2
)
295 || ( gCmd
== CMD_SEND_BYTE_2
))
300 if (( gCmd
== CMD_READ_BYTE_4
)
301 || ( gCmd
== CMD_WRITE_BYTE_4
)
302 || ( gCmd
== CMD_RECV_BYTE_4
)
303 || ( gCmd
== CMD_SEND_BYTE_4
))
308 if (( gCmd
== CMD_READ_BYTE
)
309 || ( gCmd
== CMD_READ_BYTE_2
)
310 || ( gCmd
== CMD_READ_BYTE_4
))
314 LogError( "Expecting address\n" );
320 LogError( "Unexpected extra parameters\n" );
325 gAddrStr
= argv
[ 2 ];
328 if (( gCmd
== CMD_WRITE_BYTE
)
329 || ( gCmd
== CMD_WRITE_BYTE_2
)
330 || ( gCmd
== CMD_WRITE_BYTE_4
))
334 LogError( "Expecting address and data\n" );
340 LogError( "Unexpected extra parameters\n" );
345 gAddrStr
= argv
[ 2 ];
346 gDataStr
= argv
[ 3 ];
349 if (( gCmd
== CMD_RECV_BYTE
)
350 || ( gCmd
== CMD_RECV_BYTE_2
)
351 || ( gCmd
== CMD_RECV_BYTE_4
))
355 LogError( "Unexpected extra parameters\n" );
361 if (( gCmd
== CMD_SEND_BYTE
)
362 || ( gCmd
== CMD_SEND_BYTE_2
)
363 || ( gCmd
== CMD_SEND_BYTE_4
))
367 LogError( "Expecting data\n" );
373 LogError( "Unexpected extra parameters\n" );
377 gDataStr
= argv
[ 2 ];
382 Log( "i2cAddr:0x%02x Cmd: %s (%d)", gI2cAddr
, gCmdStr
, gCmd
);
383 if ( gAddrStr
!= NULL
)
385 Log( " Addr: %s", gAddrStr
);
387 if ( gDataStr
!= NULL
)
389 Log( " Data: %s", gDataStr
);
394 // Try to open the i2c device
396 if (( i2cDev
= open( i2cDevName
, O_RDWR
)) < 0 )
398 LogError( "Error opening '%s': %s\n", i2cDevName
, strerror( errno
));
402 // Indicate which slave we wish to speak to
404 I2cSetSlaveAddress( i2cDev
, gI2cAddr
, I2C_NO_CRC
);
409 case CMD_READ_BYTE_2
:
410 case CMD_READ_BYTE_4
:
412 ProcessReadByteCommand( i2cDev
, gAddrStr
);
417 case CMD_WRITE_BYTE_2
:
418 case CMD_WRITE_BYTE_4
:
420 ProcessWriteByteCommand( i2cDev
, gAddrStr
, gDataStr
);
425 case CMD_RECV_BYTE_2
:
426 case CMD_RECV_BYTE_4
:
428 ProcessRecvByteCommand( i2cDev
);
433 case CMD_SEND_BYTE_2
:
434 case CMD_SEND_BYTE_4
:
436 ProcessSendByteCommand( i2cDev
, gDataStr
);
447 //***************************************************************************
449 * Parse a string looking for a single byte.
452 int ParseByte( const char *byteStr
, uint8_t *byte
)
456 *byte
= (uint8_t)strtol( byteStr
, &endPtr
, 0 );
458 if ( *endPtr
!= '\0' )
460 LogError( "Expecting numeric value, found '%s'\n", byteStr
);
468 //***************************************************************************
470 * Parse a string looking for an array of bytes.
473 int ParseBytes( const char *byteStr
, uint8_t *byte
, uint8_t maxBytes
, uint8_t *bytesParsed
)
477 if (( byteStr
[ 0 ] == '0' ) && ( byteStr
[ 1 ] == 'x' ))
479 const char *s
= &byteStr
[ 2 ];
482 // Could be a multi-byte hex string
486 if ( *bytesParsed
>= maxBytes
)
488 LogError( "Too many bytes, max: %d\n", maxBytes
);
495 if (( *s
>= 'A' ) && ( *s
<= 'F' ))
497 *byte
= *s
- 'A' + 10;
500 if (( *s
>= 'a' ) && ( *s
<= 'f' ))
502 *byte
= *s
- 'a' + 10;
505 if (( *s
>= '0' ) && ( *s
<= '9' ))
511 LogError( "Expecting hex digit, found '%c'\n", *s
);
522 if (( *s
>= 'A' ) && ( *s
<= 'F' ))
524 *byte
|= *s
- 'A' + 10;
527 if (( *s
>= 'a' ) && ( *s
<= 'f' ))
529 *byte
|= *s
- 'a' + 10;
532 if (( *s
>= '0' ) && ( *s
<= '9' ))
538 LogError( "Expecting hex digit, found '%c'\n", *s
);
547 // It's decimal or octal - only a single byte
549 *byte
= (uint8_t)strtol( byteStr
, &endPtr
, 0 );
551 if ( *endPtr
!= '\0' )
553 LogError( "Expecting numeric value, found '%s'\n", byteStr
);
563 //***************************************************************************
565 * Issues a read byte command to read a byte from a particular address.
568 void ProcessReadByteCommand( int i2cDev
, const char *addrStr
)
571 uint8_t dataByte
[ I2C_MAX_DATA_LEN
];
575 if ( !ParseByte( addrStr
, &addr
))
580 if (( rc
= I2cReadBytes( i2cDev
, addr
, dataByte
, gByteCount
)) != 0 )
582 LogError( "I2cReadByte failed: %d\n", rc
);
586 Log( "0x", dataByte
[0] );
588 for ( i
= 0; i
< gByteCount
; i
++ )
590 Log( "%02x", dataByte
[i
] );
594 } // ProcessReadByteCommand
596 //***************************************************************************
598 * Issues a recv byte command to read bytes with no address.
601 void ProcessRecvByteCommand( int i2cDev
)
603 uint8_t dataByte
[ I2C_MAX_DATA_LEN
];
607 if (( rc
= I2cReceiveBytes( i2cDev
, dataByte
, gByteCount
)) != 0 )
609 LogError( "I2cRecvBytes failed: %d\n", rc
);
613 Log( "0x", dataByte
[0] );
615 for ( i
= 0; i
< gByteCount
; i
++ )
617 Log( "%02x", dataByte
[i
] );
621 } // ProcessRecvByteCommand
623 //***************************************************************************
625 * Issues a write byte command to write a byte to a particular address.
628 void ProcessWriteByteCommand( int i2cDev
, const char *addrStr
, const char *dataStr
)
631 uint8_t dataByte
[ I2C_MAX_DATA_LEN
];
635 if ( !ParseByte( addrStr
, &addr
))
640 if ( !ParseBytes( dataStr
, dataByte
, sizeof( dataByte
), &bytesParsed
))
645 if (( rc
= I2cWriteBytes( i2cDev
, addr
, dataByte
, bytesParsed
)) != 0 )
647 LogError( "I2cWriteBytes failed: %d\n", rc
);
651 } // ProcessWriteByteCommand
653 //***************************************************************************
655 * Issues a send byte command to write bytes with no address specified.
658 void ProcessSendByteCommand( int i2cDev
, const char *dataStr
)
660 uint8_t dataByte
[ I2C_MAX_DATA_LEN
];
664 if ( !ParseBytes( dataStr
, dataByte
, sizeof( dataByte
), &bytesParsed
))
669 if (( rc
= I2cSendBytes( i2cDev
, dataByte
, bytesParsed
)) != 0 )
671 LogError( "I2cSendBytes failed: %d\n", rc
);
675 } // ProcessSendByteCommand
677 //***************************************************************************
684 fprintf( stderr
, "Usage: i2c [options] i2c-addr cmd [cmd-arguments]\n" );
685 fprintf( stderr
, "Send I2C commands\n" );
686 fprintf( stderr
, "\n" );
687 fprintf( stderr
, "The following commands are supported:\n" );
688 fprintf( stderr
, "ReadByte addr Retrieves byte(s) starting at the indicated address\n" );
689 fprintf( stderr
, "WriteByte addr data Write byte(s) starting at the indicated address\n" );
690 fprintf( stderr
, "ReadByte2 addr Retrieves two bytes from the indicated address\n" );
691 fprintf( stderr
, "WriteByte2 addr data Writes two bytes into the indicated address\n" );
692 fprintf( stderr
, "ReadByte4 addr Retrieves four bytes from the indicated address\n" );
693 fprintf( stderr
, "WriteByte4 addr data Writes four bytes into the indicated address\n" );
694 fprintf( stderr
, "RecvByte Retrieves byte(s)(no address specified)\n" );
695 fprintf( stderr
, "SendByte data Writes byte(s)(no address specified)\n" );
696 fprintf( stderr
, "RecvByte2 Retrieves 2 bytes (no address specified)\n" );
697 fprintf( stderr
, "SendByte2 data Writes 2 bytes(no address specified)\n" );
698 fprintf( stderr
, "RecvByte4 Retrieves 4 bytes (no address specified)\n" );
699 fprintf( stderr
, "SendByte4 data Writes 4 bytes(no address specified)\n" );
700 fprintf( stderr
, "\n" );
701 fprintf( stderr
, "The above commands can be shortened to rb, wb, rb2, wb2, rb4, wb4, vb, sd, vb2 sb2 vb4, and sb4 \n" );
702 fprintf( stderr
, "respectively.\n" );
703 fprintf( stderr
, "\n" );
704 fprintf( stderr
, "The following options may be used:\n" );
705 fprintf( stderr
, "--count=n Specifies how many bytes to read for ReadByte or RecvByte\n" );
706 fprintf( stderr
, "--version Prints the SVN version of this program\n" );
707 fprintf( stderr
, "--verbose Print additional information\n" );
708 fprintf( stderr
, "--help Prints this information\n" );