1 /* The MIT License (MIT)
3 * Copyright (c) 2005-2014 RoadNarrows LLC.
4 * http://roadnarrows.com
7 * Permission is hereby granted, free of charge, to any person obtaining
8 * a copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom
12 * the Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
26 /* Copyright 2016-present Samsung Electronics Co., Ltd. and other contributors
28 * Licensed under the Apache License, Version 2.0 (the "License");
29 * you may not use this file except in compliance with the License.
30 * You may obtain a copy of the License at
32 * http://www.apache.org/licenses/LICENSE-2.0
34 * Unless required by applicable law or agreed to in writing, software
35 * distributed under the License is distributed on an "AS IS" BASIS
36 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
37 * See the License for the specific language governing permissions and
38 * limitations under the License.
42 /* Some functions are modified from the RoadNarrows-robotics i2c library.
43 * (distributed under the MIT license.)
47 #ifndef IOTJS_MODULE_I2C_LINUX_GENERAL_INL_H
48 #define IOTJS_MODULE_I2C_LINUX_GENERAL_INL_H
56 #include <sys/ioctl.h>
58 #include <sys/types.h>
62 #include "module/iotjs_module_i2c.h"
65 #define I2C_SLAVE_FORCE 0x0706
66 #define I2C_SMBUS 0x0720
67 #define I2C_SMBUS_READ 1
68 #define I2C_SMBUS_WRITE 0
70 #define I2C_SMBUS_BYTE 1
71 #define I2C_SMBUS_BLOCK_DATA 5
72 #define I2C_SMBUS_I2C_BLOCK_DATA 8
73 #define I2C_SMBUS_BLOCK_MAX 32
74 #define I2C_MAX_ADDRESS 128
77 typedef union I2cSmbusDataUnion {
80 uint8_t block[I2C_SMBUS_BLOCK_MAX + 2];
84 typedef struct I2cSmbusIoctlDataStruct {
92 static int current_fd;
96 int I2cSmbusAccess(int fd, uint8_t read_write, uint8_t command, int size,
98 I2cSmbusIoctlData args;
100 args.read_write = read_write;
101 args.command = command;
105 return ioctl(fd, I2C_SMBUS, &args);
109 int I2cSmbusWriteByte(int fd, uint8_t byte) {
110 return I2cSmbusAccess(fd, I2C_SMBUS_WRITE, byte, I2C_SMBUS_BYTE, NULL);
114 int I2cSmbusWriteI2cBlockData(int fd, uint8_t command, uint8_t* values,
118 if (length > I2C_SMBUS_BLOCK_MAX) {
119 length = I2C_SMBUS_BLOCK_MAX;
122 for (int i = 1; i <= length; i++) {
123 data.block[i] = values[i - 1];
125 data.block[0] = length;
127 return I2cSmbusAccess(fd, I2C_SMBUS_WRITE, command, I2C_SMBUS_I2C_BLOCK_DATA,
132 int I2cSmbusReadByte(int fd) {
136 I2cSmbusAccess(fd, I2C_SMBUS_READ, I2C_NOCMD, I2C_SMBUS_BYTE, &data);
138 // Mask one byte from result (data.byte).
139 return result >= 0 ? 0xFF & data.byte : -1;
143 int I2cSmbusReadI2cBlockData(int fd, uint8_t command, uint8_t* values,
147 if (length > I2C_SMBUS_BLOCK_MAX) {
148 length = I2C_SMBUS_BLOCK_MAX;
150 data.block[0] = length;
152 int result = I2cSmbusAccess(fd, I2C_SMBUS_READ, command,
153 I2C_SMBUS_I2C_BLOCK_DATA, &data);
155 for (int i = 1; i <= data.block[0]; i++) {
156 values[i - 1] = data.block[i];
158 result = data.block[0];
165 #define I2C_WORKER_INIT_TEMPLATE \
166 iotjs_i2c_reqwrap_t* req_wrap = iotjs_i2c_reqwrap_from_request(work_req); \
167 iotjs_i2c_reqdata_t* req_data = iotjs_i2c_reqwrap_data(req_wrap);
170 void I2cSetAddress(iotjs_i2c_t* i2c, uint8_t address) {
172 ioctl(current_fd, I2C_SLAVE_FORCE, addr);
176 void OpenWorker(uv_work_t* work_req) {
177 I2C_WORKER_INIT_TEMPLATE;
179 current_fd = open(iotjs_string_data(&req_data->device), O_RDWR);
181 if (current_fd == -1) {
182 req_data->error = kI2cErrOpen;
184 req_data->error = kI2cErrOk;
189 void I2cClose(iotjs_i2c_t* i2c) {
190 if (current_fd > 0) {
196 void WriteWorker(uv_work_t* work_req) {
197 I2C_WORKER_INIT_TEMPLATE;
199 uint8_t len = req_data->buf_len;
200 char* data = req_data->buf_data;
202 if (write(current_fd, data, len) != len) {
203 req_data->error = kI2cErrWrite;
206 if (req_data->buf_data != NULL) {
207 iotjs_buffer_release(req_data->buf_data);
212 void WriteByteWorker(uv_work_t* work_req) {
213 I2C_WORKER_INIT_TEMPLATE;
215 if (I2cSmbusWriteByte(current_fd, req_data->byte) == -1) {
216 req_data->error = kI2cErrWrite;
221 void WriteBlockWorker(uv_work_t* work_req) {
222 I2C_WORKER_INIT_TEMPLATE;
224 uint8_t cmd = req_data->cmd;
225 uint8_t len = req_data->buf_len;
226 uint8_t* data = (uint8_t*)(req_data->buf_data);
228 if (I2cSmbusWriteI2cBlockData(current_fd, cmd, data, len) == -1) {
229 req_data->error = kI2cErrWrite;
232 if (req_data->buf_data != NULL) {
233 iotjs_buffer_release(req_data->buf_data);
238 void ReadWorker(uv_work_t* work_req) {
239 I2C_WORKER_INIT_TEMPLATE;
241 uint8_t len = req_data->buf_len;
242 req_data->buf_data = iotjs_buffer_allocate(len);
244 if (read(current_fd, req_data->buf_data, len) != len) {
245 req_data->error = kI2cErrRead;
250 void ReadByteWorker(uv_work_t* work_req) {
251 I2C_WORKER_INIT_TEMPLATE;
253 int result = I2cSmbusReadByte(current_fd);
255 req_data->error = kI2cErrRead;
257 req_data->byte = result;
262 void ReadBlockWorker(uv_work_t* work_req) {
263 I2C_WORKER_INIT_TEMPLATE;
265 uint8_t cmd = req_data->cmd;
266 uint8_t len = req_data->buf_len;
267 uint8_t data[I2C_SMBUS_BLOCK_MAX + 2];
269 if (I2cSmbusReadI2cBlockData(current_fd, cmd, data, len) != len) {
270 req_data->error = kI2cErrReadBlock;
273 req_data->buf_data = iotjs_buffer_allocate(len);
274 memcpy(req_data->buf_data, data, len);
278 #endif /* IOTJS_MODULE_I2C_LINUX_GENERAL_INL_H */