From 2f1970f3f953dab738bb74e59280c75b2276fbae Mon Sep 17 00:00:00 2001 From: Hyeongsik Min Date: Thu, 1 Jun 2017 11:03:25 +0900 Subject: [PATCH] Add new APIS for I2C smbus transaction 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 --- src/daemon/peripheral_bus.c | 39 +++++++++++++++++++++++++++++++++++++++ src/daemon/peripheral_bus_i2c.c | 40 ++++++++++++++++++++++++++++++++++++++++ src/daemon/peripheral_bus_i2c.h | 1 + src/daemon/peripheral_io.xml | 9 +++++++++ src/interface/i2c.c | 20 +++++++++++++++++--- src/interface/include/i2c.h | 37 ++++++++++++++++++++++++++++++++++++- 6 files changed, 142 insertions(+), 4 deletions(-) diff --git a/src/daemon/peripheral_bus.c b/src/daemon/peripheral_bus.c index 08c4d0e..f064392 100644 --- a/src/daemon/peripheral_bus.c +++ b/src/daemon/peripheral_bus.c @@ -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); diff --git a/src/daemon/peripheral_bus_i2c.c b/src/daemon/peripheral_bus_i2c.c index 81a01de..57bb90c 100644 --- a/src/daemon/peripheral_bus_i2c.c +++ b/src/daemon/peripheral_bus_i2c.c @@ -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; +} diff --git a/src/daemon/peripheral_bus_i2c.h b/src/daemon/peripheral_bus_i2c.h index d65705c..40d0272 100644 --- a/src/daemon/peripheral_bus_i2c.h +++ b/src/daemon/peripheral_bus_i2c.h @@ -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__ */ diff --git a/src/daemon/peripheral_io.xml b/src/daemon/peripheral_io.xml index c6fff55..ea4b1f9 100644 --- a/src/daemon/peripheral_io.xml +++ b/src/daemon/peripheral_io.xml @@ -80,6 +80,15 @@ + + + + + + + + + diff --git a/src/interface/i2c.c b/src/interface/i2c.c index 956f358..70c02d6 100644 --- a/src/interface/i2c.c +++ b/src/interface/i2c.c @@ -21,7 +21,6 @@ #include #include #include -#include #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; +} diff --git a/src/interface/include/i2c.h b/src/interface/include/i2c.h index bfc4a43..f0d4668 100644 --- a/src/interface/include/i2c.h +++ b/src/interface/include/i2c.h @@ -17,14 +17,49 @@ #ifndef __I2C_H__ #define __I2C_H__ +#include + #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__ */ -- 2.7.4