1 /*
2 * Copyright (C) 2015-2019 Alibaba Group Holding Limited
3 */
4
5 #include <stdint.h>
6
7 #include "amp_config.h"
8 #include "amp_defines.h"
9 #include "aos_hal_i2c.h"
10 #include "board_mgr.h"
11 #include "be_inl.h"
12
13 #define MOD_STR "I2C"
14
15 #define I2C_TIMEOUT (0xFFFFFF)
16
native_i2c_open(duk_context * ctx)17 static duk_ret_t native_i2c_open(duk_context *ctx)
18 {
19 int8_t ret = -1;
20 item_handle_t i2c_handle;
21 i2c_handle.handle = NULL;
22 i2c_dev_t *i2c_device = NULL;
23
24 if (!duk_is_string(ctx, 0)) {
25 amp_warn(MOD_STR, "parameter must be string");
26 goto out;
27 }
28 const char *id = duk_get_string(ctx, 0);
29 ret = board_attach_item(MODULE_I2C, id, &i2c_handle);
30 if (0 != ret) {
31 amp_error(MOD_STR, "board_attach_item fail!");
32 goto out;
33 }
34 amp_debug(MOD_STR, "i2c handle:%u", i2c_handle.handle);
35 i2c_device = board_get_node_by_handle(MODULE_I2C, &i2c_handle);
36 if (NULL == i2c_device) {
37 amp_error(MOD_STR, "board_get_node_by_handle fail!");
38 goto out;
39 }
40 ret = aos_hal_i2c_init(i2c_device);
41 if (0 != ret) {
42 amp_error(MOD_STR, "aos_hal_i2c_init fail!");
43 goto out;
44 }
45 out:
46 if (0 != ret) {
47 duk_push_pointer(ctx, NULL);
48 board_disattach_item(MODULE_I2C, &i2c_handle);
49 } else {
50 duk_push_pointer(ctx, (void *)i2c_handle.handle);
51 }
52 return 1;
53 }
54
native_i2c_close(duk_context * ctx)55 static duk_ret_t native_i2c_close(duk_context *ctx)
56 {
57 int8_t ret = -1;
58 item_handle_t i2c_handle;
59 i2c_dev_t *i2c_device = NULL;
60
61 if (!duk_is_pointer(ctx, 0)) {
62 amp_warn(MOD_STR, "parameter must be handle");
63 goto out;
64 }
65 i2c_handle.handle = duk_get_pointer(ctx, 0);
66 i2c_device = board_get_node_by_handle(MODULE_I2C, &i2c_handle);
67 if (NULL == i2c_device) {
68 amp_error(MOD_STR, "board_get_node_by_handle fail!");
69 goto out;
70 }
71 ret = aos_hal_i2c_finalize(i2c_device);
72 if (0 != ret) {
73 amp_error(MOD_STR, "aos_hal_i2c_finalize fail!");
74 goto out;
75 }
76 board_disattach_item(MODULE_I2C, &i2c_handle);
77 out:
78 duk_push_int(ctx, ret);
79 return 1;
80 }
81
native_i2c_write(duk_context * ctx)82 static duk_ret_t native_i2c_write(duk_context *ctx)
83 {
84 int8_t ret = -1;
85 uint8_t *data = NULL;
86 uint32_t len = 0;
87 uint32_t i = 0;
88 item_handle_t i2c_handle;
89 i2c_dev_t *i2c_device = NULL;
90 int arr_idx;
91 int err = -1;
92
93 if (!duk_is_pointer(ctx, 0) || !duk_is_array(ctx, 1)) {
94 amp_warn(MOD_STR, "parameter must be handle and array");
95 goto out;
96 }
97
98 i2c_handle.handle = duk_get_pointer(ctx, 0);
99 i2c_device = board_get_node_by_handle(MODULE_I2C, &i2c_handle);
100 if (NULL == i2c_device) {
101 amp_error(MOD_STR, "board_get_node_by_handle fail!");
102 goto out;
103 }
104
105 arr_idx = duk_normalize_index(ctx, 1);
106 len = duk_get_length(ctx, arr_idx);
107 data = (uint8_t *)aos_malloc(sizeof(uint8_t) * len);
108 if (NULL == data) {
109 amp_warn(MOD_STR, "allocate memory failed");
110 goto out;
111 }
112 for (i = 0; i < len; i++) {
113 duk_get_prop_index(ctx, arr_idx, i);
114 if (!duk_is_number(ctx, -1)) {
115 amp_warn(MOD_STR, "data is not number, index is %d", i);
116 duk_pop(ctx);
117 goto out;
118 }
119 data[i] = (uint8_t)duk_get_int(ctx, -1);
120 duk_pop(ctx);
121 }
122
123 ret = aos_hal_i2c_master_send(i2c_device, i2c_device->config.dev_addr, data,
124 len, I2C_TIMEOUT);
125 if (-1 == ret) {
126 amp_error(MOD_STR, "aos_hal_i2c_master_send fail!");
127 goto out;
128 }
129 err = 0;
130 out:
131 aos_free(data);
132 duk_push_int(ctx, err);
133 return 1;
134 }
135
native_i2c_write_reg(duk_context * ctx)136 static duk_ret_t native_i2c_write_reg(duk_context *ctx)
137 {
138 int8_t ret = -1;
139 uint8_t *data = NULL;
140 uint32_t len = 0;
141 uint32_t i = 0;
142 item_handle_t i2c_handle;
143 i2c_dev_t *i2c_device = NULL;
144 uint16_t mem_addr;
145 int arr_idx;
146 int err = -1;
147
148 if (!duk_is_pointer(ctx, 0) || !duk_is_number(ctx, 1) || !duk_is_array(ctx, 2)) {
149 amp_warn(MOD_STR, "parameter must be handle number and array");
150 goto out;
151 }
152
153 i2c_handle.handle = duk_get_pointer(ctx, 0);
154 i2c_device = board_get_node_by_handle(MODULE_I2C, &i2c_handle);
155 if (NULL == i2c_device) {
156 amp_error(MOD_STR, "board_get_node_by_handle fail!");
157 goto out;
158 }
159
160 mem_addr = (uint16_t)duk_get_int(ctx, 1);
161
162 arr_idx = duk_normalize_index(ctx, 2);
163 len = duk_get_length(ctx, arr_idx);
164 data = (uint8_t *)aos_malloc(sizeof(uint8_t) * len);
165 if (NULL == data) {
166 amp_warn(MOD_STR, "allocate memory failed");
167 goto out;
168 }
169 for (i = 0; i < len; i++) {
170 duk_get_prop_index(ctx, arr_idx, i);
171 if (!duk_is_number(ctx, -1)) {
172 amp_warn(MOD_STR, "data is not number, index is %d", i);
173 duk_pop(ctx);
174 goto out;
175 }
176 data[i] = (uint8_t)duk_get_int(ctx, -1);
177 duk_pop(ctx);
178 }
179
180 ret = aos_hal_i2c_mem_write(i2c_device, i2c_device->config.dev_addr,
181 mem_addr, 1, data, len, I2C_TIMEOUT);
182 if (-1 == ret) {
183 amp_error(MOD_STR, "aos_hal_i2c_master_send fail!");
184 goto out;
185 }
186 err = 0;
187 out:
188 aos_free(data);
189 duk_push_int(ctx, err);
190 return 1;
191 }
192
native_i2c_read(duk_context * ctx)193 static duk_ret_t native_i2c_read(duk_context *ctx)
194 {
195 int8_t ret = -1;
196 uint8_t *data = NULL;
197 uint32_t len = 0;
198 uint32_t i = 0;
199 item_handle_t i2c_handle;
200 i2c_dev_t *i2c_device = NULL;
201
202 if (!duk_is_pointer(ctx, 0) || !duk_is_number(ctx, 1)) {
203 amp_warn(MOD_STR, "parameter must be handle and number");
204 goto out;
205 }
206 i2c_handle.handle = duk_get_pointer(ctx, 0);
207 i2c_device = board_get_node_by_handle(MODULE_I2C, &i2c_handle);
208 if (NULL == i2c_device) {
209 amp_error(MOD_STR, "board_get_node_by_handle fail!");
210 goto out;
211 }
212 len = duk_get_int(ctx, 1);
213 data = (uint8_t *)aos_malloc(sizeof(uint8_t) * len);
214 if (NULL == data) {
215 amp_error(MOD_STR, "allocate memory failed");
216 goto out;
217 }
218 ret = aos_hal_i2c_master_recv(i2c_device, i2c_device->config.dev_addr, data,
219 len, I2C_TIMEOUT);
220 if (-1 == ret) {
221 amp_error(MOD_STR, "aos_hal_i2c_master_recv fail!");
222 }
223 out:
224 if (!ret) {
225 duk_idx_t arr_idx = duk_push_array(ctx);
226 for (i = 0; i < len; i++) {
227 duk_push_int(ctx, data[i]);
228 duk_put_prop_index(ctx, arr_idx, i);
229 }
230 } else {
231 duk_push_null(ctx);
232 }
233 aos_free(data);
234 return 1;
235 }
236
native_i2c_read_reg(duk_context * ctx)237 static duk_ret_t native_i2c_read_reg(duk_context *ctx)
238 {
239 int8_t ret = -1;
240 uint8_t *data = NULL;
241 uint32_t len = 0;
242 uint32_t i = 0;
243 item_handle_t i2c_handle;
244 i2c_dev_t *i2c_device = NULL;
245 uint16_t mem_addr;
246 int arr_idx;
247 int err = -1;
248
249 if (!duk_is_pointer(ctx, 0) || !duk_is_number(ctx, 1) || !duk_is_number(ctx, 2)) {
250 amp_warn(MOD_STR, "parameter must be handle number and array");
251 goto out;
252 }
253
254 i2c_handle.handle = duk_get_pointer(ctx, 0);
255 i2c_device = board_get_node_by_handle(MODULE_I2C, &i2c_handle);
256 if (NULL == i2c_device) {
257 amp_error(MOD_STR, "board_get_node_by_handle fail!");
258 goto out;
259 }
260
261 mem_addr = (uint16_t)duk_get_int(ctx, 1);
262
263 len = duk_get_int(ctx, 2);
264 data = (uint8_t *)aos_malloc(sizeof(uint8_t) * len);
265 if (NULL == data) {
266 amp_warn(MOD_STR, "allocate memory failed");
267 goto out;
268 }
269
270 ret = aos_hal_i2c_mem_read(i2c_device, i2c_device->config.dev_addr,
271 mem_addr, 1, data, len, I2C_TIMEOUT);
272
273 out:
274 if (!ret) {
275 duk_idx_t arr_idx = duk_push_array(ctx);
276 for (i = 0; i < len; i++) {
277 duk_push_int(ctx, data[i]);
278 duk_put_prop_index(ctx, arr_idx, i);
279 }
280 } else {
281 duk_push_null(ctx);
282 }
283 aos_free(data);
284 return 1;
285 }
286
module_i2c_register(void)287 void module_i2c_register(void)
288 {
289 amp_debug(MOD_STR, "module_i2c_register");
290 duk_context *ctx = be_get_context();
291
292 duk_push_object(ctx);
293
294 AMP_ADD_FUNCTION("open", native_i2c_open, 1);
295 AMP_ADD_FUNCTION("read", native_i2c_read, 2);
296 AMP_ADD_FUNCTION("write", native_i2c_write, 2);
297 AMP_ADD_FUNCTION("readReg", native_i2c_read_reg, 3);
298 AMP_ADD_FUNCTION("writeReg", native_i2c_write_reg, 3);
299 AMP_ADD_FUNCTION("close", native_i2c_close, 1);
300
301 duk_put_prop_string(ctx, -2, "I2C");
302 }
303