1 /*
2  * Copyright (c) 2023 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stddef.h>
8 #include <string.h>
9 #include <errno.h>
10 
11 #include <zephyr/kernel.h>
12 #include <zephyr/logging/log.h>
13 #include <zephyr/types.h>
14 #include <zephyr/sys/ring_buffer.h>
15 
16 #include <zephyr/bluetooth/bluetooth.h>
17 #include <zephyr/bluetooth/hci.h>
18 #include <zephyr/bluetooth/conn.h>
19 #include <zephyr/bluetooth/uuid.h>
20 #include <zephyr/bluetooth/gatt.h>
21 
22 /* Zephyr OpenThread integration Library */
23 #include <zephyr/net/openthread.h>
24 
25 /* OpenThread BLE driver API */
26 #include <openthread/error.h>
27 #include <openthread/platform/ble.h>
28 #include <openthread/tcat.h>
29 
30 /* Zephyr Logging */
31 
32 #define LOG_MODULE_NAME net_openthread_tcat
33 #define LOG_LEVEL       CONFIG_OPENTHREAD_LOG_LEVEL
34 
35 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
36 
37 /* BLE connection constants as defined in thread specification. */
38 #define TOBLE_SERVICE_UUID 0xfffb
39 #define RX_CHARACTERISTIC_UUID                                                                     \
40 	BT_UUID_128_ENCODE(0x6bd10d8b, 0x85a7, 0x4e5a, 0xba2d, 0xc83558a5f220)
41 #define TX_CHARACTERISTIC_UUID                                                                     \
42 	BT_UUID_128_ENCODE(0x7fddf61f, 0x280a, 0x4773, 0xb448, 0xba1b8fe0dd69)
43 
44 #define BT_UUID_TCAT_SERVICE    BT_UUID_DECLARE_16(TOBLE_SERVICE_UUID)
45 #define BT_UUID_TCAT_SERVICE_RX BT_UUID_DECLARE_128(RX_CHARACTERISTIC_UUID)
46 #define BT_UUID_TCAT_SERVICE_TX BT_UUID_DECLARE_128(TX_CHARACTERISTIC_UUID)
47 
48 #define PLAT_BLE_THREAD_DEALY 500
49 #define PLAT_BLE_MSG_DATA_MAX CONFIG_BT_L2CAP_TX_MTU /* must match the maximum MTU size used */
50 
51 #define PLAT_BLE_MSG_CONNECT    (PLAT_BLE_MSG_DATA_MAX + 1U)
52 #define PLAT_BLE_MSG_DISCONNECT (PLAT_BLE_MSG_CONNECT + 1U)
53 
54 /* Zephyr Kernel Objects */
55 
56 static void ot_plat_ble_thread(void *, void *, void *);
57 static uint8_t ot_plat_ble_msg_buf[PLAT_BLE_MSG_DATA_MAX];
58 
59 static K_SEM_DEFINE(ot_plat_ble_init_semaphore, 0, 1);
60 static K_SEM_DEFINE(ot_plat_ble_event_semaphore, 0, K_SEM_MAX_LIMIT);
61 RING_BUF_DECLARE(ot_plat_ble_ring_buf, CONFIG_OPENTHREAD_BLE_TCAT_RING_BUF_SIZE);
62 static K_THREAD_DEFINE(ot_plat_ble_tid, CONFIG_OPENTHREAD_BLE_TCAT_THREAD_STACK_SIZE,
63 		       ot_plat_ble_thread, NULL, NULL, NULL, 5, 0, PLAT_BLE_THREAD_DEALY);
64 
65 /* OpenThread Objects */
66 
67 static otInstance *ble_openthread_instance;
68 
69 /* BLE service Objects */
70 
71 /* forward declaration for callback functions */
72 static ssize_t on_receive(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf,
73 			  uint16_t len, uint16_t offset, uint8_t flags);
74 static void on_cccd_changed(const struct bt_gatt_attr *attr, uint16_t value);
75 
76 /* Service Declaration and Registration */
77 BT_GATT_SERVICE_DEFINE(my_service, BT_GATT_PRIMARY_SERVICE(BT_UUID_TCAT_SERVICE),
78 		       BT_GATT_CHARACTERISTIC(BT_UUID_TCAT_SERVICE_RX,
79 					      BT_GATT_CHRC_WRITE | BT_GATT_CHRC_WRITE_WITHOUT_RESP,
80 					      BT_GATT_PERM_READ | BT_GATT_PERM_WRITE, NULL,
81 					      on_receive, NULL),
82 		       BT_GATT_CHARACTERISTIC(BT_UUID_TCAT_SERVICE_TX, BT_GATT_CHRC_NOTIFY,
83 					      BT_GATT_PERM_READ, NULL, NULL, NULL),
84 		       BT_GATT_CCC(on_cccd_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),);
85 
86 /* Zephyr BLE Objects */
87 
88 /* forward declaration for callback functions */
89 static void connected(struct bt_conn *conn, uint8_t err);
90 static void disconnected(struct bt_conn *conn, uint8_t reason);
91 static bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param);
92 static void le_param_updated(struct bt_conn *conn, uint16_t interval, uint16_t latency,
93 			     uint16_t timeout);
94 
95 static struct bt_conn *ot_plat_ble_connection;
96 
97 static struct bt_conn_cb conn_callbacks = {.connected = connected,
98 					   .disconnected = disconnected,
99 					   .le_param_req = le_param_req,
100 					   .le_param_updated = le_param_updated};
101 
102 static uint8_t service_data[OT_TCAT_ADVERTISEMENT_MAX_LEN] = {0};
103 static const uint8_t service_data_size = ARRAY_SIZE(service_data);
104 
105 static struct bt_data ad[] = {
106 	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
107 	BT_DATA(BT_DATA_SVC_DATA16, service_data, service_data_size),
108 };
109 
110 static struct bt_data sd[] = {
111 	BT_DATA_BYTES(BT_DATA_UUID16_ALL, BT_UUID_16_ENCODE(TOBLE_SERVICE_UUID)),
112 	BT_DATA(BT_DATA_SVC_DATA16, service_data, service_data_size),
113 };
114 
115 /* Zephyr BLE Message Queue and Thread */
116 
ot_plat_ble_queue_msg(const uint8_t * aData,uint16_t aLen,int8_t aRssi)117 static bool ot_plat_ble_queue_msg(const uint8_t *aData, uint16_t aLen, int8_t aRssi)
118 {
119 	otError error = OT_ERROR_NONE;
120 	uint16_t len = 0;
121 
122 	if (aLen <= PLAT_BLE_MSG_DATA_MAX && aData == NULL) {
123 		return OT_ERROR_INVALID_ARGS;
124 	}
125 
126 	k_sched_lock();
127 
128 	len = sizeof(aLen) + sizeof(aRssi) + ((aLen <= PLAT_BLE_MSG_DATA_MAX) ? aLen : 0);
129 
130 	if (ring_buf_space_get(&ot_plat_ble_ring_buf) >= len) {
131 		ring_buf_put(&ot_plat_ble_ring_buf, (uint8_t *)&aLen, sizeof(aLen));
132 		ring_buf_put(&ot_plat_ble_ring_buf, &aRssi, sizeof(aRssi));
133 		if (aLen <= PLAT_BLE_MSG_DATA_MAX) {
134 			ring_buf_put(&ot_plat_ble_ring_buf, aData, aLen);
135 		}
136 		k_sem_give(&ot_plat_ble_event_semaphore);
137 	} else {
138 		error = OT_ERROR_NO_BUFS;
139 	}
140 
141 	k_sched_unlock();
142 
143 	return error;
144 }
145 
ot_plat_ble_thread(void * unused1,void * unused2,void * unused3)146 static void ot_plat_ble_thread(void *unused1, void *unused2, void *unused3)
147 {
148 	ARG_UNUSED(unused1);
149 	ARG_UNUSED(unused2);
150 	ARG_UNUSED(unused3);
151 
152 	uint16_t len;
153 	int8_t rssi;
154 	otBleRadioPacket my_packet;
155 
156 	LOG_INF("%s started", __func__);
157 
158 	while (1) {
159 		k_sem_take(&ot_plat_ble_event_semaphore, K_FOREVER);
160 		ring_buf_get(&ot_plat_ble_ring_buf, (uint8_t *)&len, sizeof(len));
161 		ring_buf_get(&ot_plat_ble_ring_buf, &rssi, sizeof(rssi));
162 		if (len <= PLAT_BLE_MSG_DATA_MAX) {
163 			ring_buf_get(&ot_plat_ble_ring_buf, ot_plat_ble_msg_buf, len);
164 		}
165 
166 		openthread_api_mutex_lock(openthread_get_default_context());
167 
168 		if (len <= PLAT_BLE_MSG_DATA_MAX) {
169 			/* The packet parameter in otPlatBleGattServerOnWriteRequest is not const.
170 			 * Re-write all members.
171 			 */
172 			my_packet.mValue = ot_plat_ble_msg_buf;
173 			my_packet.mPower = rssi;
174 			my_packet.mLength = len;
175 			otPlatBleGattServerOnWriteRequest(ble_openthread_instance, 0, &my_packet);
176 		} else if (len == PLAT_BLE_MSG_CONNECT) {
177 			otPlatBleGapOnConnected(ble_openthread_instance, 0);
178 		} else if (len == PLAT_BLE_MSG_DISCONNECT) {
179 			otPlatBleGapOnDisconnected(ble_openthread_instance, 0);
180 		}
181 		openthread_api_mutex_unlock(openthread_get_default_context());
182 	}
183 }
184 
185 /* Zephyr BLE service callbacks */
186 
187 /* This function is called whenever the RX Characteristic has been written to by a Client */
on_receive(struct bt_conn * conn,const struct bt_gatt_attr * attr,const void * buf,uint16_t len,uint16_t offset,uint8_t flags)188 static ssize_t on_receive(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf,
189 			  uint16_t len, uint16_t offset, uint8_t flags)
190 {
191 	LOG_DBG("Received data, handle %" PRIu16 ", len %" PRIu16, attr->handle, len);
192 
193 	otError error = ot_plat_ble_queue_msg(buf, len, 0);
194 
195 	if (error != OT_ERROR_NONE) {
196 		LOG_WRN("Error queuing message: %s", otThreadErrorToString(error));
197 	}
198 
199 	return len;
200 }
201 
202 /* This function is called whenever a Notification has been sent by the TX Characteristic */
on_sent(struct bt_conn * conn,void * user_data)203 static void on_sent(struct bt_conn *conn, void *user_data)
204 {
205 	ARG_UNUSED(conn);
206 	ARG_UNUSED(user_data);
207 
208 	LOG_DBG("Data sent");
209 }
210 
211 /* This function is called whenever the CCCD register has been changed by the client */
on_cccd_changed(const struct bt_gatt_attr * attr,uint16_t value)212 void on_cccd_changed(const struct bt_gatt_attr *attr, uint16_t value)
213 {
214 	uint16_t mtu;
215 	otError error = OT_ERROR_NONE;
216 
217 	ARG_UNUSED(attr);
218 
219 	switch (value) {
220 	case BT_GATT_CCC_NOTIFY:
221 
222 		error = ot_plat_ble_queue_msg(NULL, PLAT_BLE_MSG_CONNECT, 0);
223 		if (error != OT_ERROR_NONE) {
224 			LOG_WRN("Error queuing message: %s", otThreadErrorToString(error));
225 		}
226 
227 		error = otPlatBleGattMtuGet(ble_openthread_instance, &mtu);
228 		if (error != OT_ERROR_NONE) {
229 			LOG_WRN("Error retrieving mtu: %s", otThreadErrorToString(error));
230 		}
231 
232 		LOG_INF("CCCD update (mtu=%" PRIu16 ")!", mtu);
233 
234 		break;
235 
236 	default:
237 		break;
238 	}
239 }
240 
otPlatBleGattServerIndicate(otInstance * aInstance,uint16_t aHandle,const otBleRadioPacket * aPacket)241 otError otPlatBleGattServerIndicate(otInstance *aInstance, uint16_t aHandle,
242 				    const otBleRadioPacket *aPacket)
243 {
244 	ARG_UNUSED(aInstance);
245 
246 	/* TO DO change to indications. */
247 	const struct bt_gatt_attr *attr = &my_service.attrs[3];
248 
249 	struct bt_gatt_notify_params params = {.uuid = BT_UUID_TCAT_SERVICE_TX,
250 					       .attr = attr,
251 					       .data = aPacket->mValue,
252 					       .len = aPacket->mLength,
253 					       .func = on_sent};
254 
255 	LOG_DBG("Send data, handle %d, len %d", attr->handle, aPacket->mLength);
256 
257 	/* Only one connection supported */
258 	if (aHandle != 0) {
259 		return OT_ERROR_INVALID_ARGS;
260 	}
261 
262 	if (ot_plat_ble_connection == NULL) {
263 		return OT_ERROR_INVALID_STATE;
264 	}
265 
266 	/* Check whether notifications are enabled or not */
267 	if (bt_gatt_is_subscribed(ot_plat_ble_connection, attr, BT_GATT_CCC_NOTIFY)) {
268 		if (bt_gatt_notify_cb(ot_plat_ble_connection, &params)) {
269 			LOG_WRN("Error, unable to send notification");
270 			return OT_ERROR_INVALID_ARGS;
271 		}
272 	} else {
273 		LOG_WRN("Warning, notification not enabled on the selected attribute");
274 		return OT_ERROR_INVALID_STATE;
275 	}
276 
277 	return OT_ERROR_NONE;
278 }
279 
otPlatBleGattMtuGet(otInstance * aInstance,uint16_t * aMtu)280 otError otPlatBleGattMtuGet(otInstance *aInstance, uint16_t *aMtu)
281 {
282 	ARG_UNUSED(aInstance);
283 
284 	if (ot_plat_ble_connection == NULL) {
285 		return OT_ERROR_FAILED;
286 	}
287 
288 	if (aMtu != NULL) {
289 		*aMtu = bt_gatt_get_mtu(ot_plat_ble_connection);
290 	}
291 
292 	return OT_ERROR_NONE;
293 }
294 
otPlatBleGapDisconnect(otInstance * aInstance)295 otError otPlatBleGapDisconnect(otInstance *aInstance)
296 {
297 	ARG_UNUSED(aInstance);
298 
299 	if (ot_plat_ble_connection == NULL) {
300 		return OT_ERROR_INVALID_STATE;
301 	}
302 
303 	if (bt_conn_disconnect(ot_plat_ble_connection, BT_HCI_ERR_REMOTE_USER_TERM_CONN)) {
304 		return OT_ERROR_INVALID_STATE;
305 	}
306 
307 	return OT_ERROR_NONE;
308 }
309 
310 /* Zephyr BLE callbacks */
311 
connected(struct bt_conn * conn,uint8_t err)312 static void connected(struct bt_conn *conn, uint8_t err)
313 {
314 	struct bt_conn_info info;
315 	char addr[BT_ADDR_LE_STR_LEN];
316 	uint16_t mtu;
317 	otError error = OT_ERROR_NONE;
318 
319 	ot_plat_ble_connection = bt_conn_ref(conn);
320 
321 	if (err) {
322 		LOG_WRN("Connection failed err %u %s",
323 			err, bt_hci_err_to_str(err));
324 		return;
325 	} else if (bt_conn_get_info(conn, &info)) {
326 		LOG_WRN("Could not parse connection info");
327 	} else {
328 		bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
329 
330 		error = otPlatBleGattMtuGet(ble_openthread_instance, &mtu);
331 		if (error != OT_ERROR_NONE) {
332 			LOG_WRN("Error retrieving mtu: %s", otThreadErrorToString(error));
333 		}
334 
335 		LOG_INF("Connection established (mtu=%" PRIu16 ")!", mtu);
336 	}
337 }
338 
disconnected(struct bt_conn * conn,uint8_t reason)339 static void disconnected(struct bt_conn *conn, uint8_t reason)
340 {
341 	otError error = OT_ERROR_NONE;
342 
343 	LOG_INF("Disconnected, reason 0x%02x %s", reason, bt_hci_err_to_str(reason));
344 
345 	if (ot_plat_ble_connection) {
346 		bt_conn_unref(ot_plat_ble_connection);
347 		ot_plat_ble_connection = NULL;
348 
349 		error = ot_plat_ble_queue_msg(NULL, PLAT_BLE_MSG_DISCONNECT, 0);
350 		if (error != OT_ERROR_NONE) {
351 			LOG_WRN("Error queuing message: %s", otThreadErrorToString(error));
352 		}
353 	}
354 }
355 
le_param_req(struct bt_conn * conn,struct bt_le_conn_param * param)356 static bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param)
357 {
358 	return true;
359 }
360 
le_param_updated(struct bt_conn * conn,uint16_t interval,uint16_t latency,uint16_t timeout)361 static void le_param_updated(struct bt_conn *conn, uint16_t interval, uint16_t latency,
362 			     uint16_t timeout)
363 {
364 	struct bt_conn_info info;
365 	char addr[BT_ADDR_LE_STR_LEN];
366 	uint16_t mtu;
367 	otError error = OT_ERROR_NONE;
368 
369 	if (bt_conn_get_info(conn, &info)) {
370 		LOG_INF("Could not parse connection info");
371 	} else {
372 		bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
373 
374 		error = otPlatBleGattMtuGet(ble_openthread_instance, &mtu);
375 
376 		if (error != OT_ERROR_NONE) {
377 			LOG_WRN("Error retrieving mtu: %s", otThreadErrorToString(error));
378 		}
379 
380 		LOG_INF("Connection parameters updated (mtu=%" PRIu16 ")!", mtu);
381 	}
382 }
383 
bt_ready(int err)384 static void bt_ready(int err)
385 {
386 	if (err) {
387 		LOG_WRN("BLE init failed with error code %d", err);
388 		return;
389 	}
390 
391 	bt_conn_cb_register(&conn_callbacks);
392 	k_sem_give(&ot_plat_ble_init_semaphore); /* BLE stack up an running */
393 }
394 
otPlatBleGetLinkCapabilities(otInstance * aInstance,otBleLinkCapabilities * aBleLinkCapabilities)395 void otPlatBleGetLinkCapabilities(otInstance *aInstance,
396 				  otBleLinkCapabilities *aBleLinkCapabilities)
397 {
398 	ARG_UNUSED(aInstance);
399 
400 	aBleLinkCapabilities->mGattNotifications = 1;
401 	aBleLinkCapabilities->mL2CapDirect = 0;
402 	aBleLinkCapabilities->mRsv = 0;
403 }
404 
otPlatBleSupportsMultiRadio(otInstance * aInstance)405 bool otPlatBleSupportsMultiRadio(otInstance *aInstance)
406 {
407 	OT_UNUSED_VARIABLE(aInstance);
408 
409 	return IS_ENABLED(CONFIG_OPENTHREAD_TCAT_MULTIRADIO_CAPABILITIES);
410 }
411 
otPlatBleGetAdvertisementBuffer(otInstance * aInstance,uint8_t ** aAdvertisementBuffer)412 otError otPlatBleGetAdvertisementBuffer(otInstance *aInstance, uint8_t **aAdvertisementBuffer)
413 {
414 	ARG_UNUSED(aInstance);
415 
416 	*aAdvertisementBuffer = service_data;
417 
418 	return OT_ERROR_NONE;
419 }
420 
otPlatBleGapAdvSetData(otInstance * aInstance,uint8_t * aAdvertisementData,uint16_t aAdvertisementLen)421 otError otPlatBleGapAdvSetData(otInstance *aInstance, uint8_t *aAdvertisementData,
422 			       uint16_t aAdvertisementLen)
423 {
424 	ARG_UNUSED(aInstance);
425 
426 	if (aAdvertisementLen > OT_TCAT_ADVERTISEMENT_MAX_LEN || aAdvertisementData == NULL) {
427 		LOG_ERR("Invalid TCAT Advertisement parameters advlen: %d", aAdvertisementLen);
428 		return OT_ERROR_INVALID_ARGS;
429 	}
430 
431 	ad[1].data_len = (uint8_t)aAdvertisementLen;
432 	sd[1].data_len = (uint8_t)aAdvertisementLen;
433 	return OT_ERROR_NONE;
434 }
435 
otPlatBleGapAdvStart(otInstance * aInstance,uint16_t aInterval)436 otError otPlatBleGapAdvStart(otInstance *aInstance, uint16_t aInterval)
437 {
438 	ARG_UNUSED(aInstance);
439 	ARG_UNUSED(aInterval);
440 
441 	int err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
442 
443 	if (err != 0 && err != -EALREADY) {
444 		LOG_WRN("Advertising failed to start (err %d)", err);
445 		return OT_ERROR_INVALID_STATE;
446 	}
447 
448 	LOG_INF("Advertising successfully started");
449 
450 	return OT_ERROR_NONE;
451 }
452 
otPlatBleGapAdvStop(otInstance * aInstance)453 otError otPlatBleGapAdvStop(otInstance *aInstance)
454 {
455 	ARG_UNUSED(aInstance);
456 
457 	int err = bt_le_adv_stop();
458 
459 	if (err != 0 && err != -EALREADY) {
460 		LOG_WRN("Advertisement failed to stop (err %d)", err);
461 		return OT_ERROR_FAILED;
462 	}
463 	return OT_ERROR_NONE;
464 }
465 
466 /* Zephyr BLE initialization */
467 
otPlatBleEnable(otInstance * aInstance)468 otError otPlatBleEnable(otInstance *aInstance)
469 {
470 	int err;
471 
472 	ble_openthread_instance = aInstance;
473 	err = bt_enable(bt_ready);
474 
475 	if (err != 0 && err != -EALREADY) {
476 		LOG_WRN("BLE enable failed with error code %d", err);
477 		return OT_ERROR_FAILED;
478 	} else if (err == -EALREADY) {
479 		err = k_sem_take(&ot_plat_ble_init_semaphore, K_MSEC(500));
480 		return OT_ERROR_NONE;
481 	}
482 
483 	err = k_sem_take(&ot_plat_ble_init_semaphore, K_MSEC(500));
484 
485 	if (!err) {
486 		LOG_INF("Bluetooth initialized");
487 	} else {
488 		LOG_INF("BLE initialization did not complete in time");
489 		return OT_ERROR_FAILED;
490 	}
491 
492 	return OT_ERROR_NONE;
493 }
494 
otPlatBleDisable(otInstance * aInstance)495 otError otPlatBleDisable(otInstance *aInstance)
496 {
497 	ARG_UNUSED(aInstance);
498 	/* This function intentionally does nothing since disabling advertisement disables BLE
499 	 * stack.
500 	 */
501 	return OT_ERROR_NONE;
502 }
503