source: rtems/cpukit/dev/i2c/i2c-dev.c @ cf36b70

4.11
Last change on this file since cf36b70 was cf36b70, checked in by Sebastian Huber <sebastian.huber@…>, on Dec 31, 2014 at 9:56:05 AM

IMFS: Replace node union with individual struct

This reduces the average node size.

Add and use IMFS_GENERIC_INITIALIZER().

  • Property mode set to 100644
File size: 5.0 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
50  return n;
51}
52
53static ssize_t i2c_dev_write(
54  rtems_libio_t *iop,
55  const void *buffer,
56  size_t count
57)
58{
59  i2c_dev *dev = IMFS_generic_get_context_by_iop(iop);
60  ssize_t n;
61
62  n = (*dev->write)(dev, buffer, count, iop->offset);
63  if (n > 0) {
64    iop->offset += n;
65  }
66
67  return n;
68}
69
70static int i2c_dev_ioctl(
71  rtems_libio_t *iop,
72  ioctl_command_t command,
73  void *arg
74)
75{
76  i2c_dev *dev = IMFS_generic_get_context_by_iop(iop);
77  int err;
78
79  err = (*dev->ioctl)(dev, command, arg);
80
81  if (err == 0) {
82    return 0;
83  } else {
84    rtems_set_errno_and_return_minus_one(-err);
85  }
86}
87
88static int i2c_dev_fstat(
89  const rtems_filesystem_location_info_t *loc,
90  struct stat *buf
91)
92{
93  i2c_dev *dev = IMFS_generic_get_context_by_location(loc);
94
95  buf->st_size = (*dev->get_size)(dev);
96  buf->st_blksize = (*dev->get_block_size)(dev);
97
98  return IMFS_stat(loc, buf);
99}
100
101static const rtems_filesystem_file_handlers_r i2c_dev_handler = {
102  .open_h = rtems_filesystem_default_open,
103  .close_h = rtems_filesystem_default_close,
104  .read_h = i2c_dev_read,
105  .write_h = i2c_dev_write,
106  .ioctl_h = i2c_dev_ioctl,
107  .lseek_h = rtems_filesystem_default_lseek_file,
108  .fstat_h = i2c_dev_fstat,
109  .ftruncate_h = rtems_filesystem_default_ftruncate,
110  .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
111  .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
112  .fcntl_h = rtems_filesystem_default_fcntl,
113  .kqfilter_h = rtems_filesystem_default_kqfilter,
114  .poll_h = rtems_filesystem_default_poll,
115  .readv_h = rtems_filesystem_default_readv,
116  .writev_h = rtems_filesystem_default_writev
117};
118
119static void i2c_dev_node_destroy(IMFS_jnode_t *node)
120{
121  i2c_dev *dev;
122
123  dev = IMFS_generic_get_context_by_node(node);
124  (*dev->destroy)(dev);
125
126  IMFS_node_destroy_default(node);
127}
128
129static const IMFS_node_control i2c_dev_node_control = IMFS_GENERIC_INITIALIZER(
130  &i2c_dev_handler,
131  IMFS_node_initialize_generic,
132  i2c_dev_node_destroy
133);
134
135int i2c_dev_register(
136  i2c_dev *dev,
137  const char *dev_path
138)
139{
140  int rv;
141
142  rv = IMFS_make_generic_node(
143    dev_path,
144    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
145    &i2c_dev_node_control,
146    dev
147  );
148  if (rv != 0) {
149    (*dev->destroy)(dev);
150  }
151
152  return rv;
153}
154
155static ssize_t i2c_dev_read_default(
156  i2c_dev *dev,
157  void *buf,
158  size_t n,
159  off_t offset
160)
161{
162  (void) dev;
163  (void) buf;
164  (void) n;
165  (void) offset;
166
167  return -EIO;
168}
169
170static ssize_t i2c_dev_write_default(
171  i2c_dev *dev,
172  const void *buf,
173  size_t n,
174  off_t offset
175)
176{
177  (void) dev;
178  (void) buf;
179  (void) n;
180  (void) offset;
181
182  return -EIO;
183}
184
185static int i2c_dev_ioctl_default(
186  i2c_dev *dev,
187  ioctl_command_t command,
188  void *arg
189)
190{
191  (void) dev;
192  (void) command;
193  (void) arg;
194
195  return -ENOTTY;
196}
197
198static off_t i2c_dev_get_size_default(i2c_dev *dev)
199{
200  (void) dev;
201
202  return 0;
203}
204
205static blksize_t i2c_dev_get_block_size_default(i2c_dev *dev)
206{
207  (void) dev;
208
209  return 1;
210}
211
212static int i2c_dev_do_init(
213  i2c_dev *dev,
214  const char *bus_path,
215  uint16_t address,
216  void (*destroy)(i2c_dev *dev)
217)
218{
219  int rv;
220
221  dev->bus_fd = open(bus_path, O_RDWR);
222  if (dev->bus_fd < 0) {
223    (*destroy)(dev);
224
225    return -1;
226  }
227
228  rv = ioctl(dev->bus_fd, I2C_BUS_GET_CONTROL, &dev->bus);
229  if (rv != 0) {
230    (*destroy)(dev);
231
232    return -1;
233  }
234
235  dev->read = i2c_dev_read_default;
236  dev->write = i2c_dev_write_default;
237  dev->ioctl = i2c_dev_ioctl_default;
238  dev->get_size = i2c_dev_get_size_default;
239  dev->get_block_size = i2c_dev_get_block_size_default;
240  dev->destroy = destroy;
241  dev->address = address;
242
243  return 0;
244}
245
246void i2c_dev_destroy(i2c_dev *dev)
247{
248  int rv;
249
250  rv = close(dev->bus_fd);
251  _Assert(dev->bus_fd < 0 || rv == 0);
252  (void) rv;
253}
254
255void i2c_dev_destroy_and_free(i2c_dev *dev)
256{
257  i2c_dev_destroy(dev);
258  free(dev);
259}
260
261int i2c_dev_init(i2c_dev *dev, const char *bus_path, uint16_t address)
262{
263  return i2c_dev_do_init(dev, bus_path, address, i2c_dev_destroy);
264}
265
266i2c_dev *i2c_dev_alloc_and_init(
267  size_t size,
268  const char *bus_path,
269  uint16_t address
270)
271{
272  i2c_dev *dev = NULL;
273
274  if (size >= sizeof(*dev)) {
275    dev = calloc(1, size);
276    if (dev != NULL) {
277      int rv;
278
279      rv = i2c_dev_do_init(dev, bus_path, address, i2c_dev_destroy_and_free);
280      if (rv != 0) {
281        return NULL;
282      }
283    }
284  }
285
286  return dev;
287}
Note: See TracBrowser for help on using the repository browser.