Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:19

0001 /*
0002  * SPDX-License-Identifier: BSD-2-Clause
0003  *
0004  * Copyright (C) 2020 embedded brains GmbH & Co. KG
0005  *
0006  * Redistribution and use in source and binary forms, with or without
0007  * modification, are permitted provided that the following conditions
0008  * are met:
0009  * 1. Redistributions of source code must retain the above copyright
0010  *    notice, this list of conditions and the following disclaimer.
0011  * 2. Redistributions in binary form must reproduce the above copyright
0012  *    notice, this list of conditions and the following disclaimer in the
0013  *    documentation and/or other materials provided with the distribution.
0014  *
0015  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0016  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0018  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0019  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0020  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0021  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0024  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0025  * POSSIBILITY OF SUCH DAMAGE.
0026  */
0027 
0028 /*
0029  * The command implemented here has a similar interface like the one from Linux
0030  * i2c tools. Think of it as a heavily simplified version of them. Instead of
0031  * the bus number they expect a bus path.
0032  *
0033  * Additionally the i2cget has a continuous read mode that isn't available on
0034  * Linux but does something similar to i2cdump.
0035  */
0036 
0037 #include <dev/i2c/i2c.h>
0038 #include <fcntl.h>
0039 #include <stdio.h>
0040 #include <stdlib.h>
0041 
0042 #include <rtems/shell.h>
0043 
0044 static const char rtems_i2cget_shell_usage [] =
0045   "i2cget <I2C_BUS> <CHIP-ADDRESS> <DATA-ADDRESS> [<NR-BYTES>]\n"
0046   "\tGet one or more bytes from an EEPROM like i2c device.\n"
0047   "\tNote that multiple bytes will be read in continuous mode.\n";
0048 
0049 static int read_bytes(
0050   int fd,
0051   uint16_t i2c_address,
0052   uint8_t data_address,
0053   uint16_t nr_bytes
0054 )
0055 {
0056   int rv;
0057   uint8_t value[nr_bytes];
0058   i2c_msg msgs[] = {{
0059     .addr = i2c_address,
0060     .flags = 0,
0061     .buf = &data_address,
0062     .len = 1,
0063   }, {
0064     .addr = i2c_address,
0065     .flags = I2C_M_RD,
0066     .buf = value,
0067     .len = nr_bytes,
0068   }};
0069   struct i2c_rdwr_ioctl_data payload = {
0070     .msgs = msgs,
0071     .nmsgs = sizeof(msgs)/sizeof(msgs[0]),
0072   };
0073   uint16_t i;
0074 
0075   rv = ioctl(fd, I2C_RDWR, &payload);
0076   if (rv < 0) {
0077     perror("ioctl failed");
0078   } else {
0079     for (i = 0; i < nr_bytes; ++i) {
0080       printf("0x%02x ", value[i]);
0081     }
0082     printf("\n");
0083   }
0084 
0085   return rv;
0086 }
0087 
0088 static int rtems_i2cget_shell_main(int argc, char *argv[])
0089 {
0090   int fd;
0091   int rv;
0092   const char *bus;
0093   uint16_t chip_address;
0094   uint8_t data_address;
0095   uint16_t nr_bytes;
0096 
0097   if (argc < 4 || argc > 5) {
0098     printf(rtems_i2cget_shell_usage);
0099     return 1;
0100   }
0101 
0102   errno = 0;
0103   chip_address = (uint16_t) strtoul(argv[2], NULL, 0);
0104   if (errno != 0) {
0105     perror("Couldn't read chip address");
0106     return 1;
0107   }
0108 
0109   errno = 0;
0110   data_address = (uint8_t) strtoul(argv[3], NULL, 0);
0111   if (errno != 0) {
0112     perror("Couldn't read data address");
0113     return 1;
0114   }
0115 
0116   nr_bytes = 1;
0117   if (argc == 5) {
0118     errno = 0;
0119     nr_bytes = (uint16_t) strtoul(argv[4], NULL, 0);
0120     if (errno != 0) {
0121       perror("Couldn't read number of bytes");
0122       return 1;
0123     }
0124   }
0125 
0126   bus = argv[1];
0127   fd = open(bus, O_RDWR);
0128   if (fd < 0) {
0129     perror("Couldn't open bus");
0130     return 1;
0131   }
0132 
0133   rv = read_bytes(fd, chip_address, data_address, nr_bytes);
0134 
0135   close(fd);
0136 
0137   return rv;
0138 }
0139 
0140 rtems_shell_cmd_t rtems_shell_I2CGET_Command = {
0141   .name = "i2cget",
0142   .usage = rtems_i2cget_shell_usage,
0143   .topic = "misc",
0144   .command = rtems_i2cget_shell_main,
0145 };