1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  * 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  *  * Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *  * Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in
12  *    the documentation and/or other materials provided with the
13  *    distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <errno.h>
33 
34 #include <sys/time.h>
35 
36 #include "usb.h"
37 
38 static unsigned arg_size = 4096;
39 static unsigned arg_count = 4096;
40 
NOW(void)41 long long NOW(void)
42 {
43     struct timeval tv;
44     gettimeofday(&tv, 0);
45 
46     return (((long long) tv.tv_sec) * ((long long) 1000000)) +
47         (((long long) tv.tv_usec));
48 }
49 
printifc(usb_ifc_info * info)50 int printifc(usb_ifc_info *info)
51 {
52     printf("dev: csp=%02x/%02x/%02x v=%04x p=%04x  ",
53            info->dev_class, info->dev_subclass, info->dev_protocol,
54            info->dev_vendor, info->dev_product);
55     printf("ifc: csp=%02x/%02x/%02x%s%s\n",
56            info->ifc_class, info->ifc_subclass, info->ifc_protocol,
57            info->has_bulk_in ? " in" : "",
58            info->has_bulk_out ? " out" : "");
59     return -1;
60 }
61 
match_null(usb_ifc_info * info)62 int match_null(usb_ifc_info *info)
63 {
64     if(info->dev_vendor != 0x18d1) return -1;
65     if(info->ifc_class != 0xff) return -1;
66     if(info->ifc_subclass != 0xfe) return -1;
67     if(info->ifc_protocol != 0x01) return -1;
68     return 0;
69 }
70 
match_zero(usb_ifc_info * info)71 int match_zero(usb_ifc_info *info)
72 {
73     if(info->dev_vendor != 0x18d1) return -1;
74     if(info->ifc_class != 0xff) return -1;
75     if(info->ifc_subclass != 0xfe) return -1;
76     if(info->ifc_protocol != 0x02) return -1;
77     return 0;
78 }
79 
match_loop(usb_ifc_info * info)80 int match_loop(usb_ifc_info *info)
81 {
82     if(info->dev_vendor != 0x18d1) return -1;
83     if(info->ifc_class != 0xff) return -1;
84     if(info->ifc_subclass != 0xfe) return -1;
85     if(info->ifc_protocol != 0x03) return -1;
86     return 0;
87 }
88 
test_null(Transport * usb)89 int test_null(Transport* usb)
90 {
91     unsigned i;
92     unsigned char buf[4096];
93     memset(buf, 0xee, 4096);
94     long long t0, t1;
95 
96     t0 = NOW();
97     for (i = 0; i < arg_count; i++) {
98         if (usb->Write(buf, arg_size) != static_cast<int>(arg_size)) {
99             fprintf(stderr,"write failed (%s)\n", strerror(errno));
100             return -1;
101         }
102     }
103     t1 = NOW();
104     fprintf(stderr,"%d bytes in %lld uS\n", arg_count * arg_size, (t1 - t0));
105     return 0;
106 }
107 
test_zero(Transport * usb)108 int test_zero(Transport* usb)
109 {
110     unsigned i;
111     unsigned char buf[4096];
112     long long t0, t1;
113 
114     t0 = NOW();
115     for (i = 0; i < arg_count; i++) {
116         if (usb->Read(buf, arg_size) != static_cast<int>(arg_size)) {
117             fprintf(stderr,"read failed (%s)\n", strerror(errno));
118             return -1;
119         }
120     }
121     t1 = NOW();
122     fprintf(stderr,"%d bytes in %lld uS\n", arg_count * arg_size, (t1 - t0));
123     return 0;
124 }
125 
126 struct
127 {
128     const char *cmd;
129     ifc_match_func match;
130     int (*test)(Transport* usb);
131     const char *help;
132 } tests[] = {
133     { "list", printifc,   NULL,      "list interfaces" },
134     { "send", match_null, test_null, "send to null interface" },
135     { "recv", match_zero, test_zero, "recv from zero interface" },
136     { "loop", match_loop, NULL,      "exercise loopback interface" },
137     { NULL, NULL, NULL, NULL },
138 };
139 
usage(void)140 int usage(void)
141 {
142     int i;
143 
144     fprintf(stderr,"usage: usbtest <testname>\n\navailable tests:\n");
145     for(i = 0; tests[i].cmd; i++) {
146         fprintf(stderr," %-8s %s\n", tests[i].cmd, tests[i].help);
147     }
148     return -1;
149 }
150 
process_args(int argc,char ** argv)151 int process_args(int argc, char **argv)
152 {
153     while(argc-- > 0) {
154         char *arg = *argv++;
155         if(!strncmp(arg,"count=",6)) {
156             arg_count = atoi(arg + 6);
157         } else if(!strncmp(arg,"size=",5)) {
158             arg_size = atoi(arg + 5);
159         } else {
160             fprintf(stderr,"unknown argument: %s\n", arg);
161             return -1;
162         }
163     }
164 
165     if(arg_count == 0) {
166         fprintf(stderr,"count may not be zero\n");
167         return -1;
168     }
169 
170     if(arg_size > 4096) {
171         fprintf(stderr,"size may not be greater than 4096\n");
172         return -1;
173     }
174 
175     return 0;
176 }
177 
main(int argc,char ** argv)178 int main(int argc, char **argv)
179 {
180     Transport* usb;
181     int i;
182 
183     if(argc < 2)
184         return usage();
185 
186     if(argc > 2) {
187         if(process_args(argc - 2, argv + 2))
188             return -1;
189     }
190 
191     for(i = 0; tests[i].cmd; i++) {
192         if(!strcmp(argv[1], tests[i].cmd)) {
193             usb = usb_open(tests[i].match);
194             if(tests[i].test) {
195                 if(usb == 0) {
196                     fprintf(stderr,"usbtest: %s: could not find interface\n",
197                             tests[i].cmd);
198                     return -1;
199                 }
200                 if(tests[i].test(usb)) {
201                     fprintf(stderr,"usbtest: %s: FAIL\n", tests[i].cmd);
202                     return -1;
203                 } else {
204                     fprintf(stderr,"usbtest: %s: OKAY\n", tests[i].cmd);
205                 }
206             }
207             return 0;
208         }
209     }
210 
211     return usage();
212 }
213