1 /*
2  * Copyright (c) 2019 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/init.h>
8 #include <zephyr/sys/byteorder.h>
9 
10 #include <zephyr/bluetooth/bluetooth.h>
11 #include <zephyr/bluetooth/hci.h>
12 #include <zephyr/drivers/bluetooth.h>
13 
14 #include <zephyr/device.h>
15 #include <zephyr/ipc/ipc_service.h>
16 
17 #define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL
18 #include <zephyr/logging/log.h>
19 LOG_MODULE_REGISTER(bt_hci_driver);
20 
21 #define DT_DRV_COMPAT zephyr_bt_hci_ipc
22 
23 #define IPC_BOUND_TIMEOUT_IN_MS K_MSEC(1000)
24 
25 struct ipc_data {
26 	bt_hci_recv_t recv;
27 	struct ipc_ept hci_ept;
28 	struct ipc_ept_cfg hci_ept_cfg;
29 	struct k_sem bound_sem;
30 	const struct device *ipc;
31 };
32 
is_hci_event_discardable(const uint8_t * evt_data)33 static bool is_hci_event_discardable(const uint8_t *evt_data)
34 {
35 	uint8_t evt_type = evt_data[0];
36 
37 	switch (evt_type) {
38 #if defined(CONFIG_BT_CLASSIC)
39 	case BT_HCI_EVT_INQUIRY_RESULT_WITH_RSSI:
40 	case BT_HCI_EVT_EXTENDED_INQUIRY_RESULT:
41 		return true;
42 #endif
43 	case BT_HCI_EVT_LE_META_EVENT: {
44 		uint8_t subevt_type = evt_data[sizeof(struct bt_hci_evt_hdr)];
45 
46 		switch (subevt_type) {
47 		case BT_HCI_EVT_LE_ADVERTISING_REPORT:
48 			return true;
49 #if defined(CONFIG_BT_EXT_ADV)
50 		case BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT:
51 		{
52 			const struct bt_hci_evt_le_ext_advertising_report *ext_adv =
53 				(void *)&evt_data[3];
54 
55 			return (ext_adv->num_reports == 1) &&
56 				   ((ext_adv->adv_info[0].evt_type &
57 					 BT_HCI_LE_ADV_EVT_TYPE_LEGACY) != 0);
58 		}
59 #endif
60 		default:
61 			return false;
62 		}
63 	}
64 	default:
65 		return false;
66 	}
67 }
68 
bt_ipc_evt_recv(const uint8_t * data,size_t remaining)69 static struct net_buf *bt_ipc_evt_recv(const uint8_t *data, size_t remaining)
70 {
71 	bool discardable;
72 	struct bt_hci_evt_hdr hdr;
73 	struct net_buf *buf;
74 	size_t buf_tailroom;
75 
76 	if (remaining < sizeof(hdr)) {
77 		LOG_ERR("Not enough data for event header");
78 		return NULL;
79 	}
80 
81 	discardable = is_hci_event_discardable(data);
82 
83 	memcpy((void *)&hdr, data, sizeof(hdr));
84 	data += sizeof(hdr);
85 	remaining -= sizeof(hdr);
86 
87 	if (remaining != hdr.len) {
88 		LOG_ERR("Event payload length is not correct");
89 		return NULL;
90 	}
91 	LOG_DBG("len %u", hdr.len);
92 
93 	do {
94 		buf = bt_buf_get_evt(hdr.evt, discardable, discardable ? K_NO_WAIT : K_SECONDS(10));
95 		if (!buf) {
96 			if (discardable) {
97 				LOG_DBG("Discardable buffer pool full, ignoring event");
98 				return buf;
99 			}
100 			LOG_WRN("Couldn't allocate a buffer after waiting 10 seconds.");
101 		}
102 	} while (!buf);
103 
104 	net_buf_add_mem(buf, &hdr, sizeof(hdr));
105 
106 	buf_tailroom = net_buf_tailroom(buf);
107 	if (buf_tailroom < remaining) {
108 		LOG_ERR("Not enough space in buffer %zu/%zu", remaining, buf_tailroom);
109 		net_buf_unref(buf);
110 		return NULL;
111 	}
112 
113 	net_buf_add_mem(buf, data, remaining);
114 
115 	return buf;
116 }
117 
bt_ipc_acl_recv(const uint8_t * data,size_t remaining)118 static struct net_buf *bt_ipc_acl_recv(const uint8_t *data, size_t remaining)
119 {
120 	struct bt_hci_acl_hdr hdr;
121 	struct net_buf *buf;
122 	size_t buf_tailroom;
123 
124 	if (remaining < sizeof(hdr)) {
125 		LOG_ERR("Not enough data for ACL header");
126 		return NULL;
127 	}
128 
129 	buf = bt_buf_get_rx(BT_BUF_ACL_IN, K_NO_WAIT);
130 	if (buf) {
131 		memcpy((void *)&hdr, data, sizeof(hdr));
132 		data += sizeof(hdr);
133 		remaining -= sizeof(hdr);
134 
135 		net_buf_add_mem(buf, &hdr, sizeof(hdr));
136 	} else {
137 		LOG_ERR("No available ACL buffers!");
138 		return NULL;
139 	}
140 
141 	if (remaining != sys_le16_to_cpu(hdr.len)) {
142 		LOG_ERR("ACL payload length is not correct");
143 		net_buf_unref(buf);
144 		return NULL;
145 	}
146 
147 	buf_tailroom = net_buf_tailroom(buf);
148 	if (buf_tailroom < remaining) {
149 		LOG_ERR("Not enough space in buffer %zu/%zu", remaining, buf_tailroom);
150 		net_buf_unref(buf);
151 		return NULL;
152 	}
153 
154 	LOG_DBG("len %u", remaining);
155 	net_buf_add_mem(buf, data, remaining);
156 
157 	return buf;
158 }
159 
bt_ipc_iso_recv(const uint8_t * data,size_t remaining)160 static struct net_buf *bt_ipc_iso_recv(const uint8_t *data, size_t remaining)
161 {
162 	struct bt_hci_iso_hdr hdr;
163 	static size_t fail_cnt;
164 	struct net_buf *buf;
165 	size_t buf_tailroom;
166 
167 	if (remaining < sizeof(hdr)) {
168 		LOG_ERR("Not enough data for ISO header");
169 		return NULL;
170 	}
171 
172 	buf = bt_buf_get_rx(BT_BUF_ISO_IN, K_NO_WAIT);
173 	if (buf) {
174 		memcpy((void *)&hdr, data, sizeof(hdr));
175 		data += sizeof(hdr);
176 		remaining -= sizeof(hdr);
177 
178 		net_buf_add_mem(buf, &hdr, sizeof(hdr));
179 
180 		fail_cnt = 0U;
181 	} else {
182 		if ((fail_cnt % 100U) == 0U) {
183 			LOG_ERR("No available ISO buffers (%zu)!", fail_cnt);
184 		}
185 
186 		fail_cnt++;
187 
188 		return NULL;
189 	}
190 
191 	if (remaining != bt_iso_hdr_len(sys_le16_to_cpu(hdr.len))) {
192 		LOG_ERR("ISO payload length is not correct");
193 		net_buf_unref(buf);
194 		return NULL;
195 	}
196 
197 	buf_tailroom = net_buf_tailroom(buf);
198 	if (buf_tailroom < remaining) {
199 		LOG_ERR("Not enough space in buffer %zu/%zu", remaining, buf_tailroom);
200 		net_buf_unref(buf);
201 		return NULL;
202 	}
203 
204 	LOG_DBG("len %zu", remaining);
205 	net_buf_add_mem(buf, data, remaining);
206 
207 	return buf;
208 }
209 
bt_ipc_rx(const struct device * dev,const uint8_t * data,size_t len)210 static void bt_ipc_rx(const struct device *dev, const uint8_t *data, size_t len)
211 {
212 	struct ipc_data *ipc = dev->data;
213 	uint8_t pkt_indicator;
214 	struct net_buf *buf = NULL;
215 	size_t remaining = len;
216 
217 	LOG_HEXDUMP_DBG(data, len, "ipc data:");
218 
219 	pkt_indicator = *data++;
220 	remaining -= sizeof(pkt_indicator);
221 
222 	switch (pkt_indicator) {
223 	case BT_HCI_H4_EVT:
224 		buf = bt_ipc_evt_recv(data, remaining);
225 		break;
226 
227 	case BT_HCI_H4_ACL:
228 		buf = bt_ipc_acl_recv(data, remaining);
229 		break;
230 
231 	case BT_HCI_H4_ISO:
232 		buf = bt_ipc_iso_recv(data, remaining);
233 		break;
234 
235 	default:
236 		LOG_ERR("Unknown HCI type %u", pkt_indicator);
237 		return;
238 	}
239 
240 	if (buf) {
241 		LOG_DBG("Calling bt_recv(%p)", buf);
242 		ipc->recv(dev, buf);
243 
244 		LOG_HEXDUMP_DBG(buf->data, buf->len, "RX buf payload:");
245 	}
246 }
247 
bt_ipc_send(const struct device * dev,struct net_buf * buf)248 static int bt_ipc_send(const struct device *dev, struct net_buf *buf)
249 {
250 	struct ipc_data *data = dev->data;
251 	int err;
252 	uint8_t pkt_indicator;
253 
254 	LOG_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len);
255 
256 	switch (bt_buf_get_type(buf)) {
257 	case BT_BUF_ACL_OUT:
258 		pkt_indicator = BT_HCI_H4_ACL;
259 		break;
260 	case BT_BUF_CMD:
261 		pkt_indicator = BT_HCI_H4_CMD;
262 		break;
263 	case BT_BUF_ISO_OUT:
264 		pkt_indicator = BT_HCI_H4_ISO;
265 		break;
266 	default:
267 		LOG_ERR("Unknown type %u", bt_buf_get_type(buf));
268 		goto done;
269 	}
270 	net_buf_push_u8(buf, pkt_indicator);
271 
272 	LOG_HEXDUMP_DBG(buf->data, buf->len, "Final HCI buffer:");
273 	err = ipc_service_send(&data->hci_ept, buf->data, buf->len);
274 	if (err < 0) {
275 		LOG_ERR("Failed to send (err %d)", err);
276 	}
277 
278 done:
279 	net_buf_unref(buf);
280 	return 0;
281 }
282 
hci_ept_bound(void * priv)283 static void hci_ept_bound(void *priv)
284 {
285 	const struct device *dev = priv;
286 	struct ipc_data *ipc = dev->data;
287 
288 	k_sem_give(&ipc->bound_sem);
289 }
290 
hci_ept_recv(const void * data,size_t len,void * priv)291 static void hci_ept_recv(const void *data, size_t len, void *priv)
292 {
293 	const struct device *dev = priv;
294 
295 	bt_ipc_rx(dev, data, len);
296 }
297 
bt_hci_transport_setup(const struct device * dev)298 int __weak bt_hci_transport_setup(const struct device *dev)
299 {
300 	ARG_UNUSED(dev);
301 	return 0;
302 }
303 
bt_hci_transport_teardown(const struct device * dev)304 int __weak bt_hci_transport_teardown(const struct device *dev)
305 {
306 	ARG_UNUSED(dev);
307 	return 0;
308 }
309 
bt_ipc_open(const struct device * dev,bt_hci_recv_t recv)310 static int bt_ipc_open(const struct device *dev, bt_hci_recv_t recv)
311 {
312 	struct ipc_data *ipc = dev->data;
313 	int err;
314 
315 	err = bt_hci_transport_setup(NULL);
316 	if (err) {
317 		LOG_ERR("HCI transport setup failed with: %d\n", err);
318 		return err;
319 	}
320 
321 	LOG_DBG("");
322 
323 	err = ipc_service_open_instance(ipc->ipc);
324 	if (err && (err != -EALREADY)) {
325 		LOG_ERR("IPC service instance initialization failed: %d\n", err);
326 		return err;
327 	}
328 
329 	err = ipc_service_register_endpoint(ipc->ipc, &ipc->hci_ept, &ipc->hci_ept_cfg);
330 	if (err) {
331 		LOG_ERR("Registering endpoint failed with %d", err);
332 		return err;
333 	}
334 
335 	err = k_sem_take(&ipc->bound_sem, IPC_BOUND_TIMEOUT_IN_MS);
336 	if (err) {
337 		LOG_ERR("Endpoint binding failed with %d", err);
338 		return err;
339 	}
340 
341 	ipc->recv = recv;
342 
343 	return 0;
344 }
345 
bt_ipc_close(const struct device * dev)346 static int bt_ipc_close(const struct device *dev)
347 {
348 	struct ipc_data *ipc = dev->data;
349 	int err;
350 
351 	if (IS_ENABLED(CONFIG_BT_HCI_HOST)) {
352 		err = bt_hci_cmd_send_sync(BT_HCI_OP_RESET, NULL, NULL);
353 		if (err) {
354 			LOG_ERR("Sending reset command failed with: %d", err);
355 			return err;
356 		}
357 	}
358 
359 	err = ipc_service_deregister_endpoint(&ipc->hci_ept);
360 	if (err) {
361 		LOG_ERR("Deregistering HCI endpoint failed with: %d", err);
362 		return err;
363 	}
364 
365 	err = ipc_service_close_instance(ipc->ipc);
366 	if (err) {
367 		LOG_ERR("Closing IPC service failed with: %d", err);
368 		return err;
369 	}
370 
371 	err = bt_hci_transport_teardown(NULL);
372 	if (err) {
373 		LOG_ERR("HCI transport teardown failed with: %d", err);
374 		return err;
375 	}
376 
377 	ipc->recv = NULL;
378 
379 	return 0;
380 }
381 
382 static DEVICE_API(bt_hci, drv) = {
383 	.open		= bt_ipc_open,
384 	.close		= bt_ipc_close,
385 	.send		= bt_ipc_send,
386 };
387 
388 #define IPC_DEVICE_INIT(inst) \
389 	static struct ipc_data ipc_data_##inst = { \
390 		.bound_sem = Z_SEM_INITIALIZER(ipc_data_##inst.bound_sem, 0, 1), \
391 		.hci_ept_cfg = { \
392 			.name = DT_INST_PROP(inst, bt_hci_ipc_name), \
393 			.cb = { \
394 				.bound    = hci_ept_bound, \
395 				.received = hci_ept_recv, \
396 			}, \
397 			.priv = (void *)DEVICE_DT_INST_GET(inst), \
398 		}, \
399 		.ipc = DEVICE_DT_GET(DT_INST_PARENT(inst)), \
400 	}; \
401 	DEVICE_DT_INST_DEFINE(inst, NULL, NULL, &ipc_data_##inst, NULL, \
402 			      POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &drv)
403 
404 DT_INST_FOREACH_STATUS_OKAY(IPC_DEVICE_INIT)
405