2 * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <sys/ioctl.h>
20 #include <system_info.h>
22 #include "peripheral_io.h"
23 #include "peripheral_handle.h"
24 #include "peripheral_interface_i2c.h"
25 #include "peripheral_log.h"
27 #define PERIPHERAL_IO_I2C_FEATURE "http://tizen.org/feature/peripheral_io.i2c"
29 #define I2C_FEATURE_UNKNOWN -1
30 #define I2C_FEATURE_FALSE 0
31 #define I2C_FEATURE_TRUE 1
33 /* i2c_smbus_xfer read or write markers */
34 #define I2C_SMBUS_READ 1
35 #define I2C_SMBUS_WRITE 0
37 /* SMBus transaction types */
38 #define I2C_SMBUS_QUICK 0
39 #define I2C_SMBUS_BYTE 1
40 #define I2C_SMBUS_BYTE_DATA 2
41 #define I2C_SMBUS_WORD_DATA 3
43 static int i2c_feature = I2C_FEATURE_UNKNOWN;
45 static bool __is_feature_supported(void)
47 int ret = SYSTEM_INFO_ERROR_NONE;
50 if (i2c_feature == I2C_FEATURE_UNKNOWN) {
51 ret = system_info_get_platform_bool(PERIPHERAL_IO_I2C_FEATURE, &feature);
52 RETVM_IF(ret != SYSTEM_INFO_ERROR_NONE, false, "Failed to get system info");
54 i2c_feature = (feature ? I2C_FEATURE_TRUE : I2C_FEATURE_FALSE);
57 return (i2c_feature == I2C_FEATURE_TRUE ? true : false);
60 static inline void cleanup_handlep(peripheral_i2c_h *handle) {
61 if (*handle != NULL) {
62 if ((*handle)->fd != -1)
68 int peripheral_i2c_open_flags(int bus, int address, peripheral_open_flags_e flags, peripheral_i2c_h *i2c)
70 int ret = PERIPHERAL_ERROR_NONE;
71 int lock_type = LOCK_EX;
73 #define DEV_PATH_BASE "/dev/i2c-"
74 char path[sizeof(DEV_PATH_BASE "0000000000")] = {0, }; /* space for /dev/i2c-%d */
76 RETVM_IF(__is_feature_supported() == false, PERIPHERAL_ERROR_NOT_SUPPORTED, "I2C feature is not supported");
77 RETVM_IF(i2c == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "Invalid i2c handle");
78 RETVM_IF(bus < 0 || address < 0, PERIPHERAL_ERROR_INVALID_PARAMETER, "Invalid parameter");
79 RETVM_IF(flags != PERIPHERAL_OPEN_FLAGS_PRIVATE && flags != PERIPHERAL_OPEN_FLAGS_SHARED,
80 PERIPHERAL_ERROR_INVALID_PARAMETER, "Invalid flags");
82 __attribute__ ((cleanup(cleanup_handlep))) peripheral_i2c_h handle = NULL;
84 handle = (peripheral_i2c_h)malloc(sizeof(struct _peripheral_i2c_s));
86 _E("Failed to allocate peripheral_i2c_h");
87 return PERIPHERAL_ERROR_OUT_OF_MEMORY;
90 snprintf(path, sizeof path, DEV_PATH_BASE "%d", bus);
91 handle->fd = open(path, O_RDWR | O_CLOEXEC);
92 CHECK_ERROR(handle->fd < 0);
94 ret = ioctl(handle->fd, I2C_SLAVE, address);
97 if (flags == PERIPHERAL_OPEN_FLAGS_SHARED)
100 if (flock(handle->fd, lock_type | LOCK_NB)) {
101 if (errno == EWOULDBLOCK) {
102 _E("bus : %d, address : 0x%x is not available", bus, address);
103 return PERIPHERAL_ERROR_RESOURCE_BUSY;
105 _E("bus : %d, address : 0x%x flock() error: %d", bus, address, errno);
106 return PERIPHERAL_ERROR_IO_ERROR;
113 return PERIPHERAL_ERROR_NONE;
116 int peripheral_i2c_open(int bus, int address, peripheral_i2c_h *i2c)
118 return peripheral_i2c_open_flags(bus, address, PERIPHERAL_OPEN_FLAGS_PRIVATE, i2c);
121 int peripheral_i2c_close(peripheral_i2c_h i2c)
123 int ret = PERIPHERAL_ERROR_NONE;
125 RETVM_IF(__is_feature_supported() == false, PERIPHERAL_ERROR_NOT_SUPPORTED, "I2C feature is not supported");
126 RETVM_IF(i2c == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "i2c handle is NULL");
128 peripheral_interface_i2c_close(i2c);
136 int peripheral_i2c_read(peripheral_i2c_h i2c, uint8_t *data, uint32_t length)
138 RETVM_IF(__is_feature_supported() == false, PERIPHERAL_ERROR_NOT_SUPPORTED, "I2C feature is not supported");
139 RETVM_IF(i2c == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "i2c handle is NULL");
140 RETVM_IF(data == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "Invalid parameter");
142 return peripheral_interface_i2c_read(i2c, data, length);
145 int peripheral_i2c_write(peripheral_i2c_h i2c, uint8_t *data, uint32_t length)
147 RETVM_IF(__is_feature_supported() == false, PERIPHERAL_ERROR_NOT_SUPPORTED, "I2C feature is not supported");
148 RETVM_IF(i2c == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "i2c handle is NULL");
149 RETVM_IF(data == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "Invalid parameter");
151 return peripheral_interface_i2c_write(i2c, data, length);
154 int peripheral_i2c_read_register_byte(peripheral_i2c_h i2c, uint8_t reg, uint8_t *data)
156 RETVM_IF(__is_feature_supported() == false, PERIPHERAL_ERROR_NOT_SUPPORTED, "I2C feature is not supported");
157 RETVM_IF(i2c == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "i2c handle is NULL");
158 RETVM_IF(data == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "Invalid parameter");
160 return peripheral_interface_i2c_read_register_byte(i2c, reg, data);
163 int peripheral_i2c_write_register_byte(peripheral_i2c_h i2c, uint8_t reg, uint8_t data)
165 RETVM_IF(__is_feature_supported() == false, PERIPHERAL_ERROR_NOT_SUPPORTED, "I2C feature is not supported");
166 RETVM_IF(i2c == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "i2c handle is NULL");
168 return peripheral_interface_i2c_write_register_byte(i2c, reg, data);
171 int peripheral_i2c_read_register_word(peripheral_i2c_h i2c, uint8_t reg, uint16_t *data)
173 RETVM_IF(__is_feature_supported() == false, PERIPHERAL_ERROR_NOT_SUPPORTED, "I2C feature is not supported");
174 RETVM_IF(i2c == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "i2c handle is NULL");
175 RETVM_IF(data == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "Invalid parameter");
177 return peripheral_interface_i2c_read_register_word(i2c, reg, data);
180 int peripheral_i2c_write_register_word(peripheral_i2c_h i2c, uint8_t reg, uint16_t data)
182 RETVM_IF(__is_feature_supported() == false, PERIPHERAL_ERROR_NOT_SUPPORTED, "I2C feature is not supported");
183 RETVM_IF(i2c == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "i2c handle is NULL");
185 return peripheral_interface_i2c_write_register_word(i2c, reg, data);