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