1 /*
2 * Copyright (c) 2022 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/sys/printk.h>
9
10 #include <zephyr/bluetooth/bluetooth.h>
11 #include <zephyr/bluetooth/conn.h>
12 #include <zephyr/bluetooth/gatt.h>
13 #include <zephyr/bluetooth/hci.h>
14
15 extern int mtu_exchange(struct bt_conn *conn);
16 extern int write_cmd(struct bt_conn *conn);
17 extern struct bt_conn *conn_connected;
18 extern uint32_t last_write_rate;
19 extern uint32_t *write_countdown;
20
21 static const struct bt_data ad[] = {
22 BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
23 };
24
25 static const struct bt_data sd[] = {
26 BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1),
27 };
28
mtu_updated(struct bt_conn * conn,uint16_t tx,uint16_t rx)29 static void mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx)
30 {
31 printk("Updated MTU: TX: %d RX: %d bytes\n", tx, rx);
32 }
33
34 #if defined(CONFIG_BT_SMP)
auth_cancel(struct bt_conn * conn)35 static void auth_cancel(struct bt_conn *conn)
36 {
37 char addr[BT_ADDR_LE_STR_LEN];
38
39 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
40
41 printk("Pairing cancelled: %s\n", addr);
42 }
43
44 static struct bt_conn_auth_cb auth_callbacks = {
45 .cancel = auth_cancel,
46 };
47 #endif /* CONFIG_BT_SMP */
48
49 static struct bt_gatt_cb gatt_callbacks = {
50 .att_mtu_updated = mtu_updated
51 };
52
53 #define BT_LE_SCAN_PASSIVE_ALLOW_DUPILCATES \
54 BT_LE_SCAN_PARAM(BT_LE_SCAN_TYPE_PASSIVE, \
55 BT_LE_SCAN_OPT_NONE, \
56 BT_GAP_SCAN_FAST_INTERVAL_MIN, \
57 BT_GAP_SCAN_FAST_INTERVAL_MIN)
58
device_found(const bt_addr_le_t * addr,int8_t rssi,uint8_t type,struct net_buf_simple * ad)59 static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
60 struct net_buf_simple *ad)
61 {
62 char addr_str[BT_ADDR_LE_STR_LEN];
63
64 bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
65 printk("Device found: %s (RSSI %d)\n", addr_str, rssi);
66 }
67
peripheral_gatt_write(uint32_t count)68 uint32_t peripheral_gatt_write(uint32_t count)
69 {
70 int err;
71
72 err = bt_enable(NULL);
73 if (err) {
74 printk("Bluetooth init failed (err %d)\n", err);
75 return 0U;
76 }
77
78 printk("Bluetooth initialized\n");
79
80 bt_gatt_cb_register(&gatt_callbacks);
81
82 /* On target, users can enable simultaneous (background) scanning but by default do not have
83 * the scanning enabled.
84 * If both Central plus Peripheral role is built together then
85 * Peripheral is scanning (on 1M and Coded PHY windows) while there
86 * is simultaneous Write Commands.
87 */
88 if (IS_ENABLED(CONFIG_BT_OBSERVER) && !IS_ENABLED(CONFIG_USE_PHY_UPDATE_ITERATION_ONCE)) {
89 printk("Start continuous passive scanning...");
90 err = bt_le_scan_start(BT_LE_SCAN_PASSIVE_ALLOW_DUPILCATES,
91 device_found);
92 if (err != 0) {
93 printk("Scan start failed (%d).\n", err);
94 return err;
95 }
96 printk("success.\n");
97 }
98
99 #if defined(CONFIG_BT_SMP)
100 (void)bt_conn_auth_cb_register(&auth_callbacks);
101 #endif /* CONFIG_BT_SMP */
102
103 #if defined(CONFIG_BT_USER_PHY_UPDATE)
104 err = bt_conn_le_set_default_phy(BT_GAP_LE_PHY_1M, BT_GAP_LE_PHY_1M);
105 if (err) {
106 printk("Failed to set default PHY (err %d)\n", err);
107 return 0U;
108 }
109 #endif /* CONFIG_BT_USER_PHY_UPDATE */
110
111 err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
112 if (err) {
113 printk("Advertising failed to start (err %d)\n", err);
114 return 0U;
115 }
116
117 printk("Advertising successfully started\n");
118
119 conn_connected = NULL;
120 last_write_rate = 0U;
121 write_countdown = &count;
122
123 if (count != 0U) {
124 printk("GATT Write countdown %u on connection.\n", count);
125 } else {
126 printk("GATT Write forever on connection.\n");
127 }
128
129 while (true) {
130 struct bt_conn *conn = NULL;
131
132 if (conn_connected) {
133 /* Get a connection reference to ensure that a
134 * reference is maintained in case disconnected
135 * callback is called while we perform GATT Write
136 * command.
137 */
138 conn = bt_conn_ref(conn_connected);
139 }
140
141 if (conn) {
142 write_cmd(conn);
143 bt_conn_unref(conn);
144
145 if (count) {
146 if ((count % 1000U) == 0U) {
147 printk("GATT Write countdown %u\n", count);
148 }
149
150 count--;
151 if (!count) {
152 break;
153 }
154 }
155
156 k_yield();
157 } else {
158 k_sleep(K_SECONDS(1));
159 }
160 }
161
162 return last_write_rate;
163 }
164