1 
2 #include <stdint.h>
3 
4 #include "genie_service.h"
5 #include "genie_sal_ble.h"
6 #include "genie_sal_uart.h"
7 
8 static uint8_t g_rssi_mac[GENIE_BLE_MAC_LEN];
9 
genie_bin_cmds_send(uint16_t opcode,uint8_t * p_data,uint16_t len)10 static void genie_bin_cmds_send(uint16_t opcode, uint8_t *p_data, uint16_t len)
11 {
12     uint8_t checksum = 0;
13 
14     genie_sal_uart_send_one_byte(opcode >> 8);
15     genie_sal_uart_send_one_byte(opcode & 0xff);
16     genie_sal_uart_send_one_byte(len >> 8);
17     genie_sal_uart_send_one_byte(len & 0xff);
18 
19     checksum += len >> 8;
20     checksum += (len & 0xff);
21 
22     while (len--)
23     {
24         checksum += *p_data;
25         genie_sal_uart_send_one_byte(*p_data++);
26     }
27 
28     genie_sal_uart_send_one_byte(checksum);
29 }
30 
genie_bin_cmds_error(uint8_t err_code)31 static void genie_bin_cmds_error(uint8_t err_code)
32 {
33     uint8_t code = err_code;
34 
35     genie_bin_cmds_send(GENIE_BIN_OPCODE_ERR, &code, 1);
36 }
37 
mesh_adv_ctl(uint8_t ctl,uint8_t * resp)38 static uint16_t mesh_adv_ctl(uint8_t ctl, uint8_t *resp)
39 {
40     resp[0] = 0x01;
41     resp[1] = ctl;
42 
43     switch (ctl)
44     {
45     case 0x00:
46     {
47         bt_mesh_adv_stop();
48         bt_mesh_prov_disable(BT_MESH_PROV_GATT | BT_MESH_PROV_ADV);
49     }
50     break;
51     case 0x01:
52     {
53         bt_mesh_adv_stop();
54         bt_mesh_prov_enable(BT_MESH_PROV_GATT | BT_MESH_PROV_ADV);
55         genie_event(GENIE_EVT_SDK_MESH_PBADV_START, NULL);
56     }
57     break;
58     case 0x02:
59     {
60         genie_event(GENIE_EVT_SDK_MESH_PBADV_TIMEOUT, NULL);
61     }
62     break;
63     default:
64         break;
65     }
66     return 2;
67 }
68 
reset_prov_info(uint8_t * resp)69 static uint16_t reset_prov_info(uint8_t *resp)
70 {
71     resp[0] = 0x03;
72     resp[1] = 0x01;
73     resp[2] = 0x01;
74 
75     genie_event(GENIE_EVT_HW_RESET_START, NULL);
76 
77     return 3;
78 }
79 
_send_rssi_msg(int8_t rssi)80 static void _send_rssi_msg(int8_t rssi)
81 {
82     uint8_t resp[9];
83 
84     resp[0] = 0x03;
85     resp[1] = 0x02;
86     //get mac
87     memcpy(resp + 2, g_rssi_mac, GENIE_BLE_MAC_LEN);
88     //get rssi
89     resp[8] = rssi;
90 
91     genie_bin_cmds_send(GENIE_BIN_OPCODE_CMD, resp, 9);
92 }
93 
get_device_info(uint8_t type,uint8_t * resp)94 static uint16_t get_device_info(uint8_t type, uint8_t *resp)
95 {
96     switch (type)
97     {
98     case 0x00:
99     { //Get provision info
100         resp[0] = 0x03;
101         resp[1] = 0x03;
102         if (bt_mesh_is_provisioned())
103         {
104             resp[2] = 0x01;
105         }
106         else
107         {
108             resp[2] = 0x00;
109         }
110         return 3;
111     }
112     case 0x01:
113     { //Get device version
114         uint32_t app_version = genie_version_appver_get();
115 
116         resp[0] = GENIE_CTL_DEVIE_INFO_AND_EVENT;
117         resp[1] = 0x06;
118         resp[2] = (uint8_t)(app_version >> 24);
119         resp[3] = (uint8_t)(app_version >> 16);
120         resp[4] = (uint8_t)(app_version >> 8);
121         resp[5] = (uint8_t)(app_version);
122 
123         return 6;
124     }
125     default:
126         break;
127     }
128     return 0;
129 }
130 
genie_bin_cmd_type_data(uint8_t * p_data)131 static void genie_bin_cmd_type_data(uint8_t *p_data)
132 {
133     uint16_t len = p_data[3] + (p_data[2] << 8);
134 
135     if (genie_sal_ble_send_msg(0, &p_data[4], len))
136     {
137         genie_bin_cmds_error(GENIE_BINARY_CMD_TRANSPARENT_ERR);
138     }
139 }
140 
get_ble_rssi_cb(uint8_t mac[6],int8_t rssi)141 static void get_ble_rssi_cb(uint8_t mac[6], int8_t rssi)
142 {
143     if (memcmp(g_rssi_mac, mac, GENIE_BLE_MAC_LEN) == 0)
144     {
145         _send_rssi_msg(rssi);
146         memset(g_rssi_mac, 0, GENIE_BLE_MAC_LEN);
147     }
148     else
149     {
150         genie_bin_cmds_error(GENIE_BINARY_CMD_GET_RSSI_MAC_NOT_MATCH_ERR);
151     }
152 }
153 
genie_bin_cmd_update_group_addr(uint8_t * addr_list,int addr_len)154 static int genie_bin_cmd_update_group_addr(uint8_t *addr_list, int addr_len)
155 {
156     int index = 0;
157     uint8_t group_addr_list[CONFIG_BT_MESH_MODEL_GROUP_COUNT * 2] = {0};
158 
159     if ((addr_len > CONFIG_BT_MESH_MODEL_GROUP_COUNT * 2) || ((addr_len % 2) != 0))
160     {
161         return -1;
162     }
163 
164     memset(group_addr_list, 0, CONFIG_BT_MESH_MODEL_GROUP_COUNT * 2);
165     memcpy(group_addr_list, addr_list, addr_len);
166 
167     for (index = 0; index < addr_len; index++)
168     {
169         if ((index % 2) == 0)
170         {
171             if ((group_addr_list[index + 1] & 0xC0) != 0xC0) //invalid group address
172             {
173                 return -2;
174             }
175         }
176     }
177 
178     /* set group addr */
179     if (genie_storage_write_sub((uint16_t *)group_addr_list) != GENIE_STORAGE_SUCCESS)
180     {
181         return -3;
182     }
183 
184     /* get group addr */
185     if (genie_storage_read_sub((uint16_t *)g_sub_list) != GENIE_STORAGE_SUCCESS)
186     {
187         return -3;
188     }
189 
190     return 0;
191 }
192 
get_mesh_group_addr(uint8_t * response)193 static int get_mesh_group_addr(uint8_t *response)
194 {
195     int i = 0;
196     int j = 0;
197     uint8_t group_addr_list[CONFIG_BT_MESH_MODEL_GROUP_COUNT * 2] = {0};
198 
199     /* get group addr */
200     if (genie_storage_read_sub((uint16_t *)group_addr_list) != GENIE_STORAGE_SUCCESS)
201     {
202         return -1;
203     }
204 
205     for (i = 0; i < CONFIG_BT_MESH_MODEL_GROUP_COUNT * 2; i++)
206     {
207         if (i % 2 == 0)
208         {
209             if ((group_addr_list[i + 1] & 0xC0) == 0xC0) //valid group address
210             {
211                 response[j] = group_addr_list[i];
212                 response[j + 1] = group_addr_list[i + 1];
213                 j += 2;
214             }
215         }
216     }
217 
218     return j;
219 }
220 
genie_bin_cmd_type_command(uint8_t * p_data)221 static void genie_bin_cmd_type_command(uint8_t *p_data)
222 {
223     uint8_t *p_u8 = p_data;
224     uint16_t len = p_u8[3] + (p_u8[2] << 8);
225 
226     uint8_t resp[20];
227     uint16_t resp_len = 0;
228 
229     switch (p_u8[4])
230     {
231     case GENIE_CTL_MESH_ADV:
232         if (len == 2)
233         {
234             resp_len = mesh_adv_ctl(p_u8[5], resp);
235         }
236         break;
237 
238     case GENIE_CTL_CLEAR_PROV_INFO:
239         if (len == 1)
240         {
241             resp_len = reset_prov_info(resp);
242         }
243         break;
244 
245     case GENIE_CTL_TEST_MODE:
246         if (len == 8)
247         {
248             if (p_u8[5] == 0x00)
249             {
250                 memcpy(g_rssi_mac, &p_u8[6], GENIE_BLE_MAC_LEN); //backup mac addr
251                 if (genie_sal_ble_get_rssi(g_rssi_mac, (genie_sal_ble_get_rssi_cb)get_ble_rssi_cb, 5000) < 0)
252                 {
253                     return genie_bin_cmds_error(GENIE_BINARY_CMD_GET_RSSI_BLE_ERR);
254                 }
255             }
256             else
257             {
258                 return genie_bin_cmds_error(GENIE_BINARY_CMD_GET_RSSI_INPUT_ERR);
259             }
260         }
261         else
262         {
263             return genie_bin_cmds_error(GENIE_BINARY_CMD_GET_RSSI_INPUT_ERR);
264         }
265         break;
266     case GENIE_CTL_DEVICE_INFO:
267         if (len == 2)
268         {
269             resp_len = get_device_info(p_u8[5], resp);
270         }
271         break;
272     case GENIE_CTL_REBOOT_DEVICE:
273         if (len == 1)
274         {
275             aos_reboot();
276         }
277         break;
278     case GENIE_CTL_UPDATE_GROUP_ADDR:
279     {
280         int ret = 0;
281 
282         resp[0] = GENIE_CTL_UPDATE_GROUP_ADDR_RESPONSE;
283         ret = genie_bin_cmd_update_group_addr(&p_u8[5], len - 1);
284         if (0 == ret)
285         {
286             resp[1] = 0x00; //successful
287             resp_len = 2;
288         }
289         else if (-1 == ret)
290         {
291             return genie_bin_cmds_error(GENIE_BINARY_CMD_UPDATE_GROUP_ADDR_LEN_ERR);
292         }
293         else if (-2 == ret)
294         {
295             return genie_bin_cmds_error(GENIE_BINARY_CMD_UPDATE_GROUP_ADDR_INVALID_ERR);
296         }
297         else if (-3 == ret)
298         {
299             return genie_bin_cmds_error(GENIE_BINARY_CMD_UPDATE_GROUP_ADDR_FLASH_ERR);
300         }
301     }
302     break;
303     case GENIE_CTL_GET_GROUP_ADDR:
304     {
305         if (len == 1)
306         {
307             resp[0] = GENIE_CTL_GET_GOURP_ADDR_RESPONSE;
308             resp_len = get_mesh_group_addr(&resp[2]);
309             if (resp_len > 0) //Have valid group addr
310             {
311                 resp[1] = 0x00;
312                 resp_len += 2;
313             }
314             else //Have no valid group addr
315             {
316                 resp[1] = 0x01;
317                 resp_len = 2;
318             }
319         }
320     }
321     break;
322     case GENIE_CTL_FACTORY_TEST:
323     {
324         if (genie_sal_ble_set_factory_flag() != 0)
325         {
326             return genie_bin_cmds_error(GENIE_BINARY_CMD_START_FACTORY_ERR);
327         }
328         else
329         {
330             resp[0] = GENIE_CTL_FACTORY_TEST;
331             resp[1] = 0x00;
332             resp_len = 2;
333             genie_bin_cmds_send(GENIE_BIN_OPCODE_CMD, resp, resp_len);
334             aos_msleep(1000);
335             aos_reboot();
336         }
337     }
338     break;
339     case GENIE_CTL_SWITCH_DEBUG:
340     {
341         if (len == 2)
342         {
343             if (p_u8[5] > 0)
344             {
345                 g_mesh_log_mode = 1;
346                 aos_set_log_level(GENIE_MESH_DEFAULT_LOG_LEVEL);
347             }
348             else
349             {
350                 g_mesh_log_mode = 0;
351                 aos_set_log_level(LOG_EMERG);
352             }
353             resp[0] = GENIE_CTL_SWITCH_DEBUG;
354             resp[1] = 0x00;
355             resp_len = 2;
356         }
357         else
358         {
359             resp[0] = GENIE_CTL_SWITCH_DEBUG;
360             resp[1] = 0x01;
361             resp_len = 2;
362         }
363     }
364     break;
365     default:
366         break;
367     }
368 
369     //if resp_len = 0 do nothing
370     if (resp_len > 0) //need response
371     {
372         genie_bin_cmds_send(GENIE_BIN_OPCODE_CMD, resp, resp_len);
373     }
374     else if (resp_len < 0)
375     {
376         genie_bin_cmds_error(GENIE_BINARY_CMD_UNKNOW_ERR);
377     }
378 }
379 
genie_bin_cmds_handle(uint8_t * p_data,uint8_t data_len)380 int genie_bin_cmds_handle(uint8_t *p_data, uint8_t data_len)
381 {
382     uint16_t len = 0;
383     uint16_t index = 0;
384     uint8_t checksum = 0;
385 
386     if ((data_len > 0) && (p_data[0] != 0xFF) && (p_data[0] != 0xFE))
387     {
388         return 0; //Don't send any data by UART
389     }
390 
391     if (data_len < GENIE_BIN_MIN_DATA_LEN)
392     {
393         genie_bin_cmds_error(GENIE_BINARY_CMD_TOTAL_LEN_ERR);
394         return -1;
395     }
396 
397     len = p_data[3] + (p_data[2] << 8);
398     if (len != (data_len - 5))
399     {
400         genie_bin_cmds_error(GENIE_BINARY_CMD_DATA_LEN_ERR);
401         return -1;
402     }
403 
404     checksum += p_data[2];
405     checksum += p_data[3];
406 
407     while (index < len)
408     {
409         checksum += p_data[4 + index];
410         index++;
411     }
412 
413     if (checksum != p_data[data_len - 1])
414     {
415         genie_bin_cmds_error(GENIE_BINARY_CMD_CRC_ERR);
416         return -1;
417     }
418 
419     if (((p_data[0] << 8) | p_data[1]) == GENIE_BIN_OPCODE_DATA)
420     {
421         genie_bin_cmd_type_data(p_data);
422     }
423     else if (((p_data[0] << 8) | p_data[1]) == GENIE_BIN_OPCODE_CMD)
424     {
425         genie_bin_cmd_type_command(p_data);
426     }
427 
428     return 0;
429 }
430 
genie_bin_cmd_handle_event(genie_event_e event,void * p_arg)431 int genie_bin_cmd_handle_event(genie_event_e event, void *p_arg)
432 {
433     uint8_t report_data[2];
434     uint8_t report_data_len = 0;
435 
436     if (event == GENIE_EVT_MESH_READY)
437     {
438         report_data[0] = 0x03;
439         report_data[1] = 0x04;
440         report_data_len = 2;
441     }
442     else if (event == GENIE_EVT_SDK_MESH_PROV_SUCCESS)
443     {
444         report_data[0] = 0x03;
445         report_data[1] = 0x00;
446         report_data_len = 2;
447     }
448     else if (event == GENIE_EVT_SDK_MESH_PROV_FAIL)
449     {
450         report_data[0] = 0x03;
451         report_data[1] = 0x05;
452         report_data_len = 2;
453     }
454 
455     if (report_data_len > 0)
456     {
457         genie_bin_cmds_send(GENIE_BIN_OPCODE_CMD, report_data, report_data_len);
458     }
459 
460     return 0;
461 }
462 
genie_bin_cmds_send_data_to_mcu(uint8_t * p_data,uint8_t len)463 void genie_bin_cmds_send_data_to_mcu(uint8_t *p_data, uint8_t len)
464 {
465     genie_bin_cmds_send(GENIE_BIN_OPCODE_DATA, p_data, len);
466 }
467