i2c  1.4.2
RoadNarrows Robotics I2C Package
i2ccom.c
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Package: I2C
4 //
5 // Library: libi2c
6 //
7 // File: i2ccom.c
8 //
9 /*! \file
10  *
11  * $LastChangedDate: 2016-01-28 14:19:12 -0700 (Thu, 28 Jan 2016) $
12  * $Rev: 4278 $
13  *
14  * \brief Low-level I<sup>2</sup>C communication level implementation.
15  *
16  * This file has been modified from the original i2ccom.c source (see below).
17  *
18  * \todo Add ASCII line oriented input/output with cr-lf translation.
19  * i2c_readline(), i2c_writeline().
20  *
21  * \author Robin Knight (robin.knight@roadnarrows.com)
22  *
23  * \copyright
24  * \h_copy 2007-2017. RoadNarrows LLC.\n
25  * http://www.roadnarrows.com\n
26  * All Rights Reserved
27  *
28  * <hr>
29  * \par Original Source and Copyright:
30  * Copyright (C) 2004 K-TEAM SA
31  *
32  * \author Yves Piguet (Calerga Sarl)
33  * \author Pierre Bureau (K-Team SA)
34  * \author Cedric Gaudin (K-Team SA)
35  *
36  * \par Original Header:
37  * See "Original Source Header EULA" in source file.
38  *
39  * <hr>
40  */
41 /*
42  * @EulaBegin@
43  *
44  * Permission is hereby granted, without written agreement and without
45  * license or royalty fees, to use, copy, modify, and distribute this
46  * software and its documentation for any purpose, provided that
47  * (1) The above copyright notice and the following two paragraphs
48  * appear in all copies of the source code and (2) redistributions
49  * including binaries reproduces these notices in the supporting
50  * documentation. Substantial modifications to this software may be
51  * copyrighted by their authors and need not follow the licensing terms
52  * described here, provided that the new terms are clearly indicated in
53  * all files where they apply.
54  *
55  * IN NO EVENT SHALL THE AUTHOR, ROADNARROWS LLC, OR ANY MEMBERS/EMPLOYEES
56  * OF ROADNARROW LLC OR DISTRIBUTORS OF THIS SOFTWARE BE LIABLE TO ANY
57  * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
58  * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
59  * EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN ADVISED OF
60  * THE POSSIBILITY OF SUCH DAMAGE.
61  *
62  * THE AUTHOR AND ROADNARROWS LLC SPECIFICALLY DISCLAIM ANY WARRANTIES,
63  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
64  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
65  * "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO
66  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
67  *
68  * @EulaEnd@
69  */
70 ////////////////////////////////////////////////////////////////////////////////
71 
72 
73 #include <stdlib.h>
74 #include <unistd.h>
75 #include <fcntl.h>
76 #include <sys/types.h>
77 #include <sys/errno.h>
78 #include <sys/ioctl.h>
79 
80 #include "rnr/rnrconfig.h"
81 #include "rnr/i2c-dev.h"
82 #include "rnr/i2c.h"
83 
84 // ---------------------------------------------------------------------------
85 // Private Interface
86 // ---------------------------------------------------------------------------
87 
88 /*!
89  * \brief Selects the I<sup>2</sup>C device on a given I<sup>2</sup>C Bus.
90  *
91  * \param [in,out] i2c Pointer to I<sup>2</sup>C Bus handle.
92  * \param addr I<sup>2</sup>C device's 7/10-bit address.
93  *
94  * \return
95  * Returns 0 on success. Else errno is set appropriately and -1 is returned.
96  */
98 {
99  int rc;
100 
101  // change device address only if necessary
102  if( i2c->addr != addr )
103  {
104  if( (rc = ioctl(i2c->fd, I2C_SLAVE, addr)) < 0 )
105  {
106  return rc;
107  }
108  i2c->addr = addr;
109  }
110  return 0;
111 }
112 
113 
114 // ---------------------------------------------------------------------------
115 // Public Interface
116 // ---------------------------------------------------------------------------
117 
118 int i2c_open(i2c_t *i2c, char const *device)
119 {
120  // no device selected
121  i2c->addr = (ushort_t)I2C_ADDR_NONE;
122 
123  // set hte default I2C bus device
124  if( device == NULL )
125  {
126  device = "/dev/i2c/0";
127  }
128 
129  if( (i2c->fd = open(device, O_RDWR)) < 0)
130  {
131  return i2c->fd;
132  }
133 
134  return 0;
135 }
136 
138 {
139  if( i2c->fd >= 0 )
140  {
141  close(i2c->fd);
142  i2c->fd = -1;
143  i2c->addr = (ushort_t)I2C_ADDR_NONE;
144  }
145 }
146 
147 int i2c_read(i2c_t *i2c, i2c_addr_t addr, byte_t *buf, uint_t len)
148 {
149  int rc;
150 
151  if( (rc = i2c_select_device(i2c , addr)) != -1 )
152  {
153  rc = (int)read(i2c->fd, buf, (size_t)len);
154  }
155 
156  return rc;
157 }
158 
159 int i2c_write(i2c_t *i2c, i2c_addr_t addr, const byte_t *buf, uint_t len)
160 {
161  int rc;
162 
163  if( (rc = i2c_select_device(i2c , addr)) != -1 )
164  {
165  rc = (int)write(i2c->fd , buf, (size_t)len);
166  }
167 
168  return rc;
169 }
170 
172  const byte_t *write_buf , uint_t write_len,
173  byte_t *read_buf , uint_t read_len)
174 {
175  i2c_msg_t msgs[2];
176  i2c_rdwr_ioctl_data_t msgset;
177  int rc;
178 
179  // write message
180  msgs[0].addr = addr;
181  msgs[0].flags = I2C_M_NOFLAGS;
182  msgs[0].buf = (char *)write_buf;
183  msgs[0].len = (short)write_len;
184 
185  // read message
186  msgs[1].addr = addr;
187  msgs[1].flags = I2C_M_RD;
188  msgs[1].buf = (char *)read_buf;
189  msgs[1].len = (short)read_len;
190 
191  msgset.msgs = msgs;
192  msgset.nmsgs = 2;
193 
194  rc = ioctl(i2c->fd , I2C_RDWR, &msgset);
195 
196  return rc;
197 }
198 
200 {
201  i2c_msg_t msg;
202  i2c_rdwr_ioctl_data_t msgset;
203  int rc;
204 
205  msg.addr = addr;
206  msg.flags = I2C_M_NOFLAGS;
207  msg.buf = NULL;
208  msg.len = 0;
209 
210  msgset.msgs = &msg;
211  msgset.nmsgs = 1;
212 
213  rc = ioctl(i2c->fd, I2C_RDWR, &msgset);
214 
215  // answer from an I2C device
216  return rc == 1? 1: 0;
217 }
218 
220  int (*callback)(i2c_t *i2c, i2c_addr_t addr, void *context),
221  void * context)
222 {
223  i2c_addr_t addr;
224  int nFound = 0;
225  int rc;
226 
227  //
228  // Scan the whole I<sup>2</sup>C Bus range.
229  //
230  for(addr=I2C_ADDR_DEV_LOW; addr<=I2C_ADDR_DEV_HIGH; ++addr)
231  {
232  if( i2c_exists(i2c, addr) )
233  {
234  ++nFound;
235 
236  if( callback != NULL )
237  {
238  if( (rc = callback(i2c, addr, context)) < 0 )
239  {
240  return rc;
241  }
242  }
243  }
244  }
245 
246  return nFound;
247 }
i2c_addr_t addr
address of the currently selected attached I2C device
Definition: i2c.h:82
i2c_msg_t * msgs
pointers to i2c_msgs
Definition: i2c-dev.h:252
short len
message length (bytes)
Definition: i2c-dev.h:129
I2C python modules.
int fd
opened file descriptor of the I2C bus device
Definition: i2c.h:81
ushort_t addr
7/10-bit slave address 0xxx xxxx
Definition: i2c-dev.h:127
ushort_t i2c_addr_t
I2C Device Address Type.
Definition: i2c.h:72
static int i2c_select_device(i2c_t *i2c, i2c_addr_t addr)
Selects the I2C device on a given I2C Bus.
Definition: i2ccom.c:97
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
int nmsgs
number of i2c_msgs
Definition: i2c-dev.h:253
I2C Bus Handle Type.
Definition: i2c.h:79
I2C SMBus IOCTL Multi-Message Structure.
Definition: i2c-dev.h:250
int i2c_open(i2c_t *i2c, char const *device)
Open the host I2C Bus device.
Definition: i2ccom.c:118
#define I2C_ADDR_DEV_HIGH
last available device address
Definition: i2c-dev.h:103
#define I2C_ADDR_NONE
no I2C address selected
Definition: i2c.h:74
#define I2C_M_RD
read bit
Definition: i2c-dev.h:113
ushort_t flags
flags
Definition: i2c-dev.h:128
int i2c_scan(i2c_t *i2c, int(*callback)(i2c_t *i2c, i2c_addr_t addr, void *context), void *context)
Scans the given I2C Bus to find all connected devices.
Definition: i2ccom.c:219
char * buf
pointer to message data
Definition: i2c-dev.h:130
I2C character device interface.
void i2c_close(i2c_t *i2c)
Closes an I2C Bus.
Definition: i2ccom.c:137
#define I2C_RDWR
combined R/W transfer (one stop only)
Definition: i2c-dev.h:229
#define I2C_SLAVE
change 7/10-bit slave address
Definition: i2c-dev.h:224
#define I2C_M_NOFLAGS
no/clear flags
Definition: i2c-dev.h:111
int i2c_read(i2c_t *i2c, i2c_addr_t addr, byte_t *buf, uint_t len)
Read from an I2C device.
Definition: i2ccom.c:147
int i2c_exists(i2c_t *i2c, i2c_addr_t addr)
Test the existance of a device at the given address on the given I2C Bus.
Definition: i2ccom.c:199
#define I2C_ADDR_DEV_LOW
first available device address
Definition: i2c-dev.h:101
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 Message Stucture.
Definition: i2c-dev.h:125
Low-level I2C communication level.