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