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