1 /** @file
2  * @brief Bluetooth shell module
3  *
4  * Provide some Bluetooth shell commands that can be useful to applications.
5  */
6 
7 /*
8  * Copyright (c) 2017 Intel Corporation
9  *
10  * SPDX-License-Identifier: Apache-2.0
11  */
12 
13 #include <bt_errno.h>
14 #include <stddef.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <aos/ble.h>
18 #if AOS_COMP_CLI
19 #include "aos/cli.h"
20 #endif
21 
22 #include <misc/byteorder.h>
23 #include <ble_os.h>
24 #include <ble_types/types.h>
25 
26 #include <settings/settings.h>
27 //#include <yoc/partition.h>
28 #include <bluetooth/hci.h>
29 #include <bluetooth/bluetooth.h>
30 #include <bluetooth/conn.h>
31 #include <bluetooth/l2cap.h>
32 #include <bluetooth/rfcomm.h>
33 #include <bluetooth/sdp.h>
34 #include <common/log.h>
35 #include <host/conn_internal.h>
36 
37 
38 /** @brief Callback called when command is entered.
39  *
40  *  @param argc Number of parameters passed.
41  *  @param argv Array of option strings. First option is always command name.
42  *
43  * @return 0 in case of success or negative value in case of error.
44  */
45 typedef int (*shell_cmd_function_t)(int argc, char *argv[]);
46 // typedef int partition_t;
47 // static partition_t handle = -1;
48 // static hal_logic_partition_t *lp;
49 
50 
51 struct shell_cmd {
52     const char *cmd_name;
53     shell_cmd_function_t cb;
54     const char *help;
55     const char *desc;
56 };
57 
58 #include "bt.h"
59 #include "gatt.h"
60 #include "ll.h"
61 
62 #define DEVICE_NAME     CONFIG_BT_DEVICE_NAME
63 #define DEVICE_NAME_LEN     (sizeof(DEVICE_NAME) - 1)
64 #define CREDITS         15
65 #define DATA_MTU        (23 * CREDITS)
66 #define DATA_BREDR_MTU      48
67 
68 static u8_t selected_id = BT_ID_DEFAULT;
69 
70 #if defined(CONFIG_BT_CONN)
71 struct bt_conn *default_conn;
72 int16_t g_bt_conn_handle = -1;
73 int16_t g_security_level = 0;
74 uint8_t ble_init_flag = 0;
75 
76 typedef struct {
77     dev_addr_t addr;
78     uint8_t set_flag;
79 } wl_addr;
80 
81 #define MAX_WL_SZIE 10
82 wl_addr wl_list[MAX_WL_SZIE]= {0};
83 
84 
85 /* Connection context for BR/EDR legacy pairing in sec mode 3 */
86 static int16_t g_pairing_handle = -1;
87 #endif /* CONFIG_BT_CONN */
88 
89 static void device_find(ble_event_en event, void *event_data);
90 #if defined(CONFIG_BT_SMP)
91 static void smp_event(ble_event_en event, void *event_data);
92 #endif
93 static void conn_param_req(ble_event_en event, void *event_data);
94 static void conn_param_update(ble_event_en event, void *event_data);
95 
96 #define L2CAP_DYM_CHANNEL_NUM 2
97 
98 #if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
99 NET_BUF_POOL_DEFINE(data_tx_pool, L2CAP_DYM_CHANNEL_NUM, DATA_MTU, BT_BUF_USER_DATA_MIN, NULL);
100 NET_BUF_POOL_DEFINE(data_rx_pool, L2CAP_DYM_CHANNEL_NUM, DATA_MTU, BT_BUF_USER_DATA_MIN, NULL);
101 #endif
102 
103 #if defined(CONFIG_BT_BREDR)
104 NET_BUF_POOL_DEFINE(data_bredr_pool, 1, DATA_BREDR_MTU, BT_BUF_USER_DATA_MIN,
105                     NULL);
106 
107 #define SDP_CLIENT_USER_BUF_LEN     512
108 NET_BUF_POOL_DEFINE(sdp_client_pool, CONFIG_BT_MAX_CONN,
109                     SDP_CLIENT_USER_BUF_LEN, BT_BUF_USER_DATA_MIN, NULL);
110 #endif /* CONFIG_BT_BREDR */
111 
112 #if defined(CONFIG_BT_RFCOMM)
113 
114 static struct bt_sdp_attribute spp_attrs[] = {
115     BT_SDP_NEW_SERVICE,
116     BT_SDP_LIST(
117         BT_SDP_ATTR_SVCLASS_ID_LIST,
118         BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 3),
119         BT_SDP_DATA_ELEM_LIST(
120     {
121         BT_SDP_TYPE_SIZE(BT_SDP_UUID16),
122         BT_SDP_ARRAY_16(BT_SDP_SERIAL_PORT_SVCLASS)
123     },
124         )
125     ),
126     BT_SDP_LIST(
127         BT_SDP_ATTR_PROTO_DESC_LIST,
128         BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 12),
129         BT_SDP_DATA_ELEM_LIST(
130     {
131         BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 3),
132         BT_SDP_DATA_ELEM_LIST(
133         {
134             BT_SDP_TYPE_SIZE(BT_SDP_UUID16),
135             BT_SDP_ARRAY_16(BT_SDP_PROTO_L2CAP)
136         },
137         )
138     },
139     {
140         BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 5),
141         BT_SDP_DATA_ELEM_LIST(
142         {
143             BT_SDP_TYPE_SIZE(BT_SDP_UUID16),
144             BT_SDP_ARRAY_16(BT_SDP_PROTO_RFCOMM)
145         },
146         {
147             BT_SDP_TYPE_SIZE(BT_SDP_UINT8),
148             BT_SDP_ARRAY_8(BT_RFCOMM_CHAN_SPP)
149         },
150         )
151     },
152         )
153     ),
154     BT_SDP_LIST(
155         BT_SDP_ATTR_PROFILE_DESC_LIST,
156         BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 8),
157         BT_SDP_DATA_ELEM_LIST(
158     {
159         BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 6),
160         BT_SDP_DATA_ELEM_LIST(
161         {
162             BT_SDP_TYPE_SIZE(BT_SDP_UUID16),
163             BT_SDP_ARRAY_16(BT_SDP_SERIAL_PORT_SVCLASS)
164         },
165         {
166             BT_SDP_TYPE_SIZE(BT_SDP_UINT16),
167             BT_SDP_ARRAY_16(0x0102)
168         },
169         )
170     },
171         )
172     ),
173     BT_SDP_SERVICE_NAME("Serial Port"),
174 };
175 
176 static struct bt_sdp_record spp_rec = BT_SDP_RECORD(spp_attrs);
177 
178 #endif /* CONFIG_BT_RFCOMM */
179 
180 #define NAME_LEN 30
181 
addr_le_str(const bt_addr_le_t * addr)182 static char *addr_le_str(const bt_addr_le_t *addr)
183 {
184     static char bufs[2][27];
185     static u8_t cur;
186     char *str;
187 
188     str = bufs[cur++];
189     cur %= ARRAY_SIZE(bufs);
190     bt_addr_le_to_str(addr, str, sizeof(bufs[cur]));
191 
192     return str;
193 }
194 
char2u8(char c)195 static uint8_t char2u8(char c)
196 {
197     if (c >= '0' && c <= '9') {
198         return (c - '0');
199     } else if (c >= 'a' && c <= 'f') {
200         return (c - 'a' + 10);
201     } else if (c >= 'A' && c <= 'F') {
202         return (c - 'A' + 10);
203     } else {
204         return 0;
205     }
206 }
207 
str2hex(uint8_t hex[],char * s,uint8_t cnt)208 void str2hex(uint8_t hex[], char *s, uint8_t cnt)
209 {
210     uint8_t i;
211 
212     if (!s) {
213         return;
214     }
215 
216     for (i = 0; (*s != '\0') && (i < cnt); i++, s += 2) {
217         hex[i] = ((char2u8(*s) & 0x0f) << 4) | ((char2u8(*(s + 1))) & 0x0f);
218     }
219 }
220 
bt_addr2str(const dev_addr_t * addr,char * str,uint16_t len)221 static inline int bt_addr2str(const dev_addr_t *addr, char *str,
222                               uint16_t len)
223 {
224     char type[10];
225 
226     switch (addr->type) {
227     case BT_ADDR_LE_PUBLIC:
228         strcpy(type, "public");
229         break;
230 
231     case BT_ADDR_LE_RANDOM:
232         strcpy(type, "random");
233         break;
234 
235     default:
236         snprintf(type, sizeof(type), "0x%02x", addr->type);
237         break;
238     }
239 
240     return snprintf(str, len, "%02X:%02X:%02X:%02X:%02X:%02X (%s)",
241                     addr->val[5], addr->val[4], addr->val[3],
242                     addr->val[2], addr->val[1], addr->val[0], type);
243 }
244 
245 #if 0
246 static int char2hex(const char *c, u8_t *x)
247 {
248     if (*c >= '0' && *c <= '9') {
249         *x = *c - '0';
250     } else if (*c >= 'a' && *c <= 'f') {
251         *x = *c - 'a' + 10;
252     } else if (*c >= 'A' && *c <= 'F') {
253         *x = *c - 'A' + 10;
254     } else {
255         return -EINVAL;
256     }
257 
258     return 0;
259 }
260 #endif
261 
str2bt_addr(const char * str,dev_addr_t * addr)262 static int str2bt_addr(const char *str, dev_addr_t *addr)
263 {
264     int i, j;
265     u8_t tmp;
266 
267     if (strlen(str) != 17) {
268         return -EINVAL;
269     }
270 
271     for (i = 5, j = 1; *str != '\0'; str++, j++) {
272         if (!(j % 3) && (*str != ':')) {
273             return -EINVAL;
274         } else if (*str == ':') {
275             i--;
276             continue;
277         }
278 
279         addr->val[i] = addr->val[i] << 4;
280 
281         if (char2hex(*str, &tmp) < 0) {
282             return -EINVAL;
283         }
284 
285         addr->val[i] |= tmp;
286     }
287 
288     return 0;
289 }
290 
str2bt_addr_le(const char * str,const char * type,dev_addr_t * addr)291 static int str2bt_addr_le(const char *str, const char *type, dev_addr_t *addr)
292 {
293     int err;
294 
295     err = str2bt_addr(str, addr);
296 
297     if (err < 0) {
298         return err;
299     }
300 
301     if (!strcmp(type, "public") || !strcmp(type, "(public)")) {
302         addr->type = DEV_ADDR_LE_PUBLIC;
303     } else if (!strcmp(type, "random") || !strcmp(type, "(random)")) {
304         addr->type = DEV_ADDR_LE_RANDOM;
305     } else {
306         return -EINVAL;
307     }
308 
309     return 0;
310 }
311 
conn_change(ble_event_en event,void * event_data)312 static void conn_change(ble_event_en event, void *event_data)
313 {
314     evt_data_gap_conn_change_t *e = (evt_data_gap_conn_change_t *)event_data;
315 
316     connect_info_t info;
317     ble_stack_connect_info_get(e->conn_handle, &info);
318 
319     if (e->connected == CONNECTED && e->err == 0) {
320         printf("Connected (%d): %s\n", e->conn_handle, addr_le_str((bt_addr_le_t *)&info.peer_addr));
321 
322         if (g_bt_conn_handle == -1) {
323             g_bt_conn_handle = e->conn_handle;
324         }
325 
326         /* clear connection reference for sec mode 3 pairing */
327         if (g_pairing_handle != -1) {
328             g_pairing_handle  = -1;
329         }
330     } else {
331 
332         printf("Disconected (%d): %s err %d\n", e->conn_handle, addr_le_str((bt_addr_le_t *)&info.peer_addr), e->err);
333 
334         if (e->err == 31) {
335             while (1);
336         }
337 
338         if (g_bt_conn_handle == e->conn_handle) {
339             g_bt_conn_handle = -1;
340         }
341 
342         g_security_level = 0;
343     }
344 }
345 
conn_security_change(ble_event_en event,void * event_data)346 static void conn_security_change(ble_event_en event, void *event_data)
347 {
348     evt_data_gap_security_change_t *e = (evt_data_gap_security_change_t *)event_data;
349     printf("conn %d security level change to level%d\n", e->conn_handle, e->level);
350     g_security_level = e->level;
351 }
352 
event_callback(ble_event_en event,void * event_data)353 static int event_callback(ble_event_en event, void *event_data)
354 {
355     switch (event) {
356     case EVENT_GAP_CONN_CHANGE:
357         conn_change(event, event_data);
358         break;
359 
360     case EVENT_GAP_CONN_SECURITY_CHANGE:
361         conn_security_change(event, event_data);
362         break;
363 
364     case EVENT_GAP_DEV_FIND:
365         device_find(event, event_data);
366         break;
367 
368     case EVENT_GAP_CONN_PARAM_REQ:
369         conn_param_req(event, event_data);
370         break;
371 
372     case EVENT_GAP_CONN_PARAM_UPDATE:
373         conn_param_update(event, event_data);
374         break;
375 #if defined(CONFIG_BT_SMP)
376 
377     case EVENT_SMP_PASSKEY_DISPLAY:
378     case EVENT_SMP_PASSKEY_CONFIRM:
379     case EVENT_SMP_PASSKEY_ENTER:
380     case EVENT_SMP_PAIRING_CONFIRM:
381     case EVENT_SMP_PAIRING_COMPLETE:
382     case EVENT_SMP_CANCEL:
383         smp_event(event, event_data);
384         break;
385 #endif
386 
387     default:
388         //printf("Unhandle event %d\n", event);
389         break;
390     }
391 
392     return 0;
393 }
394 
395 static ble_event_cb_t ble_cb = {
396     .callback = event_callback,
397 };
398 
cmd_init(int argc,char * argv[])399 static int cmd_init(int argc, char *argv[])
400 {
401     int err;
402     dev_addr_t addr;
403     init_param_t init = {NULL, NULL, 1};
404 
405 #if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
406     NET_BUF_POOL_INIT(data_tx_pool);
407     NET_BUF_POOL_INIT(data_rx_pool);
408 #endif
409 
410 #if defined(CONFIG_BT_BREDR)
411     NET_BUF_POOL_INIT(data_bredr_pool);
412     NET_BUF_POOL_INIT(sdp_client_pool);
413 #endif /* CONFIG_BT_BREDR */
414 
415     if (argc == 3) {
416         err = str2bt_addr_le(argv[1], argv[2], &addr);
417 
418         if (err) {
419             printf("Invalid address\n");
420             return err;
421         }
422 
423         init.dev_addr = &addr;
424     }
425 
426     err = ble_stack_init(&init);
427 
428     if (err) {
429         printf("Bluetooth init failed (err %d)\n", err);
430         return err;
431     }
432 
433     err = ble_stack_event_register(&ble_cb);
434     if(err) {
435         printf("Bluetooth stack init fail\n");
436         return -1;
437     } else {
438         printf("Bluetooth stack init success\n");
439     }
440 
441     ble_init_flag = 1;
442 
443     return 0;
444 }
445 
446 #if defined(CONFIG_BT_HCI) || defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
hexdump(const u8_t * data,size_t len)447 void hexdump(const u8_t *data, size_t len)
448 {
449     int n = 0;
450 
451     while (len--) {
452         if (n % 16 == 0) {
453             printf("%08X ", n);
454         }
455 
456         printf("%02X ", *data++);
457 
458         n++;
459 
460         if (n % 8 == 0) {
461             if (n % 16 == 0) {
462                 printf("\n");
463             } else {
464                 printf(" ");
465             }
466         }
467     }
468 
469     if (n % 16) {
470         printf("\n");
471     }
472 }
473 #endif /* CONFIG_BT_HCI || CONFIG_BT_L2CAP_DYNAMIC_CHANNEL */
474 
475 #if defined(CONFIG_BT_HCI)
cmd_hci_cmd(int argc,char * argv[])476 static int cmd_hci_cmd(int argc, char *argv[])
477 {
478     u8_t ogf;
479     u16_t ocf;
480     struct net_buf *buf = NULL, *rsp;
481     int err;
482 
483     if (argc < 3) {
484         return -EINVAL;
485     }
486 
487     ogf = strtoul(argv[1], NULL, 16);
488     ocf = strtoul(argv[2], NULL, 16);
489 
490     if (argc > 3) {
491         int i;
492 
493         buf = bt_hci_cmd_create(BT_OP(ogf, ocf), argc - 3);
494 
495         for (i = 3; i < argc; i++) {
496             net_buf_add_u8(buf, strtoul(argv[i], NULL, 16));
497         }
498     }
499 
500     err = bt_hci_cmd_send_sync(BT_OP(ogf, ocf), buf, &rsp);
501 
502     if (err) {
503         printf("HCI command failed (err %d)\n", err);
504     } else {
505         hexdump(rsp->data, rsp->len);
506         net_buf_unref(rsp);
507     }
508 
509     return 0;
510 }
511 #endif /* CONFIG_BT_HCI */
512 
cmd_name(int argc,char * argv[])513 static int cmd_name(int argc, char *argv[])
514 {
515     int err;
516 
517     if (argc < 2) {
518         printf("Bluetooth Local Name: %s\n", bt_get_name());
519         return 0;
520     }
521 
522     err = bt_set_name(argv[1]);
523 
524     if (err) {
525         printf("Unable to set name %s (err %d)", argv[1], err);
526     }
527 
528     return 0;
529 }
530 
cmd_id_create(int argc,char * argv[])531 static int cmd_id_create(int argc, char *argv[])
532 {
533     dev_addr_t addr;
534     int err;
535 
536     if (argc > 1) {
537         err = str2bt_addr_le(argv[1], "random", &addr);
538 
539         if (err) {
540             printf("Invalid address\n");
541             return err;
542         }
543     } else {
544         bt_addr_le_copy((bt_addr_le_t *)&addr, BT_ADDR_LE_ANY);
545     }
546 
547     err = bt_id_create((bt_addr_le_t *)&addr, NULL);
548 
549     if (err < 0) {
550         printf("Creating new ID failed (err %d)\n", err);
551         return 0;
552     }
553 
554     printf("New identity (%d) created: %s\n", err, addr_le_str((bt_addr_le_t *)&addr));
555 
556     return 0;
557 }
558 
cmd_id_reset(int argc,char * argv[])559 static int cmd_id_reset(int argc, char *argv[])
560 {
561     bt_addr_le_t addr;
562     u8_t id;
563     int err;
564 
565     if (argc < 2) {
566         printf("Identity identifier not specified\n");
567         return -EINVAL;
568     }
569 
570     id = strtol(argv[1], NULL, 10);
571 
572     if (argc > 2) {
573         err = str2bt_addr_le(argv[2], "random", (dev_addr_t *)&addr);
574 
575         if (err) {
576             printf("Invalid address\n");
577             return err;
578         }
579     } else {
580         bt_addr_le_copy(&addr, BT_ADDR_LE_ANY);
581     }
582 
583     err = bt_id_reset(id, &addr, NULL);
584 
585     if (err < 0) {
586         printf("Resetting ID %u failed (err %d)\n", id, err);
587         return 0;
588     }
589 
590     printf("Identity %u reset: %s\n", id, addr_le_str(&addr));
591 
592     return 0;
593 }
594 
cmd_id_delete(int argc,char * argv[])595 static int cmd_id_delete(int argc, char *argv[])
596 {
597     u8_t id;
598     int err;
599 
600     if (argc < 2) {
601         printf("Identity identifier not specified\n");
602         return -EINVAL;
603     }
604 
605     id = strtol(argv[1], NULL, 10);
606 
607     err = bt_id_delete(id);
608 
609     if (err < 0) {
610         printf("Deleting ID %u failed (err %d)\n", id, err);
611         return 0;
612     }
613 
614     printf("Identity %u deleted\n", id);
615 
616     return 0;
617 }
618 
cmd_id_show(int argc,char * argv[])619 static int cmd_id_show(int argc, char *argv[])
620 {
621     bt_addr_le_t addrs[CONFIG_BT_ID_MAX];
622     size_t i, count = CONFIG_BT_ID_MAX;
623 
624     bt_id_get(addrs, &count);
625 
626     for (i = 0; i < count; i++) {
627         printf("%s%zu: %s\n", i == selected_id ? "*" : " ", i,
628                addr_le_str(&addrs[i]));
629     }
630 
631     return 0;
632 }
633 
cmd_id_select(int argc,char * argv[])634 static int cmd_id_select(int argc, char *argv[])
635 {
636     bt_addr_le_t addrs[CONFIG_BT_ID_MAX];
637     size_t count = CONFIG_BT_ID_MAX;
638     u8_t id;
639 
640     if (argc < 2) {
641         return -EINVAL;
642     }
643 
644     id = strtol(argv[1], NULL, 10);
645 
646     bt_id_get(addrs, &count);
647 
648     if (count <= id) {
649         printf("Invalid identity\n");
650         return 0;
651     }
652 
653     //printf("Selected identity: %s\n", addr_le_str(&addrs[id]));
654     selected_id = id;
655 
656     return 0;
657 }
658 
parse_ad(uint8_t * data,uint16_t len,int (* cb)(ad_data_t * data,void * arg),void * cb_arg)659 static inline int parse_ad(uint8_t *data, uint16_t len, int (* cb)(ad_data_t *data, void *arg), void *cb_arg)
660 {
661     int num = 0;
662     uint8_t *pdata = data;
663     ad_data_t ad = {0};
664     int ret;
665 
666     while (len) {
667         if (pdata[0] == 0) {
668             return num;
669         }
670 
671         if (len < pdata[0] + 1) {
672             return -1;
673         };
674 
675         ad.len = pdata[0] - 1;
676 
677         ad.type = pdata[1];
678 
679         ad.data = &pdata[2];
680 
681         if (cb) {
682             ret = cb(&ad, cb_arg);
683 
684             if (ret) {
685                 break;
686             }
687         }
688 
689         num++;
690         len -= (pdata[0] + 1);
691         pdata += (pdata[0] + 1);
692     }
693 
694     return num;
695 }
696 
697 uint8_t *pscan_ad = NULL;
698 uint8_t *pscan_sd = NULL;
699 
scan_ad_cmp(ad_data_t * ad,void * arg)700 static int scan_ad_cmp(ad_data_t *ad, void *arg)
701 {
702     ad_data_t *ad2 = arg;
703 
704     return (ad->type == ad2->type && ad->len == ad2->len
705             && 0 == memcmp(ad->data, ad2->data, ad->len));
706 }
707 
scan_ad_callback(ad_data_t * ad,void * arg)708 static int scan_ad_callback(ad_data_t *ad, void *arg)
709 {
710     evt_data_gap_dev_find_t *e = arg;
711     int ad_num;
712     uint8_t *pad = NULL;
713     int ret;
714 
715     if (e->adv_len) {
716         if (e->adv_type == 0x04) {
717             pad = pscan_sd;
718         } else {
719             pad = pscan_ad;
720         }
721 
722         ad_num = parse_ad(pad, 31, NULL, NULL);
723 
724         ret = parse_ad(pad, 31, scan_ad_cmp, (void *)ad);
725 
726         if (ret < ad_num) {
727             return 1;
728         }
729     }
730 
731     return 0;
732 }
733 
device_find(ble_event_en event,void * event_data)734 static void device_find(ble_event_en event, void *event_data)
735 {
736     evt_data_gap_dev_find_t *e = event_data;
737     int ad_num = parse_ad(e->adv_data, e->adv_len, NULL, NULL);
738     int ret;
739     char addr_str[32] = {0};
740 
741     bt_addr2str(&e->dev_addr, addr_str, sizeof(addr_str));
742 
743     if (pscan_ad || pscan_sd) {
744         ret = parse_ad(e->adv_data, e->adv_len, scan_ad_callback, event_data);
745 
746         if (ret < ad_num) {
747             printf("[DEVICE]: %s, adv type %d, rssi %d, Raw data:%s\n", addr_str, e->adv_type,  e->rssi, bt_hex(e->adv_data, e->adv_len));
748         }
749     } else {
750         printf("[DEVICE]: %s, adv type %d, rssi %d, Raw data:%s\n", addr_str, e->adv_type,  e->rssi, bt_hex(e->adv_data, e->adv_len));
751     }
752 }
753 
conn_param_req(ble_event_en event,void * event_data)754 static void conn_param_req(ble_event_en event, void *event_data)
755 {
756     evt_data_gap_conn_param_req_t *e = event_data;
757     printf("LE conn  param req: int (0x%04x, 0x%04x) lat %d to %d\n",
758            e->param.interval_min, e->param.interval_max, e->param.latency,
759            e->param.timeout);
760 
761     e->accept = 1;
762 }
763 
conn_param_update(ble_event_en event,void * event_data)764 static void conn_param_update(ble_event_en event, void *event_data)
765 {
766     evt_data_gap_conn_param_update_t *e = event_data;
767 
768     printf("LE conn param updated: int 0x%04x lat %d to %d\n", e->interval,
769            e->latency, e->timeout);
770 }
771 
772 static uint8_t scan_filter = 0;
cmd_scan_filter(int argc,char * argv[])773 static int cmd_scan_filter(int argc, char *argv[])
774 {
775     if (argc < 2) {
776         return -EINVAL;
777     }
778 
779     scan_filter = atoi(argv[1]);
780 
781     if (scan_filter > SCAN_FILTER_POLICY_WHITE_LIST) {
782         scan_filter = 0;
783         return -EINVAL;
784     }
785 
786     printf("Set scan filter %s\n", scan_filter == 0 ? "SCAN_FILTER_POLICY_ANY_ADV" : "SCAN_FILTER_POLICY_WHITE_LIST");
787     return 0;
788 }
789 
cmd_scan(int argc,char * argv[])790 static int cmd_scan(int argc, char *argv[])
791 {
792     static uint8_t scan_ad[31] = {0};
793     static uint8_t scan_sd[31] = {0};
794 
795     scan_param_t params = {
796         SCAN_PASSIVE,
797         SCAN_FILTER_DUP_DISABLE,
798         SCAN_FAST_INTERVAL,
799         SCAN_FAST_WINDOW,
800     };
801 
802     params.scan_filter = scan_filter;
803 
804     if (argc < 2) {
805         return -EINVAL;
806     }
807 
808 
809     if (argc >= 2) {
810         if (!strcmp(argv[1], "active")) {
811             params.type = SCAN_ACTIVE;
812         } else if (!strcmp(argv[1], "off")) {
813             pscan_ad = NULL;
814             pscan_sd = NULL;
815             return ble_stack_scan_stop();
816         } else if (!strcmp(argv[1], "passive")) {
817             params.type = SCAN_PASSIVE;
818         } else {
819 
820             return -EINVAL;
821         }
822     }
823 
824     if (argc >= 3) {
825         if (!strcmp(argv[2], "dups")) {
826             params.filter_dup = SCAN_FILTER_DUP_DISABLE;
827         } else if (!strcmp(argv[2], "nodups")) {
828             params.filter_dup = SCAN_FILTER_DUP_ENABLE;
829         } else {
830             return -EINVAL;
831         }
832     }
833 
834     if (argc >= 4) {
835         params.interval = strtol(argv[3], NULL, 10);
836     }
837 
838     if (argc >= 5) {
839         params.window = strtol(argv[4], NULL, 10);
840     }
841 
842     if (argc >= 6) {
843         pscan_ad = scan_ad;
844         memset(scan_ad, 0, sizeof(scan_ad));
845         str2hex(scan_ad, argv[5], sizeof(scan_ad));
846     }
847 
848     if (argc >= 7) {
849         pscan_sd = scan_sd;
850         memset(scan_sd, 0, sizeof(scan_sd));
851         str2hex(scan_sd, argv[6], sizeof(scan_sd));
852     }
853 
854     return ble_stack_scan_start(&params);
855 }
856 
parse_ad_data(uint8_t * data,uint16_t len,ad_data_t * ad,uint8_t * ad_num)857 static inline int parse_ad_data(uint8_t *data, uint16_t len, ad_data_t *ad, uint8_t *ad_num)
858 {
859     uint8_t num = 0;
860     uint8_t *pdata = data;
861 
862     while (len) {
863         if (len < pdata[0] + 1) {
864             *ad_num = 0;
865             return -1;
866         };
867 
868         num++;
869 
870         if (ad && num <= *ad_num) {
871             ad->len = pdata[0] - 1;
872             ad->type = pdata[1];
873             ad->data = &pdata[2];
874         }
875 
876         len -= (pdata[0] + 1);
877         pdata += (pdata[0] + 1);
878 
879         if (ad) {
880             ad++;
881         }
882     }
883 
884     *ad_num = num;
885     return 0;
886 }
887 
adv_ad_callback(ad_data_t * ad,void * arg)888 static inline int adv_ad_callback(ad_data_t *ad, void *arg)
889 {
890     ad_data_t **pad = (ad_data_t **)arg;
891 
892     (*pad)->type = ad->type;
893     (*pad)->len = ad->len;
894     (*pad)->data = ad->data;
895     (*pad)++;
896     return 0;
897 }
898 
cmd_advertise(int argc,char * argv[])899 static int cmd_advertise(int argc, char *argv[])
900 {
901     int err;
902     adv_param_t param = {0};
903     uint8_t ad_hex[31] = {0};
904     uint8_t sd_hex[31] = {0};
905     ad_data_t ad[10] = {0};
906     int8_t ad_num = 0;
907     ad_data_t sd[10] = {0};
908     int8_t sd_num = 0;
909 
910 
911     if (argc < 2) {
912         goto fail;
913     }
914 
915     if (!strcmp(argv[1], "stop")) {
916         if (bt_le_adv_stop() < 0) {
917             printf("Failed to stop advertising\n");
918         } else {
919             printf("Advertising stopped\n");
920         }
921 
922         return 0;
923     }
924 
925     if (!strcmp(argv[1], "nconn")) {
926         param.type = ADV_NONCONN_IND;
927     } else if (!strcmp(argv[1], "conn")) {
928         param.type = ADV_IND;
929     }
930 
931 
932     if (argc > 2) {
933         if (strlen(argv[2]) > 62) {
934             printf("max len\n");
935             goto fail;
936         }
937 
938         str2hex(ad_hex, argv[2], sizeof(ad_hex));
939 
940         ad_data_t *pad = ad;
941         ad_num = parse_ad(ad_hex, strlen(argv[2]) / 2, adv_ad_callback, (void *)&pad);
942     }
943 
944     if (argc > 3) {
945         if (strlen(argv[3]) > 62) {
946             printf("max len\n");
947             goto fail;
948         }
949 
950         str2hex(sd_hex, argv[3], sizeof(sd_hex));
951         ad_data_t *psd = sd;
952         sd_num = parse_ad(sd_hex, strlen(argv[3]) / 2, adv_ad_callback, (void *)&psd);
953     }
954 
955 
956     param.ad = ad_num > 0 ?ad:NULL;
957     param.sd = sd_num> 0 ?sd:NULL;
958     param.ad_num = (uint8_t)ad_num;
959     param.sd_num = (uint8_t)sd_num;
960     param.interval_min = ADV_FAST_INT_MIN_2;
961     param.interval_max = ADV_FAST_INT_MAX_2;
962 
963     err = ble_stack_adv_start(&param);
964 
965     if (err < 0) {
966         printf("Failed to start advertising (err %d)\n", err);
967     } else {
968         printf("adv_type:%x;adv_interval_min:%d (*0.625)ms;adv_interval_max:%d (*0.625)ms\n", param.type, (int)param.interval_min, (int)param.interval_max);
969         printf("Advertising started\n");
970     }
971 
972     return 0;
973 
974 fail:
975 
976     return -EINVAL;
977 }
978 
979 #if defined(CONFIG_BT_CONN)
cmd_connect_le(int argc,char * argv[])980 static int cmd_connect_le(int argc, char *argv[])
981 {
982     int err;
983     dev_addr_t addr;
984     int16_t conn_handle;
985     conn_param_t param = {
986         CONN_INT_MIN_INTERVAL,
987         CONN_INT_MAX_INTERVAL,
988         0,
989         400,
990     };
991 
992     if (argc < 3) {
993         return -EINVAL;
994     }
995 
996     if (argc >= 3) {
997         err = str2bt_addr_le(argv[1], argv[2], &addr);
998 
999         if (err) {
1000             printf("Invalid peer address (err %d)\n", err);
1001             return 0;
1002         }
1003     }
1004 
1005     if (argc >= 5) {
1006         param.interval_min = strtol(argv[3], NULL, 16);
1007         param.interval_max = strtol(argv[4], NULL, 16);
1008     }
1009 
1010     if (argc >= 7) {
1011         param.latency = strtol(argv[5], NULL, 16);
1012         param.timeout = strtol(argv[6], NULL, 16);
1013     }
1014 
1015     conn_handle = ble_stack_connect(&addr, &param, 0);
1016 
1017     if (conn_handle < 0) {
1018         printf("Connection failed\n");
1019         return -EIO;
1020     }
1021 
1022     return 0;
1023 }
1024 
cmd_disconnect(int argc,char * argv[])1025 static int cmd_disconnect(int argc, char *argv[])
1026 {
1027     int16_t  conn_handle = 0;
1028     int err;
1029 
1030     if (g_bt_conn_handle != -1 && argc < 2) {
1031         conn_handle = g_bt_conn_handle;
1032     } else {
1033         if (argc < 2) {
1034             return -EINVAL;
1035         }
1036 
1037         conn_handle = strtol(argv[1], NULL, 10);
1038     }
1039 
1040     err = ble_stack_disconnect(conn_handle);
1041 
1042     if (err) {
1043         printf("Disconnection failed (err %d)\n", err);
1044     }
1045 
1046     return 0;
1047 }
1048 
cmd_auto_conn(int argc,char * argv[])1049 static int cmd_auto_conn(int argc, char *argv[])
1050 {
1051     dev_addr_t addr;
1052     conn_param_t param = {
1053         CONN_INT_MIN_INTERVAL,
1054         CONN_INT_MAX_INTERVAL,
1055         0,
1056         400,
1057     };
1058     int err;
1059     conn_param_t *pparam = NULL;
1060     uint8_t auto_conn = 1;
1061 
1062     if (argc < 3) {
1063         return -EINVAL;
1064     }
1065 
1066     err = str2bt_addr_le(argv[1], argv[2], &addr);
1067 
1068     if (err) {
1069         printf("Invalid peer address (err %d)\n", err);
1070         return -EINVAL;
1071     }
1072 
1073     if (argc > 3) {
1074         if (!strcmp(argv[3], "on")) {
1075             auto_conn = 1;
1076             pparam = &param;
1077         } else if (!strcmp(argv[3], "off")) {
1078             auto_conn = 0;
1079             pparam = NULL;
1080         } else {
1081             return -EINVAL;
1082         }
1083     } else {
1084         auto_conn = 1;
1085         pparam = &param;
1086     }
1087 
1088     err = ble_stack_connect(&addr, pparam, auto_conn);
1089 
1090     if (err < 0) {
1091         return err;
1092     }
1093 
1094     printf("connect (%d) pending\n", err);
1095     return 0;
1096 }
1097 
cmd_select(int argc,char * argv[])1098 static int cmd_select(int argc, char *argv[])
1099 {
1100     struct bt_conn *conn;
1101     bt_addr_le_t addr;
1102     int err;
1103 
1104     if (argc < 3) {
1105         return -EINVAL;
1106     }
1107 
1108     err = str2bt_addr_le(argv[1], argv[2], (dev_addr_t *)&addr);
1109 
1110     if (err) {
1111         printf("Invalid peer address (err %d)\n", err);
1112         return 0;
1113     }
1114 
1115     conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &addr);
1116 
1117     if (!conn) {
1118         printf("No matching connection found\n");
1119         return 0;
1120     }
1121 
1122     if (default_conn) {
1123         bt_conn_unref(default_conn);
1124     }
1125 
1126     default_conn = conn;
1127 
1128     return 0;
1129 }
1130 
cmd_conn_update(int argc,char * argv[])1131 static int cmd_conn_update(int argc, char *argv[])
1132 {
1133     conn_param_t param;
1134     int err;
1135 
1136     if (argc < 5) {
1137         return -EINVAL;
1138     }
1139 
1140     param.interval_min = strtoul(argv[1], NULL, 16);
1141     param.interval_max = strtoul(argv[2], NULL, 16);
1142     param.latency = strtoul(argv[3], NULL, 16);
1143     param.timeout = strtoul(argv[4], NULL, 16);
1144     err = ble_stack_connect_param_update(g_bt_conn_handle, &param);
1145 
1146     if (err) {
1147         printf("conn update failed (err %d).\n", err);
1148     } else {
1149         printf("conn update initiated.\n");
1150     }
1151 
1152     return 0;
1153 }
1154 
cmd_oob(int argc,char * argv[])1155 static int cmd_oob(int argc, char *argv[])
1156 {
1157     char addr[BT_ADDR_LE_STR_LEN];
1158     struct bt_le_oob oob;
1159     int err;
1160 
1161     err = bt_le_oob_get_local(selected_id, &oob);
1162 
1163     if (err) {
1164         printf("OOB data failed\n");
1165         return 0;
1166     }
1167 
1168     bt_addr_le_to_str(&oob.addr, addr, sizeof(addr));
1169 
1170     printf("OOB data:\n");
1171     printf("  addr %s\n", addr);
1172 
1173     return 0;
1174 }
1175 
cmd_clear(int argc,char * argv[])1176 static int cmd_clear(int argc, char *argv[])
1177 {
1178     dev_addr_t addr;
1179     int err;
1180 
1181     if (argc < 2) {
1182         printf("Specify remote address or \"all\"\n");
1183         return 0;
1184     }
1185 
1186     if (strcmp(argv[1], "all") == 0) {
1187         // err = bt_unpair(selected_id, NULL);
1188         err = ble_stack_dev_unpair(NULL);
1189 
1190         if (err) {
1191             printf("Failed to clear pairings (err %d)\n", err);
1192         } else {
1193             printf("Pairings successfully cleared\n");
1194         }
1195 
1196         return 0;
1197     }
1198 
1199     if (argc < 3) {
1200 #if defined(CONFIG_BT_BREDR)
1201         addr.type = BT_ADDR_LE_PUBLIC;
1202         err = str2bt_addr(argv[1], &addr.a);
1203 #else
1204         printf("Both address and address type needed\n");
1205         return 0;
1206 #endif
1207     } else {
1208         err = str2bt_addr_le(argv[1], argv[2], (dev_addr_t *)&addr);
1209     }
1210 
1211     if (err) {
1212         printf("Invalid address\n");
1213         return 0;
1214     }
1215 
1216     //err = bt_unpair(selected_id, &addr);
1217     err = ble_stack_dev_unpair(&addr);
1218 
1219     if (err) {
1220         printf("Failed to clear pairing (err %d)\n", err);
1221     } else {
1222         printf("Pairing successfully cleared\n");
1223     }
1224 
1225     return 0;
1226 }
1227 #endif /* CONFIG_BT_CONN */
1228 
1229 #if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
cmd_security(int argc,char * argv[])1230 static int cmd_security(int argc, char *argv[])
1231 {
1232     int err, sec;
1233 
1234     if (g_bt_conn_handle == -1) {
1235         printf("Not connected\n");
1236         return 0;
1237     }
1238 
1239     if (argc < 2) {
1240         return -EINVAL;
1241     }
1242 
1243     sec = *argv[1] - '0';
1244 
1245     err = ble_stack_security(g_bt_conn_handle, sec);
1246 
1247     if (err) {
1248         printf("Setting security failed (err %d)\n", err);
1249     }
1250 
1251     return 0;
1252 }
1253 
smp_passkey_display(evt_data_smp_passkey_display_t * e)1254 static void smp_passkey_display(evt_data_smp_passkey_display_t *e)
1255 {
1256     char addr[32];
1257 
1258     bt_addr2str(&e->peer_addr, addr, 32);
1259 
1260     printf("Passkey for %s: %s\n", addr, e->passkey);
1261 }
1262 
smp_passkey_confirm(evt_data_smp_passkey_confirm_t * e)1263 static void smp_passkey_confirm(evt_data_smp_passkey_confirm_t *e)
1264 {
1265     char addr[32];
1266 
1267     bt_addr2str(&e->peer_addr, addr, 32);
1268 
1269     printf("Pairing passkey for %s: %s\n", addr, e->passkey);
1270 }
1271 
smp_passkey_entry(evt_data_smp_passkey_enter_t * e)1272 static void smp_passkey_entry(evt_data_smp_passkey_enter_t *e)
1273 {
1274     char addr[32];
1275 
1276     bt_addr2str(&e->peer_addr, addr, 32);
1277 
1278     printf("Enter passkey for %s\n", addr);
1279 }
1280 
smp_cancel(evt_data_smp_cancel_t * e)1281 static void smp_cancel(evt_data_smp_cancel_t *e)
1282 {
1283     char addr[32];
1284 
1285     bt_addr2str(&e->peer_addr, addr, 32);
1286 
1287     printf("Pairing cancelled: %s\n", addr);
1288 
1289     /* clear connection reference for sec mode 3 pairing */
1290     if (g_pairing_handle) {
1291         g_pairing_handle = -1;
1292     }
1293 }
1294 
smp_pairing_confirm(evt_data_smp_pairing_confirm_t * e)1295 static void smp_pairing_confirm(evt_data_smp_pairing_confirm_t *e)
1296 {
1297     char addr[32];
1298 
1299     bt_addr2str(&e->peer_addr, addr, 32);
1300 
1301     printf("Confirm pairing for %s\n", addr);
1302 }
1303 
smp_pairing_complete(evt_data_smp_pairing_complete_t * e)1304 static void smp_pairing_complete(evt_data_smp_pairing_complete_t *e)
1305 {
1306     char addr[32];
1307 
1308     bt_addr2str(&e->peer_addr, addr, 32);
1309 
1310     if (e->err) {
1311         printf("Pairing failed with %s, err %d\n", addr, e->err);
1312     } else {
1313         printf("%s with %s\n", e->bonded ? "Bonded" : "Paired",  addr);
1314     }
1315 }
1316 
smp_event(ble_event_en event,void * event_data)1317 static void smp_event(ble_event_en event, void *event_data)
1318 {
1319     switch (event) {
1320     case EVENT_SMP_PASSKEY_DISPLAY:
1321         smp_passkey_display(event_data);
1322         break;
1323 
1324     case EVENT_SMP_PASSKEY_CONFIRM:
1325         smp_passkey_confirm(event_data);
1326         break;
1327 
1328     case EVENT_SMP_PASSKEY_ENTER:
1329         smp_passkey_entry(event_data);
1330         break;
1331 
1332     case EVENT_SMP_PAIRING_CONFIRM:
1333         smp_pairing_confirm(event_data);
1334         break;
1335 
1336     case EVENT_SMP_PAIRING_COMPLETE:
1337         smp_pairing_complete(event_data);
1338         break;
1339 
1340     case EVENT_SMP_CANCEL:
1341         smp_cancel(event_data);
1342         break;
1343 
1344     default:
1345         break;
1346     }
1347 }
1348 
cmd_iocap_set(int argc,char * argv[])1349 static int cmd_iocap_set(int argc, char *argv[])
1350 {
1351     uint8_t io_cap = 0;
1352 
1353     if (argc < 3) {
1354         return -EINVAL;
1355     }
1356 
1357     if (!strcmp(argv[1], "NONE")) {
1358         io_cap |= IO_CAP_IN_NONE;
1359     } else if (!strcmp(argv[1], "YESNO")) {
1360         io_cap |= IO_CAP_IN_YESNO;
1361     } else if (!strcmp(argv[1], "KEYBOARD")) {
1362         io_cap |= IO_CAP_IN_KEYBOARD;
1363     } else {
1364         return -EINVAL;
1365     }
1366 
1367     if (!strcmp(argv[2], "NONE")) {
1368         io_cap |= IO_CAP_OUT_NONE;
1369     } else if (!strcmp(argv[2], "DISPLAY")) {
1370         io_cap |= IO_CAP_OUT_DISPLAY;
1371     } else {
1372         return -EINVAL;
1373     }
1374 
1375     return ble_stack_iocapability_set(io_cap);
1376 }
1377 
cmd_auth_cancel(int argc,char * argv[])1378 static int cmd_auth_cancel(int argc, char *argv[])
1379 {
1380     int16_t conn_handle;
1381 
1382     if (g_bt_conn_handle != -1) {
1383         conn_handle = g_bt_conn_handle;
1384     } else if (g_pairing_handle != -1) {
1385         conn_handle = g_pairing_handle;
1386     } else {
1387         conn_handle = 0;
1388     }
1389 
1390     ble_stack_smp_cancel(conn_handle);
1391     return 0;
1392 }
1393 
cmd_auth_passkey_confirm(int argc,char * argv[])1394 static int cmd_auth_passkey_confirm(int argc, char *argv[])
1395 {
1396     if (g_bt_conn_handle == -1) {
1397         printf("Not connected\n");
1398         return 0;
1399     }
1400 
1401     ble_stack_smp_passkey_confirm(g_bt_conn_handle);
1402     return 0;
1403 }
1404 
cmd_auth_pairing_confirm(int argc,char * argv[])1405 static int cmd_auth_pairing_confirm(int argc, char *argv[])
1406 {
1407     if (g_bt_conn_handle == -1) {
1408         printf("Not connected\n");
1409         return 0;
1410     }
1411 
1412     ble_stack_smp_pairing_confirm(g_bt_conn_handle);
1413 
1414     return 0;
1415 }
1416 
1417 #if defined(CONFIG_BT_FIXED_PASSKEY)
cmd_fixed_passkey(int argc,char * argv[])1418 static int cmd_fixed_passkey(int argc, char *argv[])
1419 {
1420     unsigned int passkey;
1421     int err;
1422 
1423     if (argc < 2) {
1424         bt_passkey_set(BT_PASSKEY_INVALID);
1425         printf("Fixed passkey cleared\n");
1426         return 0;
1427     }
1428 
1429     passkey = atoi(argv[1]);
1430 
1431     if (passkey > 999999) {
1432         printf("Passkey should be between 0-999999\n");
1433         return 0;
1434     }
1435 
1436     err = bt_passkey_set(passkey);
1437 
1438     if (err) {
1439         printf("Setting fixed passkey failed (err %d)\n", err);
1440     }
1441 
1442     return 0;
1443 }
1444 #endif
1445 
cmd_auth_passkey(int argc,char * argv[])1446 static int cmd_auth_passkey(int argc, char *argv[])
1447 {
1448     unsigned int passkey;
1449 
1450     if (g_bt_conn_handle  == -1) {
1451         printf("Not connected\n");
1452         return 0;
1453     }
1454 
1455     if (argc < 2) {
1456         return -EINVAL;
1457     }
1458 
1459     passkey = atoi(argv[1]);
1460 
1461     if (passkey > 999999) {
1462         printf("Passkey should be between 0-999999\n");
1463         return 0;
1464     }
1465 
1466     ble_stack_smp_passkey_entry(g_bt_conn_handle, passkey);
1467     return 0;
1468 }
1469 #endif /* CONFIG_BT_SMP) || CONFIG_BT_BREDR */
1470 
1471 #if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
1472 static bt_u32_t l2cap_rate;
1473 
l2cap_recv_metrics(struct bt_l2cap_chan * chan,struct net_buf * buf)1474 static void l2cap_recv_metrics(struct bt_l2cap_chan *chan, struct net_buf *buf)
1475 {
1476     return;
1477 }
1478 
l2cap_recv(struct bt_l2cap_chan * chan,struct net_buf * buf)1479 static void l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
1480 {
1481     printf("Incoming data channel %p psm %d len %u\n", chan, chan->psm, buf->len);
1482 
1483     if (buf->len) {
1484         hexdump(buf->data, buf->len);
1485     }
1486 }
1487 
l2cap_connected(struct bt_l2cap_chan * chan)1488 static void l2cap_connected(struct bt_l2cap_chan *chan)
1489 {
1490     printf("Channel %p psm %d connected\n", chan, chan->psm);
1491 }
1492 
l2cap_disconnected(struct bt_l2cap_chan * chan)1493 static void l2cap_disconnected(struct bt_l2cap_chan *chan)
1494 {
1495     printf("Channel %p psm %d disconnected\n", chan, chan->psm);
1496 }
1497 
l2cap_alloc_buf(struct bt_l2cap_chan * chan)1498 static struct net_buf *l2cap_alloc_buf(struct bt_l2cap_chan *chan)
1499 {
1500     /* print if metrics is disabled */
1501     if (chan->ops->recv != l2cap_recv_metrics) {
1502         printf("Channel %p requires buffer\n", chan);
1503     }
1504 
1505     return net_buf_alloc(&data_rx_pool, K_FOREVER);
1506 }
1507 
1508 static struct bt_l2cap_chan_ops l2cap_ops = {
1509     .alloc_buf  = l2cap_alloc_buf,
1510     .recv       = l2cap_recv,
1511     .connected  = l2cap_connected,
1512     .disconnected   = l2cap_disconnected,
1513 };
1514 
1515 static struct bt_l2cap_le_chan l2cap_chan[L2CAP_DYM_CHANNEL_NUM] = {
1516     0
1517 };
1518 
l2cap_accept(struct bt_conn * conn,struct bt_l2cap_chan ** chan)1519 static int l2cap_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
1520 {
1521     printf("Incoming conn %p\n", conn);
1522 
1523     int i;
1524 
1525     for (i = 0; i < L2CAP_DYM_CHANNEL_NUM; i++) {
1526         if (l2cap_chan[i].chan.conn == NULL) {
1527             break;
1528         }
1529     }
1530 
1531     if (i == L2CAP_DYM_CHANNEL_NUM) {
1532         printf("No channels available\n");
1533         return -ENOMEM;
1534     }
1535 
1536     l2cap_chan[i].chan.ops = &l2cap_ops;
1537     l2cap_chan[i].rx.mtu = DATA_MTU;
1538 
1539     *chan = &l2cap_chan[i].chan;
1540 
1541     return 0;
1542 }
1543 
1544 static struct bt_l2cap_server server[L2CAP_DYM_CHANNEL_NUM] = {
1545     0
1546 };
1547 
1548 
cmd_l2cap_register(int argc,char * argv[])1549 static int cmd_l2cap_register(int argc, char *argv[])
1550 {
1551     int i;
1552 
1553     if (argc < 2) {
1554         return -EINVAL;
1555     }
1556 
1557     for (i = 0; i < L2CAP_DYM_CHANNEL_NUM; i++) {
1558         if (server[i].psm == 0) {
1559             break;
1560         }
1561     }
1562 
1563     if (i == L2CAP_DYM_CHANNEL_NUM) {
1564         printf("No more channel\n");
1565         return 0;
1566     }
1567 
1568     server[i].accept = l2cap_accept;
1569     server[i].psm = strtoul(argv[1], NULL, 16);
1570 
1571     if (argc > 2) {
1572         server[i].sec_level = strtoul(argv[2], NULL, 10);
1573     }
1574 
1575     if (bt_l2cap_server_register(&server[i]) < 0) {
1576         printf("Unable to register psm\n");
1577         server[i].psm = 0;
1578     } else {
1579         printf("L2CAP psm %u sec_level %u registered\n", server[i].psm,
1580                server[i].sec_level);
1581     }
1582 
1583     return 0;
1584 }
1585 
cmd_l2cap_connect(int argc,char * argv[])1586 static int cmd_l2cap_connect(int argc, char *argv[])
1587 {
1588     u16_t psm;
1589     int err;
1590     int i;
1591 
1592     if (g_bt_conn_handle == -1) {
1593         printf("Not connected\n");
1594         return 0;
1595     }
1596 
1597     if (argc < 2) {
1598         return -EINVAL;
1599     }
1600 
1601     for (i = 0; i < L2CAP_DYM_CHANNEL_NUM; i++) {
1602         if (l2cap_chan[i].chan.conn == NULL) {
1603             break;
1604         }
1605     }
1606 
1607     if (i == L2CAP_DYM_CHANNEL_NUM) {
1608         printf("No more Channel\n");
1609         return -EINVAL;
1610     }
1611 
1612     l2cap_chan[i].chan.ops = &l2cap_ops;
1613     l2cap_chan[i].rx.mtu = DATA_MTU;
1614 
1615     psm = strtoul(argv[1], NULL, 16);
1616 
1617     err = bt_l2cap_chan_connect(bt_conn_lookup_id(g_bt_conn_handle), &l2cap_chan[i].chan, psm);
1618 
1619     if (err < 0) {
1620         printf("Unable to connect to psm %u (err %u)\n", psm, err);
1621     } else {
1622         printf("L2CAP connection pending\n");
1623     }
1624 
1625     return 0;
1626 }
1627 
cmd_l2cap_disconnect(int argc,char * argv[])1628 static int cmd_l2cap_disconnect(int argc, char *argv[])
1629 {
1630     int err;
1631     u16_t psm;
1632     int i;
1633 
1634     psm = strtoul(argv[1], NULL, 16);
1635 
1636     for (i = 0; i < L2CAP_DYM_CHANNEL_NUM; i++) {
1637         if (l2cap_chan[i].chan.psm == psm) {
1638             err = bt_l2cap_chan_disconnect(&l2cap_chan[i].chan);
1639 
1640             if (err) {
1641                 printf("Unable to disconnect: err %u\n", -err);
1642             }
1643 
1644             return err;
1645         }
1646     }
1647 
1648     return 0;
1649 }
1650 
cmd_l2cap_send(int argc,char * argv[])1651 static int cmd_l2cap_send(int argc, char *argv[])
1652 {
1653     static u8_t buf_data[DATA_MTU] = { [0 ...(DATA_MTU - 1)] = 0xff };
1654     int ret, len, count = 1;
1655     struct net_buf *buf;
1656     u16_t psm = 0;
1657     int i;
1658 
1659     if (argc > 1) {
1660         psm = strtoul(argv[1], NULL, 16);
1661     } else {
1662         return -EINVAL;
1663     }
1664 
1665     if (argc > 2) {
1666         count = strtoul(argv[2], NULL, 10);
1667     }
1668 
1669     for (i = 0; i < L2CAP_DYM_CHANNEL_NUM; i++) {
1670         if (l2cap_chan[i].chan.psm == psm) {
1671             break;
1672         }
1673     }
1674 
1675     if (i == L2CAP_DYM_CHANNEL_NUM) {
1676         printf("Can't find channel\n");
1677         return -EINVAL;
1678     }
1679 
1680     /* when mtu is 23, the max send num is 8, so 6*23 is safe */
1681     len = min(6*23, DATA_MTU - BT_L2CAP_CHAN_SEND_RESERVE);
1682 
1683     while (count--) {
1684         buf = net_buf_alloc(&data_tx_pool, K_FOREVER);
1685         net_buf_reserve(buf, BT_L2CAP_CHAN_SEND_RESERVE);
1686 
1687         net_buf_add_mem(buf, buf_data, len);
1688         ret = bt_l2cap_chan_send(&l2cap_chan[i].chan, buf);
1689 
1690         if (ret < 0) {
1691             printf("Unable to send: %d\n", -ret);
1692             net_buf_unref(buf);
1693             break;
1694         }
1695     }
1696 
1697     return 0;
1698 }
1699 
cmd_l2cap_metrics(int argc,char * argv[])1700 static int cmd_l2cap_metrics(int argc, char *argv[])
1701 {
1702     const char *action;
1703 
1704     if (argc < 2) {
1705         printf("l2cap rate: %u bps.\n", l2cap_rate);
1706 
1707         return 0;
1708     }
1709 
1710     action = argv[1];
1711 
1712     if (!strcmp(action, "on")) {
1713         l2cap_ops.recv = l2cap_recv_metrics;
1714     } else if (!strcmp(action, "off")) {
1715         l2cap_ops.recv = l2cap_recv;
1716     } else {
1717         return -EINVAL;
1718     }
1719 
1720     printf("l2cap metrics %s.\n", action);
1721 
1722     return 0;
1723 }
1724 
1725 #endif
1726 
1727 
1728 
1729 
1730 #if 0
1731 static int write_mac_addr(partition_t handle, const uint8_t *buffer, int length, int offset)
1732 {
1733     // if ((offset % lp->sector_size) == 0) {
1734     //     if (partition_erase(handle, offset, (1 + length / lp->sector_size)) < 0) {
1735     //         printf("erase addr:%x\r\n", offset);
1736     //         return -1;
1737     //     }
1738     // }
1739 
1740     // if (partition_write(handle, offset, (void *)buffer, length) >= 0) {
1741     //     return length;
1742     // }
1743 
1744     // printf("write fail addr:%x length:%x\r\n", offset, length);
1745     return -1;
1746 }
1747 
1748 
1749 static int str2_char(const char *str, uint8_t *addr)
1750 {
1751     int i, j;
1752     u8_t tmp;
1753 
1754     if (strlen(str) != 17) {
1755         return -EINVAL;
1756     }
1757 
1758     for (i = 0, j = 1; *str != '\0'; str++, j++) {
1759         if (!(j % 3) && (*str != ':')) {
1760             return -EINVAL;
1761         } else if (*str == ':') {
1762             i++;
1763             continue;
1764         }
1765 
1766         addr[i] = addr[i] << 4;
1767 
1768         if (char2hex(*str, &tmp) < 0) {
1769             return -EINVAL;
1770         }
1771 
1772         addr[i] |= tmp;
1773     }
1774 
1775     return 0;
1776 }
1777 
1778 
1779 static int  flash_opt_mac(int argc, char *argv[])
1780 {
1781     int err;
1782     uint8_t addr[6] = {0};
1783     uint8_t send_addr[6] = {0};
1784     const char *action;
1785 
1786     handle = partition_open("FCDS");
1787     lp = hal_flash_get_info(handle);
1788 
1789     action = argv[1];
1790 
1791     if ((argc == 3) && (!strcmp(action, "write"))) {
1792         err = str2_char(argv[2], addr);
1793 
1794         if (err < 0) {
1795             return err;
1796         }
1797 
1798         if (err) {
1799             printf("Invalid address\n");
1800             return err;
1801         }
1802 
1803         send_addr[0] = addr[2];
1804         send_addr[1] = addr[3];
1805         send_addr[2] = addr[4];
1806         send_addr[3] = addr[5];
1807         send_addr[4] = addr[0];
1808         send_addr[5] = addr[1];
1809 
1810         if (write_mac_addr(handle, send_addr, sizeof(send_addr), 0) < 0) {
1811             return -1;
1812         }
1813     } else if (!strcmp(action, "read")) {
1814         partition_read(handle, 0, addr, sizeof(addr));
1815         printf("mac:%x:%x:%x:%x:%x:%x", addr[4], addr[5], addr[0], addr[1], addr[2], addr[3]);
1816     }
1817 
1818     partition_close(handle);
1819 
1820     return  0;
1821 }
1822 #endif
1823 
1824 #if defined(CONFIG_BT_WHITELIST)
1825 
get_wl_size()1826 static int get_wl_size()
1827 {
1828     int wl_actal_szie;
1829     wl_actal_szie = ble_stack_white_list_size();
1830     if(wl_actal_szie <= 0) {
1831         return -1;
1832     }
1833     if(wl_actal_szie > MAX_WL_SZIE) {
1834         printf("actual wl size is %d but upper wl list size is %d\n", wl_actal_szie, MAX_WL_SZIE);
1835     }
1836     return wl_actal_szie < MAX_WL_SZIE? wl_actal_szie : MAX_WL_SZIE;
1837 }
1838 
is_wl_addr_exist(dev_addr_t addr)1839 bool is_wl_addr_exist(dev_addr_t addr)
1840 {
1841     uint8_t index = 0;
1842     uint8_t size  = 0;
1843     size = get_wl_size();
1844     for(index = 0; index < size; index++) {
1845         if(wl_list[index].set_flag) {
1846             if(!memcmp(&wl_list[index].addr,&addr,sizeof(wl_list[index].addr))) {
1847                 return 1;
1848             }
1849         }
1850     }
1851     if(index >= size) {
1852         return 0;
1853     }
1854     return 0;
1855 }
1856 
add_addr_to_wl_list(dev_addr_t addr)1857 int add_addr_to_wl_list(dev_addr_t addr)
1858 {
1859     uint8_t index = 0;
1860     uint8_t size  = 0;
1861     size = get_wl_size();
1862 
1863     for(index = 0; index < size; index++) {
1864         if(!wl_list[index].set_flag) {
1865             memcpy(&wl_list[index].addr,&addr,sizeof(wl_list[index].addr));
1866             wl_list[index].set_flag = 1;
1867             break;
1868         }
1869     }
1870 
1871     if(index >= size) {
1872         printf("wl list is full\r\n");
1873         return -1;
1874     } else {
1875         return 0;
1876     }
1877 
1878 }
1879 
remove_addr_form_wl_list(dev_addr_t addr)1880 int remove_addr_form_wl_list(dev_addr_t addr)
1881 {
1882     uint8_t index = 0;
1883     uint8_t size  = 0;
1884 
1885     size = get_wl_size();
1886 
1887     for(index = 0; index < size; index++) {
1888         if(wl_list[index].set_flag) {
1889             if(!memcmp(&wl_list[index].addr, &addr, sizeof(addr))) {
1890                 memset(&wl_list[index],0, sizeof(wl_addr));
1891                 break;
1892             }
1893         }
1894     }
1895 
1896     if(index >= size) {
1897         printf("wl addr not exist\r\n");
1898         return -1;
1899     } else {
1900         return 0;
1901     }
1902 }
1903 
show_wl_list()1904 int show_wl_list()
1905 {
1906     int found_flag = 0;
1907     uint8_t index = 0;
1908     uint8_t size  = 0;
1909     char addr_str[32] = {0};
1910 
1911     size = get_wl_size();
1912 
1913     for(index = 0; index < size; index++) {
1914         if(wl_list[index].set_flag) {
1915             bt_addr2str(&wl_list[index].addr, addr_str, sizeof(addr_str));
1916             found_flag = 1;
1917             printf("wl %d: %s\r\n",index,addr_str);
1918         }
1919     }
1920     if(!found_flag) {
1921         printf("wl addr not exit\r\n");
1922         return -1;
1923     } else {
1924         return 0;
1925     }
1926 
1927 }
1928 
clear_wl_list()1929 int clear_wl_list()
1930 {
1931     memset(wl_list,0,sizeof(wl_list));
1932     return 0;
1933 }
1934 
1935 
cmd_wl_size(int argc,char * argv[])1936 static int cmd_wl_size(int argc, char *argv[])
1937 {
1938     if(!ble_init_flag) {
1939         return -BLE_STACK_ERR_INIT;
1940     }
1941     int ret = ble_stack_white_list_size();
1942     printf("white list size is %d\n", ret);
1943     return 0;
1944 }
cmd_wl_add(int argc,char * argv[])1945 static int cmd_wl_add(int argc, char *argv[])
1946 {
1947     dev_addr_t addr;
1948     int err;
1949 
1950     if(!ble_init_flag) {
1951         return -BLE_STACK_ERR_INIT;
1952     }
1953 
1954     if (argc == 3) {
1955         err = str2bt_addr_le(argv[1], argv[2], &addr);
1956 
1957         if (err) {
1958             printf("Invalid address\n");
1959             return err;
1960         }
1961     } else {
1962         return -EINVAL;
1963     }
1964     if(is_wl_addr_exist(addr)) {
1965         printf("wl addr already exist\r\n");
1966         return 0;
1967     }
1968 
1969 
1970     err = ble_stack_white_list_add(&addr);
1971     if(!err) {
1972         err = add_addr_to_wl_list(addr);
1973         if(err) {
1974             printf("add to upper wl list faild\r\n");
1975         } else {
1976             printf("Add %s (%s) to white list\n", argv[1], argv[2]);
1977         }
1978     } else {
1979         printf("add wl addr faild\r\n");
1980     }
1981     return 0;
1982 }
1983 
cmd_wl_remove(int argc,char * argv[])1984 static int cmd_wl_remove(int argc, char *argv[])
1985 {
1986     if(!ble_init_flag) {
1987         return -BLE_STACK_ERR_INIT;
1988     }
1989 
1990     dev_addr_t addr;
1991     int err;
1992 
1993     if (argc == 3) {
1994         err = str2bt_addr_le(argv[1], argv[2], &addr);
1995 
1996         if (err) {
1997             printf("Invalid address\n");
1998             return err;
1999         }
2000     } else {
2001         return -EINVAL;
2002     }
2003 
2004     if(!is_wl_addr_exist(addr)) {
2005         printf("wl addr not exist\r\n");
2006         return -1;
2007     }
2008 
2009 
2010     err = ble_stack_white_list_remove(&addr);
2011     if(!err) {
2012         err = remove_addr_form_wl_list(addr);
2013         if(err) {
2014             printf("remove from upper wl list faild\r\n");
2015         } else {
2016             printf("Remove %s (%s) to white list\n", argv[1], argv[2]);
2017         }
2018     } else {
2019         printf("add wl addr faild\r\n");
2020     }
2021     return err;
2022 }
cmd_wl_clear(int argc,char * argv[])2023 static int cmd_wl_clear(int argc, char *argv[])
2024 {
2025     if(!ble_init_flag) {
2026         return -BLE_STACK_ERR_INIT;
2027     }
2028     int err = 0;
2029     printf("Clear white list\n");
2030     err = ble_stack_white_list_clear();
2031     if(!err) {
2032         clear_wl_list();
2033     }
2034     return err;
2035 }
2036 
cmd_wl_show(int argc,char * argv[])2037 static int cmd_wl_show(int argc, char *argv[])
2038 {
2039     if(!ble_init_flag) {
2040         return -BLE_STACK_ERR_INIT;
2041     }
2042     show_wl_list();
2043     return 0;
2044 }
2045 #endif
2046 
2047 #define HELP_NONE "[none]"
2048 #define HELP_ADDR_LE "<address: XX:XX:XX:XX:XX:XX> <type: (public|random)>"
2049 
2050 static const struct shell_cmd bt_commands[] = {
2051     { "init", cmd_init, HELP_ADDR_LE },
2052     //{ "mac", flash_opt_mac, "<val:read/write> exp:write 11:22:33:44:55:66" },
2053 #if defined(CONFIG_BT_HCI)
2054     //{ "hci-cmd", cmd_hci_cmd, "<ogf> <ocf> [data]" },
2055 #endif
2056     { "id-create", cmd_id_create, "[addr]" },
2057     { "id-reset", cmd_id_reset, "<id> [addr]" },
2058     { "id-delete", cmd_id_delete, "<id>" },
2059     { "id-show", cmd_id_show, HELP_NONE },
2060     { "id-select", cmd_id_select, "<id>" },
2061     { "name", cmd_name, "[name]" },
2062     {
2063         "scan", cmd_scan,
2064         "<value: active, passive, off> <dup filter: dups, nodups> "\
2065         "<scan interval> <scan window> "\
2066         "<ad(len|adtype|addata ...): 0xxxxxxxx> <sd(len|adtype|addata ...): 0xxxxxxxx>"
2067     },
2068     {
2069         "scan_filter", cmd_scan_filter,
2070         "<filter_policy: 0 any adv 1 white list>"
2071     },
2072 
2073     {
2074         "adv", cmd_advertise,
2075         "<type: stop, conn, nconn> <ad(len|adtype|addata ...): 0xxxxxxxx> <sd(len|adtype|addata ...): 0xxxxxxxx>"
2076     },
2077 #if defined(CONFIG_BT_CONN)
2078     {
2079         "connect", cmd_connect_le, HELP_ADDR_LE\
2080         " <interval_min> <interval_max>"\
2081         " <latency> <timeout>"
2082     },
2083     { "disconnect", cmd_disconnect, "[conn_handle]" },
2084     { "auto-conn", cmd_auto_conn, HELP_ADDR_LE" <action: on|off>"},
2085     { "select", cmd_select, HELP_ADDR_LE },
2086     { "conn-update", cmd_conn_update, "<min> <max> <latency> <timeout>" },
2087     { "oob", cmd_oob },
2088     { "clear", cmd_clear,"<dst:all,address> <type: (public|random>"},
2089 #if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
2090     { "security", cmd_security, "<security level: 0, 1, 2, 3>" },
2091     {
2092         "io-capability", cmd_iocap_set,
2093         "<io input: NONE,YESNO, KEYBOARD> <io output: NONE,DISPLAY>"
2094     },
2095     { "auth-cancel", cmd_auth_cancel, HELP_NONE },
2096     { "auth-passkey", cmd_auth_passkey, "<passkey>" },
2097     { "auth-passkey-confirm", cmd_auth_passkey_confirm, HELP_NONE },
2098     { "auth-pairing-confirm", cmd_auth_pairing_confirm, HELP_NONE },
2099 #if defined(CONFIG_BT_FIXED_PASSKEY)
2100     { "fixed-passkey", cmd_fixed_passkey, "[passkey]" },
2101 #endif
2102 
2103 #endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR) */
2104 #if defined(CONFIG_BT_GATT_CLIENT)
2105     { "gatt-exchange-mtu", cmd_gatt_exchange_mtu, HELP_NONE },
2106     {
2107         "gatt-discover-primary", cmd_gatt_discover,
2108         "<UUID> [start handle] [end handle]"
2109     },
2110     {
2111         "gatt-discover-secondary", cmd_gatt_discover,
2112         "<UUID> [start handle] [end handle]"
2113     },
2114     {
2115         "gatt-discover-include", cmd_gatt_discover,
2116         "[UUID] [start handle] [end handle]"
2117     },
2118     {
2119         "gatt-discover-characteristic", cmd_gatt_discover,
2120         "[UUID] [start handle] [end handle]"
2121     },
2122     {
2123         "gatt-discover-descriptor", cmd_gatt_discover,
2124         "[UUID] [start handle] [end handle]"
2125     },
2126     { "gatt-read-format",cmd_gatt_read_show_format,"<format:0,1>"},
2127     { "gatt-read", cmd_gatt_read, "<handle> [offset]" },
2128     { "gatt-read-multiple", cmd_gatt_mread, "<handle 1> <handle 2> ..." },
2129     { "gatt-write", cmd_gatt_write, "<handle> <offset> <data> [length]" },
2130     {
2131         "gatt-write-without-response", cmd_gatt_write_without_rsp,
2132         "<handle> <data> [length] [repeat]"
2133     },
2134     {
2135         "gatt-write-signed", cmd_gatt_write_without_rsp,
2136         "<handle> <data> [length] [repeat]"
2137     },
2138     {
2139         "gatt-subscribe", cmd_gatt_subscribe,
2140         "<CCC handle> [ind]"
2141     },
2142     { "gatt-unsubscribe", cmd_gatt_unsubscribe, "<CCC handle>"},
2143 #endif /* CONFIG_BT_GATT_CLIENT */
2144     { "gatt-show-db", cmd_gatt_show_db, HELP_NONE },
2145     {
2146         "gatt-register-service", cmd_gatt_register_test_svc,
2147         "register pre-predefined test service"
2148     },
2149     {
2150         "gatt-register-service2", cmd_gatt_register_test_svc,
2151         "register pre-predefined test2 service"
2152     },
2153     {
2154         "gatt-transport-test-config", cmd_gatt_transport_test,
2155         "<type 0:server 1 client> <mode 0:loop 1:single> <server tx mode 0:notify 1:indicate> <server rx handle> <client tx mode 0:write 1:write_withoutresponse> "\
2156         "<data_len 0:stream 1~0xFFFFFFFF data size>"
2157     },
2158     {
2159         "gatt-transport-test-op", cmd_gatt_transport_test,
2160         "<op 0:stop 1:start 2:show result 3:reset>"
2161     },
2162 
2163 #if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
2164     { "l2cap-register", cmd_l2cap_register, "<psm> [sec_level]" },
2165     { "l2cap-connect", cmd_l2cap_connect, "<psm>" },
2166     { "l2cap-disconnect", cmd_l2cap_disconnect, "<psm>" },
2167     { "l2cap-send", cmd_l2cap_send, "<psm> <number of packets>" },
2168     { "l2cap-metrics", cmd_l2cap_metrics, "<value on, off>" },
2169 #endif
2170 
2171 
2172 #endif /* CONFIG_BT_CONN */
2173 #if defined(CONFIG_BT_CTLR_ADV_EXT)
2174     { "advx", cmd_advx, "<on off> [coded] [anon] [txp]" },
2175     { "scanx", cmd_scanx, "<on passive off> [coded]" },
2176 #endif /* CONFIG_BT_CTLR_ADV_EXT */
2177 #if defined(CONFIG_BT_CTLR_DTM)
2178     { "test_tx", cmd_test_tx, "<chan> <len> <type> <phy>" },
2179     { "test_rx", cmd_test_rx, "<chan> <phy> <mod_idx>" },
2180     { "test_end", cmd_test_end, HELP_NONE},
2181 #endif /* CONFIG_BT_CTLR_ADV_EXT */
2182 #if defined(CONFIG_BT_WHITELIST)
2183     { "wl-size", cmd_wl_size, HELP_NONE},
2184     { "wl-add", cmd_wl_add, HELP_ADDR_LE},
2185     { "wl-remove", cmd_wl_remove, HELP_ADDR_LE},
2186     { "wl-clear", cmd_wl_clear, HELP_NONE},
2187     { "wl-show", cmd_wl_show, HELP_NONE},
2188 #endif
2189     { NULL, NULL, NULL }
2190 };
2191 
2192 
cmd_ble_func(char * wbuf,int wbuf_len,int argc,char ** argv)2193 static void cmd_ble_func(char *wbuf, int wbuf_len, int argc, char **argv)
2194 {
2195     int i = 0;
2196     int err;
2197 
2198     if (argc < 2) {
2199         printf("Ble support commands\n");
2200 
2201         for (i = 0; bt_commands[i].cmd_name != NULL; i ++) {
2202             printf("    %s %s\n", bt_commands[i].cmd_name, bt_commands[i].help);
2203         }
2204 
2205         return;
2206     }
2207 
2208     for (i = 0; bt_commands[i].cmd_name != NULL; i ++) {
2209         if (strlen(bt_commands[i].cmd_name) == strlen(argv[1]) &&
2210             !strncmp(bt_commands[i].cmd_name, argv[1], strlen(bt_commands[i].cmd_name))) {
2211             if (bt_commands[i].cb) {
2212                 err = bt_commands[i].cb(argc - 1, &argv[1]);
2213 
2214                 if (err) {
2215                     printf("%s execute fail, %d\n", bt_commands[i].cmd_name, err);
2216                 }
2217 
2218                 break;
2219             }
2220         }
2221     }
2222 }
2223 
2224 #if AOS_COMP_CLI
cli_reg_cmd_ble(void)2225 void cli_reg_cmd_ble(void)
2226 {
2227     static const struct cli_command cmd_info = {
2228         "ble",
2229         "ble commands",
2230         cmd_ble_func,
2231     };
2232 
2233     aos_cli_register_command(&cmd_info);
2234 }
2235 #endif /* AOS_COMP_CLI */
2236