source: rtems/cpukit/dev/i2c/i2c-dev.c @ 08135c85

Last change on this file since 08135c85 was 08135c85, checked in by Sebastian Huber <sebastian.huber@…>, on Jul 23, 2015 at 7:00:31 AM

i2c: Fix return status of i2c dev read/write

  • Property mode set to 100644
File size: 5.1 KB
Line 
1/**
2 * @file
3 *
4 * @brief Inter-Integrated Circuit (I2C) Bus Implementation
5 *
6 * @ingroup I2CDevice
7 */
8
9/*
10 * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
11 *
12 *  embedded brains GmbH
13 *  Dornierstr. 4
14 *  82178 Puchheim
15 *  Germany
16 *  <rtems@embedded-brains.de>
17 *
18 * The license and distribution terms for this file may be
19 * found in the file LICENSE in this distribution or at
20 * http://www.rtems.org/license/LICENSE.
21 */
22
23#if HAVE_CONFIG_H
24  #include "config.h"
25#endif
26
27#include <dev/i2c/i2c.h>
28
29#include <rtems/imfs.h>
30#include <rtems/score/assert.h>
31
32#include <fcntl.h>
33#include <stdlib.h>
34#include <unistd.h>
35
36static ssize_t i2c_dev_read(
37  rtems_libio_t *iop,
38  void *buffer,
39  size_t count
40)
41{
42  i2c_dev *dev = IMFS_generic_get_context_by_iop(iop);
43  ssize_t n;
44
45  n = (*dev->read)(dev, buffer, count, iop->offset);
46  if (n >= 0) {
47    iop->offset += n;
48
49    return n;
50  } else {
51    rtems_set_errno_and_return_minus_one(-n);
52  }
53}
54
55static ssize_t i2c_dev_write(
56  rtems_libio_t *iop,
57  const void *buffer,
58  size_t count
59)
60{
61  i2c_dev *dev = IMFS_generic_get_context_by_iop(iop);
62  ssize_t n;
63
64  n = (*dev->write)(dev, buffer, count, iop->offset);
65  if (n >= 0) {
66    iop->offset += n;
67
68    return n;
69  } else {
70    rtems_set_errno_and_return_minus_one(-n);
71  }
72}
73
74static int i2c_dev_ioctl(
75  rtems_libio_t *iop,
76  ioctl_command_t command,
77  void *arg
78)
79{
80  i2c_dev *dev = IMFS_generic_get_context_by_iop(iop);
81  int err;
82
83  err = (*dev->ioctl)(dev, command, arg);
84
85  if (err == 0) {
86    return 0;
87  } else {
88    rtems_set_errno_and_return_minus_one(-err);
89  }
90}
91
92static int i2c_dev_fstat(
93  const rtems_filesystem_location_info_t *loc,
94  struct stat *buf
95)
96{
97  i2c_dev *dev = IMFS_generic_get_context_by_location(loc);
98
99  buf->st_size = (*dev->get_size)(dev);
100  buf->st_blksize = (*dev->get_block_size)(dev);
101
102  return IMFS_stat(loc, buf);
103}
104
105static const rtems_filesystem_file_handlers_r i2c_dev_handler = {
106  .open_h = rtems_filesystem_default_open,
107  .close_h = rtems_filesystem_default_close,
108  .read_h = i2c_dev_read,
109  .write_h = i2c_dev_write,
110  .ioctl_h = i2c_dev_ioctl,
111  .lseek_h = rtems_filesystem_default_lseek_file,
112  .fstat_h = i2c_dev_fstat,
113  .ftruncate_h = rtems_filesystem_default_ftruncate,
114  .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
115  .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
116  .fcntl_h = rtems_filesystem_default_fcntl,
117  .kqfilter_h = rtems_filesystem_default_kqfilter,
118  .poll_h = rtems_filesystem_default_poll,
119  .readv_h = rtems_filesystem_default_readv,
120  .writev_h = rtems_filesystem_default_writev
121};
122
123static void i2c_dev_node_destroy(IMFS_jnode_t *node)
124{
125  i2c_dev *dev;
126
127  dev = IMFS_generic_get_context_by_node(node);
128  (*dev->destroy)(dev);
129
130  IMFS_node_destroy_default(node);
131}
132
133static const IMFS_node_control i2c_dev_node_control = IMFS_GENERIC_INITIALIZER(
134  &i2c_dev_handler,
135  IMFS_node_initialize_generic,
136  i2c_dev_node_destroy
137);
138
139int i2c_dev_register(
140  i2c_dev *dev,
141  const char *dev_path
142)
143{
144  int rv;
145
146  rv = IMFS_make_generic_node(
147    dev_path,
148    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
149    &i2c_dev_node_control,
150    dev
151  );
152  if (rv != 0) {
153    (*dev->destroy)(dev);
154  }
155
156  return rv;
157}
158
159static ssize_t i2c_dev_read_default(
160  i2c_dev *dev,
161  void *buf,
162  size_t n,
163  off_t offset
164)
165{
166  (void) dev;
167  (void) buf;
168  (void) n;
169  (void) offset;
170
171  return -EIO;
172}
173
174static ssize_t i2c_dev_write_default(
175  i2c_dev *dev,
176  const void *buf,
177  size_t n,
178  off_t offset
179)
180{
181  (void) dev;
182  (void) buf;
183  (void) n;
184  (void) offset;
185
186  return -EIO;
187}
188
189static int i2c_dev_ioctl_default(
190  i2c_dev *dev,
191  ioctl_command_t command,
192  void *arg
193)
194{
195  (void) dev;
196  (void) command;
197  (void) arg;
198
199  return -ENOTTY;
200}
201
202static off_t i2c_dev_get_size_default(i2c_dev *dev)
203{
204  (void) dev;
205
206  return 0;
207}
208
209static blksize_t i2c_dev_get_block_size_default(i2c_dev *dev)
210{
211  (void) dev;
212
213  return 1;
214}
215
216static int i2c_dev_do_init(
217  i2c_dev *dev,
218  const char *bus_path,
219  uint16_t address,
220  void (*destroy)(i2c_dev *dev)
221)
222{
223  int rv;
224
225  dev->bus_fd = open(bus_path, O_RDWR);
226  if (dev->bus_fd < 0) {
227    (*destroy)(dev);
228
229    return -1;
230  }
231
232  rv = ioctl(dev->bus_fd, I2C_BUS_GET_CONTROL, &dev->bus);
233  if (rv != 0) {
234    (*destroy)(dev);
235
236    return -1;
237  }
238
239  dev->read = i2c_dev_read_default;
240  dev->write = i2c_dev_write_default;
241  dev->ioctl = i2c_dev_ioctl_default;
242  dev->get_size = i2c_dev_get_size_default;
243  dev->get_block_size = i2c_dev_get_block_size_default;
244  dev->destroy = destroy;
245  dev->address = address;
246
247  return 0;
248}
249
250void i2c_dev_destroy(i2c_dev *dev)
251{
252  int rv;
253
254  rv = close(dev->bus_fd);
255  _Assert(dev->bus_fd < 0 || rv == 0);
256  (void) rv;
257}
258
259void i2c_dev_destroy_and_free(i2c_dev *dev)
260{
261  i2c_dev_destroy(dev);
262  free(dev);
263}
264
265int i2c_dev_init(i2c_dev *dev, const char *bus_path, uint16_t address)
266{
267  return i2c_dev_do_init(dev, bus_path, address, i2c_dev_destroy);
268}
269
270i2c_dev *i2c_dev_alloc_and_init(
271  size_t size,
272  const char *bus_path,
273  uint16_t address
274)
275{
276  i2c_dev *dev = NULL;
277
278  if (size >= sizeof(*dev)) {
279    dev = calloc(1, size);
280    if (dev != NULL) {
281      int rv;
282
283      rv = i2c_dev_do_init(dev, bus_path, address, i2c_dev_destroy_and_free);
284      if (rv != 0) {
285        return NULL;
286      }
287    }
288  }
289
290  return dev;
291}
Note: See TracBrowser for help on using the repository browser.