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.
16 #include "iotjs_def.h"
17 #include "iotjs_module_pwm.h"
18 #include "iotjs_objectwrap.h"
21 static void iotjs_pwm_destroy(iotjs_pwm_t* pwm);
22 static iotjs_pwm_t* iotjs_pwm_instance_from_jval(const iotjs_jval_t* jpwm);
25 static iotjs_pwm_t* iotjs_pwm_create(const iotjs_jval_t* jpwm) {
26 iotjs_pwm_t* pwm = IOTJS_ALLOC(iotjs_pwm_t);
27 IOTJS_VALIDATED_STRUCT_CONSTRUCTOR(iotjs_pwm_t, pwm);
28 iotjs_jobjectwrap_initialize(&_this->jobjectwrap, jpwm,
29 (JFreeHandlerType)iotjs_pwm_destroy);
32 _this->duty_cycle = 0;
33 #if defined(__NUTTX__)
34 _this->device_fd = -1;
40 static void iotjs_pwm_destroy(iotjs_pwm_t* pwm) {
41 IOTJS_VALIDATED_STRUCT_DESTRUCTOR(iotjs_pwm_t, pwm);
42 iotjs_jobjectwrap_destroy(&_this->jobjectwrap);
43 #if defined(__linux__)
44 iotjs_string_destroy(&_this->device);
50 #define THIS iotjs_pwm_reqwrap_t* pwm_reqwrap
53 static iotjs_pwm_reqwrap_t* iotjs_pwm_reqwrap_create(
54 const iotjs_jval_t* jcallback, const iotjs_jval_t* jpwm, PwmOp op) {
55 iotjs_pwm_reqwrap_t* pwm_reqwrap = IOTJS_ALLOC(iotjs_pwm_reqwrap_t);
56 IOTJS_VALIDATED_STRUCT_CONSTRUCTOR(iotjs_pwm_reqwrap_t, pwm_reqwrap);
58 iotjs_reqwrap_initialize(&_this->reqwrap, jcallback, (uv_req_t*)&_this->req);
60 _this->req_data.op = op;
61 _this->pwm_instance = iotjs_pwm_instance_from_jval(jpwm);
62 _this->req_data.caller = NULL;
68 static void iotjs_pwm_reqwrap_destroy(THIS) {
69 IOTJS_VALIDATED_STRUCT_DESTRUCTOR(iotjs_pwm_reqwrap_t, pwm_reqwrap);
70 iotjs_reqwrap_destroy(&_this->reqwrap);
71 IOTJS_RELEASE(pwm_reqwrap);
75 static void iotjs_pwm_reqwrap_dispatched(THIS) {
76 IOTJS_VALIDATABLE_STRUCT_METHOD_VALIDATE(iotjs_pwm_reqwrap_t, pwm_reqwrap);
77 iotjs_pwm_reqwrap_destroy(pwm_reqwrap);
81 static uv_work_t* iotjs_pwm_reqwrap_req(THIS) {
82 IOTJS_VALIDATED_STRUCT_METHOD(iotjs_pwm_reqwrap_t, pwm_reqwrap);
87 static const iotjs_jval_t* iotjs_pwm_reqwrap_jcallback(THIS) {
88 IOTJS_VALIDATED_STRUCT_METHOD(iotjs_pwm_reqwrap_t, pwm_reqwrap);
89 return iotjs_reqwrap_jcallback(&_this->reqwrap);
93 static iotjs_pwm_t* iotjs_pwm_instance_from_jval(const iotjs_jval_t* jpwm) {
94 uintptr_t handle = iotjs_jval_get_object_native_handle(jpwm);
95 return (iotjs_pwm_t*)handle;
99 iotjs_pwm_reqwrap_t* iotjs_pwm_reqwrap_from_request(uv_work_t* req) {
100 return (iotjs_pwm_reqwrap_t*)(iotjs_reqwrap_from_request((uv_req_t*)req));
104 iotjs_pwm_reqdata_t* iotjs_pwm_reqwrap_data(THIS) {
105 IOTJS_VALIDATED_STRUCT_METHOD(iotjs_pwm_reqwrap_t, pwm_reqwrap);
106 return &_this->req_data;
110 iotjs_pwm_t* iotjs_pwm_instance_from_reqwrap(THIS) {
111 IOTJS_VALIDATED_STRUCT_METHOD(iotjs_pwm_reqwrap_t, pwm_reqwrap);
112 return _this->pwm_instance;
116 static void iotjs_pwm_set_configuration(const iotjs_jval_t* jconfiguration,
118 IOTJS_VALIDATED_STRUCT_METHOD(iotjs_pwm_t, pwm);
121 iotjs_jval_get_property(jconfiguration, IOTJS_MAGIC_STRING_PIN);
122 _this->pin = iotjs_jval_as_number(&jpin);
124 #if defined(__linux__)
126 iotjs_jval_get_property(jconfiguration, IOTJS_MAGIC_STRING_CHIP);
127 _this->chip = iotjs_jval_as_number(&jchip);
128 iotjs_jval_destroy(&jchip);
131 iotjs_jval_t jperiod =
132 iotjs_jval_get_property(jconfiguration, IOTJS_MAGIC_STRING_PERIOD);
133 if (iotjs_jval_is_number(&jperiod))
134 _this->period = iotjs_jval_as_number(&jperiod);
136 iotjs_jval_t jduty_cycle =
137 iotjs_jval_get_property(jconfiguration, IOTJS_MAGIC_STRING_DUTYCYCLE);
138 if (iotjs_jval_is_number(&jduty_cycle))
139 _this->duty_cycle = iotjs_jval_as_number(&jduty_cycle);
141 iotjs_jval_destroy(&jpin);
142 iotjs_jval_destroy(&jperiod);
143 iotjs_jval_destroy(&jduty_cycle);
149 static void iotjs_pwm_common_worker(uv_work_t* work_req) {
152 IOTJS_ASSERT(req_data->caller != NULL);
154 if (!req_data->caller(pwm)) {
155 req_data->result = false;
159 req_data->result = true;
163 static void iotjs_pwm_after_worker(uv_work_t* work_req, int status) {
164 iotjs_pwm_reqwrap_t* req_wrap = iotjs_pwm_reqwrap_from_request(work_req);
165 iotjs_pwm_reqdata_t* req_data = iotjs_pwm_reqwrap_data(req_wrap);
166 iotjs_jargs_t jargs = iotjs_jargs_create(1);
167 bool result = req_data->result;
170 iotjs_jval_t error = iotjs_jval_create_error("System error");
171 iotjs_jargs_append_jval(&jargs, &error);
172 iotjs_jval_destroy(&error);
174 switch (req_data->op) {
177 iotjs_jargs_append_error(&jargs, "Failed to open PWM device");
179 iotjs_jargs_append_null(&jargs);
182 case kPwmOpSetDutyCycle:
184 iotjs_jargs_append_error(&jargs, "Failed to set duty-cycle");
186 iotjs_jargs_append_null(&jargs);
189 case kPwmOpSetPeriod:
191 iotjs_jargs_append_error(&jargs, "Failed to set period");
193 iotjs_jargs_append_null(&jargs);
196 case kPwmOpSetEnable:
198 iotjs_jargs_append_error(&jargs, "Failed to set enable");
200 iotjs_jargs_append_null(&jargs);
205 iotjs_jargs_append_error(&jargs, "Cannot close PWM device");
207 iotjs_jargs_append_null(&jargs);
211 IOTJS_ASSERT(!"Unreachable");
217 const iotjs_jval_t* jcallback = iotjs_pwm_reqwrap_jcallback(req_wrap);
218 iotjs_make_callback(jcallback, iotjs_jval_get_undefined(), &jargs);
220 iotjs_jargs_destroy(&jargs);
222 iotjs_pwm_reqwrap_dispatched(req_wrap);
226 #define PWM_ASYNC(call, jthis, jcallback, op) \
228 uv_loop_t* loop = iotjs_environment_loop(iotjs_environment_get()); \
229 iotjs_pwm_reqwrap_t* req_wrap = \
230 iotjs_pwm_reqwrap_create(jcallback, jthis, op); \
231 uv_work_t* req = iotjs_pwm_reqwrap_req(req_wrap); \
232 uv_queue_work(loop, req, iotjs_pwm_##call##_worker, \
233 iotjs_pwm_after_worker); \
237 #define PWM_ASYNC_COMMON_WORKER(call, jthis, jcallback, op) \
239 uv_loop_t* loop = iotjs_environment_loop(iotjs_environment_get()); \
240 iotjs_pwm_reqwrap_t* req_wrap = \
241 iotjs_pwm_reqwrap_create(jcallback, jthis, op); \
242 uv_work_t* req = iotjs_pwm_reqwrap_req(req_wrap); \
243 iotjs_pwm_reqdata_t* req_data = iotjs_pwm_reqwrap_data(req_wrap); \
244 req_data->caller = call; \
245 uv_queue_work(loop, req, iotjs_pwm_common_worker, iotjs_pwm_after_worker); \
249 JHANDLER_FUNCTION(PWMConstructor) {
250 JHANDLER_CHECK_THIS(object);
251 JHANDLER_CHECK_ARGS(2, object, function);
254 const iotjs_jval_t* jpwm = JHANDLER_GET_THIS(object);
255 iotjs_pwm_t* pwm = iotjs_pwm_create(jpwm);
256 IOTJS_ASSERT(pwm == iotjs_pwm_instance_from_jval(jpwm));
258 const iotjs_jval_t* jconfiguration = JHANDLER_GET_ARG(0, object);
259 const iotjs_jval_t* jcallback = JHANDLER_GET_ARG(1, function);
262 iotjs_pwm_set_configuration(jconfiguration, pwm);
264 PWM_ASYNC(open, jpwm, jcallback, kPwmOpOpen);
268 JHANDLER_FUNCTION(SetPeriod) {
269 JHANDLER_CHECK_ARGS(1, number);
270 JHANDLER_CHECK_ARG_IF_EXIST(1, function);
272 const iotjs_jval_t* jcallback = JHANDLER_GET_ARG_IF_EXIST(1, function);
273 const iotjs_jval_t* jpwm = JHANDLER_GET_THIS(object);
274 iotjs_pwm_t* pwm = iotjs_pwm_instance_from_jval(jpwm);
276 IOTJS_VALIDATED_STRUCT_METHOD(iotjs_pwm_t, pwm);
277 _this->period = JHANDLER_GET_ARG(0, number);
280 PWM_ASYNC_COMMON_WORKER(iotjs_pwm_set_period, jpwm, jcallback,
283 if (!iotjs_pwm_set_period(pwm)) {
284 JHANDLER_THROW(COMMON, "PWM SetPeriod Error");
288 iotjs_jhandler_return_null(jhandler);
292 JHANDLER_FUNCTION(SetDutyCycle) {
293 JHANDLER_CHECK_ARGS(1, number);
294 JHANDLER_CHECK_ARG_IF_EXIST(1, function);
296 const iotjs_jval_t* jcallback = JHANDLER_GET_ARG_IF_EXIST(1, function);
297 const iotjs_jval_t* jpwm = JHANDLER_GET_THIS(object);
298 iotjs_pwm_t* pwm = iotjs_pwm_instance_from_jval(jpwm);
300 IOTJS_VALIDATED_STRUCT_METHOD(iotjs_pwm_t, pwm);
301 _this->duty_cycle = JHANDLER_GET_ARG(0, number);
304 PWM_ASYNC_COMMON_WORKER(iotjs_pwm_set_dutycycle, jpwm, jcallback,
307 if (!iotjs_pwm_set_dutycycle(pwm)) {
308 JHANDLER_THROW(COMMON, "PWM SetDutyCycle Error");
312 iotjs_jhandler_return_null(jhandler);
316 JHANDLER_FUNCTION(SetEnable) {
317 JHANDLER_CHECK_ARGS(1, boolean);
318 JHANDLER_CHECK_ARG_IF_EXIST(1, function);
320 const iotjs_jval_t* jcallback = JHANDLER_GET_ARG_IF_EXIST(1, function);
321 const iotjs_jval_t* jpwm = JHANDLER_GET_THIS(object);
322 iotjs_pwm_t* pwm = iotjs_pwm_instance_from_jval(jpwm);
324 IOTJS_VALIDATED_STRUCT_METHOD(iotjs_pwm_t, pwm);
325 _this->enable = JHANDLER_GET_ARG(0, boolean);
328 PWM_ASYNC_COMMON_WORKER(iotjs_pwm_set_enable, jpwm, jcallback,
331 if (!iotjs_pwm_set_enable(pwm)) {
332 JHANDLER_THROW(COMMON, "PWM SetEnabe Error");
336 iotjs_jhandler_return_null(jhandler);
340 JHANDLER_FUNCTION(Close) {
341 JHANDLER_CHECK_THIS(object);
342 JHANDLER_CHECK_ARG_IF_EXIST(0, function);
344 const iotjs_jval_t* jcallback = JHANDLER_GET_ARG_IF_EXIST(0, function);
345 const iotjs_jval_t* jpwm = JHANDLER_GET_THIS(object);
346 iotjs_pwm_t* pwm = iotjs_pwm_instance_from_jval(jpwm);
349 PWM_ASYNC_COMMON_WORKER(iotjs_pwm_close, jpwm, jcallback, kPwmOpClose);
351 if (!iotjs_pwm_close(pwm)) {
352 JHANDLER_THROW(COMMON, "PWM Close Error");
356 iotjs_jhandler_return_null(jhandler);
360 iotjs_jval_t InitPwm() {
361 iotjs_jval_t jpwm_constructor =
362 iotjs_jval_create_function_with_dispatch(PWMConstructor);
364 iotjs_jval_t jprototype = iotjs_jval_create_object();
366 iotjs_jval_set_method(&jprototype, IOTJS_MAGIC_STRING_SETPERIOD, SetPeriod);
367 iotjs_jval_set_method(&jprototype, IOTJS_MAGIC_STRING_SETDUTYCYCLE,
369 iotjs_jval_set_method(&jprototype, IOTJS_MAGIC_STRING_SETENABLE, SetEnable);
370 iotjs_jval_set_method(&jprototype, IOTJS_MAGIC_STRING_CLOSE, Close);
372 iotjs_jval_set_property_jval(&jpwm_constructor, IOTJS_MAGIC_STRING_PROTOTYPE,
375 iotjs_jval_destroy(&jprototype);
377 return jpwm_constructor;