i2c  1.4.2
RoadNarrows Robotics I2C Package
i2cwrite.c
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Package: RCB3
4 //
5 // File: i2cwrite.c
6 //
7 /*! \file
8  *
9  * $LastChangedDate: 2011-09-12 16:08:28 -0600 (Mon, 12 Sep 2011) $
10  * $Rev: 1279 $
11  *
12  * \brief Write bytes to 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 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 buse device fd option
78 static int OptI2CAddr = -1; ///< slave i2c device address
79 static byte_t ArgWriteBuf[1024]; ///< write buffer argument
80 static int ArgWriteLen = 0; ///< write byte count arguement
81 
82 /*!
83  * \brief Program Information
84  */
85 static OptsPgmInfo_T I2CWritePgmInfo =
86 {
87  .usage_args = "byte1 [byte2 ...]",
88 
89  .synopsis = "Write bytes to a device on an I2C Bus.",
90 
91  .long_desc =
92  "The %P command write the bytes arguments to an I2C Bus for a device "
93  "with the specified address.",
94 
95  .diagnostics =
96  "Exit status is 0 if the bytes are successfully written. "
97  "Exist status is >= 2 if error(s) are encountered.",
98 };
99 
100 /*!
101  * \brief Command Line Options Information
102  */
103 static OptsInfo_T I2CWriteOptsInfo[] =
104 {
105  // I2C device address
106  {
107  .long_opt = "address",
108  .short_opt = 'a',
109  .has_arg = required_argument,
110  .opt_addr = &OptI2CAddr,
111  .fn_cvt = OptsCvtArgInt,
112  .fn_fmt = OptsFmtInt,
113  .arg_name = "<addr>",
114  .opt_desc = "I2C device address. REQUIRED"
115  },
116 
117  // I2C device name
118  {
119  .long_opt = "device",
120  .short_opt = 'd',
121  .has_arg = required_argument,
122  .has_default= true,
123  .opt_addr = &OptDevName,
124  .fn_cvt = OptsCvtArgStr,
125  .fn_fmt = OptsFmtStr,
126  .arg_name = "<device>",
127  .opt_desc = "I2C device."
128  },
129 
130  // opend I2C file descriptor
131  {
132  .long_opt = "fd",
133  .short_opt = OPTS_NO_SHORT,
134  .has_arg = required_argument,
135  .opt_addr = &OptDevFd,
136  .fn_cvt = OptsCvtArgInt,
137  .fn_fmt = OptsFmtInt,
138  .arg_name = "<n>",
139  .opt_desc = "Opened I2C device file descriptor."
140  },
141 
142  // verbose printing
143  {
144  .long_opt = "verbose",
145  .short_opt = 'v',
146  .has_arg = no_argument,
147  .has_default= true,
148  .opt_addr = &OptVerbose,
149  .fn_fmt = OptsFmtBool,
150  .opt_desc = "Set print verbosity."
151  },
152 
153  {NULL, }
154 };
155 
156 /*!
157  * \brief Execute \h_i2c slave device write.
158  *
159  * \param pI2C Pointer to \h_i2c handle.
160  * \param addr Slave device address.
161  * \param writebuf Buffer to write.
162  * \param writelen Number of write bytes.
163  *
164  * \return Returns \h_ge 0 on success, -1 on failure.
165  */
166 static int execWrite(i2c_t *pI2C, int addr, byte_t writebuf[], int writelen)
167 {
168  int n;
169 
170  if( OptVerbose )
171  {
172  printf("%s: i2cdev 0x%02x: writting %u bytes...\n",
173  Argv0, (byte_t)addr, writelen);
174  }
175 
176  n = i2c_write(pI2C, (i2c_addr_t)addr, writebuf, (uint_t)writelen);
177 
178  if( n < 0 )
179  {
180  LOGSYSERROR("i2c_write()");
181  return RC_ERROR;
182  }
183 
184  if( OptVerbose )
185  {
186  printf("Wrote %d bytes\n", n);
187  }
188 
189  if( n < writelen )
190  {
191  LOGERROR("wrote only %d bytes of %d", n, writelen);
192  }
193 
194  return n;
195 }
196 
197 /*!
198  * \brief Convert string to unsigned integer.
199  *
200  * \param s String.
201  * \param [out] pVal Pointer to converted value.
202  *
203  * \return Returns OK on success, RC_ERROR on error.
204  */
205 static int StrToUnsigned(const char *s, uint_t *pVal)
206 {
207  long lVal;
208  char *sEnd;
209 
210  if( (s == NULL) || (*s == 0) )
211  {
212  return RC_ERROR;
213  }
214 
215  lVal = strtol(s, &sEnd, 0);
216 
217  if( *sEnd != 0 )
218  {
219  return RC_ERROR;
220  }
221  else if( lVal < 0 )
222  {
223  return RC_ERROR;
224  }
225  else
226  {
227  *pVal = (uint_t)lVal;
228  return OK;
229  }
230 }
231 
232 /*!
233  * \brief Convert string to byte.
234  *
235  * \param s String.
236  * \param [out] pByte Pointer to converted value.
237  *
238  * \return Returns OK on success, RC_ERROR on error.
239  */
240 static int StrToByte(const char *s, byte_t *pByte)
241 {
242  uint_t uVal;
243 
244  if( StrToUnsigned(s, &uVal) != OK )
245  {
246  return RC_ERROR;
247  }
248  else if( uVal > 0xff )
249  {
250  return RC_ERROR;
251  }
252  else
253  {
254  *pByte = (byte_t)uVal;
255  return OK;
256  }
257 }
258 
259 /*!
260  * \brief Get write bytes from command-line arguments.
261  *
262  * \param argc Command-line argument count.
263  * \param argv Command-line arguments.
264  *
265  * \return Exits on error.
266  */
267 static void ArgsGet(int argc, char *argv[])
268 {
269  int i;
270  size_t max = sizeof(ArgWriteBuf);
271 
272  if( argc == 0 )
273  {
274  printf("%s Error: At least one byte must be specified\n", Argv0);
275  exit(EC_ERROR);
276  }
277  else if( argc > max )
278  {
279  fprintf(stderr,
280  "%s: Warning: %d: I2C write. Only %u bytes will be written.\n",
281  Argv0, argc, (uint_t)max);
282  }
283 
284  for(i=0; i<argc && i<max; ++i)
285  {
286  if( StrToByte(argv[i], ArgWriteBuf+i) != OK )
287  {
288  printf("%s Error: byte %d = '%s': bad byte value\n", Argv0, i, argv[i]);
289  exit(EC_ERROR);
290  }
291  }
292 
293  ArgWriteLen = i;
294 }
295 
296 /*!
297  * \brief Command initialization.
298  *
299  * \param argc Command-line argument count.
300  * \param argv Command-line arguments.
301  * \param pI2C Pointer to \h_i2c handle.
302  */
303 static void MainInit(int argc, char *argv[], i2c_t *pI2C)
304 {
305  // Name of this process
306  Argv0 = basename(argv[0]);
307 
308  // Get the environment
309  //EnvGet();
310 
311  // Parse input arguments
312  argv = OptsGet(Argv0, &PkgInfo, &I2CWritePgmInfo, I2CWriteOptsInfo, true,
313  &argc, argv);
314 
315  // Final option checks
316  if( OptI2CAddr < 0x00 )
317  {
318  fprintf(stderr, "%s: Address option required\n", Argv0);
319  exit(EC_BAD_OPT);
320  }
322  {
323  fprintf(stderr, "%s: Address out of range: 0x%x\n", Argv0, OptI2CAddr);
324  exit(EC_BAD_OPT);
325  }
326 
327  // Convert command-line arguments
328  ArgsGet(argc, argv);
329 
330  // Opened device specified
331  if( OptDevFd >= 0 )
332  {
333  pI2C->fd = OptDevFd;
334  pI2C->addr = (ushort_t)(-1);
335  }
336 
337  // I2C Bus device specified
338  else
339  {
340  if( OptDevName == NULL || OptDevName[0] == 0 )
341  {
342  OptDevName = "/dev/i2c/0";
343  }
344 
345  if( OptVerbose )
346  {
347  printf("I2C device: %s\n\n", OptDevName);
348  }
349 
350  if( i2c_open(pI2C, OptDevName) < 0 )
351  {
352  LOGSYSERROR("%s: Failed to open.", OptDevName);
353  exit(EC_ERROR);
354  }
355  }
356 }
357 
358 /*!
359  * \brief i2cwrite main()
360  *
361  * \param argc Count of command-line options and arguments.
362  * \param argv Array of command-line options and arguments.
363  *
364  * \return Exit value.
365  */
366 int main(int argc, char *argv[])
367 {
368  i2c_t i2c;
369  int rc;
370 
371  MainInit(argc, argv, &i2c);
372 
374 
375  return rc == ArgWriteLen? 0: (rc >= 0? 1: 2);
376 }
377 
378 /*!
379 \page i2cwrite I2CWRITE(1)
380 
381 \section NAME
382 i2cwrite - Write bytes to a device on a I<sup>2</sup>C Bus
383 
384 \section SYNOPSIS
385 i2cwrite [OPTIONS] byte1 [byte2 ...]
386 
387 \section DESCRIPTION
388 Write bytes to a device on the I<sup>2</sup>C Bus.
389 
390 \section OPTIONS RNR_OPTIONS
391 \verbatim
392  -a, --address=<addr> I2C device 7-bit address. REQUIRED.
393  -d, --device=<device> I2C device.
394  DEFAULT: /dev/i2c/0
395  --fd=<n> Opened I2C device file descriptor.
396  -v, --verbose Set print verbosity.
397  DEFAULT: false
398  RNR_OPTIONS Standard set of options provided by librnr.
399 \endverbatim
400 
401 \section DIAGNOSTICS
402 Exit status is 0 if the bytes are successfully written.
403 Exist status is >= 2 if error(s) are encountered.
404 
405 \section SEE_ALSO
406 \ref i2ccheck
407 \ref i2cread
408 \ref i2cscan
409 \ref i2ctrans
410 
411 \section AUTHOR
412 Robin Knight (robin.knight@roadnarrows.com)
413 
414 \section COPYRIGHT
415 (C) 2007. RoadNarrows LLC.
416 (http://www.roadnarrows.com)
417 \n All Rights Reserved
418 */
i2c_addr_t addr
address of the currently selected attached I2C device
Definition: i2c.h:82
static int StrToUnsigned(const char *s, uint_t *pVal)
Convert string to unsigned integer.
Definition: i2cwrite.c:205
int i2c_write(i2c_t *i2c, i2c_addr_t addr, const byte_t *buf, uint_t len)
Write to an I2C device.
Definition: i2ccom.c:159
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 void ArgsGet(int argc, char *argv[])
Get write bytes from command-line arguments.
Definition: i2cwrite.c:267
I2C Bus Handle Type.
Definition: i2c.h:79
static int OptI2CAddr
slave i2c device address
Definition: i2cwrite.c:78
#define I2C_ADDR_DEV_HIGH
last available device address
Definition: i2c-dev.h:103
static byte_t ArgWriteBuf[1024]
write buffer argument
Definition: i2cwrite.c:79
static int OptVerbose
verbose option
Definition: i2cwrite.c:75
static char * Argv0
command name
Definition: i2cwrite.c:70
I2C character device interface.
static void MainInit(int argc, char *argv[], i2c_t *pI2C)
Command initialization.
Definition: i2cwrite.c:303
static int ArgWriteLen
write byte count arguement
Definition: i2cwrite.c:80
static const PkgInfo_T PkgInfo
Definition: version.h:45
static OptsInfo_T I2CWriteOptsInfo[]
Command Line Options Information.
Definition: i2cwrite.c:103
static int StrToByte(const char *s, byte_t *pByte)
Convert string to byte.
Definition: i2cwrite.c:240
Package version information.
static int OptDevFd
opened i2c buse device fd option
Definition: i2cwrite.c:77
int i2c_open(i2c_t *i2c, const char *device)
Open the host I2C Bus device.
Definition: i2ccom.c:118
int main(int argc, char *argv[])
i2cwrite main()
Definition: i2cwrite.c:366
#define I2C_ADDR_DEV_LOW
first available device address
Definition: i2c-dev.h:101
static OptsPgmInfo_T I2CWritePgmInfo
Program Information.
Definition: i2cwrite.c:85
static char * OptDevName
i2c bus device option
Definition: i2cwrite.c:76
static int execWrite(i2c_t *pI2C, int addr, byte_t writebuf[], int writelen)
Execute I2C slave device write.
Definition: i2cwrite.c:166
Low-level I2C communication level.