1 /*
2  * Copyright (c) 2018 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /* For accept4() */
8 #define _GNU_SOURCE 1
9 
10 #define __packed __attribute__((__packed__))
11 
12 #include <stdio.h>
13 #include <stdarg.h>
14 #include <stdbool.h>
15 #include <errno.h>
16 #include <string.h>
17 #include <unistd.h>
18 #include <stdlib.h>
19 
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <sys/un.h>
23 #include <netinet/in.h>
24 #include <arpa/inet.h>
25 
26 /* Zephyr headers */
27 #include <zephyr/kernel.h>
28 #include <zephyr/usb/usb_device.h>
29 
30 #include <posix_board_if.h>
31 #include "usb_dc_native_posix_adapt.h"
32 
33 #define LOG_LEVEL CONFIG_USB_DRIVER_LOG_LEVEL
34 LOG_MODULE_REGISTER(native_posix_adapt);
35 
36 #define USBIP_PORT	3240
37 #define USBIP_VERSION	273
38 
39 #define VERBOSE_DEBUG
40 
41 int connfd_global;
42 int seqnum_global;
43 int devid_global;
44 
45 /* Helpers */
46 
47 #ifdef VERBOSE_DEBUG
usbip_header_dump(struct usbip_header * hdr)48 static void usbip_header_dump(struct usbip_header *hdr)
49 {
50 	LOG_DBG("cmd %x seq %u dir %u ep %x", ntohl(hdr->common.command),
51 		ntohl(hdr->common.seqnum), ntohl(hdr->common.direction),
52 		ntohl(hdr->common.ep));
53 
54 	switch (ntohl(hdr->common.command)) {
55 	case USBIP_CMD_SUBMIT:
56 		LOG_DBG("flags %x np %u int %u buflen %u",
57 			ntohl(hdr->u.submit.transfer_flags),
58 			ntohl(hdr->u.submit.number_of_packets),
59 			ntohl(hdr->u.submit.interval),
60 			ntohl(hdr->u.submit.transfer_buffer_length));
61 		break;
62 	case USBIP_CMD_UNLINK:
63 		LOG_DBG("seq %d", ntohl(hdr->u.unlink.seqnum));
64 		break;
65 	default:
66 		break;
67 	}
68 }
69 #else
70 #define usbip_header_dump(x)
71 #endif
72 
get_interface(uint8_t * descriptors)73 void get_interface(uint8_t *descriptors)
74 {
75 	while (descriptors[0]) {
76 		if (descriptors[1] == USB_DESC_INTERFACE) {
77 			LOG_DBG("interface found");
78 		}
79 
80 		/* skip to next descriptor */
81 		descriptors += descriptors[0];
82 	}
83 }
84 
send_interfaces(const uint8_t * descriptors,int connfd)85 static int send_interfaces(const uint8_t *descriptors, int connfd)
86 {
87 	struct devlist_interface {
88 		uint8_t bInterfaceClass;
89 		uint8_t bInterfaceSubClass;
90 		uint8_t bInterfaceProtocol;
91 		uint8_t padding;	/* alignment */
92 	} __packed iface;
93 
94 	while (descriptors[0]) {
95 		if (descriptors[1] == USB_DESC_INTERFACE) {
96 			struct usb_if_descriptor *desc = (void *)descriptors;
97 
98 			iface.bInterfaceClass = desc->bInterfaceClass;
99 			iface.bInterfaceSubClass = desc->bInterfaceSubClass;
100 			iface.bInterfaceProtocol = desc->bInterfaceProtocol;
101 			iface.padding = 0U;
102 
103 			if (send(connfd, &iface, sizeof(iface), 0) !=
104 			    sizeof(iface)) {
105 				LOG_ERR("send() failed: %s", strerror(errno));
106 				return errno;
107 			}
108 		}
109 
110 		/* skip to next descriptor */
111 		descriptors += descriptors[0];
112 	}
113 
114 	return 0;
115 }
116 
fill_device(struct devlist_device * dev,const uint8_t * desc)117 static void fill_device(struct devlist_device *dev, const uint8_t *desc)
118 {
119 	struct usb_device_descriptor *dev_dsc = (void *)desc;
120 	struct usb_cfg_descriptor *cfg =
121 		(void *)(desc + sizeof(struct usb_device_descriptor));
122 
123 	memset(dev->path, 0, 256);
124 	strcpy(dev->path, "/sys/devices/pci0000:00/0000:00:01.2/usb1/1-1");
125 	memset(dev->busid, 0, 32);
126 	strcpy(dev->busid, "1-1");
127 
128 	dev->busnum = htonl(1);
129 	dev->devnum = htonl(2);
130 	if (IS_ENABLED(CONFIG_USB_NATIVE_POSIX_HS)) {
131 		dev->speed = htonl(3);
132 	} else {
133 		dev->speed = htonl(2);
134 	}
135 
136 	dev->idVendor = htons(dev_dsc->idVendor);
137 	dev->idProduct = htons(dev_dsc->idProduct);
138 	dev->bcdDevice = htons(dev_dsc->bcdDevice);
139 	dev->bDeviceClass = dev_dsc->bDeviceClass;
140 	dev->bDeviceSubClass = dev_dsc->bDeviceSubClass;
141 	dev->bDeviceProtocol = dev_dsc->bDeviceProtocol;
142 
143 	dev->bConfigurationValue = cfg->bConfigurationValue;
144 	dev->bNumConfigurations = dev_dsc->bNumConfigurations;
145 	dev->bNumInterfaces = cfg->bNumInterfaces;
146 }
147 
send_device(const uint8_t * desc,int connfd)148 static int send_device(const uint8_t *desc, int connfd)
149 {
150 	struct devlist_device dev;
151 
152 	fill_device(&dev, desc);
153 
154 	if (send(connfd, &dev, sizeof(dev), 0) != sizeof(dev)) {
155 		LOG_ERR("send() device failed: %s", strerror(errno));
156 		return errno;
157 	}
158 
159 	return 0;
160 }
161 
handle_device_list(const uint8_t * desc,int connfd)162 static int handle_device_list(const uint8_t *desc, int connfd)
163 {
164 	struct op_common header = {
165 		.version = htons(USBIP_VERSION),
166 		.code = htons(OP_REP_DEVLIST),
167 		.status = 0,
168 	};
169 
170 	LOG_DBG("desc %p", desc);
171 
172 	if (send(connfd, &header, sizeof(header), 0) != sizeof(header)) {
173 		LOG_ERR("send() header failed: %s", strerror(errno));
174 		return errno;
175 	}
176 
177 	/* Send number of devices */
178 	uint32_t ndev = htonl(1);
179 
180 	if (send(connfd, &ndev, sizeof(ndev), 0) != sizeof(ndev)) {
181 		LOG_ERR("send() ndev failed: %s", strerror(errno));
182 		return errno;
183 	}
184 
185 	send_device(desc, connfd);
186 
187 	send_interfaces(desc, connfd);
188 
189 	return 0;
190 }
191 
handle_usbip_submit(int connfd,struct usbip_header * hdr)192 static void handle_usbip_submit(int connfd, struct usbip_header *hdr)
193 {
194 	struct usbip_submit *req = &hdr->u.submit;
195 	int read;
196 
197 	LOG_DBG("");
198 
199 	read = recv(connfd, req, sizeof(*req), 0);
200 	if (read != sizeof(*req)) {
201 		LOG_ERR("recv() failed: %s", strerror(errno));
202 		return;
203 	}
204 
205 	usbip_header_dump((void *)hdr);
206 
207 	if (ntohl(hdr->common.ep) == 0) {
208 		handle_usb_control(hdr);
209 	} else {
210 		handle_usb_data(hdr);
211 	}
212 }
213 
handle_usbip_unlink(int connfd,struct usbip_header * hdr)214 static void handle_usbip_unlink(int connfd, struct usbip_header *hdr)
215 {
216 	int read;
217 
218 	LOG_DBG("");
219 
220 	/* Need to read the whole structure */
221 	read = recv(connfd, &hdr->u, sizeof(hdr->u), 0);
222 	if (read != sizeof(hdr->u)) {
223 		LOG_ERR("recv() failed: %s", strerror(errno));
224 		return;
225 	}
226 
227 	usbip_header_dump((void *)hdr);
228 
229 	/* TODO: unlink */
230 }
231 
handle_import(const uint8_t * desc,int connfd)232 static int handle_import(const uint8_t *desc, int connfd)
233 {
234 	struct op_common header = {
235 		.version = htons(USBIP_VERSION),
236 		.code = htons(OP_REP_IMPORT),
237 		.status = 0,
238 	};
239 	char busid[32];
240 
241 	LOG_DBG("attach device");
242 
243 	if (recv(connfd, busid, 32, 0) != sizeof(busid)) {
244 		LOG_ERR("recv() failed: %s", strerror(errno));
245 		return errno;
246 	}
247 
248 	if (send(connfd, &header, sizeof(header), 0) != sizeof(header)) {
249 		LOG_ERR("send() header failed: %s", strerror(errno));
250 		return errno;
251 	}
252 
253 	send_device(desc, connfd);
254 
255 	return 0;
256 }
257 
258 extern struct usb_desc_header __usb_descriptor_start[];
259 
usbip_start(void)260 void usbip_start(void)
261 {
262 	struct sockaddr_in srv;
263 	unsigned char attached;
264 	int listenfd, connfd;
265 	const uint8_t *desc;
266 	int reuse = 1;
267 
268 	LOG_DBG("Starting");
269 
270 	/*
271 	 * Do not use usb_get_device_descriptor();
272 	 * to prevent double string fixing
273 	 */
274 	desc = (const uint8_t *)__usb_descriptor_start;
275 	if (!desc) {
276 		LOG_ERR("Descriptors are not set");
277 		posix_exit(EXIT_FAILURE);
278 	}
279 
280 	listenfd = socket(PF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
281 	if (listenfd < 0) {
282 		LOG_ERR("socket() failed: %s", strerror(errno));
283 		posix_exit(EXIT_FAILURE);
284 	}
285 
286 	if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR,
287 		       (const char *)&reuse, sizeof(reuse)) < 0) {
288 		LOG_WRN("setsockopt() failed: %s", strerror(errno));
289 	}
290 
291 	memset(&srv, 0, sizeof(srv));
292 	srv.sin_family = AF_INET;
293 	srv.sin_addr.s_addr = htonl(INADDR_ANY);
294 	srv.sin_port = htons(USBIP_PORT);
295 
296 	if (bind(listenfd, (struct sockaddr *)&srv, sizeof(srv)) < 0) {
297 		LOG_ERR("bind() failed: %s", strerror(errno));
298 		posix_exit(EXIT_FAILURE);
299 	}
300 
301 	if (listen(listenfd, SOMAXCONN) < 0) {
302 		LOG_ERR("listen() failed: %s", strerror(errno));
303 		posix_exit(EXIT_FAILURE);
304 	}
305 
306 	while (true) {
307 		struct sockaddr_in client_addr;
308 		socklen_t client_addr_len = sizeof(client_addr);
309 
310 		connfd = accept4(listenfd, (struct sockaddr *)&client_addr,
311 				 &client_addr_len, SOCK_NONBLOCK);
312 		if (connfd < 0) {
313 			if (errno == EAGAIN || errno == EWOULDBLOCK) {
314 				/* Non-blocking accept */
315 				k_sleep(K_MSEC(100));
316 
317 				continue;
318 			}
319 
320 			LOG_ERR("accept() failed: %s", strerror(errno));
321 			posix_exit(EXIT_FAILURE);
322 		}
323 
324 		connfd_global = connfd;
325 
326 		LOG_DBG("Connection: %s", inet_ntoa(client_addr.sin_addr));
327 
328 		/* Set attached 0 */
329 		attached = 0U;
330 
331 		while (true) {
332 			struct usbip_header cmd;
333 			struct usbip_header_common *hdr = &cmd.common;
334 			int read;
335 
336 			if (!attached) {
337 				struct op_common req;
338 
339 				read = recv(connfd, &req, sizeof(req), 0);
340 				if (read < 0) {
341 					if (errno == EAGAIN ||
342 					    errno == EWOULDBLOCK) {
343 						/* Non-blocking accept */
344 						k_sleep(K_MSEC(100));
345 
346 						continue;
347 					}
348 				}
349 
350 				if (read != sizeof(req)) {
351 					LOG_WRN("wrong length, %d", read);
352 
353 					/* Closing connection */
354 					break;
355 				}
356 
357 				LOG_HEXDUMP_DBG((uint8_t *)&req, sizeof(req),
358 						"Got request");
359 
360 				LOG_DBG("Code: 0x%x", ntohs(req.code));
361 
362 				switch (ntohs(req.code)) {
363 				case OP_REQ_DEVLIST:
364 					handle_device_list(desc, connfd);
365 					break;
366 				case OP_REQ_IMPORT:
367 					if (!handle_import(desc, connfd)) {
368 						attached = 1U;
369 					}
370 					break;
371 				default:
372 					LOG_ERR("Unhandled code: 0x%x",
373 						ntohs(req.code));
374 					break;
375 				}
376 
377 				continue;
378 			}
379 
380 			/* Handle attached case */
381 
382 			read = recv(connfd, hdr, sizeof(*hdr), 0);
383 			if (read < 0) {
384 				if (errno == EAGAIN || errno == EWOULDBLOCK) {
385 					/* Non-blocking accept */
386 					k_sleep(K_MSEC(100));
387 
388 					continue;
389 				}
390 			}
391 
392 			LOG_HEXDUMP_DBG((uint8_t *)hdr, read, "Got cmd");
393 
394 			if (read != sizeof(*hdr)) {
395 				LOG_ERR("recv wrong length: %d", read);
396 
397 				/* Closing connection */
398 				break;
399 			}
400 
401 			devid_global = ntohl(hdr->devid);
402 			seqnum_global = ntohl(hdr->seqnum);
403 
404 			switch (ntohl(hdr->command)) {
405 			case USBIP_CMD_SUBMIT:
406 				handle_usbip_submit(connfd, &cmd);
407 				break;
408 			case USBIP_CMD_UNLINK:
409 				handle_usbip_unlink(connfd, &cmd);
410 				break;
411 			default:
412 				LOG_ERR("Unknown command: 0x%x",
413 					ntohl(hdr->command));
414 				close(connfd);
415 				return;
416 			}
417 		}
418 
419 		LOG_DBG("Closing connection");
420 		close(connfd);
421 	}
422 }
423 
usbip_recv(uint8_t * buf,size_t len)424 int usbip_recv(uint8_t *buf, size_t len)
425 {
426 	return recv(connfd_global, buf, len, 0);
427 }
428 
usbip_send(uint8_t ep,const uint8_t * data,size_t len)429 int usbip_send(uint8_t ep, const uint8_t *data, size_t len)
430 {
431 	return send(connfd_global, data, len, 0);
432 }
433 
usbip_send_common(uint8_t ep,uint32_t data_len)434 bool usbip_send_common(uint8_t ep, uint32_t data_len)
435 {
436 	struct usbip_submit_rsp rsp;
437 	uint32_t ep_dir = USB_EP_DIR_IS_IN(ep) ? USBIP_DIR_IN : USBIP_DIR_OUT;
438 	uint32_t ep_idx = USB_EP_GET_IDX(ep);
439 
440 	rsp.common.command = htonl(USBIP_RET_SUBMIT);
441 	rsp.common.seqnum = htonl(seqnum_global);
442 	rsp.common.devid = htonl(0);
443 	rsp.common.direction = htonl(ep_dir);
444 	rsp.common.ep = htonl(ep_idx);
445 
446 	rsp.status = htonl(0);
447 	rsp.actual_length = htonl(data_len);
448 	rsp.start_frame = htonl(0);
449 	rsp.number_of_packets = htonl(0);
450 	rsp.error_count = htonl(0);
451 
452 	rsp.setup = htonl(0);
453 
454 	if (usbip_send(ep, (uint8_t *)&rsp, sizeof(rsp)) == sizeof(rsp)) {
455 		return true;
456 	}
457 
458 	return false;
459 }
460