1 /*
2  * Copyright (c) 2018 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief USB native_posix device driver
10  */
11 
12 #include <string.h>
13 #include <stdio.h>
14 #include <zephyr/kernel.h>
15 #include <zephyr/sys/byteorder.h>
16 #include <zephyr/drivers/usb/usb_dc.h>
17 #include <zephyr/usb/usb_device.h>
18 #include <zephyr/net/net_ip.h>
19 
20 #include "usb_dc_native_posix_adapt.h"
21 
22 #define LOG_LEVEL CONFIG_USB_DRIVER_LOG_LEVEL
23 #include <zephyr/logging/log.h>
24 LOG_MODULE_REGISTER(native_posix);
25 
26 #define USBIP_IN_EP_NUM		8
27 #define USBIP_OUT_EP_NUM	8
28 
29 #define USBIP_MAX_PACKET_SIZE	64
30 
31 K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_ARCH_POSIX_RECOMMENDED_STACK_SIZE);
32 static struct k_thread thread;
33 
thread_main(void * a,void * b,void * c)34 static void thread_main(void *a, void *b, void *c)
35 {
36 	LOG_DBG("");
37 
38 	usbip_start();
39 }
40 
41 /*
42  * USBIP private structures and logic initially copied from
43  * Designware USB driver
44  */
45 
46 /*
47  * USB endpoint private structure.
48  */
49 struct usb_ep_ctrl_prv {
50 	uint8_t ep_ena;
51 	uint16_t mps;
52 	usb_dc_ep_callback cb;
53 	uint32_t data_len;
54 	uint8_t buf[64];
55 	uint8_t buf_len;
56 };
57 
58 /*
59  * USB controller private structure.
60  */
61 static struct usbip_ctrl_prv {
62 	usb_dc_status_callback status_cb;
63 	struct usb_ep_ctrl_prv in_ep_ctrl[USBIP_IN_EP_NUM];
64 	struct usb_ep_ctrl_prv out_ep_ctrl[USBIP_OUT_EP_NUM];
65 	uint8_t attached;
66 } usbip_ctrl;
67 
usbip_ep_is_valid(uint8_t ep)68 static uint8_t usbip_ep_is_valid(uint8_t ep)
69 {
70 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
71 
72 	/* Check if ep is valid */
73 	if ((USB_EP_DIR_IS_OUT(ep)) &&
74 	    ep_idx < USBIP_OUT_EP_NUM) {
75 		return 1;
76 	} else if ((USB_EP_DIR_IS_IN(ep)) &&
77 	    ep_idx < USBIP_IN_EP_NUM) {
78 		return 1;
79 	}
80 
81 	return 0;
82 }
83 
usbip_ep_is_enabled(uint8_t ep)84 static uint8_t usbip_ep_is_enabled(uint8_t ep)
85 {
86 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
87 
88 	LOG_DBG("ep %x", ep);
89 
90 	/* Check if ep enabled */
91 	if ((USB_EP_DIR_IS_OUT(ep)) &&
92 	    usbip_ctrl.out_ep_ctrl[ep_idx].ep_ena) {
93 		return 1;
94 	} else if ((USB_EP_DIR_IS_IN(ep)) &&
95 	    usbip_ctrl.in_ep_ctrl[ep_idx].ep_ena) {
96 		return 1;
97 	}
98 
99 	return 0;
100 }
101 
usb_dc_attach(void)102 int usb_dc_attach(void)
103 {
104 	LOG_DBG("");
105 
106 	if (usbip_ctrl.attached) {
107 		LOG_WRN("Already attached");
108 		return 0;
109 	}
110 
111 	k_thread_create(&thread, thread_stack,
112 			CONFIG_ARCH_POSIX_RECOMMENDED_STACK_SIZE,
113 			thread_main, NULL, NULL, NULL,
114 			K_PRIO_COOP(2), 0, K_NO_WAIT);
115 
116 	usbip_ctrl.attached = 1U;
117 
118 	return 0;
119 }
120 
usb_dc_detach(void)121 int usb_dc_detach(void)
122 {
123 	LOG_DBG("");
124 
125 	if (!usbip_ctrl.attached) {
126 		return 0;
127 	}
128 
129 	usbip_ctrl.attached = 0U;
130 
131 	return 0;
132 }
133 
usb_dc_reset(void)134 int usb_dc_reset(void)
135 {
136 	LOG_DBG("");
137 
138 	/* Clear private data */
139 	memset(&usbip_ctrl, 0, sizeof(usbip_ctrl));
140 
141 	return 0;
142 }
143 
usb_dc_set_address(const uint8_t addr)144 int usb_dc_set_address(const uint8_t addr)
145 {
146 	LOG_DBG("");
147 
148 	return 0;
149 }
150 
usb_dc_ep_check_cap(const struct usb_dc_ep_cfg_data * const cfg)151 int usb_dc_ep_check_cap(const struct usb_dc_ep_cfg_data * const cfg)
152 {
153 	uint8_t ep_idx = USB_EP_GET_IDX(cfg->ep_addr);
154 
155 	LOG_DBG("ep %x, mps %d, type %d", cfg->ep_addr, cfg->ep_mps,
156 		cfg->ep_type);
157 
158 	if ((cfg->ep_type == USB_DC_EP_CONTROL) && ep_idx) {
159 		LOG_ERR("invalid endpoint configuration");
160 		return -1;
161 	}
162 
163 	if (cfg->ep_mps > USBIP_MAX_PACKET_SIZE) {
164 		LOG_WRN("unsupported packet size");
165 		return -1;
166 	}
167 
168 	if ((USB_EP_DIR_IS_OUT(cfg->ep_addr)) &&
169 	    (ep_idx >= USBIP_OUT_EP_NUM)) {
170 		LOG_WRN("OUT endpoint address out of range");
171 		return -1;
172 	}
173 
174 	if ((USB_EP_DIR_IS_IN(cfg->ep_addr)) &&
175 	    (ep_idx >= USBIP_IN_EP_NUM)) {
176 		LOG_WRN("IN endpoint address out of range");
177 		return -1;
178 	}
179 
180 	return 0;
181 }
182 
usb_dc_ep_configure(const struct usb_dc_ep_cfg_data * const cfg)183 int usb_dc_ep_configure(const struct usb_dc_ep_cfg_data * const cfg)
184 {
185 	uint16_t ep_mps = cfg->ep_mps;
186 	uint8_t ep = cfg->ep_addr;
187 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
188 
189 	if (usb_dc_ep_check_cap(cfg)) {
190 		return -EINVAL;
191 	}
192 
193 	if (!usbip_ctrl.attached || !usbip_ep_is_valid(ep)) {
194 		LOG_ERR("Not attached / Invalid endpoint: EP 0x%x", ep);
195 		return -EINVAL;
196 	}
197 
198 	if (USB_EP_DIR_IS_OUT(ep)) {
199 		usbip_ctrl.out_ep_ctrl[ep_idx].mps = ep_mps;
200 	} else {
201 		usbip_ctrl.in_ep_ctrl[ep_idx].mps = ep_mps;
202 	}
203 
204 	return 0;
205 }
206 
usb_dc_ep_set_stall(const uint8_t ep)207 int usb_dc_ep_set_stall(const uint8_t ep)
208 {
209 	LOG_DBG("ep %x", ep);
210 
211 	if (!usbip_ctrl.attached || !usbip_ep_is_valid(ep)) {
212 		LOG_ERR("Not attached / Invalid endpoint: EP 0x%x", ep);
213 		return -EINVAL;
214 	}
215 
216 	/* Use standard reply for now */
217 	usb_dc_ep_write(0x80,  NULL, 0, NULL);
218 
219 	return 0;
220 }
221 
usb_dc_ep_clear_stall(const uint8_t ep)222 int usb_dc_ep_clear_stall(const uint8_t ep)
223 {
224 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
225 
226 	LOG_DBG("ep %x", ep);
227 
228 	if (!usbip_ctrl.attached || !usbip_ep_is_valid(ep)) {
229 		LOG_ERR("Not attached / Invalid endpoint: EP 0x%x", ep);
230 		return -EINVAL;
231 	}
232 
233 	if (!ep_idx) {
234 		/* Not possible to clear stall for EP0 */
235 		return -EINVAL;
236 	}
237 
238 	return 0;
239 }
240 
usb_dc_ep_halt(const uint8_t ep)241 int usb_dc_ep_halt(const uint8_t ep)
242 {
243 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
244 
245 	LOG_DBG("ep %x", ep);
246 
247 	if (!usbip_ctrl.attached || !usbip_ep_is_valid(ep)) {
248 		LOG_ERR("Not attached / Invalid endpoint: EP 0x%x", ep);
249 		return -EINVAL;
250 	}
251 
252 	if (!ep_idx) {
253 		/* Cannot disable EP0, just set stall */
254 		usb_dc_ep_set_stall(ep);
255 	}
256 
257 	return 0;
258 }
259 
usb_dc_ep_is_stalled(const uint8_t ep,uint8_t * const stalled)260 int usb_dc_ep_is_stalled(const uint8_t ep, uint8_t *const stalled)
261 {
262 	LOG_DBG("ep %x", ep);
263 
264 	if (!usbip_ctrl.attached || !usbip_ep_is_valid(ep)) {
265 		LOG_ERR("Not attached / Invalid endpoint: EP 0x%x", ep);
266 		return -EINVAL;
267 	}
268 
269 	if (!stalled) {
270 		return -EINVAL;
271 	}
272 
273 	return 0;
274 }
275 
usb_dc_ep_enable(const uint8_t ep)276 int usb_dc_ep_enable(const uint8_t ep)
277 {
278 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
279 
280 	LOG_DBG("ep %x", ep);
281 
282 	if (!usbip_ctrl.attached || !usbip_ep_is_valid(ep)) {
283 		LOG_ERR("Not attached / Invalid endpoint: EP 0x%x", ep);
284 		return -EINVAL;
285 	}
286 
287 	/* Enable Ep */
288 	if (USB_EP_DIR_IS_OUT(ep)) {
289 		usbip_ctrl.out_ep_ctrl[ep_idx].ep_ena = 1U;
290 	} else {
291 		usbip_ctrl.in_ep_ctrl[ep_idx].ep_ena = 1U;
292 	}
293 
294 	return 0;
295 }
296 
usb_dc_ep_disable(const uint8_t ep)297 int usb_dc_ep_disable(const uint8_t ep)
298 {
299 	LOG_DBG("ep %x", ep);
300 
301 	if (!usbip_ep_is_valid(ep)) {
302 		LOG_ERR("Invalid endpoint: EP 0x%x", ep);
303 		return -EINVAL;
304 	}
305 
306 	return 0;
307 }
308 
usb_dc_ep_flush(const uint8_t ep)309 int usb_dc_ep_flush(const uint8_t ep)
310 {
311 	LOG_DBG("ep %x", ep);
312 
313 	if (!usbip_ctrl.attached || !usbip_ep_is_valid(ep)) {
314 		LOG_ERR("Not attached / Invalid endpoint: EP 0x%x", ep);
315 		return -EINVAL;
316 	}
317 
318 	if (USB_EP_DIR_IS_OUT(ep)) {
319 		/* RX FIFO is global and cannot be flushed per EP */
320 		return -EINVAL;
321 	}
322 
323 	return 0;
324 }
325 
usb_dc_ep_write(const uint8_t ep,const uint8_t * const data,const uint32_t data_len,uint32_t * const ret_bytes)326 int usb_dc_ep_write(const uint8_t ep, const uint8_t *const data,
327 		    const uint32_t data_len, uint32_t * const ret_bytes)
328 {
329 	LOG_DBG("ep %x len %u", ep, data_len);
330 
331 	if (!usbip_ctrl.attached || !usbip_ep_is_valid(ep)) {
332 		LOG_ERR("Not attached / Invalid endpoint: EP 0x%x", ep);
333 		return -EINVAL;
334 	}
335 
336 	/* Check if IN ep */
337 	if (USB_EP_GET_DIR(ep) != USB_EP_DIR_IN) {
338 		return -EINVAL;
339 	}
340 
341 	/* Check if ep enabled */
342 	if (!usbip_ep_is_enabled(ep)) {
343 		LOG_WRN("ep %x disabled", ep);
344 		return -EINVAL;
345 	}
346 
347 	if (USB_EP_GET_IDX(ep) == 0) {
348 		if (!usbip_send_common(ep, data_len)) {
349 			return -EIO;
350 		}
351 
352 		if (usbip_send(ep, data, data_len) != data_len) {
353 			return -EIO;
354 		}
355 	} else {
356 		uint8_t ep_idx = USB_EP_GET_IDX(ep);
357 		struct usb_ep_ctrl_prv *ctrl = &usbip_ctrl.in_ep_ctrl[ep_idx];
358 
359 		if (data_len > ARRAY_SIZE(ctrl->buf)) {
360 			return -EINVAL;
361 		}
362 
363 		memcpy(ctrl->buf, data, data_len);
364 		ctrl->buf_len = data_len;
365 	}
366 
367 	if (ret_bytes) {
368 		*ret_bytes = data_len;
369 	}
370 
371 	return 0;
372 }
373 
usb_dc_ep_read_wait(uint8_t ep,uint8_t * data,uint32_t max_data_len,uint32_t * read_bytes)374 int usb_dc_ep_read_wait(uint8_t ep, uint8_t *data, uint32_t max_data_len,
375 			uint32_t *read_bytes)
376 {
377 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
378 	uint32_t to_copy;
379 
380 	if (!usbip_ctrl.attached || !usbip_ep_is_valid(ep)) {
381 		LOG_ERR("Not attached / Invalid endpoint: EP 0x%x", ep);
382 		return -EINVAL;
383 	}
384 
385 	/* Check if OUT ep */
386 	if (USB_EP_GET_DIR(ep) != USB_EP_DIR_OUT) {
387 		LOG_ERR("Wrong endpoint direction");
388 		return -EINVAL;
389 	}
390 
391 	/* Allow to read 0 bytes */
392 	if (!data && max_data_len) {
393 		LOG_ERR("Wrong arguments");
394 		return -EINVAL;
395 	}
396 
397 	/* Check if ep enabled */
398 	if (!usbip_ep_is_enabled(ep)) {
399 		LOG_ERR("Not enabled endpoint");
400 		return -EINVAL;
401 	}
402 
403 	if (data == NULL && max_data_len == 0 && read_bytes != NULL) {
404 		/* Return length of the available data in endpoint buffer */
405 		*read_bytes = usbip_ctrl.out_ep_ctrl[ep_idx].data_len;
406 		return 0;
407 	}
408 
409 	to_copy = MIN(usbip_ctrl.out_ep_ctrl[ep_idx].data_len, max_data_len);
410 	LOG_DBG("ep 0x%02x, to_copy %u", ep, to_copy);
411 	memcpy(data, usbip_ctrl.out_ep_ctrl[ep_idx].buf, to_copy);
412 
413 	if (read_bytes) {
414 		*read_bytes = to_copy;
415 	}
416 
417 	return 0;
418 }
419 
usb_dc_ep_read_continue(uint8_t ep)420 int usb_dc_ep_read_continue(uint8_t ep)
421 {
422 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
423 
424 	if (!usbip_ctrl.attached || !usbip_ep_is_valid(ep)) {
425 		LOG_ERR("Not attached / Invalid endpoint: EP 0x%x", ep);
426 		return -EINVAL;
427 	}
428 
429 	/* Check if OUT ep */
430 	if (USB_EP_GET_DIR(ep) != USB_EP_DIR_OUT) {
431 		LOG_ERR("Wrong endpoint direction");
432 		return -EINVAL;
433 	}
434 
435 	if (!usbip_ctrl.out_ep_ctrl[ep_idx].data_len) {
436 		/* TODO: continue read */
437 		/* usbip_prep_rx(ep_idx, 0); */
438 	}
439 
440 	return 0;
441 }
442 
usb_dc_ep_read(const uint8_t ep,uint8_t * const data,const uint32_t max_data_len,uint32_t * const read_bytes)443 int usb_dc_ep_read(const uint8_t ep, uint8_t *const data,
444 		   const uint32_t max_data_len, uint32_t * const read_bytes)
445 {
446 	LOG_DBG("ep %x max_data_len %u", ep, max_data_len);
447 
448 	if (usb_dc_ep_read_wait(ep, data, max_data_len, read_bytes) != 0) {
449 		return -EINVAL;
450 	}
451 
452 	if (!data && !max_data_len) {
453 		/* When both buffer and max data to read are zero the above
454 		 * call would fetch the data len and we simply return.
455 		 */
456 		return 0;
457 	}
458 
459 	if (usb_dc_ep_read_continue(ep) != 0) {
460 		return -EINVAL;
461 	}
462 
463 	return 0;
464 }
465 
usb_dc_ep_set_callback(const uint8_t ep,const usb_dc_ep_callback cb)466 int usb_dc_ep_set_callback(const uint8_t ep, const usb_dc_ep_callback cb)
467 {
468 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
469 
470 	LOG_DBG("ep %x callback %p", ep, cb);
471 
472 	if (!usbip_ctrl.attached || !usbip_ep_is_valid(ep)) {
473 		LOG_ERR("Not attached / Invalid endpoint: EP 0x%x", ep);
474 		return -EINVAL;
475 	}
476 
477 	if (USB_EP_DIR_IS_IN(ep)) {
478 		usbip_ctrl.in_ep_ctrl[ep_idx].cb = cb;
479 	} else {
480 		usbip_ctrl.out_ep_ctrl[ep_idx].cb = cb;
481 	}
482 
483 	return 0;
484 }
485 
usb_dc_set_status_callback(const usb_dc_status_callback cb)486 void usb_dc_set_status_callback(const usb_dc_status_callback cb)
487 {
488 	usbip_ctrl.status_cb = cb;
489 }
490 
usb_dc_ep_mps(const uint8_t ep)491 int usb_dc_ep_mps(const uint8_t ep)
492 {
493 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
494 
495 	LOG_DBG("ep %x", ep);
496 
497 	if (!usbip_ctrl.attached || !usbip_ep_is_valid(ep)) {
498 		LOG_ERR("Not attached / Invalid endpoint: EP 0x%x", ep);
499 		return -EINVAL;
500 	}
501 
502 	if (USB_EP_DIR_IS_OUT(ep)) {
503 		return usbip_ctrl.out_ep_ctrl[ep_idx].mps;
504 	} else {
505 		return usbip_ctrl.in_ep_ctrl[ep_idx].mps;
506 	}
507 }
508 
handle_usb_control(struct usbip_header * hdr)509 int handle_usb_control(struct usbip_header *hdr)
510 {
511 	uint8_t ep_idx = USB_EP_GET_IDX(ntohl(hdr->common.ep));
512 	struct usb_ep_ctrl_prv *ep_ctrl;
513 
514 	ep_ctrl = &usbip_ctrl.out_ep_ctrl[ep_idx];
515 	if (ep_ctrl->cb == NULL) {
516 		LOG_ERR("Control endpoint callback not set");
517 		return -EIO;
518 	}
519 
520 	if ((ntohl(hdr->common.direction) == USBIP_DIR_IN) ^
521 	    USB_REQTYPE_GET_DIR(hdr->u.submit.bmRequestType)) {
522 		LOG_ERR("Failed to verify bmRequestType");
523 		return -EIO;
524 	}
525 
526 	ep_ctrl->data_len = 8;
527 	LOG_DBG("SETUP event ep 0x%02x %u", ep_idx, ep_ctrl->data_len);
528 	memcpy(ep_ctrl->buf, &hdr->u.submit.bmRequestType, ep_ctrl->data_len);
529 	ep_ctrl->cb(ep_idx, USB_DC_EP_SETUP);
530 
531 	if (ntohl(hdr->common.direction) == USBIP_DIR_OUT) {
532 		uint32_t data_len = ntohl(hdr->u.submit.transfer_buffer_length);
533 
534 		/* Data OUT stage availably */
535 		if (data_len > ARRAY_SIZE(ep_ctrl->buf)) {
536 			return -EIO;
537 		}
538 
539 		ep_ctrl->data_len = data_len;
540 
541 		if (usbip_recv(ep_ctrl->buf, ep_ctrl->data_len) < 0) {
542 			return -EIO;
543 		}
544 
545 		LOG_DBG("DATA OUT event ep 0x%02x %u",
546 			ep_idx, ep_ctrl->data_len);
547 		ep_ctrl->cb(ep_idx, USB_DC_EP_DATA_OUT);
548 	}
549 
550 	return 0;
551 }
552 
handle_usb_data(struct usbip_header * hdr)553 int handle_usb_data(struct usbip_header *hdr)
554 {
555 	uint8_t ep_idx = ntohl(hdr->common.ep);
556 	struct usb_ep_ctrl_prv *ep_ctrl;
557 	uint8_t ep;
558 
559 	if (ntohl(hdr->common.direction) == USBIP_DIR_OUT) {
560 		uint32_t data_len;
561 
562 		if (ep_idx >= USBIP_OUT_EP_NUM) {
563 			return -EINVAL;
564 		}
565 
566 		ep_ctrl = &usbip_ctrl.out_ep_ctrl[ep_idx];
567 		ep = ep_idx | USB_EP_DIR_OUT;
568 		data_len = ntohl(hdr->u.submit.transfer_buffer_length);
569 
570 		if (data_len > ARRAY_SIZE(ep_ctrl->buf)) {
571 			return -EIO;
572 		}
573 
574 		ep_ctrl->data_len = data_len;
575 
576 		if (usbip_recv(ep_ctrl->buf, ep_ctrl->data_len) < 0) {
577 			return -EIO;
578 		}
579 
580 		LOG_DBG("DATA OUT event ep 0x%02x %u", ep, ep_ctrl->data_len);
581 		ep_ctrl->cb(ep, USB_DC_EP_DATA_OUT);
582 
583 		/* Send ACK reply */
584 		if (!usbip_send_common(ep, ep_ctrl->data_len)) {
585 			return -EIO;
586 		}
587 	} else {
588 		if (ep_idx >= USBIP_IN_EP_NUM) {
589 			return -EINVAL;
590 		}
591 
592 		ep_ctrl = &usbip_ctrl.in_ep_ctrl[ep_idx];
593 		ep = ep_idx | USB_EP_DIR_IN;
594 		LOG_DBG("DATA IN event ep 0x%02x %u", ep, ep_ctrl->buf_len);
595 
596 		/* Send queued data */
597 		if (!usbip_send_common(ep, ep_ctrl->buf_len)) {
598 			return -EIO;
599 		}
600 
601 		if (usbip_send(ep, ep_ctrl->buf, ep_ctrl->buf_len) !=
602 		    ep_ctrl->buf_len) {
603 			return -EIO;
604 		}
605 
606 		LOG_HEXDUMP_DBG(ep_ctrl->buf, ep_ctrl->buf_len, ">");
607 
608 		/*
609 		 * Call the callback only if data in usb_dc_ep_write()
610 		 * is actually written to the intermediate buffer and sent.
611 		 */
612 		if (ep_ctrl->buf_len != 0) {
613 			ep_ctrl->cb(ep, USB_DC_EP_DATA_IN);
614 			usbip_ctrl.in_ep_ctrl[ep_idx].buf_len = 0;
615 		}
616 	}
617 
618 	return 0;
619 }
620