i2c  1.4.2
RoadNarrows Robotics I2C Package
i2ctrans.c
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Package: RCB3
4 //
5 // File: i2ctrans.c
6 //
7 /*! \file
8  *
9  * $LastChangedDate: 2011-09-12 16:08:28 -0600 (Mon, 12 Sep 2011) $
10  * $Rev: 1279 $
11  *
12  * \brief Do a write/read transaction for a device on the I2C Bus.
13  *
14  * \author Robin Knight (robin.knight@roadnarrows.com)
15  *
16  * \copyright
17  * \h_copy 2007-2017. RoadNarrows LLC.\n
18  * http://www.roadnarrows.com\n
19  * All Rights Reserved
20  */
21 // Permission is hereby granted, without written agreement and without
22 // license or royalty fees, to use, copy, modify, and distribute this
23 // software and its documentation for any purpose, provided that
24 // (1) The above copyright notice and the following two paragraphs
25 // appear in all copies of the source code and (2) redistributions
26 // including binaries reproduces these notices in the supporting
27 // documentation. Substantial modifications to this software may be
28 // copyrighted by their authors and need not follow the licensing terms
29 // described here, provided that the new terms are clearly indicated in
30 // all files where they apply.
31 //
32 // IN NO EVENT SHALL THE AUTHOR, ROADNARROWS LLC, OR ANY MEMBERS/EMPLOYEES
33 // OF ROADNARROW LLC OR DISTRIBUTORS OF THIS SOFTWARE BE LIABLE TO ANY
34 // PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
35 // DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
36 // EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN ADVISED OF
37 // THE POSSIBILITY OF SUCH DAMAGE.
38 //
39 // THE AUTHOR AND ROADNARROWS LLC SPECIFICALLY DISCLAIM ANY WARRANTIES,
40 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
41 // FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
42 // "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO
43 // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
44 //
45 ////////////////////////////////////////////////////////////////////////////////
46 
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <stdarg.h>
50 #include <string.h>
51 #include <errno.h>
52 #include <ctype.h>
53 #include <libgen.h>
54 #include <unistd.h>
55 
56 #include "rnr/rnrconfig.h"
57 #include "rnr/log.h"
58 #include "rnr/opts.h"
59 
60 #include "rnr/i2c-dev.h"
61 #include "rnr/i2c.h"
62 
63 #include "version.h"
64 
65 // ---------------------------------------------------------------------------
66 // Private Interface
67 // ---------------------------------------------------------------------------
68 
69 // The Command
70 static char *Argv0; ///< command name
71 
72 //
73 // Command Option and Argument Values
74 //
75 static int OptVerbose = 0; ///< verbose option
76 static char *OptDevName = "/dev/i2c/0"; ///< i2c bus device option
77 static int OptDevFd = -1; ///< opened i2c bus device fd option
78 static int OptI2CAddr = -1; ///< slave i2c device address option
79 static int OptReadCount = 1; ///< read byte count option
80 static byte_t ArgWriteBuf[1024]; ///< write buffer argument
81 static int ArgWriteLen = 0; ///< write byte count argument
82 
83 /*!
84  * \brief Program Information
85  */
86 static OptsPgmInfo_T I2CTransPgmInfo =
87 {
88  .usage_args = "byte1 [byte2 ...]",
89 
90  .synopsis = "Do a write/read transaction for a device on the I2C Bus.",
91 
92  .long_desc =
93  "The %P command performs a message request/response transaction with "
94  "a device of the specified address on the I2C Bus. "
95  "The specified bytes are writen to the device. Then <count> bytes are "
96  "read.\n\n"
97  "The bytes read are printed to stdout in ASCII hex format.",
98 
99  .diagnostics =
100  "Exit status is 0 if the transaction was completed successfully. "
101  "Exist status is >= 2 if error(s) are encountered.",
102 };
103 
104 /*!
105  * \brief Command Line Options Information
106  */
107 static OptsInfo_T I2CTransOptsInfo[] =
108 {
109  // I2C device address
110  {
111  .long_opt = "address",
112  .short_opt = 'a',
113  .has_arg = required_argument,
114  .opt_addr = &OptI2CAddr,
115  .fn_cvt = OptsCvtArgInt,
116  .fn_fmt = OptsFmtInt,
117  .arg_name = "<addr>",
118  .opt_desc = "I2C device address. REQUIRED"
119  },
120 
121  // I2C device read count
122  {
123  .long_opt = "count",
124  .short_opt = 'c',
125  .has_arg = required_argument,
126  .has_default= true,
127  .opt_addr = &OptReadCount,
128  .fn_cvt = OptsCvtArgInt,
129  .fn_fmt = OptsFmtInt,
130  .arg_name = "<count>",
131  .opt_desc = "I2C device read byte count"
132  },
133 
134  // I2C device name
135  {
136  .long_opt = "device",
137  .short_opt = 'd',
138  .has_arg = required_argument,
139  .has_default= true,
140  .opt_addr = &OptDevName,
141  .fn_cvt = OptsCvtArgStr,
142  .fn_fmt = OptsFmtStr,
143  .arg_name = "<device>",
144  .opt_desc = "I2C device."
145  },
146 
147  // opend I2C file descriptor
148  {
149  .long_opt = "fd",
150  .short_opt = OPTS_NO_SHORT,
151  .has_arg = required_argument,
152  .opt_addr = &OptDevFd,
153  .fn_cvt = OptsCvtArgInt,
154  .fn_fmt = OptsFmtInt,
155  .arg_name = "<n>",
156  .opt_desc = "Opened I2C device file descriptor."
157  },
158 
159  // verbose printing
160  {
161  .long_opt = "verbose",
162  .short_opt = 'v',
163  .has_arg = no_argument,
164  .has_default= true,
165  .opt_addr = &OptVerbose,
166  .fn_fmt = OptsFmtBool,
167  .opt_desc = "Set print verbosity."
168  },
169 
170  {NULL, }
171 };
172 
173 /*!
174  * \brief Execute \h_i2c slave device write/read transaction.
175  *
176  * \param pI2C Pointer to \h_i2c handle.
177  * \param addr Slave device address.
178  * \param writebuf Buffer to write.
179  * \param writelen Number of write bytes.
180  * \param readlen Number of bytes to read.
181  *
182  * \return Returns number of bytes read \h_ge 0 on success, RC_ERROR on failure.
183  */
184 static int execTrans(i2c_t *pI2C, int addr, byte_t writebuf[], int writelen,
185  int readlen)
186 {
187  byte_t readbuf[1024];
188  int n;
189  int i;
190 
191  if( readlen > sizeof(readbuf) )
192  {
193  readlen = sizeof(readbuf);
194  fprintf(stderr,
195  "%s: Warning: %d: I2C read length too long. Resetting to %u\n",
196  Argv0, readlen, (uint_t)sizeof(readbuf));
197  }
198 
199  if( OptVerbose )
200  {
201  printf("%s: i2cdev 0x%02x: transaction write %u bytes, read %u bytes\n",
202  Argv0, (byte_t)addr, (uint_t)writelen, (uint_t)readlen);
203  }
204 
205  n = i2c_transfer(pI2C, (i2c_addr_t)addr, writebuf, (uint_t)writelen,
206  readbuf, (uint_t)readlen);
207 
208  if( n < 0 )
209  {
210  LOGSYSERROR("i2c_transfer()");
211  return RC_ERROR;
212  }
213 
214  else
215  {
216  if( OptVerbose )
217  {
218  printf("Response %d bytes: ", readlen);
219  }
220  for(i=0; i<readlen; ++i)
221  {
222  printf("0x%02x ", readbuf[i]);
223  }
224  if( (readlen > 0) || OptVerbose )
225  {
226  printf("\n");
227  }
228  }
229 
230  return n;
231 }
232 
233 /*!
234  * \brief Convert string to unsigned integer.
235  *
236  * \param s String.
237  * \param [out] pVal Pointer to converted value.
238  *
239  * \return Returns OK on success, RC_ERROR on error.
240  */
241 static int StrToUnsigned(const char *s, uint_t *pVal)
242 {
243  long lVal;
244  char *sEnd;
245 
246  if( (s == NULL) || (*s == 0) )
247  {
248  return RC_ERROR;
249  }
250 
251  lVal = strtol(s, &sEnd, 0);
252 
253  if( *sEnd != 0 )
254  {
255  return RC_ERROR;
256  }
257  else if( lVal < 0 )
258  {
259  return RC_ERROR;
260  }
261  else
262  {
263  *pVal = (uint_t)lVal;
264  return OK;
265  }
266 }
267 
268 /*!
269  * \brief Convert string to byte.
270  *
271  * \param s String.
272  * \param [out] pByte Pointer to converted value.
273  *
274  * \return Returns OK on success, RC_ERROR on error.
275  */
276 static int StrToByte(const char *s, byte_t *pByte)
277 {
278  uint_t uVal;
279 
280  if( StrToUnsigned(s, &uVal) != OK )
281  {
282  return RC_ERROR;
283  }
284  else if( uVal > 0xff )
285  {
286  return RC_ERROR;
287  }
288  else
289  {
290  *pByte = (byte_t)uVal;
291  return OK;
292  }
293 }
294 
295 /*!
296  * \brief Get write bytes from command-line arguments.
297  *
298  * \param argc Command-line argument count.
299  * \param argv Command-line arguments.
300  *
301  * \return Exits on error.
302  */
303 static void ArgsGet(int argc, char *argv[])
304 {
305  int i;
306  size_t max = sizeof(ArgWriteBuf);
307 
308  if( argc == 0 )
309  {
310  printf("%s Error: At least one byte must be specified\n", Argv0);
311  exit(EC_ERROR);
312  }
313  else if( argc > max )
314  {
315  fprintf(stderr,
316  "%s: Warning: %d: I2C write. Only %u bytes will be written.\n",
317  Argv0, argc, (uint_t)max);
318  }
319 
320  for(i=0; i<argc && i<max; ++i)
321  {
322  if( StrToByte(argv[i], ArgWriteBuf+i) != OK )
323  {
324  printf("%s Error: byte %d = '%s': bad byte value\n", Argv0, i, argv[i]);
325  exit(EC_ERROR);
326  }
327  }
328 
329  ArgWriteLen = i;
330 }
331 
332 /*!
333  * \brief Command initialization.
334  *
335  * \param argc Command-line argument count.
336  * \param argv Command-line arguments.
337  * \param pI2C Pointer to \h_i2c handle.
338  */
339 static void MainInit(int argc, char *argv[], i2c_t *pI2C)
340 {
341  // Name of this process
342  Argv0 = basename(argv[0]);
343 
344  // Get the environment
345  //EnvGet();
346 
347  // Parse input arguments
348  argv = OptsGet(Argv0, &PkgInfo, &I2CTransPgmInfo, I2CTransOptsInfo, true,
349  &argc, argv);
350 
351  // Final option checks
352  if( OptI2CAddr < 0 )
353  {
354  fprintf(stderr, "%s: Address option required\n", Argv0);
355  exit(EC_BAD_OPT);
356  }
358  {
359  fprintf(stderr, "%s: Address out of range: 0x%x\n", Argv0, OptI2CAddr);
360  exit(EC_BAD_OPT);
361  }
362 
363  // Convert command-line arguments
364  ArgsGet(argc, argv);
365 
366  // Opened device specified
367  if( OptDevFd >= 0 )
368  {
369  pI2C->fd = OptDevFd;
370  pI2C->addr = (ushort_t)(-1);
371  }
372 
373  // I2C Bus device specified
374  else
375  {
376  if( OptDevName == NULL || OptDevName[0] == 0 )
377  {
378  OptDevName = "/dev/i2c/0";
379  }
380 
381  if( OptVerbose )
382  {
383  printf("I2C device: %s\n\n", OptDevName);
384  }
385 
386  if( i2c_open(pI2C, OptDevName) < 0 )
387  {
388  LOGSYSERROR("%s: Failed to open.", OptDevName);
389  exit(EC_ERROR);
390  }
391  }
392 }
393 
394 /*!
395  * \brief i2ctrans main()
396  *
397  * \param argc Count of command-line options and arguments.
398  * \param argv Array of command-line options and arguments.
399  *
400  * \return Exit value.
401  */
402 int main(int argc, char *argv[])
403 {
404  i2c_t i2c;
405  int rc;
406 
407  MainInit(argc, argv, &i2c);
408 
410 
411  return rc > 0? 0: 2;
412 }
413 
414 /*!
415 \page i2ctrans I2CTRANS(1)
416 
417 \section NAME
418 i2ctrans - Do a write/read transaction for a device on the I<sup>2</sup>C Bus
419 
420 \section SYNOPSIS
421 i2ctrans [OPTIONS] byte1 [byte2 ...]
422 
423 \section DESCRIPTION
424 Perform a message request/response transaction with a device of the given
425 address on the I<sup>2</sup>C Bus.
426 The specified bytes are writen to the device. Then <count> bytes are read.
427 The bytes read are printed to \p stdout in ASCII hex format.
428 
429 \section OPTIONS RNR_OPTIONS
430 \verbatim
431  -a, --address=<addr> I2C device 7-bit address. REQUIRED.
432  -c, --count=<count> Read count bytes.
433  DEFAULT: 1
434  -d, --device=<device> I2C device.
435  DEFAULT: /dev/i2c/0
436  --fd=<n> Opened I2C device file descriptor.
437  -v, --verbose Set print verbosity.
438  DEFAULT: false
439  RNR_OPTIONS Standard set of options provided by librnr.
440 \endverbatim
441 
442 \section DIAGNOSTICS
443 Exit status is 0 if the transaction was completed successfully.
444 Exist status is >= 2 if error(s) are encountered.
445 
446 \section SEE_ALSO
447 \ref i2ccheck,
448 \ref i2cread,
449 \ref i2cscan,
450 \ref i2cwrite
451 
452 \section AUTHOR
453 Robin Knight (robin.knight@roadnarrows.com)
454 
455 \section COPYRIGHT
456 (C) 2007. RoadNarrows LLC.
457 (http://www.roadnarrows.com)
458 \n All Rights Reserved
459 */
i2c_addr_t addr
address of the currently selected attached I2C device
Definition: i2c.h:82
static int StrToByte(const char *s, byte_t *pByte)
Convert string to byte.
Definition: i2ctrans.c:276
I2C python modules.
int fd
opened file descriptor of the I2C bus device
Definition: i2c.h:81
ushort_t i2c_addr_t
I2C Device Address Type.
Definition: i2c.h:72
static byte_t ArgWriteBuf[1024]
write buffer argument
Definition: i2ctrans.c:80
I2C Bus Handle Type.
Definition: i2c.h:79
static int StrToUnsigned(const char *s, uint_t *pVal)
Convert string to unsigned integer.
Definition: i2ctrans.c:241
#define I2C_ADDR_DEV_HIGH
last available device address
Definition: i2c-dev.h:103
static OptsInfo_T I2CTransOptsInfo[]
Command Line Options Information.
Definition: i2ctrans.c:107
static void MainInit(int argc, char *argv[], i2c_t *pI2C)
Command initialization.
Definition: i2ctrans.c:339
static void ArgsGet(int argc, char *argv[])
Get write bytes from command-line arguments.
Definition: i2ctrans.c:303
static int OptVerbose
verbose option
Definition: i2ctrans.c:75
int main(int argc, char *argv[])
i2ctrans main()
Definition: i2ctrans.c:402
static char * OptDevName
i2c bus device option
Definition: i2ctrans.c:76
int i2c_transfer(i2c_t *i2c, i2c_addr_t addr, const byte_t *write_buf, uint_t write_len, byte_t *read_buf, uint_t read_len)
Perform a transfer with an I2C device.
Definition: i2ccom.c:171
I2C character device interface.
static int ArgWriteLen
write byte count argument
Definition: i2ctrans.c:81
static const PkgInfo_T PkgInfo
Definition: version.h:45
static int OptDevFd
opened i2c bus device fd option
Definition: i2ctrans.c:77
static char * Argv0
command name
Definition: i2ctrans.c:70
Package version information.
static OptsPgmInfo_T I2CTransPgmInfo
Program Information.
Definition: i2ctrans.c:86
static int OptReadCount
read byte count option
Definition: i2ctrans.c:79
int i2c_open(i2c_t *i2c, const char *device)
Open the host I2C Bus device.
Definition: i2ccom.c:118
#define I2C_ADDR_DEV_LOW
first available device address
Definition: i2c-dev.h:101
static int OptI2CAddr
slave i2c device address option
Definition: i2ctrans.c:78
static int execTrans(i2c_t *pI2C, int addr, byte_t writebuf[], int writelen, int readlen)
Execute I2C slave device write/read transaction.
Definition: i2ctrans.c:184
Low-level I2C communication level.