File indexing completed on 2025-05-11 08:24:11
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #ifdef HAVE_CONFIG_H
0018 #include "config.h"
0019 #endif
0020
0021 #include <dev/i2c/i2c.h>
0022
0023 #include <rtems/imfs.h>
0024 #include <rtems/score/assert.h>
0025
0026 #include <fcntl.h>
0027 #include <stdlib.h>
0028 #include <unistd.h>
0029
0030 static ssize_t i2c_dev_read(
0031 rtems_libio_t *iop,
0032 void *buffer,
0033 size_t count
0034 )
0035 {
0036 i2c_dev *dev = IMFS_generic_get_context_by_iop(iop);
0037 ssize_t n;
0038
0039 n = (*dev->read)(dev, buffer, count, iop->offset);
0040 if (n >= 0) {
0041 iop->offset += n;
0042
0043 return n;
0044 } else {
0045 rtems_set_errno_and_return_minus_one(-n);
0046 }
0047 }
0048
0049 static ssize_t i2c_dev_write(
0050 rtems_libio_t *iop,
0051 const void *buffer,
0052 size_t count
0053 )
0054 {
0055 i2c_dev *dev = IMFS_generic_get_context_by_iop(iop);
0056 ssize_t n;
0057
0058 n = (*dev->write)(dev, buffer, count, iop->offset);
0059 if (n >= 0) {
0060 iop->offset += n;
0061
0062 return n;
0063 } else {
0064 rtems_set_errno_and_return_minus_one(-n);
0065 }
0066 }
0067
0068 static int i2c_dev_ioctl(
0069 rtems_libio_t *iop,
0070 ioctl_command_t command,
0071 void *arg
0072 )
0073 {
0074 i2c_dev *dev = IMFS_generic_get_context_by_iop(iop);
0075 int err;
0076
0077 err = (*dev->ioctl)(dev, command, arg);
0078
0079 if (err == 0) {
0080 return 0;
0081 } else {
0082 rtems_set_errno_and_return_minus_one(-err);
0083 }
0084 }
0085
0086 static int i2c_dev_fstat(
0087 const rtems_filesystem_location_info_t *loc,
0088 struct stat *buf
0089 )
0090 {
0091 i2c_dev *dev = IMFS_generic_get_context_by_location(loc);
0092
0093 buf->st_size = (*dev->get_size)(dev);
0094 buf->st_blksize = (*dev->get_block_size)(dev);
0095
0096 return IMFS_stat(loc, buf);
0097 }
0098
0099 static const rtems_filesystem_file_handlers_r i2c_dev_handler = {
0100 .open_h = rtems_filesystem_default_open,
0101 .close_h = rtems_filesystem_default_close,
0102 .read_h = i2c_dev_read,
0103 .write_h = i2c_dev_write,
0104 .ioctl_h = i2c_dev_ioctl,
0105 .lseek_h = rtems_filesystem_default_lseek_file,
0106 .fstat_h = i2c_dev_fstat,
0107 .ftruncate_h = rtems_filesystem_default_ftruncate,
0108 .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
0109 .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
0110 .fcntl_h = rtems_filesystem_default_fcntl,
0111 .kqfilter_h = rtems_filesystem_default_kqfilter,
0112 .mmap_h = rtems_filesystem_default_mmap,
0113 .poll_h = rtems_filesystem_default_poll,
0114 .readv_h = rtems_filesystem_default_readv,
0115 .writev_h = rtems_filesystem_default_writev
0116 };
0117
0118 static void i2c_dev_node_destroy(IMFS_jnode_t *node)
0119 {
0120 i2c_dev *dev;
0121
0122 dev = IMFS_generic_get_context_by_node(node);
0123 (*dev->destroy)(dev);
0124
0125 IMFS_node_destroy_default(node);
0126 }
0127
0128 static const IMFS_node_control i2c_dev_node_control = IMFS_GENERIC_INITIALIZER(
0129 &i2c_dev_handler,
0130 IMFS_node_initialize_generic,
0131 i2c_dev_node_destroy
0132 );
0133
0134 int i2c_dev_register(
0135 i2c_dev *dev,
0136 const char *dev_path
0137 )
0138 {
0139 int rv;
0140
0141 rv = IMFS_make_generic_node(
0142 dev_path,
0143 S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
0144 &i2c_dev_node_control,
0145 dev
0146 );
0147 if (rv != 0) {
0148 (*dev->destroy)(dev);
0149 }
0150
0151 return rv;
0152 }
0153
0154 static ssize_t i2c_dev_read_default(
0155 i2c_dev *dev,
0156 void *buf,
0157 size_t n,
0158 off_t offset
0159 )
0160 {
0161 (void) dev;
0162 (void) buf;
0163 (void) n;
0164 (void) offset;
0165
0166 return -EIO;
0167 }
0168
0169 static ssize_t i2c_dev_write_default(
0170 i2c_dev *dev,
0171 const void *buf,
0172 size_t n,
0173 off_t offset
0174 )
0175 {
0176 (void) dev;
0177 (void) buf;
0178 (void) n;
0179 (void) offset;
0180
0181 return -EIO;
0182 }
0183
0184 static int i2c_dev_ioctl_default(
0185 i2c_dev *dev,
0186 ioctl_command_t command,
0187 void *arg
0188 )
0189 {
0190 (void) dev;
0191 (void) command;
0192 (void) arg;
0193
0194 return -ENOTTY;
0195 }
0196
0197 static off_t i2c_dev_get_size_default(i2c_dev *dev)
0198 {
0199 (void) dev;
0200
0201 return 0;
0202 }
0203
0204 static blksize_t i2c_dev_get_block_size_default(i2c_dev *dev)
0205 {
0206 (void) dev;
0207
0208 return 1;
0209 }
0210
0211 static int i2c_dev_do_init(
0212 i2c_dev *dev,
0213 const char *bus_path,
0214 uint16_t address,
0215 void (*destroy)(i2c_dev *dev)
0216 )
0217 {
0218 int rv;
0219
0220 dev->bus_fd = open(bus_path, O_RDWR);
0221 if (dev->bus_fd < 0) {
0222 (*destroy)(dev);
0223
0224 return -1;
0225 }
0226
0227 rv = ioctl(dev->bus_fd, I2C_BUS_GET_CONTROL, &dev->bus);
0228 if (rv != 0) {
0229 (*destroy)(dev);
0230
0231 return -1;
0232 }
0233
0234 dev->read = i2c_dev_read_default;
0235 dev->write = i2c_dev_write_default;
0236 dev->ioctl = i2c_dev_ioctl_default;
0237 dev->get_size = i2c_dev_get_size_default;
0238 dev->get_block_size = i2c_dev_get_block_size_default;
0239 dev->destroy = destroy;
0240 dev->address = address;
0241
0242 return 0;
0243 }
0244
0245 void i2c_dev_destroy(i2c_dev *dev)
0246 {
0247 int rv;
0248
0249 rv = close(dev->bus_fd);
0250 _Assert(dev->bus_fd < 0 || rv == 0);
0251 (void) rv;
0252 }
0253
0254 void i2c_dev_destroy_and_free(i2c_dev *dev)
0255 {
0256 i2c_dev_destroy(dev);
0257 free(dev);
0258 }
0259
0260 int i2c_dev_init(i2c_dev *dev, const char *bus_path, uint16_t address)
0261 {
0262 return i2c_dev_do_init(dev, bus_path, address, i2c_dev_destroy);
0263 }
0264
0265 i2c_dev *i2c_dev_alloc_and_init(
0266 size_t size,
0267 const char *bus_path,
0268 uint16_t address
0269 )
0270 {
0271 i2c_dev *dev = NULL;
0272
0273 if (size >= sizeof(*dev)) {
0274 dev = calloc(1, size);
0275 if (dev != NULL) {
0276 int rv;
0277
0278 rv = i2c_dev_do_init(dev, bus_path, address, i2c_dev_destroy_and_free);
0279 if (rv != 0) {
0280 return NULL;
0281 }
0282 }
0283 }
0284
0285 return dev;
0286 }