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

Last change on this file since c6bb1c33 was c6bb1c33, checked in by Kevin Kirspel <kevin-kirspel@…>, on Jun 29, 2017 at 2:36:43 PM

posix/mmap: Add support for file handler and MAP_ANON

Added a mmap file handler to struct _rtems_filesystem_file_handlers_r.
Updated each file handler object to support the default mmap handler.
Updated mmap() to call the mmap handler for MAP_SHARED.
Added a mmap file handler for shm

Added support for MAP_ANON in mmap().

Updates #2859

  • Property mode set to 100644
File size: 5.2 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  .mmap_h = rtems_filesystem_default_mmap,
119  .poll_h = rtems_filesystem_default_poll,
120  .readv_h = rtems_filesystem_default_readv,
121  .writev_h = rtems_filesystem_default_writev
122};
123
124static void i2c_dev_node_destroy(IMFS_jnode_t *node)
125{
126  i2c_dev *dev;
127
128  dev = IMFS_generic_get_context_by_node(node);
129  (*dev->destroy)(dev);
130
131  IMFS_node_destroy_default(node);
132}
133
134static const IMFS_node_control i2c_dev_node_control = IMFS_GENERIC_INITIALIZER(
135  &i2c_dev_handler,
136  IMFS_node_initialize_generic,
137  i2c_dev_node_destroy
138);
139
140int i2c_dev_register(
141  i2c_dev *dev,
142  const char *dev_path
143)
144{
145  int rv;
146
147  rv = IMFS_make_generic_node(
148    dev_path,
149    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
150    &i2c_dev_node_control,
151    dev
152  );
153  if (rv != 0) {
154    (*dev->destroy)(dev);
155  }
156
157  return rv;
158}
159
160static ssize_t i2c_dev_read_default(
161  i2c_dev *dev,
162  void *buf,
163  size_t n,
164  off_t offset
165)
166{
167  (void) dev;
168  (void) buf;
169  (void) n;
170  (void) offset;
171
172  return -EIO;
173}
174
175static ssize_t i2c_dev_write_default(
176  i2c_dev *dev,
177  const void *buf,
178  size_t n,
179  off_t offset
180)
181{
182  (void) dev;
183  (void) buf;
184  (void) n;
185  (void) offset;
186
187  return -EIO;
188}
189
190static int i2c_dev_ioctl_default(
191  i2c_dev *dev,
192  ioctl_command_t command,
193  void *arg
194)
195{
196  (void) dev;
197  (void) command;
198  (void) arg;
199
200  return -ENOTTY;
201}
202
203static off_t i2c_dev_get_size_default(i2c_dev *dev)
204{
205  (void) dev;
206
207  return 0;
208}
209
210static blksize_t i2c_dev_get_block_size_default(i2c_dev *dev)
211{
212  (void) dev;
213
214  return 1;
215}
216
217static int i2c_dev_do_init(
218  i2c_dev *dev,
219  const char *bus_path,
220  uint16_t address,
221  void (*destroy)(i2c_dev *dev)
222)
223{
224  int rv;
225
226  dev->bus_fd = open(bus_path, O_RDWR);
227  if (dev->bus_fd < 0) {
228    (*destroy)(dev);
229
230    return -1;
231  }
232
233  rv = ioctl(dev->bus_fd, I2C_BUS_GET_CONTROL, &dev->bus);
234  if (rv != 0) {
235    (*destroy)(dev);
236
237    return -1;
238  }
239
240  dev->read = i2c_dev_read_default;
241  dev->write = i2c_dev_write_default;
242  dev->ioctl = i2c_dev_ioctl_default;
243  dev->get_size = i2c_dev_get_size_default;
244  dev->get_block_size = i2c_dev_get_block_size_default;
245  dev->destroy = destroy;
246  dev->address = address;
247
248  return 0;
249}
250
251void i2c_dev_destroy(i2c_dev *dev)
252{
253  int rv;
254
255  rv = close(dev->bus_fd);
256  _Assert(dev->bus_fd < 0 || rv == 0);
257  (void) rv;
258}
259
260void i2c_dev_destroy_and_free(i2c_dev *dev)
261{
262  i2c_dev_destroy(dev);
263  free(dev);
264}
265
266int i2c_dev_init(i2c_dev *dev, const char *bus_path, uint16_t address)
267{
268  return i2c_dev_do_init(dev, bus_path, address, i2c_dev_destroy);
269}
270
271i2c_dev *i2c_dev_alloc_and_init(
272  size_t size,
273  const char *bus_path,
274  uint16_t address
275)
276{
277  i2c_dev *dev = NULL;
278
279  if (size >= sizeof(*dev)) {
280    dev = calloc(1, size);
281    if (dev != NULL) {
282      int rv;
283
284      rv = i2c_dev_do_init(dev, bus_path, address, i2c_dev_destroy_and_free);
285      if (rv != 0) {
286        return NULL;
287      }
288    }
289  }
290
291  return dev;
292}
Note: See TracBrowser for help on using the repository browser.