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