1 /*
2  * Copyright (c) 2022 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdlib.h>
8 #include <string.h>
9 #include <errno.h>
10 #include <zephyr/sys/util.h>
11 #include <zephyr/shell/shell.h>
12 #include <zephyr/sys/byteorder.h>
13 #include <zephyr/usb/usbh.h>
14 
15 #include "usbh_internal.h"
16 #include "usbh_ch9.h"
17 
18 #include <zephyr/logging/log.h>
19 LOG_MODULE_REGISTER(usbh_shell, CONFIG_USBH_LOG_LEVEL);
20 
21 #define FOOBAZ_VREQ_OUT		0x5b
22 #define FOOBAZ_VREQ_IN		0x5c
23 
24 USBH_CONTROLLER_DEFINE(uhs_ctx, DEVICE_DT_GET(DT_NODELABEL(zephyr_uhc0)));
25 
26 const static struct shell *ctx_shell;
27 
print_dev_desc(const struct shell * sh,const struct usb_device_descriptor * const desc)28 static void print_dev_desc(const struct shell *sh,
29 			   const struct usb_device_descriptor *const desc)
30 {
31 	shell_print(sh, "bLength\t\t\t%u", desc->bLength);
32 	shell_print(sh, "bDescriptorType\t\t%u", desc->bDescriptorType);
33 	shell_print(sh, "bcdUSB\t\t\t%x", desc->bcdUSB);
34 	shell_print(sh, "bDeviceClass\t\t%u", desc->bDeviceClass);
35 	shell_print(sh, "bDeviceSubClass\t\t%u", desc->bDeviceSubClass);
36 	shell_print(sh, "bDeviceProtocol\t\t%u", desc->bDeviceProtocol);
37 	shell_print(sh, "bMaxPacketSize0\t\t%u", desc->bMaxPacketSize0);
38 	shell_print(sh, "idVendor\t\t%x", desc->idVendor);
39 	shell_print(sh, "idProduct\t\t%x", desc->idProduct);
40 	shell_print(sh, "bcdDevice\t\t%x", desc->bcdDevice);
41 	shell_print(sh, "iManufacturer\t\t%u", desc->iManufacturer);
42 	shell_print(sh, "iProduct\t\t%u", desc->iProduct);
43 	shell_print(sh, "iSerial\t\t\t%u", desc->iSerialNumber);
44 	shell_print(sh, "bNumConfigurations\t%u", desc->bNumConfigurations);
45 }
46 
print_cfg_desc(const struct shell * sh,const struct usb_cfg_descriptor * const desc)47 static void print_cfg_desc(const struct shell *sh,
48 			   const struct usb_cfg_descriptor *const desc)
49 {
50 	shell_print(sh, "bLength\t\t\t%u", desc->bLength);
51 	shell_print(sh, "bDescriptorType\t\t%u", desc->bDescriptorType);
52 	shell_print(sh, "wTotalLength\t\t%x", desc->wTotalLength);
53 	shell_print(sh, "bNumInterfaces\t\t%u", desc->bNumInterfaces);
54 	shell_print(sh, "bConfigurationValue\t%u", desc->bConfigurationValue);
55 	shell_print(sh, "iConfiguration\t\t%u", desc->iConfiguration);
56 	shell_print(sh, "bmAttributes\t\t%02x", desc->bmAttributes);
57 	shell_print(sh, "bMaxPower\t\t%u mA", desc->bMaxPower * 2);
58 }
59 
print_desc(const struct shell * sh,const struct net_buf * const buf)60 static void print_desc(const struct shell *sh, const struct net_buf *const buf)
61 {
62 	struct usb_desc_header *head = (void *)buf->data;
63 
64 	if (buf->len < sizeof(struct usb_desc_header)) {
65 		return;
66 	}
67 
68 	switch (head->bDescriptorType) {
69 	case USB_DESC_DEVICE: {
70 		struct usb_device_descriptor *desc = (void *)buf->data;
71 
72 		if (buf->len < sizeof(struct usb_device_descriptor)) {
73 			shell_hexdump(ctx_shell, buf->data, buf->len);
74 			break;
75 		}
76 
77 		desc->bcdUSB = sys_le16_to_cpu(desc->bcdUSB);
78 		desc->idVendor = sys_le16_to_cpu(desc->idVendor);
79 		desc->idProduct = sys_le16_to_cpu(desc->idProduct);
80 		desc->bcdDevice = sys_le16_to_cpu(desc->bcdDevice);
81 		print_dev_desc(sh, desc);
82 		break;
83 	}
84 	case USB_DESC_CONFIGURATION: {
85 		struct usb_cfg_descriptor *desc = (void *)buf->data;
86 
87 		if (buf->len < sizeof(struct usb_cfg_descriptor)) {
88 			shell_hexdump(ctx_shell, buf->data, buf->len);
89 			break;
90 		}
91 
92 		desc->wTotalLength = sys_le16_to_cpu(desc->wTotalLength);
93 		print_cfg_desc(sh, desc);
94 		break;
95 	}
96 	default:
97 		shell_hexdump(ctx_shell, buf->data, buf->len);
98 		break;
99 	}
100 }
101 
bazfoo_request(struct usbh_contex * const ctx,struct uhc_transfer * const xfer,int err)102 static int bazfoo_request(struct usbh_contex *const ctx,
103 			  struct uhc_transfer *const xfer,
104 			  int err)
105 {
106 	const struct device *dev = ctx->dev;
107 
108 	shell_info(ctx_shell, "host: transfer finished %p, err %d", xfer, err);
109 
110 	while (!k_fifo_is_empty(&xfer->done)) {
111 		struct net_buf *buf;
112 
113 		buf = net_buf_get(&xfer->done, K_NO_WAIT);
114 		if (buf) {
115 			/*
116 			 * FIXME: We don not distinguish the context
117 			 * of the request and always try to print it
118 			 * as descriptor first. If it is not a known descriptor,
119 			 * we show a hexdump in any case.
120 			 * This is just simple enough for first steps and will
121 			 * be revised with coming peripheral device management.
122 			 */
123 			if (xfer->ep == USB_CONTROL_EP_IN) {
124 				print_desc(ctx_shell, buf);
125 			} else {
126 				shell_hexdump(ctx_shell, buf->data, buf->len);
127 			}
128 
129 			uhc_xfer_buf_free(dev, buf);
130 		}
131 	}
132 
133 	return uhc_xfer_free(dev, xfer);
134 }
135 
bazfoo_connected(struct usbh_contex * const uhs_ctx)136 static int bazfoo_connected(struct usbh_contex *const uhs_ctx)
137 {
138 	shell_info(ctx_shell, "host: USB device connected");
139 
140 	return 0;
141 }
142 
bazfoo_removed(struct usbh_contex * const uhs_ctx)143 static int bazfoo_removed(struct usbh_contex *const uhs_ctx)
144 {
145 	shell_info(ctx_shell, "host: USB device removed");
146 
147 	return 0;
148 }
149 
bazfoo_rwup(struct usbh_contex * const uhs_ctx)150 static int bazfoo_rwup(struct usbh_contex *const uhs_ctx)
151 {
152 	shell_info(ctx_shell, "host: Bus remote wakeup event");
153 
154 	return 0;
155 }
156 
bazfoo_suspended(struct usbh_contex * const uhs_ctx)157 static int bazfoo_suspended(struct usbh_contex *const uhs_ctx)
158 {
159 	shell_info(ctx_shell, "host: Bus suspended");
160 
161 	return 0;
162 }
163 
bazfoo_resumed(struct usbh_contex * const uhs_ctx)164 static int bazfoo_resumed(struct usbh_contex *const uhs_ctx)
165 {
166 	shell_info(ctx_shell, "host: Bus resumed");
167 
168 	return 0;
169 }
170 
171 USBH_DEFINE_CLASS(bazfoo) = {
172 	.request = bazfoo_request,
173 	.connected = bazfoo_connected,
174 	.removed = bazfoo_removed,
175 	.rwup = bazfoo_rwup,
176 	.suspended = bazfoo_suspended,
177 	.resumed = bazfoo_resumed,
178 };
179 
180 static uint8_t vreq_test_buf[1024];
181 
cmd_bulk(const struct shell * sh,size_t argc,char ** argv)182 static int cmd_bulk(const struct shell *sh, size_t argc, char **argv)
183 {
184 	struct uhc_transfer *xfer;
185 	struct net_buf *buf;
186 	uint8_t addr;
187 	uint8_t ep;
188 	size_t len;
189 
190 	addr = strtol(argv[1], NULL, 10);
191 	ep = strtol(argv[2], NULL, 16);
192 	len = MIN(sizeof(vreq_test_buf), strtol(argv[3], NULL, 10));
193 
194 	xfer = uhc_xfer_alloc(uhs_ctx.dev, addr, ep, 0, 512, 10, NULL);
195 	if (!xfer) {
196 		return -ENOMEM;
197 	}
198 
199 	buf = uhc_xfer_buf_alloc(uhs_ctx.dev, xfer, len);
200 	if (!buf) {
201 		return -ENOMEM;
202 	}
203 
204 	if (USB_EP_DIR_IS_OUT(ep)) {
205 		net_buf_add_mem(buf, vreq_test_buf, len);
206 	}
207 
208 	return uhc_ep_enqueue(uhs_ctx.dev, xfer);
209 }
210 
cmd_vendor_in(const struct shell * sh,size_t argc,char ** argv)211 static int cmd_vendor_in(const struct shell *sh,
212 			 size_t argc, char **argv)
213 {
214 	const uint8_t bmRequestType = (USB_REQTYPE_DIR_TO_HOST << 7) |
215 				      (USB_REQTYPE_TYPE_VENDOR << 5);
216 	const uint8_t bRequest = FOOBAZ_VREQ_IN;
217 	const uint16_t wValue = 0x0000;
218 	uint16_t wLength;
219 	uint8_t addr;
220 
221 	addr = strtol(argv[1], NULL, 10);
222 	wLength = MIN(sizeof(vreq_test_buf), strtol(argv[2], NULL, 10));
223 
224 	return usbh_req_setup(uhs_ctx.dev, addr,
225 			      bmRequestType, bRequest, wValue, 0, wLength,
226 			      NULL);
227 }
228 
cmd_vendor_out(const struct shell * sh,size_t argc,char ** argv)229 static int cmd_vendor_out(const struct shell *sh,
230 			  size_t argc, char **argv)
231 {
232 	const uint8_t bmRequestType = (USB_REQTYPE_DIR_TO_DEVICE << 7) |
233 				      (USB_REQTYPE_TYPE_VENDOR << 5);
234 	const uint8_t bRequest = FOOBAZ_VREQ_OUT;
235 	const uint16_t wValue = 0x0000;
236 	uint16_t wLength;
237 	uint8_t addr;
238 
239 	addr = strtol(argv[1], NULL, 10);
240 	wLength = MIN(sizeof(vreq_test_buf), strtol(argv[2], NULL, 10));
241 
242 	for (int i = 0; i < wLength; i++) {
243 		vreq_test_buf[i] = i;
244 	}
245 
246 	return usbh_req_setup(uhs_ctx.dev, addr,
247 			      bmRequestType, bRequest, wValue, 0, wLength,
248 			      vreq_test_buf);
249 }
250 
cmd_desc_device(const struct shell * sh,size_t argc,char ** argv)251 static int cmd_desc_device(const struct shell *sh,
252 			   size_t argc, char **argv)
253 {
254 	uint8_t addr;
255 	int err;
256 
257 	addr = strtol(argv[1], NULL, 10);
258 
259 	err = usbh_req_desc_dev(uhs_ctx.dev, addr);
260 	if (err) {
261 		shell_print(sh, "host: Failed to request device descriptor");
262 	}
263 
264 	return err;
265 }
266 
cmd_desc_config(const struct shell * sh,size_t argc,char ** argv)267 static int cmd_desc_config(const struct shell *sh,
268 			   size_t argc, char **argv)
269 {
270 	uint8_t addr;
271 	uint8_t cfg;
272 	int err;
273 
274 	addr = strtol(argv[1], NULL, 10);
275 	cfg = strtol(argv[2], NULL, 10);
276 
277 	/* TODO: cfg is ignored, add to usbh_req_desc_cfg */
278 	err = usbh_req_desc_cfg(uhs_ctx.dev, addr, cfg, 128);
279 	if (err) {
280 		shell_print(sh, "host: Failed to request configuration descriptor");
281 	}
282 
283 	return err;
284 }
285 
cmd_desc_string(const struct shell * sh,size_t argc,char ** argv)286 static int cmd_desc_string(const struct shell *sh,
287 			   size_t argc, char **argv)
288 {
289 	const uint8_t type = USB_DESC_STRING;
290 	uint8_t addr;
291 	uint8_t id;
292 	uint8_t idx;
293 	int err;
294 
295 	addr = strtol(argv[1], NULL, 10);
296 	id = strtol(argv[2], NULL, 10);
297 	idx = strtol(argv[3], NULL, 10);
298 
299 	err = usbh_req_desc(uhs_ctx.dev, addr, type, idx, id, 128);
300 	if (err) {
301 		shell_print(sh, "host: Failed to request configuration descriptor");
302 	}
303 
304 	return err;
305 }
306 
cmd_feature_set_halt(const struct shell * sh,size_t argc,char ** argv)307 static int cmd_feature_set_halt(const struct shell *sh,
308 				size_t argc, char **argv)
309 {
310 	uint8_t addr;
311 	uint8_t ep;
312 	int err;
313 
314 	addr = strtol(argv[1], NULL, 10);
315 	ep = strtol(argv[2], NULL, 16);
316 
317 	/* TODO: add usbh_req_set_sfs_halt(uhs_ctx.dev, 0); */
318 	err = usbh_req_set_sfs_rwup(uhs_ctx.dev, addr);
319 	if (err) {
320 		shell_error(sh, "host: Failed to set halt feature");
321 	} else {
322 		shell_print(sh, "host: Device 0x%02x, ep 0x%02x halt feature set",
323 			    addr, ep);
324 	}
325 
326 	return err;
327 }
328 
cmd_feature_clear_rwup(const struct shell * sh,size_t argc,char ** argv)329 static int cmd_feature_clear_rwup(const struct shell *sh,
330 				  size_t argc, char **argv)
331 {
332 	uint8_t addr;
333 	int err;
334 
335 	addr = strtol(argv[1], NULL, 10);
336 
337 	err = usbh_req_clear_sfs_rwup(uhs_ctx.dev, addr);
338 	if (err) {
339 		shell_error(sh, "host: Failed to clear rwup feature");
340 	} else {
341 		shell_print(sh, "host: Device 0x%02x, rwup feature cleared", addr);
342 	}
343 
344 	return err;
345 }
346 
cmd_feature_set_rwup(const struct shell * sh,size_t argc,char ** argv)347 static int cmd_feature_set_rwup(const struct shell *sh,
348 				size_t argc, char **argv)
349 {
350 	uint8_t addr;
351 	int err;
352 
353 	addr = strtol(argv[1], NULL, 10);
354 
355 	err = usbh_req_set_sfs_rwup(uhs_ctx.dev, addr);
356 	if (err) {
357 		shell_error(sh, "host: Failed to set rwup feature");
358 	} else {
359 		shell_print(sh, "host: Device 0x%02x, rwup feature set", addr);
360 	}
361 
362 	return err;
363 }
364 
cmd_feature_set_ppwr(const struct shell * sh,size_t argc,char ** argv)365 static int cmd_feature_set_ppwr(const struct shell *sh,
366 				size_t argc, char **argv)
367 {
368 	uint8_t addr;
369 	uint8_t port;
370 	int err;
371 
372 	addr = strtol(argv[1], NULL, 10);
373 	port = strtol(argv[2], NULL, 10);
374 
375 	err = usbh_req_set_hcfs_ppwr(uhs_ctx.dev, addr, port);
376 	if (err) {
377 		shell_error(sh, "host: Failed to set ppwr feature");
378 	} else {
379 		shell_print(sh, "host: Device 0x%02x, port %d, ppwr feature set",
380 			    addr, port);
381 	}
382 
383 	return err;
384 }
385 
cmd_feature_set_prst(const struct shell * sh,size_t argc,char ** argv)386 static int cmd_feature_set_prst(const struct shell *sh,
387 				size_t argc, char **argv)
388 {
389 	uint8_t addr;
390 	uint8_t port;
391 	int err;
392 
393 	addr = strtol(argv[1], NULL, 10);
394 	port = strtol(argv[2], NULL, 10);
395 
396 	err = usbh_req_set_hcfs_prst(uhs_ctx.dev, addr, port);
397 	if (err) {
398 		shell_error(sh, "host: Failed to set prst feature");
399 	} else {
400 		shell_print(sh, "host: Device 0x%02x, port %d, prst feature set",
401 			    addr, port);
402 	}
403 
404 	return err;
405 }
406 
cmd_device_config(const struct shell * sh,size_t argc,char ** argv)407 static int cmd_device_config(const struct shell *sh,
408 			     size_t argc, char **argv)
409 {
410 	uint8_t addr;
411 	uint8_t cfg;
412 	int err;
413 
414 	addr = strtol(argv[1], NULL, 10);
415 	cfg = strtol(argv[2], NULL, 10);
416 
417 	err = usbh_req_set_cfg(uhs_ctx.dev, addr, cfg);
418 	if (err) {
419 		shell_error(sh, "host: Failed to set configuration");
420 	} else {
421 		shell_print(sh, "host: Device 0x%02x, new configuration %u",
422 			    addr, cfg);
423 	}
424 
425 	return err;
426 }
427 
cmd_device_interface(const struct shell * sh,size_t argc,char ** argv)428 static int cmd_device_interface(const struct shell *sh,
429 				size_t argc, char **argv)
430 {
431 	uint8_t addr;
432 	uint8_t iface;
433 	uint8_t alt;
434 	int err;
435 
436 	addr = strtol(argv[1], NULL, 10);
437 	iface = strtol(argv[2], NULL, 10);
438 	alt = strtol(argv[3], NULL, 10);
439 
440 	err = usbh_req_set_alt(uhs_ctx.dev, addr, iface, alt);
441 	if (err) {
442 		shell_error(sh, "host: Failed to set interface alternate");
443 	} else {
444 		shell_print(sh, "host: Device 0x%02x, new %u alternate %u",
445 			    addr, iface, alt);
446 	}
447 
448 	return err;
449 }
450 
cmd_device_address(const struct shell * sh,size_t argc,char ** argv)451 static int cmd_device_address(const struct shell *sh,
452 			      size_t argc, char **argv)
453 {
454 	uint8_t addr;
455 	int err;
456 
457 	addr = strtol(argv[1], NULL, 10);
458 
459 	err = usbh_req_set_address(uhs_ctx.dev, 0, addr);
460 	if (err) {
461 		shell_error(sh, "host: Failed to set address");
462 	} else {
463 		shell_print(sh, "host: New device address is 0x%02x", addr);
464 	}
465 
466 	return err;
467 }
468 
cmd_bus_suspend(const struct shell * sh,size_t argc,char ** argv)469 static int cmd_bus_suspend(const struct shell *sh,
470 			   size_t argc, char **argv)
471 {
472 	int err;
473 
474 	err = uhc_bus_suspend(uhs_ctx.dev);
475 	if (err) {
476 		shell_error(sh, "host: Failed to perform bus suspend %d", err);
477 	} else {
478 		shell_print(sh, "host: USB bus suspended");
479 	}
480 
481 	return err;
482 }
483 
cmd_bus_resume(const struct shell * sh,size_t argc,char ** argv)484 static int cmd_bus_resume(const struct shell *sh,
485 			  size_t argc, char **argv)
486 {
487 	int err;
488 
489 	err = uhc_bus_resume(uhs_ctx.dev);
490 	if (err) {
491 		shell_error(sh, "host: Failed to perform bus resume %d", err);
492 	} else {
493 		shell_print(sh, "host: USB bus resumed");
494 	}
495 
496 	err = uhc_sof_enable(uhs_ctx.dev);
497 	if (err) {
498 		shell_error(sh, "host: Failed to start SoF generator %d", err);
499 	}
500 
501 	return err;
502 }
503 
cmd_bus_reset(const struct shell * sh,size_t argc,char ** argv)504 static int cmd_bus_reset(const struct shell *sh,
505 			 size_t argc, char **argv)
506 {
507 	int err;
508 
509 	err = uhc_bus_reset(uhs_ctx.dev);
510 	if (err) {
511 		shell_error(sh, "host: Failed to perform bus reset %d", err);
512 	} else {
513 		shell_print(sh, "host: USB bus reseted");
514 	}
515 
516 	err = uhc_sof_enable(uhs_ctx.dev);
517 	if (err) {
518 		shell_error(sh, "host: Failed to start SoF generator %d", err);
519 	}
520 
521 	return err;
522 }
523 
cmd_usbh_init(const struct shell * sh,size_t argc,char ** argv)524 static int cmd_usbh_init(const struct shell *sh,
525 			 size_t argc, char **argv)
526 {
527 	int err;
528 
529 	ctx_shell = sh;
530 
531 	err = usbh_init(&uhs_ctx);
532 	if (err == -EALREADY) {
533 		shell_error(sh, "host: USB host already initialized");
534 	} else if (err) {
535 		shell_error(sh, "host: Failed to initialize %d", err);
536 	} else {
537 		shell_print(sh, "host: USB host initialized");
538 	}
539 
540 	return err;
541 }
542 
cmd_usbh_enable(const struct shell * sh,size_t argc,char ** argv)543 static int cmd_usbh_enable(const struct shell *sh,
544 			   size_t argc, char **argv)
545 {
546 	int err;
547 
548 	err = usbh_enable(&uhs_ctx);
549 	if (err) {
550 		shell_error(sh, "host: Failed to enable USB host support");
551 	} else {
552 		shell_print(sh, "host: USB host enabled");
553 	}
554 
555 	return err;
556 }
557 
cmd_usbh_disable(const struct shell * sh,size_t argc,char ** argv)558 static int cmd_usbh_disable(const struct shell *sh,
559 			    size_t argc, char **argv)
560 {
561 	int err;
562 
563 	err = usbh_disable(&uhs_ctx);
564 	if (err) {
565 		shell_error(sh, "host: Failed to disable USB host support");
566 	} else {
567 		shell_print(sh, "host: USB host disabled");
568 	}
569 
570 	return err;
571 }
572 
573 SHELL_STATIC_SUBCMD_SET_CREATE(desc_cmds,
574 	SHELL_CMD_ARG(device, NULL, "<address>",
575 		      cmd_desc_device, 2, 0),
576 	SHELL_CMD_ARG(configuration, NULL, "<address> <index>",
577 		      cmd_desc_config, 3, 0),
578 	SHELL_CMD_ARG(string, NULL, "<address> <id> <index>",
579 		      cmd_desc_string, 4, 0),
580 	SHELL_SUBCMD_SET_END
581 );
582 
583 SHELL_STATIC_SUBCMD_SET_CREATE(feature_set_cmds,
584 	SHELL_CMD_ARG(rwup, NULL, "<address>",
585 		      cmd_feature_set_rwup, 2, 0),
586 	SHELL_CMD_ARG(ppwr, NULL, "<address> <port>",
587 		      cmd_feature_set_ppwr, 3, 0),
588 	SHELL_CMD_ARG(prst, NULL, "<address> <port>",
589 		      cmd_feature_set_prst, 3, 0),
590 	SHELL_CMD_ARG(halt, NULL, "<address> <endpoint>",
591 		      cmd_feature_set_halt, 3, 0),
592 	SHELL_SUBCMD_SET_END
593 );
594 
595 SHELL_STATIC_SUBCMD_SET_CREATE(feature_clear_cmds,
596 	SHELL_CMD_ARG(rwup, NULL, "<address>",
597 		      cmd_feature_clear_rwup, 2, 0),
598 	SHELL_CMD_ARG(halt, NULL, "<address> <endpoint>",
599 		      cmd_feature_set_halt, 3, 0),
600 	SHELL_SUBCMD_SET_END
601 );
602 
603 SHELL_STATIC_SUBCMD_SET_CREATE(device_cmds,
604 	SHELL_CMD_ARG(address, NULL, "<address>",
605 		      cmd_device_address, 2, 0),
606 	SHELL_CMD_ARG(config, NULL, "<address> <config>",
607 		      cmd_device_config, 3, 0),
608 	SHELL_CMD_ARG(interface, NULL, "<address> <interface> <alternate>",
609 		      cmd_device_interface, 4, 0),
610 	SHELL_CMD_ARG(descriptor, &desc_cmds, "descriptor request",
611 		      NULL, 1, 0),
612 	SHELL_CMD_ARG(feature-set, &feature_set_cmds, "feature selector",
613 		      NULL, 1, 0),
614 	SHELL_CMD_ARG(feature-clear, &feature_clear_cmds, "feature selector",
615 		      NULL, 1, 0),
616 	SHELL_CMD_ARG(vendor_in, NULL, "<address> <length>",
617 		      cmd_vendor_in, 3, 0),
618 	SHELL_CMD_ARG(vendor_out, NULL, "<address> <length>",
619 		      cmd_vendor_out, 3, 0),
620 	SHELL_CMD_ARG(bulk, NULL, "<address> <endpoint> <length>",
621 		      cmd_bulk, 4, 0),
622 	SHELL_SUBCMD_SET_END
623 );
624 
625 SHELL_STATIC_SUBCMD_SET_CREATE(bus_cmds,
626 	SHELL_CMD_ARG(suspend, NULL, "[nono]",
627 		      cmd_bus_suspend, 1, 0),
628 	SHELL_CMD_ARG(resume, NULL, "[nono]",
629 		      cmd_bus_resume, 1, 0),
630 	SHELL_CMD_ARG(reset, NULL, "[nono]",
631 		      cmd_bus_reset, 1, 0),
632 	SHELL_SUBCMD_SET_END
633 );
634 
635 SHELL_STATIC_SUBCMD_SET_CREATE(sub_usbh_cmds,
636 	SHELL_CMD_ARG(init, NULL, "[none]",
637 		      cmd_usbh_init, 1, 0),
638 	SHELL_CMD_ARG(enable, NULL, "[none]",
639 		      cmd_usbh_enable, 1, 0),
640 	SHELL_CMD_ARG(disable, NULL, "[none]",
641 		      cmd_usbh_disable, 1, 0),
642 	SHELL_CMD_ARG(bus, &bus_cmds, "bus commands",
643 		      NULL, 1, 0),
644 	SHELL_CMD_ARG(device, &device_cmds, "device commands",
645 		      NULL, 1, 0),
646 	SHELL_SUBCMD_SET_END
647 );
648 
649 SHELL_CMD_REGISTER(usbh, &sub_usbh_cmds, "USBH commands", NULL);
650