Add new APIS for I2C smbus transaction 52/132052/5
authorHyeongsik Min <hyeongsik.min@samsung.com>
Thu, 1 Jun 2017 02:03:25 +0000 (11:03 +0900)
committerHyeongsik Min <hyeongsik.min@samsung.com>
Thu, 1 Jun 2017 05:34:57 +0000 (14:34 +0900)
This patch support below peripheral-io APIs.
- peripheral_i2c_read_register_byte()
- peripheral_i2c_write_register_byte()
- peripheral_i2c_read_register_word()
- peripheral_i2c_write_register_word()

Below APIs already existed, but they are changed to use SMBUS ioctl in
this patch.
- peripheral_i2c_read_byte()
- peripheral_i2c_write_byte()

Change-Id: Ie22dd237fce9b731c7ecbbd904ec0f5219b005e1
Signed-off-by: Hyeongsik Min <hyeongsik.min@samsung.com>
src/daemon/peripheral_bus.c
src/daemon/peripheral_bus_i2c.c
src/daemon/peripheral_bus_i2c.h
src/daemon/peripheral_io.xml
src/interface/i2c.c
src/interface/include/i2c.h

index 08c4d0e..f064392 100644 (file)
@@ -416,6 +416,41 @@ out:
        return true;
 }
 
+gboolean handle_i2c_smbus_ioctl(
+               PeripheralIoGdbusI2c *i2c,
+               GDBusMethodInvocation *invocation,
+               gint handle,
+               guchar read_write,
+               guchar command,
+               guint size,
+               guint16 data_in,
+               gpointer user_data)
+{
+       peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
+       pb_i2c_data_h i2c_handle = GUINT_TO_POINTER(handle);
+       const gchar *id;
+       uint16_t data;
+
+       /* Handle validation */
+       if (!i2c_handle || !i2c_handle->client_info.id) {
+               _E("i2c handle is not valid");
+               ret = PERIPHERAL_ERROR_UNKNOWN;
+               goto out;
+       }
+       id = g_dbus_method_invocation_get_sender(invocation);
+       if (strcmp(i2c_handle->client_info.id, id)) {
+               _E("Invalid access, handle id : %s, current id : %s", i2c_handle->client_info.id, id);
+               ret = PERIPHERAL_ERROR_INVALID_OPERATION;
+               goto out;
+       }
+
+       ret = peripheral_bus_i2c_smbus_ioctl(i2c_handle, read_write, command, size, data_in, &data);
+out:
+       peripheral_io_gdbus_i2c_complete_smbus_ioctl(i2c, invocation, data, ret);
+
+       return true;
+}
+
 gboolean handle_pwm_open(
                PeripheralIoGdbusPwm *pwm,
                GDBusMethodInvocation *invocation,
@@ -1484,6 +1519,10 @@ static gboolean __i2c_init(peripheral_bus_s *pb_data)
                        "handle-write",
                        G_CALLBACK(handle_i2c_write),
                        pb_data);
+       g_signal_connect(pb_data->i2c_skeleton,
+                       "handle-smbus-ioctl",
+                       G_CALLBACK(handle_i2c_smbus_ioctl),
+                       pb_data);
 
        manager = g_dbus_object_manager_server_new(PERIPHERAL_GDBUS_I2C_PATH);
 
index 81a01de..57bb90c 100644 (file)
@@ -203,3 +203,43 @@ int peripheral_bus_i2c_write(pb_i2c_data_h i2c, int length, GVariant *data_array
 
        return i2c_write(i2c->fd, i2c->buffer, length);
 }
