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