1 /* Copyright 2016-present Samsung Electronics Co., Ltd. and other contributors
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
17 #include "iotjs_def.h"
18 #include "iotjs_module_i2c.h"
19 #include "iotjs_objectwrap.h"
22 #define THIS iotjs_i2c_reqwrap_t* i2c_reqwrap
25 iotjs_i2c_reqwrap_t* iotjs_i2c_reqwrap_create(const iotjs_jval_t* jcallback,
26 const iotjs_jval_t* ji2c,
28 iotjs_i2c_reqwrap_t* i2c_reqwrap = IOTJS_ALLOC(iotjs_i2c_reqwrap_t);
29 IOTJS_VALIDATED_STRUCT_CONSTRUCTOR(iotjs_i2c_reqwrap_t, i2c_reqwrap);
31 iotjs_reqwrap_initialize(&_this->reqwrap, jcallback, (uv_req_t*)&_this->req);
33 _this->req_data.op = op;
34 #if defined(__linux__) || defined(__APPLE__)
35 _this->req_data.device = iotjs_string_create("");
37 _this->i2c_data = iotjs_i2c_instance_from_jval(ji2c);
42 static void iotjs_i2c_reqwrap_destroy(THIS) {
43 IOTJS_VALIDATED_STRUCT_DESTRUCTOR(iotjs_i2c_reqwrap_t, i2c_reqwrap);
44 iotjs_reqwrap_destroy(&_this->reqwrap);
45 #if defined(__linux__) || defined(__APPLE__)
46 iotjs_string_destroy(&_this->req_data.device);
48 IOTJS_RELEASE(i2c_reqwrap);
52 void iotjs_i2c_reqwrap_dispatched(THIS) {
53 IOTJS_VALIDATABLE_STRUCT_METHOD_VALIDATE(iotjs_i2c_reqwrap_t, i2c_reqwrap);
54 iotjs_i2c_reqwrap_destroy(i2c_reqwrap);
58 uv_work_t* iotjs_i2c_reqwrap_req(THIS) {
59 IOTJS_VALIDATED_STRUCT_METHOD(iotjs_i2c_reqwrap_t, i2c_reqwrap);
64 const iotjs_jval_t* iotjs_i2c_reqwrap_jcallback(THIS) {
65 IOTJS_VALIDATED_STRUCT_METHOD(iotjs_i2c_reqwrap_t, i2c_reqwrap);
66 return iotjs_reqwrap_jcallback(&_this->reqwrap);
70 iotjs_i2c_reqwrap_t* iotjs_i2c_reqwrap_from_request(uv_work_t* req) {
71 return (iotjs_i2c_reqwrap_t*)(iotjs_reqwrap_from_request((uv_req_t*)req));
75 iotjs_i2c_reqdata_t* iotjs_i2c_reqwrap_data(THIS) {
76 IOTJS_VALIDATED_STRUCT_METHOD(iotjs_i2c_reqwrap_t, i2c_reqwrap);
77 return &_this->req_data;
81 iotjs_i2c_t* iotjs_i2c_instance_from_reqwrap(THIS) {
82 IOTJS_VALIDATED_STRUCT_METHOD(iotjs_i2c_reqwrap_t, i2c_reqwrap);
83 return _this->i2c_data;
89 static void iotjs_i2c_destroy(iotjs_i2c_t* i2c);
92 iotjs_i2c_t* iotjs_i2c_create(const iotjs_jval_t* ji2c) {
93 iotjs_i2c_t* i2c = IOTJS_ALLOC(iotjs_i2c_t);
94 IOTJS_VALIDATED_STRUCT_CONSTRUCTOR(iotjs_i2c_t, i2c);
96 #if defined(__NUTTX__)
97 _this->i2c_master = NULL;
100 iotjs_jobjectwrap_initialize(&_this->jobjectwrap, ji2c,
101 (JFreeHandlerType)iotjs_i2c_destroy);
106 static void iotjs_i2c_destroy(iotjs_i2c_t* i2c) {
107 IOTJS_VALIDATED_STRUCT_DESTRUCTOR(iotjs_i2c_t, i2c);
108 iotjs_jobjectwrap_destroy(&_this->jobjectwrap);
113 iotjs_i2c_t* iotjs_i2c_instance_from_jval(const iotjs_jval_t* ji2c) {
114 iotjs_jobjectwrap_t* jobjectwrap = iotjs_jobjectwrap_from_jobject(ji2c);
115 return (iotjs_i2c_t*)jobjectwrap;
119 void AfterI2CWork(uv_work_t* work_req, int status) {
120 iotjs_i2c_reqwrap_t* req_wrap = iotjs_i2c_reqwrap_from_request(work_req);
121 iotjs_i2c_reqdata_t* req_data = iotjs_i2c_reqwrap_data(req_wrap);
123 iotjs_jargs_t jargs = iotjs_jargs_create(2);
126 iotjs_jval_t error = iotjs_jval_create_error("System error");
127 iotjs_jargs_append_jval(&jargs, &error);
128 iotjs_jval_destroy(&error);
130 switch (req_data->op) {
132 if (req_data->error == kI2cErrOpen) {
134 iotjs_jval_create_error("Failed to open I2C device");
135 iotjs_jargs_append_jval(&jargs, &error);
136 iotjs_jval_destroy(&error);
138 iotjs_jargs_append_null(&jargs);
143 case kI2cOpWriteByte:
144 case kI2cOpWriteBlock: {
145 if (req_data->error == kI2cErrWrite) {
147 iotjs_jval_create_error("Cannot write to device");
148 iotjs_jargs_append_jval(&jargs, &error);
149 iotjs_jval_destroy(&error);
151 iotjs_jargs_append_null(&jargs);
156 case kI2cOpReadBlock: {
157 if (req_data->error == kI2cErrRead) {
159 iotjs_jval_create_error("Cannot read from device");
160 iotjs_jargs_append_jval(&jargs, &error);
161 iotjs_jargs_append_null(&jargs);
162 iotjs_jval_destroy(&error);
163 } else if (req_data->error == kI2cErrReadBlock) {
165 iotjs_jval_create_error("Error reading length of bytes");
166 iotjs_jargs_append_jval(&jargs, &error);
167 iotjs_jargs_append_null(&jargs);
168 iotjs_jval_destroy(&error);
170 iotjs_jargs_append_null(&jargs);
171 iotjs_jval_t result =
172 iotjs_jval_create_byte_array(req_data->buf_len,
174 iotjs_jargs_append_jval(&jargs, &result);
175 iotjs_jval_destroy(&result);
177 if (req_data->delay > 0) {
178 uv_sleep(req_data->delay);
181 if (req_data->buf_data != NULL) {
182 iotjs_buffer_release(req_data->buf_data);
187 case kI2cOpReadByte: {
188 if (req_data->error == kI2cErrRead) {
190 iotjs_jval_create_error("Cannot read from device");
191 iotjs_jargs_append_jval(&jargs, &error);
192 iotjs_jargs_append_null(&jargs);
193 iotjs_jval_destroy(&error);
195 iotjs_jargs_append_null(&jargs);
196 iotjs_jargs_append_number(&jargs, req_data->byte);
201 IOTJS_ASSERT(!"Unreachable");
207 const iotjs_jval_t* jcallback = iotjs_i2c_reqwrap_jcallback(req_wrap);
208 iotjs_make_callback(jcallback, iotjs_jval_get_undefined(), &jargs);
210 iotjs_jargs_destroy(&jargs);
211 iotjs_i2c_reqwrap_dispatched(req_wrap);
215 static void GetI2cArray(const iotjs_jval_t* jarray,
216 iotjs_i2c_reqdata_t* req_data) {
218 // Need to implement a function to get array info from iotjs_jval_t Array.
219 iotjs_jval_t jlength =
220 iotjs_jval_get_property(jarray, IOTJS_MAGIC_STRING_LENGTH);
221 IOTJS_ASSERT(!iotjs_jval_is_undefined(&jlength));
223 req_data->buf_len = iotjs_jval_as_number(&jlength);
224 req_data->buf_data = iotjs_buffer_allocate(req_data->buf_len);
226 for (int i = 0; i < req_data->buf_len; i++) {
227 iotjs_jval_t jdata = iotjs_jval_get_property_by_index(jarray, i);
228 req_data->buf_data[i] = iotjs_jval_as_number(&jdata);
229 iotjs_jval_destroy(&jdata);
232 iotjs_jval_destroy(&jlength);
236 #define I2C_ASYNC(op) \
238 uv_loop_t* loop = iotjs_environment_loop(iotjs_environment_get()); \
239 uv_work_t* req = iotjs_i2c_reqwrap_req(req_wrap); \
240 uv_queue_work(loop, req, op##Worker, AfterI2CWork); \
244 JHANDLER_FUNCTION(I2cCons) {
245 JHANDLER_CHECK_THIS(object);
246 #if defined(__linux__) || defined(__APPLE__)
247 JHANDLER_CHECK_ARGS(2, string, function);
248 iotjs_string_t device = JHANDLER_GET_ARG(0, string);
249 #elif defined(__NUTTX__)
250 JHANDLER_CHECK_ARGS(2, number, function);
251 uint32_t device = JHANDLER_GET_ARG(0, number);
255 const iotjs_jval_t* ji2c = JHANDLER_GET_THIS(object);
256 iotjs_i2c_t* i2c = iotjs_i2c_create(ji2c);
258 (iotjs_i2c_t*)(iotjs_jval_get_object_native_handle(ji2c)));
260 // Create I2C request wrap
261 const iotjs_jval_t* jcallback = JHANDLER_GET_ARG(1, function);
262 iotjs_i2c_reqwrap_t* req_wrap =
263 iotjs_i2c_reqwrap_create(jcallback, ji2c, kI2cOpOpen);
265 iotjs_i2c_reqdata_t* req_data = iotjs_i2c_reqwrap_data(req_wrap);
266 #if defined(__linux__) || defined(__APPLE__)
267 iotjs_string_append(&req_data->device, iotjs_string_data(&device),
268 iotjs_string_size(&device));
269 #elif defined(__NUTTX__)
270 req_data->device = device;
277 JHANDLER_FUNCTION(SetAddress) {
278 JHANDLER_CHECK_THIS(object);
279 JHANDLER_CHECK_ARGS(1, number);
280 iotjs_i2c_t* i2c = iotjs_i2c_instance_from_jval(JHANDLER_GET_THIS(object));
282 I2cSetAddress(i2c, JHANDLER_GET_ARG(0, number));
284 iotjs_jhandler_return_null(jhandler);
288 JHANDLER_FUNCTION(Close) {
289 JHANDLER_CHECK_THIS(object);
290 JHANDLER_CHECK_ARGS(0);
292 iotjs_i2c_t* i2c = iotjs_i2c_instance_from_jval(JHANDLER_GET_THIS(object));
295 iotjs_jhandler_return_null(jhandler);
299 JHANDLER_FUNCTION(Write) {
300 JHANDLER_CHECK_THIS(object);
301 JHANDLER_CHECK_ARGS(2, array, function);
303 const iotjs_jval_t* jcallback = JHANDLER_GET_ARG(1, function);
304 const iotjs_jval_t* ji2c = JHANDLER_GET_THIS(object);
306 iotjs_i2c_reqwrap_t* req_wrap =
307 iotjs_i2c_reqwrap_create(jcallback, ji2c, kI2cOpWrite);
308 iotjs_i2c_reqdata_t* req_data = iotjs_i2c_reqwrap_data(req_wrap);
310 GetI2cArray(JHANDLER_GET_ARG(0, array), req_data);
314 iotjs_jhandler_return_null(jhandler);
318 JHANDLER_FUNCTION(WriteByte) {
319 JHANDLER_CHECK_THIS(object);
320 JHANDLER_CHECK_ARGS(2, number, function);
322 uint8_t byte = JHANDLER_GET_ARG(0, number);
323 const iotjs_jval_t* jcallback = JHANDLER_GET_ARG(1, function);
324 const iotjs_jval_t* ji2c = JHANDLER_GET_THIS(object);
326 iotjs_i2c_reqwrap_t* req_wrap =
327 iotjs_i2c_reqwrap_create(jcallback, ji2c, kI2cOpWriteByte);
329 iotjs_i2c_reqdata_t* req_data = iotjs_i2c_reqwrap_data(req_wrap);
330 req_data->byte = byte;
332 I2C_ASYNC(WriteByte);
334 iotjs_jhandler_return_null(jhandler);
338 JHANDLER_FUNCTION(WriteBlock) {
339 JHANDLER_CHECK_THIS(object);
340 JHANDLER_CHECK_ARGS(3, number, array, function);
342 const iotjs_jval_t* jcallback = JHANDLER_GET_ARG(2, function);
343 const iotjs_jval_t* ji2c = JHANDLER_GET_THIS(object);
345 iotjs_i2c_reqwrap_t* req_wrap =
346 iotjs_i2c_reqwrap_create(jcallback, ji2c, kI2cOpWriteBlock);
348 iotjs_i2c_reqdata_t* req_data = iotjs_i2c_reqwrap_data(req_wrap);
349 req_data->cmd = JHANDLER_GET_ARG(0, number);
350 GetI2cArray(JHANDLER_GET_ARG(1, array), req_data);
352 I2C_ASYNC(WriteBlock);
354 iotjs_jhandler_return_null(jhandler);
358 JHANDLER_FUNCTION(Read) {
359 JHANDLER_CHECK_THIS(object);
360 JHANDLER_CHECK_ARGS(2, number, function);
362 const iotjs_jval_t* jcallback = JHANDLER_GET_ARG(1, function);
363 const iotjs_jval_t* ji2c = JHANDLER_GET_THIS(object);
365 iotjs_i2c_reqwrap_t* req_wrap =
366 iotjs_i2c_reqwrap_create(jcallback, ji2c, kI2cOpRead);
368 iotjs_i2c_reqdata_t* req_data = iotjs_i2c_reqwrap_data(req_wrap);
369 req_data->buf_len = JHANDLER_GET_ARG(0, number);
374 iotjs_jhandler_return_null(jhandler);
378 JHANDLER_FUNCTION(ReadByte) {
379 JHANDLER_CHECK_THIS(object);
380 JHANDLER_CHECK_ARGS(1, function);
382 const iotjs_jval_t* jcallback = JHANDLER_GET_ARG(0, function);
383 const iotjs_jval_t* ji2c = JHANDLER_GET_THIS(object);
385 iotjs_i2c_reqwrap_t* req_wrap =
386 iotjs_i2c_reqwrap_create(jcallback, ji2c, kI2cOpReadByte);
390 iotjs_jhandler_return_null(jhandler);
394 JHANDLER_FUNCTION(ReadBlock) {
395 JHANDLER_CHECK_THIS(object);
396 JHANDLER_CHECK_ARGS(4, number, number, number, function);
398 const iotjs_jval_t* jcallback = JHANDLER_GET_ARG(3, function);
399 const iotjs_jval_t* ji2c = JHANDLER_GET_THIS(object);
401 iotjs_i2c_reqwrap_t* req_wrap =
402 iotjs_i2c_reqwrap_create(jcallback, ji2c, kI2cOpReadBlock);
404 iotjs_i2c_reqdata_t* req_data = iotjs_i2c_reqwrap_data(req_wrap);
405 req_data->cmd = JHANDLER_GET_ARG(0, number);
406 req_data->buf_len = JHANDLER_GET_ARG(1, number);
407 req_data->delay = JHANDLER_GET_ARG(2, number);
409 I2C_ASYNC(ReadBlock);
411 iotjs_jhandler_return_null(jhandler);
415 iotjs_jval_t InitI2c() {
416 iotjs_jval_t jI2cCons = iotjs_jval_create_function_with_dispatch(I2cCons);
418 iotjs_jval_t prototype = iotjs_jval_create_object();
420 iotjs_jval_set_method(&prototype, IOTJS_MAGIC_STRING_SETADDRESS, SetAddress);
421 iotjs_jval_set_method(&prototype, IOTJS_MAGIC_STRING_CLOSE, Close);
422 iotjs_jval_set_method(&prototype, IOTJS_MAGIC_STRING_WRITE, Write);
423 iotjs_jval_set_method(&prototype, IOTJS_MAGIC_STRING_WRITEBYTE, WriteByte);
424 iotjs_jval_set_method(&prototype, IOTJS_MAGIC_STRING_WRITEBLOCK, WriteBlock);
425 iotjs_jval_set_method(&prototype, IOTJS_MAGIC_STRING_READ, Read);
426 iotjs_jval_set_method(&prototype, IOTJS_MAGIC_STRING_READBYTE, ReadByte);
427 iotjs_jval_set_method(&prototype, IOTJS_MAGIC_STRING_READBLOCK, ReadBlock);
429 iotjs_jval_set_property_jval(&jI2cCons, IOTJS_MAGIC_STRING_PROTOTYPE,
432 iotjs_jval_destroy(&prototype);