+
+int peripheral_bus_i2c_smbus_ioctl(pb_i2c_data_h i2c, uint8_t read_write, uint8_t command, uint32_t size, uint16_t data_in, uint16_t *data_out)
+{
+       struct i2c_smbus_ioctl_data data_arg;
+       union i2c_smbus_data data;
+       int ret;
+
+       memset(&data_arg, 0x0, sizeof(struct i2c_smbus_ioctl_data));
+       memset(&data, 0x0, sizeof(data.block));
+
+       data_arg.read_write = read_write;
+       data_arg.size = size;
+       data_arg.data = &data;
+
+       RETV_IF(size < I2C_SMBUS_BYTE || size > I2C_SMBUS_WORD_DATA, PERIPHERAL_ERROR_INVALID_PARAMETER);
+       RETV_IF(read_write > I2C_SMBUS_READ, PERIPHERAL_ERROR_INVALID_PARAMETER);
+
+       if (read_write == I2C_SMBUS_WRITE) {
+               data_arg.command = command;
+               if (size == I2C_SMBUS_BYTE_DATA)
+                       data.byte = (uint8_t)data_in;
+               else if (size == I2C_SMBUS_WORD_DATA)
+                       data.word = data_in;
+               else if (size == I2C_SMBUS_BYTE)
+                       data_arg.command = (uint8_t)data_in; // Data should be set to command.
+       } else if (read_write == I2C_SMBUS_READ && size != I2C_SMBUS_BYTE)  {
+               data_arg.command = command;
+       }
+
+       ret = i2c_smbus_ioctl(i2c->fd, &data_arg);
+
+       if (ret == 0 && read_write == I2C_SMBUS_READ) {
+               if (size == I2C_SMBUS_BYTE_DATA || size == I2C_SMBUS_BYTE)
+                       *data_out = (uint8_t)data.byte;
+               else if (size == I2C_SMBUS_WORD_DATA)
+                       *data_out = data.word;
+       }
+
+       return ret;
+}
index d65705c..40d0272 100644 (file)
@@ -21,5 +21,6 @@ int peripheral_bus_i2c_open(int bus, int address, pb_i2c_data_h *i2c, gpointer u
 int peripheral_bus_i2c_close(pb_i2c_data_h i2c);
 int peripheral_bus_i2c_read(pb_i2c_data_h i2c, int length, GVariant **data_array);
 int peripheral_bus_i2c_write(pb_i2c_data_h i2c, int length, GVariant *data_array);
+int peripheral_bus_i2c_smbus_ioctl(pb_i2c_data_h i2c, uint8_t read_write, uint8_t command, uint32_t size, uint16_t data_in, uint16_t *data_out);
 
 #endif /* __PERIPHERAL_BUS_I2C_H__ */
index c6fff55..ea4b1f9 100644 (file)
                        </arg>
                        <arg type="i" name="result" direction="out"/>
                </method>
+               <method name="SmbusIoctl">
+                       <arg type="u" name="handle" direction="in"/>
+                       <arg type="y" name="read_write" direction="in"/>
+                       <arg type="y" name="command" direction="in"/>
+                       <arg type="u" name="size" direction="in"/>
+                       <arg type="q" name="data_in" direction="in"/>
+                       <arg type="q" name="data_out" direction="out"/>
+                       <arg type="i" name="result" direction="out"/>
+               </method>
        </interface>
        <interface name="org.tizen.peripheral_io.pwm">
                <method name="Open">
index 956f358..70c02d6 100644 (file)
@@ -21,7 +21,6 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
-#include <linux/i2c.h>
 
 #include "i2c.h"
 #include "peripheral_common.h"
@@ -94,8 +93,7 @@ int i2c_read(int fd, unsigned char *data, int length)
                strerror_r(errno, errmsg, MAX_ERR_LEN);
                _E("i2c_read failed : %s", errmsg);
                return -EIO;
-       } else
-               _D("[SUCCESS] data : [%02x][%02x]", data[0], data[1]);
+       }
 
        return 0;
 }
@@ -116,3 +114,19 @@ int i2c_write(int fd, const unsigned char *data, int length)
 
        return 0;
 }
+
+int i2c_smbus_ioctl(int fd, struct i2c_smbus_ioctl_data *data)
+{
+       int status;
+
+       _D("fd : %d", fd);
+       status = ioctl(fd, I2C_SMBUS, data);
+       if (status < 0) {
+               char errmsg[MAX_ERR_LEN];
+               strerror_r(errno, errmsg, MAX_ERR_LEN);
+               _E("i2c write failed : %s\n", errmsg);
+               return -EIO;
+       }
+
+       return 0;
+}
index bfc4a43..f0d4668 100644 (file)
 #ifndef __I2C_H__
 #define __I2C_H__
 
+#include <stdint.h>
+
 #define SYSFS_I2C_DIR "/dev/i2c"
 #define I2C_BUFFER_MAX 64
-#define I2C_SLAVE 0x0703
+
+#define I2C_SLAVE      0x0703  /* Use this slave address */
+#define I2C_SMBUS      0x0720  /* SMBus transfer */
+
+/* i2c_smbus_xfer read or write markers */
+#define I2C_SMBUS_READ 1
+#define I2C_SMBUS_WRITE        0
+
+/* SMBus transaction types */
+#define I2C_SMBUS_QUICK                    0
+#define I2C_SMBUS_BYTE             1
+#define I2C_SMBUS_BYTE_DATA        2
+#define I2C_SMBUS_WORD_DATA        3
+
+/*
+ * Data for SMBus Messages
+ */
+#define I2C_SMBUS_BLOCK_MAX    32      /* As specified in SMBus standard */
+
+union i2c_smbus_data {
+       uint8_t byte;
+       uint16_t word;
+       uint8_t block[I2C_SMBUS_BLOCK_MAX + 2]; /* block[0] is used for length */
+                              /* and one more for user-space compatibility */
+};
+
+/* This is the structure as used in the I2C_SMBUS ioctl call */
+struct i2c_smbus_ioctl_data {
+       uint8_t read_write;
+       uint8_t command;
+       uint32_t size;
+       union i2c_smbus_data *data;
+};
 
 int i2c_open(int bus, int *fd);
 int i2c_close(int fd);
 int i2c_set_address(int fd, int address);
 int i2c_read(int fd, unsigned char *data, int length);
 int i2c_write(int fd, const unsigned char *data, int length);
+int i2c_smbus_ioctl(int fd, struct i2c_smbus_ioctl_data *data);
 
 #endif/* __I2C_H__ */