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 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 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 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 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 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 89 int test_null(usb_handle *usb) 90 { 91 int 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(usb, buf, arg_size) != 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 108 int test_zero(usb_handle *usb) 109 { 110 int 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(usb, buf, arg_size) != 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)(usb_handle *usb); 131 const char *help; 132 } tests[] = { 133 { "list", printifc, 0, "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, 0, "exercise loopback interface" }, 137 {}, 138 }; 139 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 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 178 int main(int argc, char **argv) 179 { 180 usb_handle *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