Update Iot.js
[platform/upstream/iotjs.git] / tools / src / module / iotjs_module_adc.c
1 /* Copyright 2016-present Samsung Electronics Co., Ltd. and other contributors
2  *
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
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
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.
14  */
15
16 #include "iotjs_def.h"
17 #include "iotjs_module_adc.h"
18 #include "iotjs_objectwrap.h"
19
20
21 static void iotjs_adc_destroy(iotjs_adc_t* adc);
22 static iotjs_adc_t* iotjs_adc_instance_from_jval(const iotjs_jval_t* jadc);
23
24
25 static iotjs_adc_t* iotjs_adc_create(const iotjs_jval_t* jadc) {
26   iotjs_adc_t* adc = IOTJS_ALLOC(iotjs_adc_t);
27   IOTJS_VALIDATED_STRUCT_CONSTRUCTOR(iotjs_adc_t, adc);
28   iotjs_jobjectwrap_initialize(&_this->jobjectwrap, jadc,
29                                (JFreeHandlerType)iotjs_adc_destroy);
30
31   return adc;
32 }
33
34
35 static void iotjs_adc_destroy(iotjs_adc_t* adc) {
36   IOTJS_VALIDATED_STRUCT_DESTRUCTOR(iotjs_adc_t, adc);
37   iotjs_jobjectwrap_destroy(&_this->jobjectwrap);
38 #if defined(__linux__)
39   iotjs_string_destroy(&_this->device);
40 #endif
41   IOTJS_RELEASE(adc);
42 }
43
44
45 #define THIS iotjs_adc_reqwrap_t* adc_reqwrap
46
47
48 static iotjs_adc_reqwrap_t* iotjs_adc_reqwrap_create(
49     const iotjs_jval_t* jcallback, const iotjs_jval_t* jadc, AdcOp op) {
50   iotjs_adc_reqwrap_t* adc_reqwrap = IOTJS_ALLOC(iotjs_adc_reqwrap_t);
51   IOTJS_VALIDATED_STRUCT_CONSTRUCTOR(iotjs_adc_reqwrap_t, adc_reqwrap);
52
53   iotjs_reqwrap_initialize(&_this->reqwrap, jcallback, (uv_req_t*)&_this->req);
54
55   _this->req_data.op = op;
56   _this->adc_instance = iotjs_adc_instance_from_jval(jadc);
57   return adc_reqwrap;
58 }
59
60
61 static void iotjs_adc_reqwrap_destroy(THIS) {
62   IOTJS_VALIDATED_STRUCT_DESTRUCTOR(iotjs_adc_reqwrap_t, adc_reqwrap);
63   iotjs_reqwrap_destroy(&_this->reqwrap);
64   IOTJS_RELEASE(adc_reqwrap);
65 }
66
67
68 static void iotjs_adc_reqwrap_dispatched(THIS) {
69   IOTJS_VALIDATABLE_STRUCT_METHOD_VALIDATE(iotjs_adc_reqwrap_t, adc_reqwrap);
70   iotjs_adc_reqwrap_destroy(adc_reqwrap);
71 }
72
73
74 static uv_work_t* iotjs_adc_reqwrap_req(THIS) {
75   IOTJS_VALIDATED_STRUCT_METHOD(iotjs_adc_reqwrap_t, adc_reqwrap);
76   return &_this->req;
77 }
78
79
80 static const iotjs_jval_t* iotjs_adc_reqwrap_jcallback(THIS) {
81   IOTJS_VALIDATED_STRUCT_METHOD(iotjs_adc_reqwrap_t, adc_reqwrap);
82   return iotjs_reqwrap_jcallback(&_this->reqwrap);
83 }
84
85
86 static iotjs_adc_t* iotjs_adc_instance_from_jval(const iotjs_jval_t* jadc) {
87   uintptr_t handle = iotjs_jval_get_object_native_handle(jadc);
88   return (iotjs_adc_t*)handle;
89 }
90
91
92 iotjs_adc_reqwrap_t* iotjs_adc_reqwrap_from_request(uv_work_t* req) {
93   return (iotjs_adc_reqwrap_t*)(iotjs_reqwrap_from_request((uv_req_t*)req));
94 }
95
96
97 iotjs_adc_reqdata_t* iotjs_adc_reqwrap_data(THIS) {
98   IOTJS_VALIDATED_STRUCT_METHOD(iotjs_adc_reqwrap_t, adc_reqwrap);
99   return &_this->req_data;
100 }
101
102
103 iotjs_adc_t* iotjs_adc_instance_from_reqwrap(THIS) {
104   IOTJS_VALIDATED_STRUCT_METHOD(iotjs_adc_reqwrap_t, adc_reqwrap);
105   return _this->adc_instance;
106 }
107
108
109 #undef THIS
110
111
112 static void iotjs_adc_after_work(uv_work_t* work_req, int status) {
113   iotjs_adc_reqwrap_t* req_wrap = iotjs_adc_reqwrap_from_request(work_req);
114   iotjs_adc_reqdata_t* req_data = iotjs_adc_reqwrap_data(req_wrap);
115   iotjs_jargs_t jargs = iotjs_jargs_create(2);
116   bool result = req_data->result;
117
118   if (status) {
119     iotjs_jval_t error = iotjs_jval_create_error("System error");
120     iotjs_jargs_append_jval(&jargs, &error);
121     iotjs_jval_destroy(&error);
122   } else {
123     switch (req_data->op) {
124       case kAdcOpOpen:
125         if (!result) {
126           iotjs_jargs_append_error(&jargs, "Failed to open ADC device");
127         } else {
128           iotjs_jargs_append_null(&jargs);
129         }
130         break;
131       case kAdcOpRead:
132         if (!result) {
133           iotjs_jargs_append_error(&jargs, "Cannot read from ADC device");
134         } else {
135           iotjs_jargs_append_null(&jargs);
136           iotjs_jargs_append_number(&jargs, req_data->value);
137         }
138         break;
139       case kAdcOpClose:
140         if (!result) {
141           iotjs_jargs_append_error(&jargs, "Cannot close ADC device");
142         } else {
143           iotjs_jargs_append_null(&jargs);
144         }
145         break;
146       default: {
147         IOTJS_ASSERT(!"Unreachable");
148         break;
149       }
150     }
151   }
152
153   const iotjs_jval_t* jcallback = iotjs_adc_reqwrap_jcallback(req_wrap);
154   iotjs_make_callback(jcallback, iotjs_jval_get_undefined(), &jargs);
155
156   iotjs_jargs_destroy(&jargs);
157
158   iotjs_adc_reqwrap_dispatched(req_wrap);
159 }
160
161
162 static void iotjs_adc_set_configuration(iotjs_adc_t* adc,
163                                         const iotjs_jval_t* jconfiguration) {
164 #if defined(__linux__)
165   IOTJS_VALIDATED_STRUCT_METHOD(iotjs_adc_t, adc);
166   iotjs_jval_t jdevice =
167       iotjs_jval_get_property(jconfiguration, IOTJS_MAGIC_STRING_DEVICE);
168   _this->device = iotjs_jval_as_string(&jdevice);
169   iotjs_jval_destroy(&jdevice);
170 #elif defined(__NUTTX__)
171   IOTJS_VALIDATED_STRUCT_METHOD(iotjs_adc_t, adc);
172   iotjs_jval_t jpin =
173       iotjs_jval_get_property(jconfiguration, IOTJS_MAGIC_STRING_PIN);
174   _this->pin = iotjs_jval_as_number(&jpin);
175   iotjs_jval_destroy(&jpin);
176 #endif
177 }
178
179
180 static void iotjs_adc_read_worker(uv_work_t* work_req) {
181   ADC_WORKER_INIT;
182   int32_t value = iotjs_adc_read(adc);
183
184   if (value < 0) {
185     req_data->result = false;
186     return;
187   }
188
189   req_data->value = value;
190   req_data->result = true;
191 }
192
193
194 static void iotjs_adc_close_worker(uv_work_t* work_req) {
195   ADC_WORKER_INIT;
196
197   // Release driver
198   if (!iotjs_adc_close(adc)) {
199     req_data->result = false;
200     return;
201   }
202
203   req_data->result = true;
204 }
205
206
207 #define ADC_ASYNC(call, jthis, jcallback, op)                                  \
208   do {                                                                         \
209     uv_loop_t* loop = iotjs_environment_loop(iotjs_environment_get());         \
210     iotjs_adc_reqwrap_t* req_wrap =                                            \
211         iotjs_adc_reqwrap_create(jcallback, jthis, op);                        \
212     uv_work_t* req = iotjs_adc_reqwrap_req(req_wrap);                          \
213     uv_queue_work(loop, req, iotjs_adc_##call##_worker, iotjs_adc_after_work); \
214   } while (0)
215
216
217 JHANDLER_FUNCTION(AdcConstructor) {
218   JHANDLER_CHECK_THIS(object);
219   JHANDLER_CHECK_ARGS(2, object, function);
220
221   // Create ADC object
222   const iotjs_jval_t* jadc = JHANDLER_GET_THIS(object);
223   iotjs_adc_t* adc = iotjs_adc_create(jadc);
224   IOTJS_ASSERT(adc == iotjs_adc_instance_from_jval(jadc));
225
226   iotjs_adc_set_configuration(adc, JHANDLER_GET_ARG(0, object));
227
228   const iotjs_jval_t* jcallback = JHANDLER_GET_ARG(1, function);
229   ADC_ASYNC(open, jadc, jcallback, kAdcOpOpen);
230 }
231
232
233 JHANDLER_FUNCTION(Read) {
234   JHANDLER_CHECK_THIS(object);
235   JHANDLER_CHECK_ARG_IF_EXIST(0, function);
236
237   const iotjs_jval_t* jcallback = JHANDLER_GET_ARG_IF_EXIST(0, function);
238   const iotjs_jval_t* jadc = JHANDLER_GET_THIS(object);
239   iotjs_adc_t* adc = iotjs_adc_instance_from_jval(jadc);
240
241   if (jcallback) {
242     ADC_ASYNC(read, jadc, jcallback, kAdcOpRead);
243   } else {
244     int32_t value = iotjs_adc_read(adc);
245     if (value < 0) {
246       JHANDLER_THROW(COMMON, "ADC Read Error");
247     } else {
248       iotjs_jhandler_return_number(jhandler, value);
249     }
250   }
251 }
252
253
254 JHANDLER_FUNCTION(Close) {
255   JHANDLER_CHECK_THIS(object);
256   JHANDLER_CHECK_ARG_IF_EXIST(0, function);
257
258   const iotjs_jval_t* jcallback = JHANDLER_GET_ARG_IF_EXIST(0, function);
259   const iotjs_jval_t* jadc = JHANDLER_GET_THIS(object);
260   iotjs_adc_t* adc = iotjs_adc_instance_from_jval(jadc);
261
262   if (jcallback) {
263     ADC_ASYNC(close, jadc, jcallback, kAdcOpClose);
264   } else {
265     if (!iotjs_adc_close(adc)) {
266       JHANDLER_THROW(COMMON, "ADC Close Error");
267     }
268   }
269
270   iotjs_jhandler_return_null(jhandler);
271 }
272
273
274 iotjs_jval_t InitAdc() {
275   iotjs_jval_t jadc = iotjs_jval_create_object();
276   iotjs_jval_t jadcConstructor =
277       iotjs_jval_create_function_with_dispatch(AdcConstructor);
278   iotjs_jval_set_property_jval(&jadc, IOTJS_MAGIC_STRING_ADC, &jadcConstructor);
279
280   iotjs_jval_t jprototype = iotjs_jval_create_object();
281   iotjs_jval_set_method(&jprototype, IOTJS_MAGIC_STRING_READ, Read);
282   iotjs_jval_set_method(&jprototype, IOTJS_MAGIC_STRING_CLOSE, Close);
283   iotjs_jval_set_property_jval(&jadcConstructor, IOTJS_MAGIC_STRING_PROTOTYPE,
284                                &jprototype);
285
286   iotjs_jval_destroy(&jprototype);
287   iotjs_jval_destroy(&jadcConstructor);
288
289   return jadc;
290 }