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