1 /*
2  * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3  */
4 #include <stdlib.h>
5 
6 //#include <aos/aos.h>
7 #include <aos/kernel.h>
8 #include <port/mesh_hal_ble.h>
9 #include "mesh.h"
10 #include "common/log.h"
11 #include "flash.h"
12 #include "genie_service.h"
13 #include "genie_sal_uart.h"
14 
15 #define at_debug printf
16 
17 static const at_cmd_t genie_at_commands[] = {
18     //AT+CMD      AT+CMD=?        AT+CMD?
19     {BLE_MESH_ADV, genie_at_cmd_adv_start, "AT+" BLE_MESH_ADV "=<mode>", genie_at_cmd_adv_query},
20     {BLE_MESH_RESET, genie_at_cmd_mesh_reset, "AT+" BLE_MESH_RESET, NULL},
21     {BLE_MESH_REBOOT, genie_at_cmd_reboot, "AT+" BLE_MESH_REBOOT, NULL},
22     {BLE_MESH_INFO, NULL, "AT+" BLE_MESH_INFO, genie_at_cmd_mesh_info},
23     {BLE_MESH_VER, NULL, "AT+" BLE_MESH_VER, genie_at_cmd_mesh_ver},
24     {BLE_MESH_MAC, NULL, "AT+" BLE_MESH_MAC, genie_at_cmd_mesh_mac},
25     {BLE_MESH_FACTY_TEST, genie_at_cmd_facty_test, "AT+" BLE_MESH_FACTY_TEST, NULL},
26     {BLE_MESH_LOG, genie_at_cmd_mesh_log, "AT+" BLE_MESH_LOG "=<mode>", genie_at_cmd_mesh_log_query},
27     {BLE_MESH_TEST, genie_at_cmd_mesh_test, "AT+" BLE_MESH_TEST "=<opcode>,[param]", NULL},
28     {BLE_MESH_GROUP, genie_at_cmd_mesh_group, "AT+" BLE_MESH_GROUP "=<addr1>,[addr2]...", genie_at_cmd_mesh_group_query},
29     {BLE_MESH_MSG_TX, genie_at_cmd_mesh_trans_send, "AT+" BLE_MESH_MSG_TX "=<data>", NULL},
30     {BLE_MESH_EVENT, NULL, "+" BLE_MESH_EVENT ":<state>", NULL},
31     {BLE_MESH_MSG_RX, NULL, "+" BLE_MESH_MSG_RX ":<len>,<data>", NULL},
32     {NULL, NULL, NULL, NULL},
33 };
34 
35 static u8_t g_current_adv_mode = MESH_ADV_START;
36 static uint8_t test_dev_mac[6] = {0};
37 
str_chr(char * d,char * s,int c)38 static char *str_chr(char *d, char *s, int c)
39 {
40     int i = 0;
41     char *q = d;
42     char *p = s;
43 
44     for (i = 0; *(s + i) != (char)c; i++)
45     {
46         *(q++) = *(p++);
47 
48         if (*(s + i) == '\0')
49         {
50             return NULL;
51         }
52     }
53 
54     *(q++) = '\0';
55     return d;
56 }
57 
char_cut(char * d,char * s,int b,int e)58 static char *char_cut(char *d, char *s, int b, int e)
59 {
60     char *stc;
61 
62     if (b == '\0')
63     {
64         return NULL;
65     }
66 
67     stc = strchr(s, b);
68 
69     if (stc == NULL)
70     {
71         at_debug("not execute\r\n");
72         return NULL;
73     }
74 
75     stc++;
76     str_chr(d, stc, e);
77 
78     return d; //(char *)d;
79 }
80 
char2_hex(const char * c,uint8_t * x)81 static int char2_hex(const char *c, uint8_t *x)
82 {
83     if (*c >= '0' && *c <= '9')
84     {
85         *x = *c - '0';
86     }
87     else if (*c >= 'a' && *c <= 'f')
88     {
89         *x = *c - 'a' + 10;
90     }
91     else if (*c >= 'A' && *c <= 'F')
92     {
93         *x = *c - 'A' + 10;
94     }
95     else
96     {
97         return -EINVAL;
98     }
99 
100     return 0;
101 }
102 
str2_char(const char * str,uint8_t * addr)103 static int str2_char(const char *str, uint8_t *addr)
104 {
105     int i, j;
106     uint8_t tmp;
107 
108     if (strlen(str) != 17)
109     {
110         return -EINVAL;
111     }
112 
113     for (i = 0, j = 1; *str != '\0'; str++, j++)
114     {
115         if (!(j % 3) && (*str != ':'))
116         {
117             return -EINVAL;
118         }
119         else if (*str == ':')
120         {
121             i++;
122             continue;
123         }
124 
125         addr[i] = addr[i] << 4;
126 
127         if (char2_hex(str, &tmp) < 0)
128         {
129             return -EINVAL;
130         }
131 
132         addr[i] |= tmp;
133     }
134 
135     return 0;
136 }
137 
argv_type(char * s)138 static int argv_type(char *s)
139 {
140     int flag = 0;
141 
142     flag |= AT_CMD_NO_ADD;
143 
144     for (int i = 0; *(s + i) != '\0'; i++)
145     {
146         if (*(s + i) == '+')
147         {
148             flag = flag & (~0x1);
149             flag |= AT_CMD_ADD; //+ no =
150         }
151 
152         if (*(s + i) == '=')
153         { //, or not ,
154             if (*(s + i + 1) == '?')
155             {
156                 return AT_CMD_FIND;
157             }
158             else if (*(s + i + 1) != '\0')
159             {
160                 return AT_CMD_DOU;
161             }
162             else
163             {
164                 return 0;
165             }
166         }
167 
168         if (*(s + i) == '?')
169         {
170             flag = flag & (~0x2); //no +
171             flag |= AT_CMD_QUERY;
172         }
173     }
174 
175     return flag;
176 }
177 
argc_len(char * s)178 static int argc_len(char *s)
179 {
180     int i = 0;
181     int j = 0;
182 
183     for (i = 0; *(s + i) != '\0'; i++)
184     {
185         if ((*(s + i) == ',') || (*(s + i) == '?') || (*(s + i) == '='))
186         {
187             j++;
188         }
189     }
190 
191     return j;
192 }
193 
cmd_cli_func(int type,int argc,char ** argv)194 static void cmd_cli_func(int type, int argc, char **argv)
195 {
196     int i = 0;
197     int err;
198 
199     if (argc < 2)
200     {
201         genie_sal_uart_send_str("AT support commands\r\n");
202         for (i = 0; genie_at_commands[i].cmd_name != NULL; i++)
203         {
204             genie_sal_uart_send_str("%s %s\r\n", genie_at_commands[i].cmd_name, genie_at_commands[i].help);
205         }
206         return;
207     }
208 
209     for (i = 0; genie_at_commands[i].cmd_name != NULL; i++)
210     {
211         if (strlen(genie_at_commands[i].cmd_name) == strlen(argv[1]) &&
212             !strncmp(genie_at_commands[i].cmd_name, argv[1], strlen(genie_at_commands[i].cmd_name)))
213         {
214             if (type == AT_OP_EXECUTE)
215             {
216                 if (genie_at_commands[i].cb)
217                 {
218                     err = genie_at_commands[i].cb(argc - 1, &argv[1]);
219                     if (err == 0)
220                     {
221                         genie_sal_uart_send_str(AT_OK_STR);
222                     }
223                     else
224                     {
225                         genie_sal_uart_send_str(AT_CME_ERROR_STR, err);
226                     }
227                 }
228                 else
229                 {
230                     genie_sal_uart_send_str(AT_CME_ERROR_STR, AT_ERR_NOT_FOUND);
231                 }
232             }
233             else if (type == AT_OP_FCURRENT)
234             {
235                 if (genie_at_commands[i].fcb)
236                 {
237                     err = genie_at_commands[i].fcb(argc - 1, &argv[1]);
238                     if (err == 0)
239                     {
240                         genie_sal_uart_send_str(AT_OK_STR);
241                     }
242                     else
243                     {
244                         genie_sal_uart_send_str(AT_CME_ERROR_STR, err);
245                     }
246                 }
247                 else
248                 {
249                     genie_sal_uart_send_str(AT_CME_ERROR_STR, AT_ERR_NOT_FOUND);
250                 }
251             }
252             else
253             { //HLOOKUP
254                 if (genie_at_commands[i].help)
255                 {
256                     genie_sal_uart_send_str("%s\n", genie_at_commands[i].help);
257                     genie_sal_uart_send_str(AT_OK_STR);
258                 }
259             }
260 
261             break;
262         }
263     }
264 
265     if ((i + 1) == ARRAY_SIZE(genie_at_commands))
266     {
267         genie_sal_uart_send_str(AT_CME_ERROR_STR, AT_ERR_NOT_FOUND);
268     }
269 }
270 
is_at_cmd(char * data)271 static int is_at_cmd(char *data)
272 {
273     if (strlen(data) < 2)
274     {
275         return 1;
276     }
277 
278     if (((*data == 'A') || (*data == 'a')) && ((*(data + 1) == 'T') || (*(data + 1) == 't')))
279     {
280         return 0;
281     }
282 
283     return 1;
284 }
285 
genie_at_cmd_parser(char data[])286 int genie_at_cmd_parser(char data[])
287 {
288     char argv[AT_MAX_ARGC][AT_MAX_ARGV_LEN];
289     char *hcc;
290     char *argqv[AT_MAX_ARGC];
291 
292     if (is_at_cmd(data))
293     {
294         return -1;
295     }
296 
297     memset(argv, 0, sizeof(argv));
298     int ustype = argv_type(data);
299     argv[0][0] = 'A';
300     argv[0][1] = 'T';
301     argv[0][2] = '\0';
302 
303     //at_debug("ustype: %d, data: %s\n", ustype, data);
304     switch (ustype)
305     {
306     case AT_CMD_NO_ADD:
307         cmd_cli_func(AT_OP_HELP, 1, NULL);
308         genie_sal_uart_send_str(AT_OK_STR);
309         break;
310 
311     case AT_CMD_ADD: //execute
312         if (char_cut(argv[1], data, '+', '\0') == NULL)
313         {
314             return -1;
315         }
316 
317         argqv[0] = (char *)(&argv[0]);
318         argqv[1] = (char *)(&argv[1]);
319         cmd_cli_func(AT_OP_EXECUTE, 2, (char **)(&argqv));
320         break;
321 
322     case AT_CMD_QUERY: //?
323         if (char_cut((char *)argv[1], data, '+', '?') == NULL)
324         {
325             return -1;
326         }
327 
328         argqv[0] = (char *)(&argv[0]);
329         argqv[1] = (char *)(&argv[1]);
330         cmd_cli_func(AT_OP_FCURRENT, 2, (char **)(&argqv));
331         break;
332 
333     case AT_CMD_DOU:
334         if (char_cut((char *)argv[1], data, '+', '=') == NULL)
335         {
336             return -1;
337         }
338 
339         hcc = strchr(data, '=');
340         int num = argc_len(hcc);
341         //at_debug("num:%d, len:%d\n", num, strlen(hcc));
342         if ((num > AT_MAX_ARGC - 2) || (strlen(hcc) > (AT_MAX_ARGC * AT_MAX_ARGV_LEN)))
343         {
344             at_debug("argv out of the max len\r\n");
345             return -1;
346         }
347 
348         if (num == 0)
349         {
350             at_debug("num:err 0\r\n");
351             return -1;
352         }
353 
354         if (num == 1)
355         {
356             char_cut((char *)argv[2], hcc, '=', '\0');
357             argqv[2] = (char *)(&argv[2]);
358         }
359         else
360         {
361             char_cut((char *)argv[2], hcc, '=', ',');
362             argqv[2] = (char *)(&argv[2]);
363 
364             for (int i = 1; i < num; i++)
365             {
366                 hcc = strchr(hcc, ',');
367                 char_cut((char *)argv[2 + i], hcc, ',', ',');
368                 argqv[2 + i] = (char *)(&argv[2 + i]);
369                 hcc++;
370             }
371         }
372 
373         argqv[0] = (char *)(&argv[0]);
374         argqv[1] = (char *)(&argv[1]);
375         cmd_cli_func(AT_OP_EXECUTE, num + 2, (char **)(&argqv));
376         break;
377 
378     case AT_CMD_FIND: //=?
379         hcc = strrchr(data, '+');
380         hcc++;
381         str_chr(argv[1], hcc, '=');
382         argqv[0] = (char *)(&argv[0]);
383         argqv[1] = (char *)(&argv[1]);
384         cmd_cli_func(AT_OP_HLOOKUP, 2, (char **)(&argqv));
385         break;
386 
387     default:
388         at_debug("unknow type:%d\r\n", ustype);
389         return -1;
390     }
391 
392     return 0;
393 }
394 
genie_at_cmd_reboot(int argc,char * argv[])395 int genie_at_cmd_reboot(int argc, char *argv[])
396 {
397     /* AT+REBOOT */
398     if (argc > 1)
399     {
400         return AT_ERR_FORMAT;
401     }
402 
403     genie_sal_uart_send_str("OK\r\n");
404     aos_msleep(30);
405     aos_reboot();
406     return 0;
407 }
408 
genie_at_cmd_mesh_reset(int argc,char * argv[])409 int genie_at_cmd_mesh_reset(int argc, char *argv[])
410 {
411     /* AT+MESHRST */
412     if (argc > 1)
413     {
414         return AT_ERR_FORMAT;
415     }
416 
417     genie_sal_uart_send_str("OK\r\n");
418     genie_event(GENIE_EVT_HW_RESET_START, NULL);
419     return 0;
420 }
421 
genie_at_cmd_adv_start(int argc,char * argv[])422 int genie_at_cmd_adv_start(int argc, char *argv[])
423 {
424     /* AT+MESHADV=<mode> */
425     uint8_t mode = 0;
426 
427     if (argc != 2)
428     {
429         return AT_ERR_FORMAT;
430     }
431 
432     mode = strtoul(argv[1], NULL, 0);
433     if (mode == MESH_ADV_CLOSE)
434     {
435         /* close adv */
436         bt_mesh_adv_stop();
437         bt_mesh_prov_disable(BT_MESH_PROV_GATT | BT_MESH_PROV_ADV);
438     }
439     else if (mode == MESH_ADV_START)
440     {
441         /* start adv */
442         bt_mesh_adv_stop();
443         bt_mesh_prov_enable(BT_MESH_PROV_GATT | BT_MESH_PROV_ADV);
444         genie_event(GENIE_EVT_SDK_MESH_PBADV_START, NULL);
445     }
446     else if (mode == MESH_ADV_SILENT)
447     {
448         /* start silent adv */
449         genie_event(GENIE_EVT_SDK_MESH_PBADV_TIMEOUT, NULL);
450     }
451     else
452     {
453         return AT_ERR_FORMAT;
454     }
455 
456     g_current_adv_mode = mode;
457     return 0;
458 }
459 
genie_at_cmd_adv_query(int argc,char * argv[])460 int genie_at_cmd_adv_query(int argc, char *argv[])
461 {
462     /* AT+MESHADV? */
463     if (argc > 1)
464     {
465         return AT_ERR_FORMAT;
466     }
467 
468     genie_sal_uart_send_str(AT_RESPONSE_STR "%d\r\n", BLE_MESH_ADV, g_current_adv_mode);
469     return 0;
470 }
471 
genie_at_cmd_mesh_log(int argc,char * argv[])472 int genie_at_cmd_mesh_log(int argc, char *argv[])
473 {
474     /* AT+MESHLOG=<mode> */
475     uint8_t mode = 0;
476 
477     if (argc != 2)
478     {
479         return AT_ERR_FORMAT;
480     }
481 
482     mode = strtoul(argv[1], NULL, 0);
483     if ((mode == 1) || (mode == 0))
484     {
485         g_mesh_log_mode = mode;
486         if (!g_mesh_log_mode)
487         {
488             genie_sal_uart_send_str("OK\r\n");
489             aos_set_log_level(LOG_EMERG);
490         }
491         else
492         {
493             aos_set_log_level(GENIE_MESH_DEFAULT_LOG_LEVEL);
494         }
495         return 0;
496     }
497     else
498     {
499         return AT_ERR_FORMAT;
500     }
501 }
502 
genie_at_cmd_mesh_log_query(int argc,char * argv[])503 int genie_at_cmd_mesh_log_query(int argc, char *argv[])
504 {
505     /* AT+MESHLOG? */
506     if (argc > 1)
507     {
508         return AT_ERR_FORMAT;
509     }
510 
511     genie_sal_uart_send_str("+%s:%d\r\n", BLE_MESH_LOG, g_mesh_log_mode);
512     return 0;
513 }
514 
genie_at_cmd_mesh_info(int argc,char * argv[])515 int genie_at_cmd_mesh_info(int argc, char *argv[])
516 {
517     bool status;
518 
519     /* AT+MESHINF? */
520     if (argc > 1)
521     {
522         return AT_ERR_FORMAT;
523     }
524 
525     status = bt_mesh_is_provisioned();
526     genie_sal_uart_send_str(AT_RESPONSE_STR "%d\r\n", BLE_MESH_INFO, status);
527     return 0;
528 }
529 
genie_at_cmd_mesh_ver(int argc,char * argv[])530 int genie_at_cmd_mesh_ver(int argc, char *argv[])
531 {
532     /* AT+MESHVER? */
533     if (argc > 1)
534     {
535         return AT_ERR_FORMAT;
536     }
537 
538     genie_sal_uart_send_str(AT_RESPONSE_STR "%08x\r\n", BLE_MESH_VER, genie_version_appver_get());
539     return 0;
540 }
541 
genie_at_cmd_mesh_mac(int argc,char * argv[])542 int genie_at_cmd_mesh_mac(int argc, char *argv[])
543 {
544     uint8_t addr[6] = {0};
545 
546     /* AT+MESHMAC? */
547     if (argc > 1)
548     {
549         return AT_ERR_FORMAT;
550     }
551 
552     hal_flash_read_mac_params(addr, sizeof(addr));
553     genie_sal_uart_send_str(AT_RESPONSE_STR " %02x:%02x:%02x:%02x:%02x:%02x\r\n", BLE_MESH_MAC, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
554     return 0;
555 }
556 
genie_at_cmd_facty_test(int argc,char * argv[])557 int genie_at_cmd_facty_test(int argc, char *argv[])
558 {
559     int ret = -1;
560 
561     /* AT+FACTYTEST */
562     if (argc > 1)
563     {
564         return AT_ERR_FORMAT;
565     }
566 
567     ret = genie_sal_ble_set_factory_flag();
568     if (ret != 0)
569     {
570         return AT_ERR_EXE;
571     }
572 
573     genie_sal_uart_send_str("OK\r\n");
574     aos_reboot();
575     return 0;
576 }
577 
578 static int8_t get_rssi_result = 0;
get_ble_rssi_cb(uint8_t mac[6],int16_t rssi)579 static void get_ble_rssi_cb(uint8_t mac[6], int16_t rssi)
580 {
581     if (memcmp(test_dev_mac, mac, sizeof(test_dev_mac)) == 0)
582     {
583         get_rssi_result = 0;
584         memset(test_dev_mac, 0, sizeof(test_dev_mac));
585         genie_sal_uart_send_str(AT_RESPONSE_STR "%d,%d\r\n", BLE_MESH_TEST, MESH_TEST_RSSI, rssi);
586     }
587     else
588     {
589         get_rssi_result = -1;
590         at_debug("cann't find mac: %s rssi\n", bt_hex(test_dev_mac, sizeof(test_dev_mac)));
591     }
592 }
593 
genie_at_cmd_mesh_test(int argc,char * argv[])594 int genie_at_cmd_mesh_test(int argc, char *argv[])
595 {
596     uint32_t opcode;
597     int err;
598 
599     /* AT+MESHTEST=<opcode>,[param] */
600     if (argc < 2)
601     {
602         return AT_ERR_FORMAT;
603     }
604 
605     opcode = strtoul(argv[1], NULL, 0);
606     switch (opcode)
607     {
608     case MESH_TEST_RSSI:
609         err = str2_char(argv[2], test_dev_mac);
610         //at_debug("test_dev_mac: %s\n", bt_hex(test_dev_mac, sizeof(test_dev_mac)));
611         if (err != 0)
612         {
613             at_debug("invalid address\n");
614             return AT_ERR_FORMAT;
615         }
616 
617         /* start scan,find the dev and get rssi */
618         err = genie_sal_ble_get_rssi(test_dev_mac, (genie_sal_ble_get_rssi_cb)get_ble_rssi_cb, 5000);
619         if (err != 0)
620         {
621             at_debug("start scan error\n");
622             return AT_ERR_EXE;
623         }
624         break;
625 
626     default:
627         return AT_ERR_FORMAT;
628     }
629 
630     return get_rssi_result;
631 }
632 
genie_at_cmd_mesh_group(int argc,char * argv[])633 int genie_at_cmd_mesh_group(int argc, char *argv[])
634 {
635     u16_t group_list[CONFIG_BT_MESH_MODEL_GROUP_COUNT] = {0};
636     int group_num = argc - 1;
637 
638     /* AT+MESHGRP=<addr1>,[addr2]... */
639     if (argc > (CONFIG_BT_MESH_MODEL_GROUP_COUNT + 1) || argc < 2)
640     {
641         return AT_ERR_FORMAT;
642     }
643 
644     for (int i = 0; i < group_num; i++)
645     {
646         group_list[i] = strtoul(argv[i + 1], NULL, 0);
647         if (group_list[i] < GENIE_ADDR_MIN || group_list[i] > GENIE_ADDR_MAX)
648         {
649             return AT_ERR_FORMAT;
650         }
651     }
652 
653     /* set group addr */
654     if (genie_storage_write_sub(group_list) != GENIE_STORAGE_SUCCESS)
655     {
656         return AT_ERR_EXE;
657     }
658 
659     /* get group addr */
660     if (genie_storage_read_sub(g_sub_list) != GENIE_STORAGE_SUCCESS)
661     {
662         return AT_ERR_EXE;
663     }
664 
665     return 0;
666 }
667 
genie_at_cmd_mesh_group_query(int argc,char * argv[])668 int genie_at_cmd_mesh_group_query(int argc, char *argv[])
669 {
670     u16_t group_list[CONFIG_BT_MESH_MODEL_GROUP_COUNT] = {0};
671     char result[100] = {0};
672     int len = 0;
673 
674     /* AT+MESHGRP? */
675     if (argc > 2)
676     {
677         return AT_ERR_FORMAT;
678     }
679 
680     /* get group addr */
681     if (genie_storage_read_sub(group_list) != GENIE_STORAGE_SUCCESS)
682     {
683         return AT_ERR_EXE;
684     }
685 
686     len = snprintf(result, sizeof(result), AT_RESPONSE_STR, BLE_MESH_GROUP);
687     for (int i = 0; i < CONFIG_BT_MESH_MODEL_GROUP_COUNT; i++)
688     {
689         if (len < (sizeof(result) - 5) && group_list[i] != 0x0000)
690         {
691             len += snprintf(result + len, sizeof(result) - len, "0x%04X,", group_list[i]);
692         }
693     }
694 
695     result[len - 1] = '\0';
696     genie_sal_uart_send_str("%s\r\n", result);
697 
698     return 0;
699 }
700 
_send_trans_msg(char * data)701 static int _send_trans_msg(char *data)
702 {
703     uint8_t count = 0;
704     uint8_t msg_b[GENIE_HAL_BLE_SEND_MAX_DATA_LEN];
705     uint8_t ret = 0;
706 
707     count = strlen(data) >> 1;
708     if (count > GENIE_HAL_BLE_SEND_MAX_DATA_LEN)
709     {
710         at_debug("data out of the max len\n");
711         return AT_ERR_FORMAT;
712     }
713     memset(msg_b, 0x0, sizeof(msg_b));
714     ret = stringtohex(data, msg_b, count);
715     if (ret == 0)
716     {
717         at_debug("stringtohex error\n");
718         return AT_ERR_FORMAT;
719     }
720 
721     if (genie_sal_ble_send_msg(0, msg_b, count))
722     {
723         return AT_ERR_EXE;
724     }
725 
726     return 0;
727 }
728 
genie_at_cmd_mesh_trans_send(int argc,char * argv[])729 int genie_at_cmd_mesh_trans_send(int argc, char *argv[])
730 {
731     /* AT+MESHMSGTX=<data> */
732     if (argc < 2)
733     {
734         return AT_ERR_FORMAT;
735     }
736 
737     return _send_trans_msg(argv[1]);
738 }
739 
genie_at_cmd_send_data_to_mcu(uint8_t * p_data,uint16_t data_len)740 int genie_at_cmd_send_data_to_mcu(uint8_t *p_data, uint16_t data_len)
741 {
742     int i = 0;
743     int len = 0;
744     char *p_send_buff = NULL;
745     uint16_t send_buff_len = 0;
746 
747     send_buff_len = strlen(BLE_MESH_MSG_RX) + 2 * data_len + 10;
748 
749     p_send_buff = (char *)aos_malloc(send_buff_len);
750     if (NULL == p_send_buff)
751     {
752         return -1;
753     }
754     memset(p_send_buff, '\0', send_buff_len);
755 
756     len = snprintf(p_send_buff, send_buff_len, "\r\n" AT_RESPONSE_STR "%d,", BLE_MESH_MSG_RX, data_len);
757     for (i = 0; i < data_len; i++)
758     {
759         len += snprintf(p_send_buff + len, send_buff_len - len, "%02X", p_data[i]);
760     }
761 
762     genie_sal_uart_send_str("%s\r\n", p_send_buff);
763     aos_free(p_send_buff);
764 
765     return 0;
766 }
767 
genie_at_output_event(genie_event_e event,void * p_arg)768 int genie_at_output_event(genie_event_e event, void *p_arg)
769 {
770     char result[100] = {0};
771     int len = 0;
772 
773     /* +MESHEVT:<state> */
774     len = snprintf(result, sizeof(result), AT_RESPONSE_STR, BLE_MESH_EVENT);
775 
776     if (event == GENIE_EVT_MESH_READY)
777     {
778         len += snprintf(result + len, sizeof(result) - len, "0x%02X", MESH_EVENT_DEV_READY);
779     }
780     else if (event == GENIE_EVT_SDK_MESH_PROV_SUCCESS)
781     {
782         len += snprintf(result + len, sizeof(result) - len, "0x%02X", MESH_EVENT_PROV_SUCCESS);
783         g_current_adv_mode = MESH_ADV_CLOSE;
784     }
785     else if (event == GENIE_EVT_SDK_MESH_PROV_FAIL)
786     {
787         len += snprintf(result + len, sizeof(result) - len, "0x%02X", MESH_EVENT_PROV_FAILED);
788     }
789     else
790     {
791         if (event == GENIE_EVT_SDK_MESH_SILENT_START)
792         {
793             g_current_adv_mode = MESH_ADV_SILENT;
794         }
795         return 0;
796     }
797 
798     genie_sal_uart_send_str("%s\r\n", result);
799 
800     return 0;
801 }
802