1 /*
2 * Copyright (c) 2022 Nordic Semiconductor ASA
3 * Copyright (c) 2015-2016 Intel Corporation
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <zephyr/sys/printk.h>
9 #include <zephyr/bluetooth/bluetooth.h>
10 #include <zephyr/bluetooth/hci.h>
11
12 #define NAME_LEN 30
13
device_found(const bt_addr_le_t * addr,int8_t rssi,uint8_t type,struct net_buf_simple * ad)14 static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
15 struct net_buf_simple *ad)
16 {
17 char addr_str[BT_ADDR_LE_STR_LEN];
18
19 bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
20 printk("Device found: %s (RSSI %d), type %u, AD data len %u\n",
21 addr_str, rssi, type, ad->len);
22 }
23
24 #if defined(CONFIG_BT_EXT_ADV)
data_cb(struct bt_data * data,void * user_data)25 static bool data_cb(struct bt_data *data, void *user_data)
26 {
27 char *name = user_data;
28 uint8_t len;
29
30 switch (data->type) {
31 case BT_DATA_NAME_SHORTENED:
32 case BT_DATA_NAME_COMPLETE:
33 len = MIN(data->data_len, NAME_LEN - 1);
34 (void)memcpy(name, data->data, len);
35 name[len] = '\0';
36 return false;
37 default:
38 return true;
39 }
40 }
41
phy2str(uint8_t phy)42 static const char *phy2str(uint8_t phy)
43 {
44 switch (phy) {
45 case BT_GAP_LE_PHY_NONE: return "No packets";
46 case BT_GAP_LE_PHY_1M: return "LE 1M";
47 case BT_GAP_LE_PHY_2M: return "LE 2M";
48 case BT_GAP_LE_PHY_CODED: return "LE Coded";
49 default: return "Unknown";
50 }
51 }
52
scan_recv(const struct bt_le_scan_recv_info * info,struct net_buf_simple * buf)53 static void scan_recv(const struct bt_le_scan_recv_info *info,
54 struct net_buf_simple *buf)
55 {
56 char le_addr[BT_ADDR_LE_STR_LEN];
57 char name[NAME_LEN];
58 uint8_t data_status;
59 uint16_t data_len;
60
61 (void)memset(name, 0, sizeof(name));
62
63 data_len = buf->len;
64 bt_data_parse(buf, data_cb, name);
65
66 data_status = BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS(info->adv_props);
67
68 bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
69 printk("[DEVICE]: %s, AD evt type %u, Tx Pwr: %i, RSSI %i "
70 "Data status: %u, AD data len: %u Name: %s "
71 "C:%u S:%u D:%u SR:%u E:%u Pri PHY: %s, Sec PHY: %s, "
72 "Interval: 0x%04x (%u ms), SID: %u\n",
73 le_addr, info->adv_type, info->tx_power, info->rssi,
74 data_status, data_len, name,
75 (info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) != 0,
76 (info->adv_props & BT_GAP_ADV_PROP_SCANNABLE) != 0,
77 (info->adv_props & BT_GAP_ADV_PROP_DIRECTED) != 0,
78 (info->adv_props & BT_GAP_ADV_PROP_SCAN_RESPONSE) != 0,
79 (info->adv_props & BT_GAP_ADV_PROP_EXT_ADV) != 0,
80 phy2str(info->primary_phy), phy2str(info->secondary_phy),
81 info->interval, info->interval * 5 / 4, info->sid);
82 }
83
84 static struct bt_le_scan_cb scan_callbacks = {
85 .recv = scan_recv,
86 };
87 #endif /* CONFIG_BT_EXT_ADV */
88
observer_start(void)89 int observer_start(void)
90 {
91 struct bt_le_scan_param scan_param = {
92 .type = BT_LE_SCAN_TYPE_PASSIVE,
93 .options = BT_LE_SCAN_OPT_FILTER_DUPLICATE,
94 .interval = BT_GAP_SCAN_FAST_INTERVAL,
95 .window = BT_GAP_SCAN_FAST_WINDOW,
96 };
97 int err;
98
99 #if defined(CONFIG_BT_EXT_ADV)
100 bt_le_scan_cb_register(&scan_callbacks);
101 printk("Registered scan callbacks\n");
102 #endif /* CONFIG_BT_EXT_ADV */
103
104 err = bt_le_scan_start(&scan_param, device_found);
105 if (err) {
106 printk("Start scanning failed (err %d)\n", err);
107 return err;
108 }
109 printk("Started scanning...\n");
110
111 return 0;
112 }
113