• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }