0b15663830
(Second upload of this CL; original upload had the wrong version of usb_windows.cpp that caused a compilation error. Fixed error and re-tested.) This CL creates a Transport object to provide a generic interface for various transports. Specifically this is designed to be able to add UDP support to fastboot in an upcoming CL without changing the main program logic. Also includes some minor code style fixes and replaces malloc/free in the USB implementation files with smart pointers and std::string. Bug: http://b/22029765 Change-Id: I1175bbce08690fbd15f51e68166be9b3e9973ea0
212 lines
5.8 KiB
C++
212 lines
5.8 KiB
C++
/*
|
|
* Copyright (C) 2008 The Android Open Source Project
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in
|
|
* the documentation and/or other materials provided with the
|
|
* distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include "usb.h"
|
|
|
|
static unsigned arg_size = 4096;
|
|
static unsigned arg_count = 4096;
|
|
|
|
long long NOW(void)
|
|
{
|
|
struct timeval tv;
|
|
gettimeofday(&tv, 0);
|
|
|
|
return (((long long) tv.tv_sec) * ((long long) 1000000)) +
|
|
(((long long) tv.tv_usec));
|
|
}
|
|
|
|
int printifc(usb_ifc_info *info)
|
|
{
|
|
printf("dev: csp=%02x/%02x/%02x v=%04x p=%04x ",
|
|
info->dev_class, info->dev_subclass, info->dev_protocol,
|
|
info->dev_vendor, info->dev_product);
|
|
printf("ifc: csp=%02x/%02x/%02x%s%s\n",
|
|
info->ifc_class, info->ifc_subclass, info->ifc_protocol,
|
|
info->has_bulk_in ? " in" : "",
|
|
info->has_bulk_out ? " out" : "");
|
|
return -1;
|
|
}
|
|
|
|
int match_null(usb_ifc_info *info)
|
|
{
|
|
if(info->dev_vendor != 0x18d1) return -1;
|
|
if(info->ifc_class != 0xff) return -1;
|
|
if(info->ifc_subclass != 0xfe) return -1;
|
|
if(info->ifc_protocol != 0x01) return -1;
|
|
return 0;
|
|
}
|
|
|
|
int match_zero(usb_ifc_info *info)
|
|
{
|
|
if(info->dev_vendor != 0x18d1) return -1;
|
|
if(info->ifc_class != 0xff) return -1;
|
|
if(info->ifc_subclass != 0xfe) return -1;
|
|
if(info->ifc_protocol != 0x02) return -1;
|
|
return 0;
|
|
}
|
|
|
|
int match_loop(usb_ifc_info *info)
|
|
{
|
|
if(info->dev_vendor != 0x18d1) return -1;
|
|
if(info->ifc_class != 0xff) return -1;
|
|
if(info->ifc_subclass != 0xfe) return -1;
|
|
if(info->ifc_protocol != 0x03) return -1;
|
|
return 0;
|
|
}
|
|
|
|
int test_null(Transport* usb)
|
|
{
|
|
unsigned i;
|
|
unsigned char buf[4096];
|
|
memset(buf, 0xee, 4096);
|
|
long long t0, t1;
|
|
|
|
t0 = NOW();
|
|
for (i = 0; i < arg_count; i++) {
|
|
if (usb->Write(buf, arg_size) != static_cast<int>(arg_size)) {
|
|
fprintf(stderr,"write failed (%s)\n", strerror(errno));
|
|
return -1;
|
|
}
|
|
}
|
|
t1 = NOW();
|
|
fprintf(stderr,"%d bytes in %lld uS\n", arg_count * arg_size, (t1 - t0));
|
|
return 0;
|
|
}
|
|
|
|
int test_zero(Transport* usb)
|
|
{
|
|
unsigned i;
|
|
unsigned char buf[4096];
|
|
long long t0, t1;
|
|
|
|
t0 = NOW();
|
|
for (i = 0; i < arg_count; i++) {
|
|
if (usb->Read(buf, arg_size) != static_cast<int>(arg_size)) {
|
|
fprintf(stderr,"read failed (%s)\n", strerror(errno));
|
|
return -1;
|
|
}
|
|
}
|
|
t1 = NOW();
|
|
fprintf(stderr,"%d bytes in %lld uS\n", arg_count * arg_size, (t1 - t0));
|
|
return 0;
|
|
}
|
|
|
|
struct
|
|
{
|
|
const char *cmd;
|
|
ifc_match_func match;
|
|
int (*test)(Transport* usb);
|
|
const char *help;
|
|
} tests[] = {
|
|
{ "list", printifc, NULL, "list interfaces" },
|
|
{ "send", match_null, test_null, "send to null interface" },
|
|
{ "recv", match_zero, test_zero, "recv from zero interface" },
|
|
{ "loop", match_loop, NULL, "exercise loopback interface" },
|
|
{ NULL, NULL, NULL, NULL },
|
|
};
|
|
|
|
int usage(void)
|
|
{
|
|
int i;
|
|
|
|
fprintf(stderr,"usage: usbtest <testname>\n\navailable tests:\n");
|
|
for(i = 0; tests[i].cmd; i++) {
|
|
fprintf(stderr," %-8s %s\n", tests[i].cmd, tests[i].help);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int process_args(int argc, char **argv)
|
|
{
|
|
while(argc-- > 0) {
|
|
char *arg = *argv++;
|
|
if(!strncmp(arg,"count=",6)) {
|
|
arg_count = atoi(arg + 6);
|
|
} else if(!strncmp(arg,"size=",5)) {
|
|
arg_size = atoi(arg + 5);
|
|
} else {
|
|
fprintf(stderr,"unknown argument: %s\n", arg);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if(arg_count == 0) {
|
|
fprintf(stderr,"count may not be zero\n");
|
|
return -1;
|
|
}
|
|
|
|
if(arg_size > 4096) {
|
|
fprintf(stderr,"size may not be greater than 4096\n");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
Transport* usb;
|
|
int i;
|
|
|
|
if(argc < 2)
|
|
return usage();
|
|
|
|
if(argc > 2) {
|
|
if(process_args(argc - 2, argv + 2))
|
|
return -1;
|
|
}
|
|
|
|
for(i = 0; tests[i].cmd; i++) {
|
|
if(!strcmp(argv[1], tests[i].cmd)) {
|
|
usb = usb_open(tests[i].match);
|
|
if(tests[i].test) {
|
|
if(usb == 0) {
|
|
fprintf(stderr,"usbtest: %s: could not find interface\n",
|
|
tests[i].cmd);
|
|
return -1;
|
|
}
|
|
if(tests[i].test(usb)) {
|
|
fprintf(stderr,"usbtest: %s: FAIL\n", tests[i].cmd);
|
|
return -1;
|
|
} else {
|
|
fprintf(stderr,"usbtest: %s: OKAY\n", tests[i].cmd);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return usage();
|
|
}
|