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