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

4.115
Last change on this file since a0bf44e was a0bf44e, checked in by Joel Sherrill <joel.sherrill@…>, on 11/24/14 at 20:06:49

cpukit/dev/i2c/i2c-dev.c: Fix leak on error path

Coverity ID 1255520. fd was not closed on error path.

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