1 /*
2 * Copyright (c) 2021 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/types.h>
8 #include <stddef.h>
9 #include <string.h>
10 #include <errno.h>
11 #include <zephyr/sys/printk.h>
12 #include <zephyr/sys/byteorder.h>
13 #include <zephyr/kernel.h>
14
15 #include <zephyr/bluetooth/bluetooth.h>
16 #include <zephyr/bluetooth/hci.h>
17 #include <zephyr/bluetooth/conn.h>
18 #include <zephyr/bluetooth/iso.h>
19 #include <zephyr/settings/settings.h>
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
connected(struct bt_conn * conn,uint8_t err)25 static void connected(struct bt_conn *conn, uint8_t err)
26 {
27 char addr[BT_ADDR_LE_STR_LEN];
28
29 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
30
31 if (err) {
32 printk("Failed to connect to %s (%u)\n", addr, err);
33 return;
34 }
35
36 printk("Connected %s\n", addr);
37 }
38
disconnected(struct bt_conn * conn,uint8_t reason)39 static void disconnected(struct bt_conn *conn, uint8_t reason)
40 {
41 char addr[BT_ADDR_LE_STR_LEN];
42
43 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
44
45 printk("Disconnected from %s (reason 0x%02x)\n", addr, reason);
46 }
47
48 BT_CONN_CB_DEFINE(conn_callbacks) = {
49 .connected = connected,
50 .disconnected = disconnected,
51 };
52
53 /** Print data as d_0 d_1 d_2 ... d_(n-2) d_(n-1) d_(n) to show the 3 first and 3 last octets
54 *
55 * Examples:
56 * 01
57 * 0102
58 * 010203
59 * 01020304
60 * 0102030405
61 * 010203040506
62 * 010203...050607
63 * 010203...060708
64 * etc.
65 */
iso_print_data(uint8_t * data,size_t data_len)66 static void iso_print_data(uint8_t *data, size_t data_len)
67 {
68 /* Maximum number of octets from each end of the data */
69 const uint8_t max_octets = 3;
70 char data_str[35];
71 size_t str_len;
72
73 str_len = bin2hex(data, MIN(max_octets, data_len), data_str, sizeof(data_str));
74 if (data_len > max_octets) {
75 if (data_len > (max_octets * 2)) {
76 static const char dots[] = "...";
77
78 strcat(&data_str[str_len], dots);
79 str_len += strlen(dots);
80 }
81
82 str_len += bin2hex(data + (data_len - MIN(max_octets, data_len - max_octets)),
83 MIN(max_octets, data_len - max_octets),
84 data_str + str_len,
85 sizeof(data_str) - str_len);
86 }
87
88 printk("\t %s\n", data_str);
89 }
90
iso_recv(struct bt_iso_chan * chan,const struct bt_iso_recv_info * info,struct net_buf * buf)91 static void iso_recv(struct bt_iso_chan *chan, const struct bt_iso_recv_info *info,
92 struct net_buf *buf)
93 {
94 if (info->flags & BT_ISO_FLAGS_VALID) {
95 printk("Incoming data channel %p len %u\n", chan, buf->len);
96 iso_print_data(buf->data, buf->len);
97 }
98 }
99
iso_connected(struct bt_iso_chan * chan)100 static void iso_connected(struct bt_iso_chan *chan)
101 {
102 printk("ISO Channel %p connected\n", chan);
103 }
104
iso_disconnected(struct bt_iso_chan * chan,uint8_t reason)105 static void iso_disconnected(struct bt_iso_chan *chan, uint8_t reason)
106 {
107 printk("ISO Channel %p disconnected (reason 0x%02x)\n", chan, reason);
108 }
109
110 static struct bt_iso_chan_ops iso_ops = {
111 .recv = iso_recv,
112 .connected = iso_connected,
113 .disconnected = iso_disconnected,
114 };
115
116 static struct bt_iso_chan_io_qos iso_rx = {
117 .sdu = CONFIG_BT_ISO_TX_MTU,
118 .path = NULL,
119 };
120
121 static struct bt_iso_chan_qos iso_qos = {
122 .rx = &iso_rx,
123 .tx = NULL,
124 };
125
126 static struct bt_iso_chan iso_chan = {
127 .ops = &iso_ops,
128 .qos = &iso_qos,
129 };
130
iso_accept(const struct bt_iso_accept_info * info,struct bt_iso_chan ** chan)131 static int iso_accept(const struct bt_iso_accept_info *info,
132 struct bt_iso_chan **chan)
133 {
134 printk("Incoming request from %p\n", (void *)info->acl);
135
136 if (iso_chan.iso) {
137 printk("No channels available\n");
138 return -ENOMEM;
139 }
140
141 *chan = &iso_chan;
142
143 return 0;
144 }
145
146 static struct bt_iso_server iso_server = {
147 #if defined(CONFIG_BT_SMP)
148 .sec_level = BT_SECURITY_L1,
149 #endif /* CONFIG_BT_SMP */
150 .accept = iso_accept,
151 };
152
main(void)153 int main(void)
154 {
155 int err;
156
157 err = bt_enable(NULL);
158 if (err) {
159 printk("Bluetooth init failed (err %d)\n", err);
160 return 0;
161 }
162
163 if (IS_ENABLED(CONFIG_SETTINGS)) {
164 settings_load();
165 }
166
167 printk("Bluetooth initialized\n");
168
169 err = bt_iso_server_register(&iso_server);
170 if (err) {
171 printk("Unable to register ISO server (err %d)\n", err);
172 return 0;
173 }
174
175 err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, ad, ARRAY_SIZE(ad), NULL, 0);
176 if (err) {
177 printk("Advertising failed to start (err %d)\n", err);
178 return 0;
179 }
180
181 printk("Advertising successfully started\n");
182 return 0;
183 }
184