1 /*-
2 * Copyright (c) 2010-2022 Hans Petter Selasky
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26 #include <stdio.h>
27 #include <stdint.h>
28 #include <err.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <stdarg.h>
32 #include <stdlib.h>
33
34 #include <capsicum_helpers.h>
35
36 #include <sys/types.h>
37 #include <sys/sysctl.h>
38
39 #include <libusb20.h>
40
41 #include <dev/usb/usb_ioctl.h>
42
43 #include "usbtest.h"
44
45 #include <g_keyboard.h>
46 #include <g_mouse.h>
47 #include <g_modem.h>
48 #include <g_audio.h>
49
50 static uint8_t usb_ts_select[USB_TS_MAX_LEVELS];
51
52 struct libusb20_be_ctx *usb_be_ctx;
53
54 const char *indent[USB_TS_MAX_LEVELS] = {
55 " ",
56 " ",
57 " ",
58 " ",
59 " ",
60 " ",
61 " ",
62 " ",
63 };
64
65 /* a perceptual white noise generator (after HPS' invention) */
66
67 int32_t
usb_ts_rand_noise(void)68 usb_ts_rand_noise(void)
69 {
70 uint32_t temp;
71 const uint32_t prime = 0xFFFF1D;
72 static uint32_t noise_rem = 1;
73
74 if (noise_rem & 1) {
75 noise_rem += prime;
76 }
77 noise_rem /= 2;
78
79 temp = noise_rem;
80
81 /* unsigned to signed conversion */
82
83 temp ^= 0x800000;
84 if (temp & 0x800000) {
85 temp |= (-0x800000);
86 }
87 return temp;
88 }
89
90 uint8_t
usb_ts_show_menu(uint8_t level,const char * title,const char * fmt,...)91 usb_ts_show_menu(uint8_t level, const char *title, const char *fmt,...)
92 {
93 va_list args;
94 uint8_t x;
95 uint8_t retval;
96 char *pstr;
97 char buf[16];
98 char menu[80 * 20];
99
100 va_start(args, fmt);
101 vsnprintf(menu, sizeof(menu), fmt, args);
102 va_end(args);
103
104 printf("[");
105
106 for (x = 0; x != level; x++) {
107 if ((x + 1) == level)
108 printf("%d", usb_ts_select[x]);
109 else
110 printf("%d.", usb_ts_select[x]);
111 }
112
113 printf("] - %s:\n\n", title);
114
115 x = 1;
116 for (pstr = menu; *pstr; pstr++) {
117 if (x != 0) {
118 printf("%s", indent[level]);
119 x = 0;
120 }
121 printf("%c", *pstr);
122
123 if (*pstr == '\n')
124 x = 1;
125 }
126
127 printf("\n>");
128
129 if (fgets(buf, sizeof(buf), stdin) == NULL)
130 err(1, "Cannot read input");
131
132 if (buf[0] == 'x')
133 retval = 255;
134 else
135 retval = atoi(buf);
136
137 usb_ts_select[level] = retval;
138
139 return (retval);
140 }
141
142 void
get_string(char * ptr,int size)143 get_string(char *ptr, int size)
144 {
145 printf("\nEnter string>");
146
147 if (fgets(ptr, size, stdin) == NULL)
148 err(1, "Cannot read input");
149
150 ptr[size - 1] = 0;
151
152 size = strlen(ptr);
153
154 /* strip trailing newline, if any */
155 if (size == 0)
156 return;
157 else if (ptr[size - 1] == '\n')
158 ptr[size - 1] = 0;
159 }
160
161 int
get_integer(void)162 get_integer(void)
163 {
164 char buf[32];
165
166 printf("\nEnter integer value>");
167
168 if (fgets(buf, sizeof(buf), stdin) == NULL)
169 err(1, "Cannot read input");
170
171 if (strcmp(buf, "x\n") == 0)
172 return (-1);
173 if (strcmp(buf, "r\n") == 0)
174 return (-2);
175
176 return ((int)strtol(buf, 0, 0));
177 }
178
179 static void
set_template(int template)180 set_template(int template)
181 {
182 int error;
183
184 error = sysctlbyname("hw.usb.template", NULL, NULL,
185 &template, sizeof(template));
186
187 if (error != 0) {
188 printf("WARNING: Could not set USB template "
189 "to %d (error=%d)\n", template, errno);
190 }
191 }
192
193 static void
show_default_audio_select(uint8_t level)194 show_default_audio_select(uint8_t level)
195 {
196 int error;
197 int retval;
198 int mode = 0;
199 int pattern_interval = 128;
200 int throughput = 0;
201 size_t len;
202 char pattern[G_AUDIO_MAX_STRLEN] = {"0123456789abcdef"};
203
204 set_template(USB_TEMP_AUDIO);
205
206 while (1) {
207
208 error = sysctlbyname("hw.usb.g_audio.mode", NULL, NULL,
209 &mode, sizeof(mode));
210
211 if (error != 0) {
212 printf("WARNING: Could not set audio mode "
213 "to %d (error=%d)\n", mode, errno);
214 }
215 error = sysctlbyname("hw.usb.g_audio.pattern_interval", NULL, NULL,
216 &pattern_interval, sizeof(pattern_interval));
217
218 if (error != 0) {
219 printf("WARNING: Could not set pattern interval "
220 "to %d (error=%d)\n", pattern_interval, errno);
221 }
222 len = sizeof(throughput);
223
224 error = sysctlbyname("hw.usb.g_audio.throughput",
225 &throughput, &len, 0, 0);
226
227 if (error != 0) {
228 printf("WARNING: Could not get throughput "
229 "(error=%d)\n", errno);
230 }
231 error = sysctlbyname("hw.usb.g_audio.pattern", NULL, NULL,
232 &pattern, strlen(pattern));
233
234 if (error != 0) {
235 printf("WARNING: Could not set audio pattern "
236 "to '%s' (error=%d)\n", pattern, errno);
237 }
238 retval = usb_ts_show_menu(level, "Default Audio Settings",
239 "1) Set Silent mode %s\n"
240 "2) Set Dump mode %s\n"
241 "3) Set Loop mode %s\n"
242 "4) Set Pattern mode %s\n"
243 "5) Change DTMF pattern: '%s'\n"
244 "6) Change pattern advance interval: %d ms\n"
245 "x) Return to previous menu\n"
246 "s: Ready for enumeration\n"
247 "t: Throughput: %d bytes/second\n",
248 (mode == G_AUDIO_MODE_SILENT) ? "(selected)" : "",
249 (mode == G_AUDIO_MODE_DUMP) ? "(selected)" : "",
250 (mode == G_AUDIO_MODE_LOOP) ? "(selected)" : "",
251 (mode == G_AUDIO_MODE_PATTERN) ? "(selected)" : "",
252 pattern, pattern_interval, throughput);
253
254 switch (retval) {
255 case 0:
256 break;
257 case 1:
258 mode = G_AUDIO_MODE_SILENT;
259 break;
260 case 2:
261 mode = G_AUDIO_MODE_DUMP;
262 break;
263 case 3:
264 mode = G_AUDIO_MODE_LOOP;
265 break;
266 case 4:
267 mode = G_AUDIO_MODE_PATTERN;
268 break;
269 case 5:
270 get_string(pattern, sizeof(pattern));
271 break;
272 case 6:
273 pattern_interval = get_integer();
274 break;
275 default:
276 return;
277 }
278 }
279 }
280
281 static void
show_device_audio_select(uint8_t level)282 show_device_audio_select(uint8_t level)
283 {
284 uint8_t retval;
285
286 while (1) {
287
288 retval = usb_ts_show_menu(level, "Select Audio Device Model",
289 "1) Generic Audio Device\n"
290 "x) Return to previous menu\n");
291
292 switch (retval) {
293 case 0:
294 break;
295 case 1:
296 show_default_audio_select(level + 1);
297 break;
298 default:
299 return;
300 }
301 }
302 }
303
304 static void
show_device_msc_select(uint8_t level)305 show_device_msc_select(uint8_t level)
306 {
307 set_template(USB_TEMP_MSC);
308 }
309
310 static void
show_device_ethernet_select(uint8_t level)311 show_device_ethernet_select(uint8_t level)
312 {
313 set_template(USB_TEMP_CDCE);
314 }
315
316 static void
show_default_keyboard_select(uint8_t level)317 show_default_keyboard_select(uint8_t level)
318 {
319 int error;
320 int retval;
321 int mode = 0;
322 int interval = 1023;
323 char pattern[G_KEYBOARD_MAX_STRLEN] = {"abcdefpattern"};
324
325 set_template(USB_TEMP_KBD);
326
327 while (1) {
328
329 error = sysctlbyname("hw.usb.g_keyboard.mode", NULL, NULL,
330 &mode, sizeof(mode));
331
332 if (error != 0) {
333 printf("WARNING: Could not set keyboard mode "
334 " to %d (error=%d) \n", mode, errno);
335 }
336 error = sysctlbyname("hw.usb.g_keyboard.key_press_interval", NULL, NULL,
337 &interval, sizeof(interval));
338
339 if (error != 0) {
340 printf("WARNING: Could not set key press interval "
341 "to %d (error=%d)\n", interval, errno);
342 }
343 error = sysctlbyname("hw.usb.g_keyboard.key_press_pattern", NULL, NULL,
344 &pattern, strlen(pattern));
345
346 if (error != 0) {
347 printf("WARNING: Could not set key pattern "
348 "to '%s' (error=%d)\n", pattern, errno);
349 }
350 retval = usb_ts_show_menu(level, "Default Keyboard Settings",
351 "1) Set silent mode %s\n"
352 "2) Set pattern mode %s\n"
353 "3) Change pattern: '%s'\n"
354 "4) Change key press interval: %d ms\n"
355 "x) Return to previous menu\n"
356 "s: Ready for enumeration\n",
357 (mode == G_KEYBOARD_MODE_SILENT) ? "(selected)" : "",
358 (mode == G_KEYBOARD_MODE_PATTERN) ? "(selected)" : "",
359 pattern, interval);
360
361 switch (retval) {
362 case 0:
363 break;
364 case 1:
365 mode = G_KEYBOARD_MODE_SILENT;
366 break;
367 case 2:
368 mode = G_KEYBOARD_MODE_PATTERN;
369 break;
370 case 3:
371 get_string(pattern, sizeof(pattern));
372 break;
373 case 4:
374 interval = get_integer();
375 break;
376 default:
377 return;
378 }
379 }
380 }
381
382 static void
show_device_keyboard_select(uint8_t level)383 show_device_keyboard_select(uint8_t level)
384 {
385 uint8_t retval;
386
387 while (1) {
388
389 retval = usb_ts_show_menu(level, "Select Keyboard Model",
390 "1) Generic Keyboard \n"
391 "x) Return to previous menu \n");
392
393 switch (retval) {
394 case 0:
395 break;
396 case 1:
397 show_default_keyboard_select(level + 1);
398 break;
399 default:
400 return;
401 }
402 }
403 }
404
405 static void
show_default_mouse_select(uint8_t level)406 show_default_mouse_select(uint8_t level)
407 {
408 int error;
409 int retval;
410 int mode = 0;
411 int cursor_interval = 128;
412 int cursor_radius = 75;
413 int button_interval = 0;
414
415 set_template(USB_TEMP_MOUSE);
416
417 while (1) {
418
419 error = sysctlbyname("hw.usb.g_mouse.mode", NULL, NULL,
420 &mode, sizeof(mode));
421
422 if (error != 0) {
423 printf("WARNING: Could not set mouse mode "
424 "to %d (error=%d)\n", mode, errno);
425 }
426 error = sysctlbyname("hw.usb.g_mouse.cursor_update_interval", NULL, NULL,
427 &cursor_interval, sizeof(cursor_interval));
428
429 if (error != 0) {
430 printf("WARNING: Could not set cursor update interval "
431 "to %d (error=%d)\n", cursor_interval, errno);
432 }
433 error = sysctlbyname("hw.usb.g_mouse.button_press_interval", NULL, NULL,
434 &button_interval, sizeof(button_interval));
435
436 if (error != 0) {
437 printf("WARNING: Could not set button press interval "
438 "to %d (error=%d)\n", button_interval, errno);
439 }
440 error = sysctlbyname("hw.usb.g_mouse.cursor_radius", NULL, NULL,
441 &cursor_radius, sizeof(cursor_radius));
442
443 if (error != 0) {
444 printf("WARNING: Could not set cursor radius "
445 "to %d (error=%d)\n", cursor_radius, errno);
446 }
447 retval = usb_ts_show_menu(level, "Default Mouse Settings",
448 "1) Set Silent mode %s\n"
449 "2) Set Circle mode %s\n"
450 "3) Set Square mode %s\n"
451 "4) Set Spiral mode %s\n"
452 "5) Change cursor radius: %d pixels\n"
453 "6) Change cursor update interval: %d ms\n"
454 "7) Change button[0] press interval: %d ms\n"
455 "x) Return to previous menu\n"
456 "s: Ready for enumeration\n",
457 (mode == G_MOUSE_MODE_SILENT) ? "(selected)" : "",
458 (mode == G_MOUSE_MODE_CIRCLE) ? "(selected)" : "",
459 (mode == G_MOUSE_MODE_BOX) ? "(selected)" : "",
460 (mode == G_MOUSE_MODE_SPIRAL) ? "(selected)" : "",
461 cursor_radius, cursor_interval, button_interval);
462
463 switch (retval) {
464 case 0:
465 break;
466 case 1:
467 mode = G_MOUSE_MODE_SILENT;
468 break;
469 case 2:
470 mode = G_MOUSE_MODE_CIRCLE;
471 break;
472 case 3:
473 mode = G_MOUSE_MODE_BOX;
474 break;
475 case 4:
476 mode = G_MOUSE_MODE_SPIRAL;
477 break;
478 case 5:
479 cursor_radius = get_integer();
480 break;
481 case 6:
482 cursor_interval = get_integer();
483 break;
484 case 7:
485 button_interval = get_integer();
486 break;
487 default:
488 return;
489 }
490 }
491 }
492
493 static void
show_device_mouse_select(uint8_t level)494 show_device_mouse_select(uint8_t level)
495 {
496 uint8_t retval;
497
498 while (1) {
499
500 retval = usb_ts_show_menu(level, "Select Mouse Model",
501 "1) Generic Mouse\n"
502 "x) Return to previous menu\n");
503
504 switch (retval) {
505 case 0:
506 break;
507 case 1:
508 show_default_mouse_select(level + 1);
509 break;
510 default:
511 return;
512 }
513 }
514 }
515
516 static void
show_device_mtp_select(uint8_t level)517 show_device_mtp_select(uint8_t level)
518 {
519 set_template(USB_TEMP_MTP);
520 }
521
522 static void
show_default_modem_select(uint8_t level)523 show_default_modem_select(uint8_t level)
524 {
525 int error;
526 int retval;
527 int mode = 0;
528 int pattern_interval = 128;
529 int throughput = 0;
530 size_t len;
531 char pattern[G_MODEM_MAX_STRLEN] = {"abcdefpattern"};
532
533 set_template(USB_TEMP_MODEM);
534
535 while (1) {
536
537 error = sysctlbyname("hw.usb.g_modem.mode", NULL, NULL,
538 &mode, sizeof(mode));
539
540 if (error != 0) {
541 printf("WARNING: Could not set modem mode "
542 "to %d (error=%d)\n", mode, errno);
543 }
544 error = sysctlbyname("hw.usb.g_modem.pattern_interval", NULL, NULL,
545 &pattern_interval, sizeof(pattern_interval));
546
547 if (error != 0) {
548 printf("WARNING: Could not set pattern interval "
549 "to %d (error=%d)\n", pattern_interval, errno);
550 }
551 len = sizeof(throughput);
552
553 error = sysctlbyname("hw.usb.g_modem.throughput",
554 &throughput, &len, 0, 0);
555
556 if (error != 0) {
557 printf("WARNING: Could not get throughput "
558 "(error=%d)\n", errno);
559 }
560 error = sysctlbyname("hw.usb.g_modem.pattern", NULL, NULL,
561 &pattern, strlen(pattern));
562
563 if (error != 0) {
564 printf("WARNING: Could not set modem pattern "
565 "to '%s' (error=%d)\n", pattern, errno);
566 }
567 retval = usb_ts_show_menu(level, "Default Modem Settings",
568 "1) Set Silent mode %s\n"
569 "2) Set Dump mode %s\n"
570 "3) Set Loop mode %s\n"
571 "4) Set Pattern mode %s\n"
572 "5) Change test pattern: '%s'\n"
573 "6) Change data transmit interval: %d ms\n"
574 "x) Return to previous menu\n"
575 "s: Ready for enumeration\n"
576 "t: Throughput: %d bytes/second\n",
577 (mode == G_MODEM_MODE_SILENT) ? "(selected)" : "",
578 (mode == G_MODEM_MODE_DUMP) ? "(selected)" : "",
579 (mode == G_MODEM_MODE_LOOP) ? "(selected)" : "",
580 (mode == G_MODEM_MODE_PATTERN) ? "(selected)" : "",
581 pattern, pattern_interval, throughput);
582
583 switch (retval) {
584 case 0:
585 break;
586 case 1:
587 mode = G_MODEM_MODE_SILENT;
588 break;
589 case 2:
590 mode = G_MODEM_MODE_DUMP;
591 break;
592 case 3:
593 mode = G_MODEM_MODE_LOOP;
594 break;
595 case 4:
596 mode = G_MODEM_MODE_PATTERN;
597 break;
598 case 5:
599 get_string(pattern, sizeof(pattern));
600 break;
601 case 6:
602 pattern_interval = get_integer();
603 break;
604 default:
605 return;
606 }
607 }
608 }
609
610 static void
show_device_modem_select(uint8_t level)611 show_device_modem_select(uint8_t level)
612 {
613 uint8_t retval;
614
615 while (1) {
616
617 retval = usb_ts_show_menu(level, "Select Modem Model",
618 "1) Generic Modem\n"
619 "x) Return to previous menu\n");
620
621 switch (retval) {
622 case 0:
623 break;
624 case 1:
625 show_default_modem_select(level + 1);
626 break;
627 default:
628 return;
629 }
630 }
631 }
632
633 static void
show_device_generic_select(uint8_t level)634 show_device_generic_select(uint8_t level)
635 {
636 }
637
638 static void
show_device_select(uint8_t level)639 show_device_select(uint8_t level)
640 {
641 uint8_t retval;
642
643 while (1) {
644
645 retval = usb_ts_show_menu(level, "Select Device Mode Test Group",
646 "1) Audio (UAUDIO)\n"
647 "2) Mass Storage (MSC)\n"
648 "3) Ethernet (CDCE)\n"
649 "4) Keyboard Input Device (UKBD)\n"
650 "5) Mouse Input Device (UMS)\n"
651 "6) Message Transfer Protocol (MTP)\n"
652 "7) Modem (CDC)\n"
653 "8) Generic Endpoint Loopback (GENERIC)\n"
654 "x) Return to previous menu\n");
655
656 switch (retval) {
657 case 0:
658 break;
659 case 1:
660 show_device_audio_select(level + 1);
661 break;
662 case 2:
663 show_device_msc_select(level + 1);
664 break;
665 case 3:
666 show_device_ethernet_select(level + 1);
667 break;
668 case 4:
669 show_device_keyboard_select(level + 1);
670 break;
671 case 5:
672 show_device_mouse_select(level + 1);
673 break;
674 case 6:
675 show_device_mtp_select(level + 1);
676 break;
677 case 7:
678 show_device_modem_select(level + 1);
679 break;
680 case 8:
681 show_device_generic_select(level + 1);
682 break;
683 default:
684 return;
685 }
686 }
687 }
688
689 static void
show_host_select(uint8_t level)690 show_host_select(uint8_t level)
691 {
692 int force_fs = 0;
693 int error;
694 uint32_t duration = 60;
695
696 struct uaddr uaddr = {};
697
698 uint8_t retval;
699
700 while (1) {
701
702 error = sysctlbyname("hw.usb.ehci.no_hs", NULL, NULL,
703 &force_fs, sizeof(force_fs));
704
705 if (error != 0) {
706 printf("WARNING: Could not set non-FS mode "
707 "to %d (error=%d)\n", force_fs, errno);
708 }
709 retval = usb_ts_show_menu(level, "Select Host Mode Test (via LibUSB)",
710 " 1) Select USB device (VID=0x%04x, PID=0x%04x, ugen%u.%u)\n"
711 " 2) Manually enter USB vendor and product ID\n"
712 " 3) Force FULL speed operation: <%s>\n"
713 " 4) Mass Storage (UMASS)\n"
714 " 5) Modem (UMODEM)\n"
715 "10) Start String Descriptor Test\n"
716 "11) Start Port Reset Test\n"
717 "12) Start Set Config Test\n"
718 "13) Start Get Descriptor Test\n"
719 "14) Start Suspend and Resume Test\n"
720 "15) Start Set and Clear Endpoint Stall Test\n"
721 "16) Start Set Alternate Interface Setting Test\n"
722 "17) Start Invalid Control Request Test\n"
723 "30) Duration: <%d> seconds\n"
724 "x) Return to previous menu\n",
725 uaddr.vid, uaddr.pid, uaddr.bus, uaddr.addr,
726 force_fs ? "YES" : "NO",
727 (int)duration);
728
729 switch (retval) {
730 case 0:
731 break;
732 case 1:
733 show_host_device_selection(level + 1, &uaddr);
734 break;
735 case 2:
736 /* only match VID and PID */
737 uaddr.vid = get_integer() & 0xFFFF;
738 uaddr.pid = get_integer() & 0xFFFF;
739 uaddr.bus = 0;
740 uaddr.addr = 0;
741 break;
742 case 3:
743 force_fs ^= 1;
744 break;
745 case 4:
746 show_host_msc_test(level + 1, uaddr, duration);
747 break;
748 case 5:
749 show_host_modem_test(level + 1, uaddr, duration);
750 break;
751 case 10:
752 usb_get_string_desc_test(uaddr);
753 break;
754 case 11:
755 usb_port_reset_test(uaddr, duration);
756 break;
757 case 12:
758 usb_set_config_test(uaddr, duration);
759 break;
760 case 13:
761 usb_get_descriptor_test(uaddr, duration);
762 break;
763 case 14:
764 usb_suspend_resume_test(uaddr, duration);
765 break;
766 case 15:
767 usb_set_and_clear_stall_test(uaddr);
768 break;
769 case 16:
770 usb_set_alt_interface_test(uaddr);
771 break;
772 case 17:
773 usb_control_ep_error_test(uaddr);
774 break;
775 case 30:
776 duration = get_integer();
777 break;
778 default:
779 return;
780 }
781 }
782 }
783
784 static void
show_mode_select(uint8_t level)785 show_mode_select(uint8_t level)
786 {
787 uint8_t retval;
788
789 while (1) {
790
791 retval = usb_ts_show_menu(level, "Select Computer Mode",
792 "1) This computer is Running the Device Side\n"
793 "2) This computer is Running the Host Side\n"
794 "x) Return to previous menu\n");
795
796 switch (retval) {
797 case 0:
798 break;
799 case 1:
800 show_device_select(level + 1);
801 break;
802 case 2:
803 show_host_select(level + 1);
804 break;
805 default:
806 return;
807 }
808 }
809 }
810
811 int
main(int argc,char ** argv)812 main(int argc, char **argv)
813 {
814 /*
815 * The backend context acquires the descriptors needed to
816 * reach the USB devices before entering capability mode.
817 */
818 usb_be_ctx = libusb20_be_ctx_alloc();
819 if (usb_be_ctx == NULL)
820 err(1, "could not allocate USB backend context");
821
822 if (caph_enter() < 0)
823 err(1, "caph_enter() failed");
824
825 show_mode_select(1);
826
827 libusb20_be_ctx_free(usb_be_ctx);
828
829 return (0);
830 }
831