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

Last change on this file was bcef89f2, checked in by Sebastian Huber <sebastian.huber@…>, on 05/19/23 at 06:18:25

Update company name

The embedded brains GmbH & Co. KG is the legal successor of embedded
brains GmbH.

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