1 /*
2  * Copyright (c) 2022,2024 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/usb/usbd.h>
13 #include <zephyr/drivers/usb/udc.h>
14 #include <zephyr/sys/byteorder.h>
15 #include <zephyr/sys/iterable_sections.h>
16 
17 /* Default configurations used in the shell context. */
18 USBD_CONFIGURATION_DEFINE(config_1_fs, USB_SCD_REMOTE_WAKEUP, 200, NULL);
19 USBD_CONFIGURATION_DEFINE(config_1_hs, USB_SCD_REMOTE_WAKEUP, 200, NULL);
20 USBD_CONFIGURATION_DEFINE(config_2_fs, USB_SCD_SELF_POWERED, 200, NULL);
21 USBD_CONFIGURATION_DEFINE(config_2_hs, USB_SCD_SELF_POWERED, 200, NULL);
22 
23 static struct usbd_shell_config {
24 	struct usbd_config_node *cfg_nd;
25 	enum usbd_speed speed;
26 	const char *name;
27 } sh_configs[] = {
28 	{.cfg_nd = &config_1_fs, .speed = USBD_SPEED_FS, .name = "FS1",},
29 	{.cfg_nd = &config_1_hs, .speed = USBD_SPEED_HS, .name = "HS1",},
30 	{.cfg_nd = &config_2_fs, .speed = USBD_SPEED_FS, .name = "FS2",},
31 	{.cfg_nd = &config_2_hs, .speed = USBD_SPEED_HS, .name = "HS2",},
32 };
33 
34 static struct usbd_shell_speed {
35 	enum usbd_speed speed;
36 	const char *name;
37 } sh_speed[] = {
38 	{.speed = USBD_SPEED_FS, .name = "fs",},
39 	{.speed = USBD_SPEED_HS, .name = "hs",},
40 };
41 
42 /* Default string descriptors used in the shell context. */
43 USBD_DESC_LANG_DEFINE(lang);
44 USBD_DESC_MANUFACTURER_DEFINE(mfr, "ZEPHYR");
45 USBD_DESC_PRODUCT_DEFINE(product, "Zephyr USBD foobaz");
46 IF_ENABLED(CONFIG_HWINFO, (USBD_DESC_SERIAL_NUMBER_DEFINE(sn)));
47 
48 /* Default device descriptors and context used in the shell. */
49 USBD_DEVICE_DEFINE(sh_uds_ctx, DEVICE_DT_GET(DT_NODELABEL(zephyr_udc0)),
50 		   0x2fe3, 0xffff);
51 
52 static struct usbd_context *my_uds_ctx = &sh_uds_ctx;
53 static enum usbd_speed current_cmd_speed = USBD_SPEED_FS;
54 
cmd_wakeup_request(const struct shell * sh,size_t argc,char ** argv)55 static int cmd_wakeup_request(const struct shell *sh,
56 			      size_t argc, char **argv)
57 {
58 	int err;
59 
60 	err = usbd_wakeup_request(my_uds_ctx);
61 	if (err) {
62 		shell_error(sh, "dev: Failed to wakeup remote %d", err);
63 	} else {
64 		shell_print(sh, "dev: Requested remote wakeup");
65 	}
66 
67 	return err;
68 }
69 
cmd_register(const struct shell * sh,size_t argc,char ** argv)70 static int cmd_register(const struct shell *sh,
71 			size_t argc, char **argv)
72 {
73 	uint8_t cfg;
74 	int ret;
75 
76 	cfg = strtol(argv[3], NULL, 10);
77 	ret = usbd_register_class(my_uds_ctx, argv[1], current_cmd_speed, cfg);
78 	if (ret) {
79 		shell_error(sh,
80 			    "dev: failed to register USB class %s to configuration %s %u",
81 			    argv[1], argv[2], cfg);
82 	} else {
83 		shell_print(sh,
84 			    "dev: register USB class %s to configuration %s %u",
85 			    argv[1], argv[2], cfg);
86 	}
87 
88 	return ret;
89 }
90 
cmd_unregister(const struct shell * sh,size_t argc,char ** argv)91 static int cmd_unregister(const struct shell *sh,
92 			  size_t argc, char **argv)
93 {
94 	uint8_t cfg;
95 	int ret;
96 
97 	cfg = strtol(argv[3], NULL, 10);
98 	ret = usbd_unregister_class(my_uds_ctx, argv[1], current_cmd_speed, cfg);
99 	if (ret) {
100 		shell_error(sh,
101 			    "dev: failed to remove USB class %s from configuration %s %u",
102 			    argv[1], argv[2], cfg);
103 	} else {
104 		shell_print(sh,
105 			    "dev: removed USB class %s from configuration %s %u",
106 			    argv[1], argv[2], cfg);
107 	}
108 
109 	return ret;
110 }
111 
cmd_usbd_default_strings(const struct shell * sh,size_t argc,char ** argv)112 static int cmd_usbd_default_strings(const struct shell *sh,
113 				    size_t argc, char **argv)
114 {
115 	int err;
116 
117 	err = usbd_add_descriptor(my_uds_ctx, &lang);
118 	err |= usbd_add_descriptor(my_uds_ctx, &mfr);
119 	err |= usbd_add_descriptor(my_uds_ctx, &product);
120 	IF_ENABLED(CONFIG_HWINFO, (
121 		err |= usbd_add_descriptor(my_uds_ctx, &sn);
122 	))
123 
124 	if (err) {
125 		shell_error(sh, "dev: Failed to add default string descriptors, %d", err);
126 	} else {
127 		shell_print(sh, "dev: added default string descriptors");
128 	}
129 
130 	return err;
131 }
132 
register_classes(const struct shell * sh)133 static int register_classes(const struct shell *sh)
134 {
135 	int err;
136 
137 	STRUCT_SECTION_FOREACH_ALTERNATE(usbd_class_fs, usbd_class_node, c_nd) {
138 		err = usbd_register_class(my_uds_ctx, c_nd->c_data->name,
139 					  USBD_SPEED_FS, 1);
140 		if (err) {
141 			shell_error(sh,
142 				    "dev: failed to register FS %s (%d)",
143 				    c_nd->c_data->name, err);
144 			return err;
145 		}
146 
147 		shell_print(sh, "dev: register FS %s", c_nd->c_data->name);
148 	}
149 
150 	if (!USBD_SUPPORTS_HIGH_SPEED ||
151 	    usbd_caps_speed(my_uds_ctx) != USBD_SPEED_HS) {
152 		return 0;
153 	}
154 
155 	STRUCT_SECTION_FOREACH_ALTERNATE(usbd_class_hs, usbd_class_node, c_nd) {
156 		err = usbd_register_class(my_uds_ctx, c_nd->c_data->name,
157 					  USBD_SPEED_HS, 1);
158 		if (err) {
159 			shell_error(sh,
160 				    "dev: failed to register HS %s (%d)",
161 				    c_nd->c_data->name, err);
162 			return err;
163 		}
164 
165 		shell_print(sh, "dev: register HS %s", c_nd->c_data->name);
166 	}
167 
168 	return 0;
169 }
170 
cmd_usbd_init(const struct shell * sh,size_t argc,char ** argv)171 static int cmd_usbd_init(const struct shell *sh,
172 			 size_t argc, char **argv)
173 {
174 	int err;
175 
176 	err = usbd_init(my_uds_ctx);
177 
178 	if (err == -EALREADY) {
179 		shell_error(sh, "dev: USB already initialized");
180 	} else if (err) {
181 		shell_error(sh, "dev: Failed to initialize device support (%d)", err);
182 	} else {
183 		shell_print(sh, "dev: USB initialized");
184 	}
185 
186 	return err;
187 }
188 
cmd_usbd_default_config(const struct shell * sh,size_t argc,char ** argv)189 static int cmd_usbd_default_config(const struct shell *sh,
190 				   size_t argc, char **argv)
191 {
192 	int err;
193 
194 	err = cmd_usbd_default_strings(sh, 0, NULL);
195 	if (err) {
196 		return err;
197 	}
198 
199 	if (usbd_caps_speed(my_uds_ctx) == USBD_SPEED_HS) {
200 		err = usbd_add_configuration(my_uds_ctx, USBD_SPEED_HS, &config_1_hs);
201 		if (err) {
202 			shell_error(sh, "dev: Failed to add HS configuration");
203 			return err;
204 		}
205 	}
206 
207 	err = usbd_add_configuration(my_uds_ctx, USBD_SPEED_FS, &config_1_fs);
208 	if (err) {
209 		shell_error(sh, "dev: Failed to add FS configuration");
210 		return err;
211 	}
212 
213 	err = register_classes(sh);
214 	if (err) {
215 		return err;
216 	}
217 
218 	return cmd_usbd_init(sh, 0, NULL);
219 }
220 
cmd_usbd_enable(const struct shell * sh,size_t argc,char ** argv)221 static int cmd_usbd_enable(const struct shell *sh,
222 			   size_t argc, char **argv)
223 {
224 	int err;
225 
226 	err = usbd_enable(my_uds_ctx);
227 
228 	if (err == -EALREADY) {
229 		shell_error(sh, "dev: USB already enabled");
230 	} else if (err) {
231 		shell_error(sh, "dev: Failed to enable USB, error %d", err);
232 	} else {
233 		shell_print(sh, "dev: USB enabled");
234 	}
235 
236 	return err;
237 }
238 
cmd_usbd_disable(const struct shell * sh,size_t argc,char ** argv)239 static int cmd_usbd_disable(const struct shell *sh,
240 			    size_t argc, char **argv)
241 {
242 	int err;
243 
244 	err = usbd_disable(my_uds_ctx);
245 
246 	if (err) {
247 		shell_error(sh, "dev: Failed to disable USB");
248 		return err;
249 	}
250 
251 	shell_print(sh, "dev: USB disabled");
252 
253 	return 0;
254 }
255 
cmd_usbd_shutdown(const struct shell * sh,size_t argc,char ** argv)256 static int cmd_usbd_shutdown(const struct shell *sh,
257 			     size_t argc, char **argv)
258 {
259 	int err;
260 
261 	err = usbd_shutdown(my_uds_ctx);
262 
263 	if (err) {
264 		shell_error(sh, "dev: Failed to shutdown USB");
265 		return err;
266 	}
267 
268 	shell_print(sh, "dev: USB completely disabled");
269 
270 	return 0;
271 }
272 
cmd_select(const struct shell * sh,size_t argc,char ** argv)273 static int cmd_select(const struct shell *sh, size_t argc, char **argv)
274 {
275 	STRUCT_SECTION_FOREACH(usbd_context, ctx) {
276 		if (strcmp(argv[1], ctx->name) == 0) {
277 			my_uds_ctx = ctx;
278 			shell_print(sh,
279 				    "dev: select %s as my USB device context",
280 				    argv[1]);
281 
282 			return 0;
283 		}
284 	}
285 
286 	shell_error(sh, "dev: failed to select %s", argv[1]);
287 
288 	return -ENODEV;
289 }
290 
cmd_device_bcd_usb(const struct shell * sh,size_t argc,char * argv[])291 static int cmd_device_bcd_usb(const struct shell *sh, size_t argc,
292 			      char *argv[])
293 {
294 	uint16_t bcd;
295 	int ret;
296 
297 	bcd = strtol(argv[2], NULL, 16);
298 	ret = usbd_device_set_bcd_usb(my_uds_ctx, current_cmd_speed, bcd);
299 	if (ret) {
300 		shell_error(sh, "dev: failed to set device bcdUSB to %x", bcd);
301 	} else {
302 		shell_error(sh, "dev: set device bcdUSB to %x", bcd);
303 	}
304 
305 	return ret;
306 }
307 
cmd_device_pid(const struct shell * sh,size_t argc,char * argv[])308 static int cmd_device_pid(const struct shell *sh, size_t argc,
309 			  char *argv[])
310 {
311 	uint16_t pid;
312 	int ret;
313 
314 	pid = strtol(argv[1], NULL, 16);
315 	ret = usbd_device_set_pid(my_uds_ctx, pid);
316 	if (ret) {
317 		shell_error(sh, "dev: failed to set device idProduct to %x", pid);
318 	}
319 
320 	return ret;
321 }
322 
cmd_device_vid(const struct shell * sh,size_t argc,char * argv[])323 static int cmd_device_vid(const struct shell *sh, size_t argc,
324 			  char *argv[])
325 {
326 	uint16_t vid;
327 	int ret;
328 
329 	vid = strtol(argv[1], NULL, 16);
330 	ret = usbd_device_set_vid(my_uds_ctx, vid);
331 	if (ret) {
332 		shell_error(sh, "dev: failed to set device idVendor to %x", vid);
333 	}
334 
335 	return ret;
336 }
337 
cmd_device_code_triple(const struct shell * sh,size_t argc,char * argv[])338 static int cmd_device_code_triple(const struct shell *sh, size_t argc,
339 				  char *argv[])
340 {
341 	uint8_t class, subclass, protocol;
342 	int ret;
343 
344 	class = strtol(argv[2], NULL, 16);
345 	subclass = strtol(argv[3], NULL, 16);
346 	protocol = strtol(argv[4], NULL, 16);
347 	ret = usbd_device_set_code_triple(my_uds_ctx, current_cmd_speed,
348 					  class, subclass, protocol);
349 	if (ret) {
350 		shell_error(sh, "dev: failed to set device code triple to %x %x %x",
351 			    class, subclass, protocol);
352 	} else {
353 		shell_error(sh, "dev: set device code triple to %x %x %x",
354 			    class, subclass, protocol);
355 	}
356 
357 	return ret;
358 }
359 
cmd_config_add(const struct shell * sh,size_t argc,char * argv[])360 static int cmd_config_add(const struct shell *sh, size_t argc,
361 			  char *argv[])
362 {
363 	int ret = -EINVAL;
364 
365 	for (unsigned int i = 0; i < ARRAY_SIZE(sh_configs); i++) {
366 		if (!strcmp(argv[1], sh_configs[i].name)) {
367 			ret = usbd_add_configuration(my_uds_ctx,
368 						     sh_configs[i].speed,
369 						     sh_configs[i].cfg_nd);
370 			break;
371 		}
372 	}
373 
374 	if (ret) {
375 		shell_error(sh, "dev: failed to add configuration %s", argv[1]);
376 	}
377 
378 	return ret;
379 }
380 
cmd_config_set_selfpowered(const struct shell * sh,const bool self,size_t argc,char * argv[])381 static int cmd_config_set_selfpowered(const struct shell *sh, const bool self,
382 				      size_t argc, char *argv[])
383 {
384 	uint8_t cfg;
385 	int ret;
386 
387 	cfg = strtol(argv[2], NULL, 10);
388 
389 	ret = usbd_config_attrib_self(my_uds_ctx, current_cmd_speed, cfg, self);
390 	if (ret) {
391 		shell_error(sh,
392 			    "dev: failed to set attribute Self-powered to %u",
393 			    cfg);
394 	} else {
395 		shell_print(sh,
396 			    "dev: set configuration %u attribute Self-powered to %u",
397 			    cfg, self);
398 	}
399 
400 	return ret;
401 }
402 
cmd_config_selfpowered(const struct shell * sh,size_t argc,char * argv[])403 static int cmd_config_selfpowered(const struct shell *sh,
404 				  size_t argc, char *argv[])
405 {
406 	return cmd_config_set_selfpowered(sh, true, argc, argv);
407 }
408 
cmd_config_buspowered(const struct shell * sh,size_t argc,char * argv[])409 static int cmd_config_buspowered(const struct shell *sh,
410 				 size_t argc, char *argv[])
411 {
412 	return cmd_config_set_selfpowered(sh, false, argc, argv);
413 }
414 
cmd_config_rwup(const struct shell * sh,const bool rwup,size_t argc,char * argv[])415 static int cmd_config_rwup(const struct shell *sh, const bool rwup,
416 			   size_t argc, char *argv[])
417 {
418 	uint8_t cfg;
419 	int ret;
420 
421 	cfg = strtol(argv[2], NULL, 10);
422 
423 	ret = usbd_config_attrib_rwup(my_uds_ctx, current_cmd_speed, cfg, rwup);
424 	if (ret) {
425 		shell_error(sh,
426 			    "dev: failed set configuration %u Remote Wakeup to %u",
427 			    cfg, rwup);
428 	} else {
429 		shell_print(sh,
430 			    "dev: set configuration %u Remote Wakeup to %u",
431 			    cfg, rwup);
432 	}
433 
434 	return ret;
435 }
436 
cmd_config_set_rwup(const struct shell * sh,size_t argc,char * argv[])437 static int cmd_config_set_rwup(const struct shell *sh,
438 			       size_t argc, char *argv[])
439 {
440 	return cmd_config_rwup(sh, true, argc, argv);
441 }
442 
cmd_config_clear_rwup(const struct shell * sh,size_t argc,char * argv[])443 static int cmd_config_clear_rwup(const struct shell *sh,
444 				 size_t argc, char *argv[])
445 {
446 	return cmd_config_rwup(sh, false, argc, argv);
447 }
448 
cmd_config_power(const struct shell * sh,size_t argc,char * argv[])449 static int cmd_config_power(const struct shell *sh, size_t argc,
450 			    char *argv[])
451 {
452 	uint16_t power;
453 	uint8_t cfg;
454 	int ret;
455 
456 	cfg = strtol(argv[2], NULL, 10);
457 	power = strtol(argv[3], NULL, 10);
458 
459 	if (power > UINT8_MAX) {
460 		power = UINT8_MAX;
461 		shell_print(sh, "dev: limit bMaxPower value to %u", power);
462 	}
463 
464 	ret = usbd_config_maxpower(my_uds_ctx, current_cmd_speed, cfg, power);
465 	if (ret) {
466 		shell_error(sh,
467 			    "dev: failed to set configuration %u bMaxPower value to %u",
468 			    cfg, power);
469 	} else {
470 		shell_print(sh,
471 			    "dev: set configuration %u bMaxPower value to %u",
472 			    cfg, power);
473 	}
474 
475 	return ret;
476 }
477 
configuration_speed(size_t idx,struct shell_static_entry * entry)478 static void configuration_speed(size_t idx, struct shell_static_entry *entry)
479 {
480 	size_t match_idx = 0;
481 
482 	entry->syntax = NULL;
483 	entry->handler = NULL;
484 	entry->help = NULL;
485 	entry->subcmd = NULL;
486 
487 	for (unsigned int i = 0; i < ARRAY_SIZE(sh_speed); i++) {
488 		if (match_idx == idx) {
489 			entry->syntax = sh_speed[i].name;
490 			current_cmd_speed = sh_speed[i].speed;
491 			break;
492 		}
493 
494 		++match_idx;
495 	}
496 }
497 
498 SHELL_DYNAMIC_CMD_CREATE(dsub_config_speed, configuration_speed);
499 
configuration_lookup(size_t idx,struct shell_static_entry * entry)500 static void configuration_lookup(size_t idx, struct shell_static_entry *entry)
501 {
502 	size_t match_idx = 0;
503 
504 	entry->syntax = NULL;
505 	entry->handler = NULL;
506 	entry->help = NULL;
507 	entry->subcmd = NULL;
508 
509 	for (unsigned int i = 0; i < ARRAY_SIZE(sh_configs); i++) {
510 		if (match_idx == idx) {
511 			entry->syntax = sh_configs[i].name;
512 			break;
513 		}
514 
515 		++match_idx;
516 	}
517 }
518 
519 SHELL_DYNAMIC_CMD_CREATE(dsub_config_name, configuration_lookup);
520 
class_node_name_lookup(size_t idx,struct shell_static_entry * entry)521 static void class_node_name_lookup(size_t idx, struct shell_static_entry *entry)
522 {
523 	size_t match_idx = 0;
524 
525 	entry->syntax = NULL;
526 	entry->handler = NULL;
527 	entry->help = NULL;
528 	entry->subcmd = &dsub_config_speed;
529 
530 	STRUCT_SECTION_FOREACH_ALTERNATE(usbd_class_fs, usbd_class_node, c_nd) {
531 		if ((c_nd->c_data->name != NULL) &&
532 		    (strlen(c_nd->c_data->name) != 0)) {
533 			if (match_idx == idx) {
534 				entry->syntax = c_nd->c_data->name;
535 				break;
536 			}
537 
538 			++match_idx;
539 		}
540 	}
541 }
542 
device_context_lookup(size_t idx,struct shell_static_entry * entry)543 static void device_context_lookup(size_t idx, struct shell_static_entry *entry)
544 {
545 	size_t match_idx = 0;
546 
547 	entry->syntax = NULL;
548 	entry->handler = NULL;
549 	entry->help = NULL;
550 	entry->subcmd = NULL;
551 
552 	STRUCT_SECTION_FOREACH(usbd_context, ctx) {
553 		if ((ctx->name != NULL) && (strlen(ctx->name) != 0)) {
554 			if (match_idx == idx) {
555 				entry->syntax = ctx->name;
556 				break;
557 			}
558 
559 			++match_idx;
560 		}
561 	}
562 }
563 
564 SHELL_DYNAMIC_CMD_CREATE(dsub_node_name, class_node_name_lookup);
565 SHELL_DYNAMIC_CMD_CREATE(dsub_context_name, device_context_lookup);
566 
567 SHELL_STATIC_SUBCMD_SET_CREATE(device_cmds,
568 	SHELL_CMD_ARG(pid, NULL,
569 		      "<idProduct> sets device Product ID",
570 		      cmd_device_pid, 2, 0),
571 	SHELL_CMD_ARG(vid, NULL,
572 		      "<idVendor> sets device Vendor ID",
573 		      cmd_device_vid, 2, 0),
574 	SHELL_CMD_ARG(bcd_usb, &dsub_config_speed,
575 		      "<speed> <bcdUSB> sets device USB specification version",
576 		      cmd_device_bcd_usb, 3, 0),
577 	SHELL_CMD_ARG(triple, &dsub_config_speed,
578 		      "<speed> <Base Class> <SubClass> <Protocol> sets device code triple",
579 		      cmd_device_code_triple, 5, 0),
580 	SHELL_SUBCMD_SET_END
581 );
582 
583 SHELL_STATIC_SUBCMD_SET_CREATE(config_cmds,
584 	SHELL_CMD_ARG(add, &dsub_config_name,
585 		      "<configuration name> adds one of the pre-defined configurations",
586 		      cmd_config_add, 2, 0),
587 	SHELL_CMD_ARG(power, &dsub_config_speed,
588 		      "<speed> <configuration value> <bMaxPower> sets the bMaxPower",
589 		      cmd_config_power, 4, 0),
590 	SHELL_CMD_ARG(set-rwup, &dsub_config_speed,
591 		      "<speed> <configuration value> sets Remote Wakeup bit",
592 		      cmd_config_set_rwup, 3, 0),
593 	SHELL_CMD_ARG(clear-rwup, &dsub_config_speed,
594 		      "<speed> <configuration value> clears Remote Wakeup bit",
595 		      cmd_config_clear_rwup, 3, 0),
596 	SHELL_CMD_ARG(selfpowered, &dsub_config_speed,
597 		      "<speed> <configuration value> sets Self-power bit",
598 		      cmd_config_selfpowered, 3, 0),
599 	SHELL_CMD_ARG(buspowered, &dsub_config_speed,
600 		      "<speed> <configuration value> clears Self-power bit",
601 		      cmd_config_buspowered, 3, 0),
602 	SHELL_SUBCMD_SET_END
603 );
604 
605 SHELL_STATIC_SUBCMD_SET_CREATE(class_cmds,
606 	SHELL_CMD_ARG(register, &dsub_node_name,
607 		      "<name> <speed> <configuration value> registers class instance",
608 		      cmd_register, 4, 0),
609 	SHELL_CMD_ARG(unregister, &dsub_node_name,
610 		      "<name> <speed> <configuration value> unregisters class instance",
611 		      cmd_unregister, 4, 0),
612 	SHELL_SUBCMD_SET_END
613 );
614 
615 SHELL_STATIC_SUBCMD_SET_CREATE(sub_usbd_cmds,
616 	SHELL_CMD_ARG(defstr, NULL,
617 		      "[none] adds default string descriptors",
618 		      cmd_usbd_default_strings, 1, 0),
619 	SHELL_CMD_ARG(defcfg, NULL,
620 		      "[none] initializes default configuration with all available classes",
621 		      cmd_usbd_default_config, 1, 0),
622 	SHELL_CMD_ARG(init, NULL,
623 		      "[none] initializes USB device support",
624 		      cmd_usbd_init, 1, 0),
625 	SHELL_CMD_ARG(enable, NULL,
626 		      "[none] enables USB device support]",
627 		      cmd_usbd_enable, 1, 0),
628 	SHELL_CMD_ARG(disable, NULL,
629 		      "[none] disables USB device support",
630 		      cmd_usbd_disable, 1, 0),
631 	SHELL_CMD_ARG(shutdown, NULL,
632 		      "[none] shutdown USB device support",
633 		      cmd_usbd_shutdown, 1, 0),
634 	SHELL_CMD_ARG(select, &dsub_context_name,
635 		      "<USB device context name> selects context used by the shell",
636 		      cmd_select, 2, 0),
637 	SHELL_CMD_ARG(device, &device_cmds,
638 		      "device commands",
639 		      NULL, 1, 0),
640 	SHELL_CMD_ARG(config, &config_cmds,
641 		      "configuration commands",
642 		      NULL, 1, 0),
643 	SHELL_CMD_ARG(class, &class_cmds,
644 		      "class commands",
645 		      NULL, 1, 0),
646 	SHELL_CMD_ARG(wakeup, NULL,
647 		      "[none] signals remote wakeup",
648 		      cmd_wakeup_request, 1, 0),
649 	SHELL_SUBCMD_SET_END
650 );
651 
652 SHELL_CMD_REGISTER(usbd, &sub_usbd_cmds, "USB device support commands", NULL);
653