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 extern void (*start_scan_func)(void);
21
device_found(const bt_addr_le_t * addr,int8_t rssi,uint8_t type,struct net_buf_simple * ad)22 static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
23 struct net_buf_simple *ad)
24 {
25 char dev[BT_ADDR_LE_STR_LEN];
26 struct bt_conn *conn;
27 int err;
28
29 bt_addr_le_to_str(addr, dev, sizeof(dev));
30 printk("[DEVICE]: %s, AD evt type %u, AD data len %u, RSSI %i\n",
31 dev, type, ad->len, rssi);
32
33 /* We're only interested in connectable events */
34 if (type != BT_GAP_ADV_TYPE_ADV_IND &&
35 type != BT_GAP_ADV_TYPE_ADV_DIRECT_IND) {
36 return;
37 }
38
39 /* connect only to devices in close proximity */
40 if (rssi < -50) {
41 return;
42 }
43
44 err = bt_le_scan_stop();
45 if (err) {
46 printk("%s: Stop LE scan failed (err %d)\n", __func__, err);
47 return;
48 }
49
50 err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
51 BT_LE_CONN_PARAM_DEFAULT, &conn);
52 if (err) {
53 printk("%s: Create conn failed (err %d)\n", __func__, err);
54 start_scan_func();
55 } else {
56 bt_conn_unref(conn);
57 }
58 }
59
start_scan(void)60 static void start_scan(void)
61 {
62 int err;
63
64 err = bt_le_scan_start(BT_LE_SCAN_ACTIVE, device_found);
65 if (err) {
66 printk("%s: Scanning failed to start (err %d)\n", __func__,
67 err);
68 return;
69 }
70
71 printk("%s: Scanning successfully started\n", __func__);
72 }
73
mtu_updated(struct bt_conn * conn,uint16_t tx,uint16_t rx)74 void mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx)
75 {
76 printk("Updated MTU: TX: %d RX: %d bytes\n", tx, rx);
77 }
78
79 static struct bt_gatt_cb gatt_callbacks = {
80 .att_mtu_updated = mtu_updated
81 };
82
central_gatt_write(uint32_t count)83 uint32_t central_gatt_write(uint32_t count)
84 {
85 int err;
86
87 err = bt_enable(NULL);
88 if (err) {
89 printk("Bluetooth init failed (err %d)\n", err);
90 return 0U;
91 }
92 printk("Bluetooth initialized\n");
93
94 bt_gatt_cb_register(&gatt_callbacks);
95
96 conn_connected = NULL;
97 last_write_rate = 0U;
98 write_countdown = &count;
99
100 if (count != 0U) {
101 printk("GATT Write countdown %u on connection.\n", count);
102 } else {
103 printk("GATT Write forever on connection.\n");
104 }
105
106 #if defined(CONFIG_BT_USER_PHY_UPDATE)
107 err = bt_conn_le_set_default_phy(BT_GAP_LE_PHY_1M, BT_GAP_LE_PHY_1M);
108 if (err) {
109 printk("Failed to set default PHY (err %d)\n", err);
110 return 0U;
111 }
112 #endif /* CONFIG_BT_USER_PHY_UPDATE */
113
114 start_scan_func = start_scan;
115 start_scan_func();
116
117 while (true) {
118 struct bt_conn *conn = NULL;
119
120 if (conn_connected) {
121 /* Get a connection reference to ensure that a
122 * reference is maintained in case disconnected
123 * callback is called while we perform GATT Write
124 * command.
125 */
126 conn = bt_conn_ref(conn_connected);
127 }
128
129 if (conn) {
130 (void)write_cmd(conn);
131 bt_conn_unref(conn);
132
133 /* Passing `0` will not use GATT Write Cmd countdown.
134 * Below code block will be optimized out by the linker.
135 */
136 if (count) {
137 if ((count % 1000U) == 0U) {
138 printk("GATT Write countdown %u\n", count);
139 }
140
141 count--;
142 if (!count) {
143 break;
144 }
145 }
146
147 k_yield();
148 } else {
149 k_sleep(K_SECONDS(1));
150 }
151 }
152
153 return last_write_rate;
154 }
155