1 /*
2  * Copyright (c) 2022 Codecoup
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <stddef.h>
7 #include <stdint.h>
8 
9 #include <zephyr/bluetooth/bluetooth.h>
10 #include <zephyr/bluetooth/byteorder.h>
11 #include <zephyr/bluetooth/conn.h>
12 #include <zephyr/bluetooth/audio/audio.h>
13 #include <zephyr/bluetooth/audio/bap.h>
14 #include <zephyr/bluetooth/audio/pacs.h>
15 #include <zephyr/bluetooth/audio/csip.h>
16 #include <zephyr/bluetooth/gap.h>
17 #include <zephyr/bluetooth/services/ias.h>
18 #include <zephyr/bluetooth/uuid.h>
19 #include <zephyr/kernel.h>
20 #include <zephyr/sys/__assert.h>
21 #include <zephyr/sys/byteorder.h>
22 #include <zephyr/sys/printk.h>
23 #include <zephyr/sys/util.h>
24 #include <zephyr/sys/util_macro.h>
25 
26 #include "hap_ha.h"
27 
28 #define MANDATORY_SINK_CONTEXT (BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED | \
29 				BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | \
30 				BT_AUDIO_CONTEXT_TYPE_MEDIA | \
31 				BT_AUDIO_CONTEXT_TYPE_LIVE)
32 
33 #define AVAILABLE_SINK_CONTEXT   MANDATORY_SINK_CONTEXT
34 #define AVAILABLE_SOURCE_CONTEXT MANDATORY_SINK_CONTEXT
35 
36 static uint8_t unicast_server_addata[] = {
37 	BT_UUID_16_ENCODE(BT_UUID_ASCS_VAL), /* ASCS UUID */
38 	BT_AUDIO_UNICAST_ANNOUNCEMENT_TARGETED, /* Target Announcement */
39 	BT_BYTES_LIST_LE16(AVAILABLE_SINK_CONTEXT),
40 	BT_BYTES_LIST_LE16(AVAILABLE_SOURCE_CONTEXT),
41 	0x00, /* Metadata length */
42 };
43 
44 static uint8_t csis_rsi_addata[BT_CSIP_RSI_SIZE];
45 
46 /* TODO: Expand with BAP data */
47 static const struct bt_data ad[] = {
48 	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
49 	BT_DATA_BYTES(BT_DATA_UUID16_ALL, BT_UUID_16_ENCODE(BT_UUID_ASCS_VAL)),
50 #if defined(CONFIG_BT_CSIP_SET_MEMBER)
51 	BT_DATA(BT_DATA_CSIS_RSI, csis_rsi_addata, ARRAY_SIZE(csis_rsi_addata)),
52 #endif /* CONFIG_BT_CSIP_SET_MEMBER */
53 	BT_DATA(BT_DATA_SVC_DATA16, unicast_server_addata, ARRAY_SIZE(unicast_server_addata)),
54 	BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1),
55 };
56 
57 static struct k_work_delayable adv_work;
58 static struct bt_le_ext_adv *ext_adv;
59 
disconnected(struct bt_conn * conn,uint8_t reason)60 static void disconnected(struct bt_conn *conn, uint8_t reason)
61 {
62 	/* Restart advertising after disconnection */
63 	k_work_schedule(&adv_work, K_SECONDS(1));
64 }
65 
66 BT_CONN_CB_DEFINE(conn_callbacks) = {
67 	.disconnected = disconnected,
68 };
69 
70 #if defined(CONFIG_BT_PRIVACY) && defined(CONFIG_BT_CSIP_SET_MEMBER)
adv_rpa_expired_cb(struct bt_le_ext_adv * adv)71 static bool adv_rpa_expired_cb(struct bt_le_ext_adv *adv)
72 {
73 	char rsi_str[13];
74 	int err;
75 
76 	err = csip_generate_rsi(csis_rsi_addata);
77 	if (err != 0) {
78 		printk("Failed to generate RSI (err %d)\n", err);
79 		return false;
80 	}
81 
82 	snprintk(rsi_str, ARRAY_SIZE(rsi_str), "%02x%02x%02x%02x%02x%02x",
83 		 csis_rsi_addata[0], csis_rsi_addata[1], csis_rsi_addata[2],
84 		 csis_rsi_addata[3], csis_rsi_addata[4], csis_rsi_addata[5]);
85 
86 	printk("PRSI: 0x%s\n", rsi_str);
87 
88 	err = bt_le_ext_adv_set_data(adv, ad, ARRAY_SIZE(ad), NULL, 0);
89 	if (err) {
90 		printk("Failed to set advertising data (err %d)\n", err);
91 		return false;
92 	}
93 
94 	return true;
95 }
96 #endif /* CONFIG_BT_PRIVACY && CONFIG_BT_CSIP_SET_MEMBER */
97 
98 static const struct bt_le_ext_adv_cb adv_cb = {
99 #if defined(CONFIG_BT_PRIVACY) && defined(CONFIG_BT_CSIP_SET_MEMBER)
100 	.rpa_expired = adv_rpa_expired_cb,
101 #endif /* CONFIG_BT_PRIVACY && CONFIG_BT_CSIP_SET_MEMBER */
102 };
103 
adv_work_handler(struct k_work * work)104 static void adv_work_handler(struct k_work *work)
105 {
106 	int err;
107 
108 	if (ext_adv == NULL) {
109 		/* Create a connectable advertising set */
110 		err = bt_le_ext_adv_create(BT_BAP_ADV_PARAM_CONN_QUICK, &adv_cb, &ext_adv);
111 		if (err) {
112 			printk("Failed to create advertising set (err %d)\n", err);
113 		}
114 
115 		err = bt_le_ext_adv_set_data(ext_adv, ad, ARRAY_SIZE(ad), NULL, 0);
116 		if (err) {
117 			printk("Failed to set advertising data (err %d)\n", err);
118 		}
119 
120 		__ASSERT_NO_MSG(err == 0);
121 	}
122 
123 	err = bt_le_ext_adv_start(ext_adv, BT_LE_EXT_ADV_START_DEFAULT);
124 	if (err) {
125 		printk("Failed to start advertising set (err %d)\n", err);
126 	} else {
127 		printk("Advertising successfully started\n");
128 	}
129 }
130 
131 #if defined(CONFIG_BT_IAS)
alert_stop(void)132 static void alert_stop(void)
133 {
134 	printk("Alert stopped\n");
135 }
136 
alert_start(void)137 static void alert_start(void)
138 {
139 	printk("Mild alert started\n");
140 }
141 
alert_high_start(void)142 static void alert_high_start(void)
143 {
144 	printk("High alert started\n");
145 }
146 
147 BT_IAS_CB_DEFINE(ias_callbacks) = {
148 	.no_alert = alert_stop,
149 	.mild_alert = alert_start,
150 	.high_alert = alert_high_start,
151 };
152 #endif /* CONFIG_BT_IAS */
153 
main(void)154 int main(void)
155 {
156 	int err;
157 
158 	err = bt_enable(NULL);
159 	if (err != 0) {
160 		printk("Bluetooth init failed (err %d)\n", err);
161 		return 0;
162 	}
163 
164 	printk("Bluetooth initialized\n");
165 
166 	err = has_server_init();
167 	if (err != 0) {
168 		printk("HAS Server init failed (err %d)\n", err);
169 		return 0;
170 	}
171 
172 	err = bap_unicast_sr_init();
173 	if (err != 0) {
174 		printk("BAP Unicast Server init failed (err %d)\n", err);
175 		return 0;
176 	}
177 
178 	if (IS_ENABLED(CONFIG_HAP_HA_HEARING_AID_BINAURAL)) {
179 		err = csip_set_member_init();
180 		if (err != 0) {
181 			printk("CSIP Set Member init failed (err %d)\n", err);
182 			return 0;
183 		}
184 
185 		err = csip_generate_rsi(csis_rsi_addata);
186 		if (err != 0) {
187 			printk("Failed to generate RSI (err %d)\n", err);
188 			return 0;
189 		}
190 	}
191 
192 	err = vcp_vol_renderer_init();
193 	if (err != 0) {
194 		printk("VCP Volume Renderer init failed (err %d)\n", err);
195 		return 0;
196 	}
197 
198 	if (IS_ENABLED(CONFIG_BT_ASCS_ASE_SRC)) {
199 		err = micp_mic_dev_init();
200 		if (err != 0) {
201 			printk("MICP Microphone Device init failed (err %d)\n", err);
202 			return 0;
203 		}
204 	}
205 
206 	if (IS_ENABLED(CONFIG_BT_TBS_CLIENT)) {
207 		err = ccp_call_ctrl_init();
208 		if (err != 0) {
209 			printk("MICP Microphone Device init failed (err %d)\n", err);
210 			return 0;
211 		}
212 	}
213 
214 	if (IS_ENABLED(CONFIG_HAP_HA_HEARING_AID_BANDED)) {
215 		/* HAP_d1.0r00; 3.7 BAP Unicast Server role requirements
216 		 * A Banded Hearing Aid in the HA role shall set the
217 		 * Front Left and the Front Right bits to a value of 0b1
218 		 * in the Sink Audio Locations characteristic value.
219 		 */
220 		bt_pacs_set_location(BT_AUDIO_DIR_SINK,
221 				    (BT_AUDIO_LOCATION_FRONT_LEFT |
222 				     BT_AUDIO_LOCATION_FRONT_RIGHT));
223 	} else {
224 		bt_pacs_set_location(BT_AUDIO_DIR_SINK,
225 				     BT_AUDIO_LOCATION_FRONT_LEFT);
226 	}
227 
228 	bt_pacs_set_available_contexts(BT_AUDIO_DIR_SINK,
229 				       AVAILABLE_SINK_CONTEXT);
230 
231 	if (IS_ENABLED(CONFIG_BT_ASCS_ASE_SRC)) {
232 		bt_pacs_set_location(BT_AUDIO_DIR_SOURCE,
233 				     BT_AUDIO_LOCATION_FRONT_LEFT);
234 		bt_pacs_set_available_contexts(BT_AUDIO_DIR_SOURCE,
235 					       AVAILABLE_SOURCE_CONTEXT);
236 	}
237 
238 	k_work_init_delayable(&adv_work, adv_work_handler);
239 	k_work_schedule(&adv_work, K_NO_WAIT);
240 	return 0;
241 }
242