1 /* userchan.c - HCI User Channel based Bluetooth driver */
2 
3 /*
4  * Copyright (c) 2018 Intel Corporation
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include <zephyr.h>
10 #include <device.h>
11 #include <init.h>
12 #include <sys/util.h>
13 #include <sys/byteorder.h>
14 
15 #include <errno.h>
16 #include <stddef.h>
17 #include <stdlib.h>
18 #include <poll.h>
19 #include <errno.h>
20 #include <sys/socket.h>
21 #include <string.h>
22 #include <unistd.h>
23 
24 #include "soc.h"
25 #include "cmdline.h" /* native_posix command line options header */
26 
27 #include <bluetooth/bluetooth.h>
28 #include <bluetooth/hci.h>
29 #include <drivers/bluetooth/hci_driver.h>
30 
31 #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
32 #define LOG_MODULE_NAME bt_driver
33 #include "common/log.h"
34 
35 #define BTPROTO_HCI      1
36 struct sockaddr_hci {
37 	sa_family_t     hci_family;
38 	unsigned short  hci_dev;
39 	unsigned short  hci_channel;
40 };
41 #define HCI_CHANNEL_USER 1
42 
43 #define SOL_HCI          0
44 
45 #define H4_CMD           0x01
46 #define H4_ACL           0x02
47 #define H4_SCO           0x03
48 #define H4_EVT           0x04
49 #define H4_ISO           0x05
50 
51 static K_KERNEL_STACK_DEFINE(rx_thread_stack,
52 			     CONFIG_ARCH_POSIX_RECOMMENDED_STACK_SIZE);
53 static struct k_thread rx_thread_data;
54 
55 static int uc_fd = -1;
56 
57 static int bt_dev_index = -1;
58 
get_rx(const uint8_t * buf)59 static struct net_buf *get_rx(const uint8_t *buf)
60 {
61 	bool discardable = false;
62 	k_timeout_t timeout = K_FOREVER;
63 
64 	switch (buf[0]) {
65 	case H4_EVT:
66 		if (buf[1] == BT_HCI_EVT_LE_META_EVENT &&
67 		    (buf[3] == BT_HCI_EVT_LE_ADVERTISING_REPORT ||
68 		     buf[3] == BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT)) {
69 			discardable = true;
70 			timeout = K_NO_WAIT;
71 		}
72 
73 		return bt_buf_get_evt(buf[1], discardable, timeout);
74 	case H4_ACL:
75 		return bt_buf_get_rx(BT_BUF_ACL_IN, K_FOREVER);
76 	case H4_ISO:
77 		if (IS_ENABLED(CONFIG_BT_ISO)) {
78 			return bt_buf_get_rx(BT_BUF_ISO_IN, K_FOREVER);
79 		}
80 		__fallthrough;
81 	default:
82 		BT_ERR("Unknown packet type: %u", buf[0]);
83 	}
84 
85 	return NULL;
86 }
87 
uc_ready(void)88 static bool uc_ready(void)
89 {
90 	struct pollfd pollfd = { .fd = uc_fd, .events = POLLIN };
91 
92 	return (poll(&pollfd, 1, 0) == 1);
93 }
94 
rx_thread(void * p1,void * p2,void * p3)95 static void rx_thread(void *p1, void *p2, void *p3)
96 {
97 	ARG_UNUSED(p1);
98 	ARG_UNUSED(p2);
99 	ARG_UNUSED(p3);
100 
101 	BT_DBG("started");
102 
103 	while (1) {
104 		static uint8_t frame[512];
105 		struct net_buf *buf;
106 		ssize_t len;
107 
108 		if (!uc_ready()) {
109 			k_sleep(K_MSEC(1));
110 			continue;
111 		}
112 
113 		BT_DBG("calling read()");
114 
115 		len = read(uc_fd, frame, sizeof(frame));
116 		if (len < 0) {
117 			if (errno == EINTR) {
118 				k_yield();
119 				continue;
120 			}
121 
122 			BT_ERR("Reading socket failed, errno %d", errno);
123 			close(uc_fd);
124 			uc_fd = -1;
125 			return;
126 		}
127 
128 		buf = get_rx(frame);
129 		if (!buf) {
130 			BT_DBG("Discard adv report due to insufficient buf");
131 			continue;
132 		}
133 
134 		net_buf_add_mem(buf, &frame[1], len - 1);
135 
136 		BT_DBG("Calling bt_recv(%p)", buf);
137 
138 		bt_recv(buf);
139 
140 		k_yield();
141 	}
142 }
143 
uc_send(struct net_buf * buf)144 static int uc_send(struct net_buf *buf)
145 {
146 	BT_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len);
147 
148 	if (uc_fd < 0) {
149 		BT_ERR("User channel not open");
150 		return -EIO;
151 	}
152 
153 	switch (bt_buf_get_type(buf)) {
154 	case BT_BUF_ACL_OUT:
155 		net_buf_push_u8(buf, H4_ACL);
156 		break;
157 	case BT_BUF_CMD:
158 		net_buf_push_u8(buf, H4_CMD);
159 		break;
160 	case BT_BUF_ISO_OUT:
161 		if (IS_ENABLED(CONFIG_BT_ISO)) {
162 			net_buf_push_u8(buf, H4_ISO);
163 			break;
164 		}
165 		__fallthrough;
166 	default:
167 		BT_ERR("Unknown buffer type");
168 		return -EINVAL;
169 	}
170 
171 	if (write(uc_fd, buf->data, buf->len) < 0) {
172 		return -errno;
173 	}
174 
175 	net_buf_unref(buf);
176 	return 0;
177 }
178 
user_chan_open(uint16_t index)179 static int user_chan_open(uint16_t index)
180 {
181 	struct sockaddr_hci addr;
182 	int fd;
183 
184 	fd = socket(PF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK,
185 		    BTPROTO_HCI);
186 	if (fd < 0) {
187 		return -errno;
188 	}
189 
190 	(void)memset(&addr, 0, sizeof(addr));
191 	addr.hci_family = AF_BLUETOOTH;
192 	addr.hci_dev = index;
193 	addr.hci_channel = HCI_CHANNEL_USER;
194 
195 	if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
196 		int err = -errno;
197 
198 		close(fd);
199 		return err;
200 	}
201 
202 	return fd;
203 }
204 
uc_open(void)205 static int uc_open(void)
206 {
207 	if (bt_dev_index < 0) {
208 		BT_ERR("No Bluetooth device specified");
209 		return -ENODEV;
210 	}
211 
212 	BT_DBG("hci%d", bt_dev_index);
213 
214 	uc_fd = user_chan_open(bt_dev_index);
215 	if (uc_fd < 0) {
216 		return uc_fd;
217 	}
218 
219 	BT_DBG("User Channel opened as fd %d", uc_fd);
220 
221 	k_thread_create(&rx_thread_data, rx_thread_stack,
222 			K_KERNEL_STACK_SIZEOF(rx_thread_stack),
223 			rx_thread, NULL, NULL, NULL,
224 			K_PRIO_COOP(CONFIG_BT_DRIVER_RX_HIGH_PRIO),
225 			0, K_NO_WAIT);
226 
227 	BT_DBG("returning");
228 
229 	return 0;
230 }
231 
232 static const struct bt_hci_driver drv = {
233 	.name		= "HCI User Channel",
234 	.bus		= BT_HCI_DRIVER_BUS_UART,
235 	.open		= uc_open,
236 	.send		= uc_send,
237 };
238 
bt_uc_init(const struct device * unused)239 static int bt_uc_init(const struct device *unused)
240 {
241 	ARG_UNUSED(unused);
242 
243 	bt_hci_driver_register(&drv);
244 
245 	return 0;
246 }
247 
248 SYS_INIT(bt_uc_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
249 
cmd_bt_dev_found(char * argv,int offset)250 static void cmd_bt_dev_found(char *argv, int offset)
251 {
252 	if (strncmp(&argv[offset], "hci", 3) || strlen(&argv[offset]) < 4) {
253 		posix_print_error_and_exit("Error: Invalid Bluetooth device "
254 					   "name '%s' (should be e.g. hci0)\n",
255 					   &argv[offset]);
256 		return;
257 	}
258 
259 	bt_dev_index = strtol(&argv[offset + 3], NULL, 10);
260 }
261 
add_btuserchan_arg(void)262 static void add_btuserchan_arg(void)
263 {
264 	static struct args_struct_t btuserchan_args[] = {
265 		/*
266 		 * Fields:
267 		 * manual, mandatory, switch,
268 		 * option_name, var_name ,type,
269 		 * destination, callback,
270 		 * description
271 		 */
272 		{ false, true, false,
273 		"bt-dev", "hciX", 's',
274 		NULL, cmd_bt_dev_found,
275 		"A local HCI device to be used for Bluetooth (e.g. hci0)" },
276 		ARG_TABLE_ENDMARKER
277 	};
278 
279 	native_add_command_line_opts(btuserchan_args);
280 }
281 
btuserchan_check_arg(void)282 static void btuserchan_check_arg(void)
283 {
284 	if (bt_dev_index < 0) {
285 		posix_print_error_and_exit("Error: Bluetooth device missing. "
286 					   "Specify one using --bt-dev=hciN\n");
287 	}
288 }
289 
290 NATIVE_TASK(add_btuserchan_arg, PRE_BOOT_1, 10);
291 NATIVE_TASK(btuserchan_check_arg, PRE_BOOT_2, 10);
292