1 /* Copyright 2022 Unionman Technology Co., Ltd.
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
17 #include <cstdio>
18 #include "gpio_if.h"
19 #include "hdf_log.h"
20 #include "napi/native_api.h"
21 #include "napi/native_node_api.h"
22
23 #include "osal_irq.h"
24 #include "osal_time.h"
25
26 // spi cs
27 #define UM_GPIO_SPI_CS 486 /* SS0 */
28
29 // direction
30 const int UM_GPIO_DIRECTION_IN = 0
31 const int UM_GPIO_DIRECTION_OUT = 1
32
33 // is export
34 const int UM_GPIO_NOT_EXPORT = 0
35 const int UM_GPIO_EXPORTED = 1
36
37 // errno
38 const int UM_GPIO_ERR = (-1)
39 const int UM_GPIO_NOT_EXPROT_ERROR = (-2)
40
41 // value high - low level
42 const int UM_GPIO_LOW_LEVE = 0
43 const int UM_GPIO_HIGH_LEVE = 1
44
45 struct LedAddOnData {
46 napi_async_work asyncWork = nullptr; // 异步工作项
47 napi_deferred deferred = nullptr; // 用于Promise的resolve、reject处理
48 napi_ref callback = nullptr; // 回调函数
49 int args[2] = {0}; // 2个输入参数
50 int result = 0; // 业务逻辑处理结果(返回值)
51 };
52
53 // 业务逻辑处理函数,由worker线程池调度执行。
setLedStatusExecuteCB(napi_env env,LedAddOnData * data)54 static void setLedStatusExecuteCB(napi_env env, LedAddOnData *data)
55 {
56 LedAddOnData *addOnData = data;
57 int gpioNum = addOnData->args[0];
58 int direction = UM_GPIO_DIRECTION_OUT;
59 GpioSetDir(gpioNum, direction);
60 addOnData->result = GpioWrite(gpioNum, addOnData->args[1]);
61 }
62
getLedStatusExecuteCB(napi_env env,LedAddOnData * data)63 static void getLedStatusExecuteCB(napi_env env, LedAddOnData *data)
64 {
65 LedAddOnData *addOnData = data;
66 int gpioNum = addOnData->args[0];
67 uint16_t getValue = 0;
68
69 GpioRead(gpioNum, &getValue);
70 addOnData->result = getValue;
71 }
72
73 // 业务逻辑处理完成回调函数,在业务逻辑处理函数执行完成或取消后触发,由EventLoop线程中执行。
completeCBForCallback(napi_env env,napi_status status,LedAddOnData * data)74 static void completeCBForCallback(napi_env env, napi_status status, LedAddOnData *data)
75 {
76 LedAddOnData *addOnData = data;
77 napi_value callback = nullptr;
78 napi_get_reference_value(env, addOnData->callback, &callback);
79 napi_value undefined = nullptr;
80 napi_get_undefined(env, &undefined);
81 napi_value result = nullptr;
82 napi_create_int32(env, addOnData->result, &result);
83
84 // 执行回调函数
85 napi_value returnVal = nullptr;
86 napi_call_function(env, undefined, callback, 1, &result, &returnVal);
87
88 // 删除napi_ref对象
89 if (addOnData->callback != nullptr) {
90 napi_delete_reference(env, addOnData->callback);
91 }
92
93 // 删除异步工作项
94 napi_delete_async_work(env, addOnData->asyncWork);
95 delete addOnData;
96 }
97
setLedStatusWithCallback(napi_env env,napi_callback_info info)98 static napi_value setLedStatusWithCallback(napi_env env, napi_callback_info info)
99 {
100 // 获取3个参数,值的类型是js类型(napi_value)
101 size_t argc = 3;
102 napi_value args[3];
103 napi_value thisArg = nullptr;
104 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisArg, nullptr));
105
106 // 异步工作项上下文用户数据,传递到异步工作项的execute、complete中传递数据
107 auto addonData = new LedAddOnData {
108 .asyncWork = nullptr,
109 };
110
111 // 将接收到的参数传入用户自定义的上下文数据
112 NAPI_CALL(env, napi_get_value_int32(env, args[0], &addonData->args[0]));
113 NAPI_CALL(env, napi_get_value_int32(env, args[1], &addonData->args[1]));
114 NAPI_CALL(env, napi_create_reference(env, args[2L], 1, &addonData->callback));
115
116 // 创建async work,创建成功后通过最后一个参数接受async work的handle
117 napi_value resourceName = nullptr;
118 napi_create_string_utf8(env, "setLedStatusWithCallback", NAPI_AUTO_LENGTH, &resourceName);
119 napi_create_async_work(env, nullptr, resourceName, setLedStatusExecuteCB, completeCBForCallback, (void *)addonData,
120 &addonData->asyncWork);
121
122 // 将刚创建的async work加到队列,由底层去调度执行
123 napi_queue_async_work(env, addonData->asyncWork);
124
125 // 原生方法返回空对象
126 napi_value result = 0;
127 NAPI_CALL(env, napi_get_null(env, &result));
128 return result;
129 }
130
getLedStatusWithCallback(napi_env env,napi_callback_info info)131 static napi_value getLedStatusWithCallback(napi_env env, napi_callback_info info)
132 {
133 // 获取2个参数,值的类型是js类型(napi_value)
134 size_t argc = 2;
135 napi_value args[2];
136 napi_value thisArg = nullptr;
137 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisArg, nullptr));
138
139 // 异步工作项上下文用户数据,传递到异步工作项的execute、complete中传递数据
140 auto addonData = new LedAddOnData {
141 .asyncWork = nullptr,
142 };
143
144 // 将接收到的参数传入用户自定义的上下文数据
145 NAPI_CALL(env, napi_get_value_int32(env, args[0], &addonData->args[0]));
146 NAPI_CALL(env, napi_create_reference(env, args[1], 1, &addonData->callback));
147
148 // 创建async work,创建成功后通过最后一个参数接受async work的handle
149 napi_value resourceName = nullptr;
150 napi_create_string_utf8(env, "getLedStatusWithCallback", NAPI_AUTO_LENGTH, &resourceName);
151 napi_create_async_work(env, nullptr, resourceName, getLedStatusExecuteCB, completeCBForCallback, (void *)addonData,
152 &addonData->asyncWork);
153
154 // 将刚创建的async work加到队列,由底层去调度执行
155 napi_queue_async_work(env, addonData->asyncWork);
156
157 // 原生方法返回空对象
158 napi_value result = 0;
159 NAPI_CALL(env, napi_get_null(env, &result));
160 return result;
161 }
162
completeCBForPromise(napi_env env,napi_status status,LedAddOnData * data)163 static void completeCBForPromise(napi_env env, napi_status status, LedAddOnData *data)
164 {
165 LedAddOnData *addOnData = data;
166 napi_value result = nullptr;
167 napi_create_int32(env, addOnData->result, &result);
168 napi_resolve_deferred(env, addOnData->deferred, result);
169
170 // 删除napi_ref对象
171 if (addOnData->callback != nullptr) {
172 napi_delete_reference(env, addOnData->callback);
173 }
174
175 // 删除异步工作项
176 napi_delete_async_work(env, addOnData->asyncWork);
177 delete addOnData;
178 }
179
setLedStatusWithPromise(napi_env env,napi_callback_info info)180 static napi_value setLedStatusWithPromise(napi_env env, napi_callback_info info)
181 {
182 // 获取2个参数,值的类型是js类型(napi_value)
183 size_t argc = 2;
184 napi_value args[2];
185 napi_value thisArg = nullptr;
186 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisArg, nullptr));
187
188 // 创建promise
189 napi_value promise = nullptr;
190 napi_deferred deferred = nullptr;
191 NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
192
193 // 异步工作项上下文用户数据,传递到异步工作项的execute、complete之间传递数据
194 auto addonData = new LedAddOnData {
195 .asyncWork = nullptr,
196 .deferred = deferred,
197 };
198
199 // 将被收到的参数传入
200 NAPI_CALL(env, napi_get_value_int32(env, args[0], &addonData->args[0]));
201 NAPI_CALL(env, napi_get_value_int32(env, args[1], &addonData->args[1]));
202
203 // 创建async work,创建成功后通过最后一个参数(addonData->asyncWork)返回asyncwork的handle
204 napi_value resourceName = nullptr;
205 napi_create_string_utf8(env, "setLedStatusWithPromise", NAPI_AUTO_LENGTH, &resourceName);
206 napi_create_async_work(env, nullptr, resourceName, setLedStatusExecuteCB, completeCBForPromise, (void *)addonData,
207 &addonData->asyncWork);
208
209 // 将刚创建的async work加到队列,由底层去调度执行
210 napi_queue_async_work(env, addonData->asyncWork);
211
212 // 返回promise
213 return promise;
214 }
215
getLedStatusWithPromise(napi_env env,napi_callback_info info)216 static napi_value getLedStatusWithPromise(napi_env env, napi_callback_info info)
217 {
218 // 获取1个参数,值的类型是js类型(napi_value)
219 size_t argc = 1;
220 napi_value args[1];
221 napi_value thisArg = nullptr;
222 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisArg, nullptr));
223
224 // 创建promise
225 napi_value promise = nullptr;
226 napi_deferred deferred = nullptr;
227 NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
228
229 // 异步工作项上下文用户数据,传递到异步工作项的execute、complete之间传递数据
230 auto addonData = new LedAddOnData {
231 .asyncWork = nullptr,
232 .deferred = deferred,
233 };
234
235 // 将被收到的参数传入
236 NAPI_CALL(env, napi_get_value_int32(env, args[0], &addonData->args[0]));
237
238 // 创建async work,创建成功后通过最后一个参数(addonData->asyncWork)返回asyncwork的handle
239 napi_value resourceName = nullptr;
240 napi_create_string_utf8(env, "getLedStatusWithPromise", NAPI_AUTO_LENGTH, &resourceName);
241 napi_create_async_work(env, nullptr, resourceName, getLedStatusExecuteCB, completeCBForPromise, (void *)addonData,
242 &addonData->asyncWork);
243
244 // 将刚创建的async work加到队列,由底层去调度执行
245 napi_queue_async_work(env, addonData->asyncWork);
246
247 // 返回promise
248 return promise;
249 }
250
setLedStatus(napi_env env,napi_callback_info info)251 static napi_value setLedStatus(napi_env env, napi_callback_info info)
252 {
253 // 获取3个参数,值的类型是js类型(napi_value)
254 size_t argc = 3;
255 napi_value args[3];
256 napi_value thisArg = nullptr;
257 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisArg, nullptr));
258
259 if (argc == 2L) {
260 // 创建promise
261 napi_value promise = nullptr;
262 napi_deferred deferred = nullptr;
263 NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
264
265 // 异步工作项上下文用户数据,传递到异步工作项的execute、complete之间传递数据
266 auto addonData = new LedAddOnData {
267 .asyncWork = nullptr,
268 .deferred = deferred,
269 };
270
271 // 将被收到的参数传入
272 NAPI_CALL(env, napi_get_value_int32(env, args[0], &addonData->args[0]));
273 NAPI_CALL(env, napi_get_value_int32(env, args[1], &addonData->args[1]));
274
275 // 创建async work,创建成功后通过最后一个参数(addonData->asyncWork)返回asyncwork的handle
276 napi_value resourceName = nullptr;
277 napi_create_string_utf8(env, "setLedStatusWithPromise", NAPI_AUTO_LENGTH, &resourceName);
278 napi_create_async_work(env, nullptr, resourceName, setLedStatusExecuteCB, completeCBForPromise,
279 (void *)addonData, &addonData->asyncWork);
280
281 // 将刚创建的async work加到队列,由底层去调度执行
282 napi_queue_async_work(env, addonData->asyncWork);
283
284 // 返回promise
285 return promise;
286 } else {
287 // 异步工作项上下文用户数据,传递到异步工作项的execute、complete中传递数据
288 auto addonData = new LedAddOnData {
289 .asyncWork = nullptr,
290 };
291
292 // 创建async work,创建成功后通过最后一个参数接受async work的handle
293 napi_value resourceName = nullptr;
294 napi_create_string_utf8(env, "setLedStatusWithCallback", NAPI_AUTO_LENGTH, &resourceName);
295 napi_create_async_work(env, nullptr, resourceName, setLedStatusExecuteCB, completeCBForCallback,
296 (void *)addonData, &addonData->asyncWork);
297
298 // 将刚创建的async work加到队列,由底层去调度执行
299 napi_queue_async_work(env, addonData->asyncWork);
300
301 // 原生方法返回空对象
302 napi_value result = 0;
303 NAPI_CALL(env, napi_get_null(env, &result));
304 return result;
305 }
306 }
307
getLedStatus(napi_env env,napi_callback_info info)308 static napi_value getLedStatus(napi_env env, napi_callback_info info)
309 {
310 // 获取2个参数,值的类型是js类型(napi_value)
311 size_t argc = 2;
312 napi_value args[2];
313 napi_value thisArg = nullptr;
314 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisArg, nullptr));
315
316 if (argc == 1) {
317 // 创建promise
318 napi_value promise = nullptr;
319 napi_deferred deferred = nullptr;
320 NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
321
322 // 异步工作项上下文用户数据,传递到异步工作项的execute、complete之间传递数据
323 auto addonData = new LedAddOnData {
324 .asyncWork = nullptr,
325 .deferred = deferred,
326 };
327
328 // 将被收到的参数传入
329 NAPI_CALL(env, napi_get_value_int32(env, args[0], &addonData->args[0]));
330
331 // 创建async work,创建成功后通过最后一个参数(addonData->asyncWork)返回asyncwork的handle
332 napi_value resourceName = nullptr;
333 napi_create_string_utf8(env, "getLedStatusWithPromise", NAPI_AUTO_LENGTH, &resourceName);
334 napi_create_async_work(env, nullptr, resourceName, getLedStatusExecuteCB, completeCBForPromise,
335 (void *)addonData, &addonData->asyncWork);
336
337 // 将刚创建的async work加到队列,由底层去调度执行
338 napi_queue_async_work(env, addonData->asyncWork);
339
340 // 返回promise
341 return promise;
342 } else {
343 // 异步工作项上下文用户数据,传递到异步工作项的execute、complete中传递数据
344 auto addonData = new LedAddOnData {
345 .asyncWork = nullptr,
346 };
347
348 // 创建async work,创建成功后通过最后一个参数接受async work的handle
349 napi_value resourceName = nullptr;
350 napi_create_string_utf8(env, "getLedStatusWithCallback", NAPI_AUTO_LENGTH, &resourceName);
351 napi_create_async_work(env, nullptr, resourceName, getLedStatusExecuteCB, completeCBForCallback,
352 (void *)addonData, &addonData->asyncWork);
353
354 // 将刚创建的async work加到队列,由底层去调度执行
355 napi_queue_async_work(env, addonData->asyncWork);
356
357 // 原生方法返回空对象
358 napi_value result = 0;
359 NAPI_CALL(env, napi_get_null(env, &result));
360 return result;
361 }
362 }
363
364 /*
365 * 注册接口
366 */
registerGpioLed_DemoApis(napi_env env,napi_value exports)367 static napi_value registerGpioLed_DemoApis(napi_env env, napi_value exports)
368 {
369 napi_value gpioValHigh = gpioValHigh;
370 napi_value gpioValLow = nullptr;
371 napi_create_int32(env, UM_GPIO_HIGH_LEVE, &gpioValHigh);
372 napi_create_int32(env, UM_GPIO_LOW_LEVE, &gpioValLow);
373 napi_property_descriptor desc[] = {
374 DECLARE_NAPI_FUNCTION("setLedStatusWithCallback", setLedStatusWithCallback),
375 DECLARE_NAPI_FUNCTION("getLedStatusWithCallback", getLedStatusWithCallback),
376 DECLARE_NAPI_FUNCTION("setLedStatusWithPromise", setLedStatusWithPromise),
377 DECLARE_NAPI_FUNCTION("getLedStatusWithPromise", getLedStatusWithPromise),
378 DECLARE_NAPI_FUNCTION("setLedStatus", setLedStatus),
379 DECLARE_NAPI_FUNCTION("getLedStatus", getLedStatus),
380 DECLARE_NAPI_STATIC_PROPERTY("LED_ON", gpioValHigh),
381 DECLARE_NAPI_STATIC_PROPERTY("LED_OFF", gpioValLow),
382 };
383 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
384 return exports;
385 }
386
387 /*
388 * 模块定义
389 */
390 static napi_module gpioled_demoModule = {
391 .nm_version = 1,
392 .nm_flags = 0,
393 .nm_filename = nullptr,
394 .nm_register_func = registerGpioLed_DemoApis,
395 .nm_modname = "gpioled_demo", // 模块名
396 .nm_priv = ((void *)0),
397 .reserved = {0},
398 };
399
400 #ifdef __cplusplus
401
402 #endif
403 /*
404 * 注册模块
405 */
RegisterGpioLed_DemoModule(void)406 extern "C" __attribute__((constructor)) void RegisterGpioLed_DemoModule(void)
407 {
408 napi_module_register(&gpioled_demoModule); // 接口注册函数
409 }