⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbtool.c

📁 AVR_usb_ISP
💻 C
字号:
/* Name: usbtool.c * Project: AVR-USB examples, host side * Author: Christian Starkjohann * Creation Date: 2008-04-06 * Tabsize: 4 * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) * This Revision: $Id: usbtool.c 692 2008-11-07 15:07:40Z cs $ *//*General Description:This command line tool can perform various USB requests at arbitraryUSB devices. It is intended as universal host side tool for experimentationand debugging purposes. It must be linked with libusb, a library for accessingthe USB bus from Linux, FreeBSD, Mac OS X and other Unix operating systems.Libusb can be obtained from http://libusb.sourceforge.net/.On Windows use libusb-win32 from http://libusb-win32.sourceforge.net/.*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <stdarg.h>#include <ctype.h>#include <errno.h>#include <usb.h>        /* this is libusb, see http://libusb.sourceforge.net/ */#include "opendevice.h" /* common code moved to separate module */#define DEFAULT_USB_VID         0   /* any */#define DEFAULT_USB_PID         0   /* any */static void usage(char *name){    fprintf(stderr, "usage: %s [options] <command>\n", name);    fprintf(stderr,        "Options are:\n"        "  -h or -? (print this help and exit)\n"        "  -v <vendor-id> (defaults to 0x%x, can be '*' for any VID)\n"        "  -p <product-id> (defaults to 0x%x, can be '*' for any PID)\n"        "  -V <vendor-name-pattern> (shell style matching, defaults to '*')\n"        "  -P <product-name-pattern> (shell style matching, defaults to '*')\n"        "  -S <serial-pattern> (shell style matching, defaults to '*')\n"        "  -d <databytes> (data byte for request, comma separated list)\n"        "  -D <file> (binary data for request taken from file)\n"        "  -O <file> (write received data bytes to file)\n"        "  -b (binary output format, default is hex)\n"        "  -n <count> (maximum number of bytes to receive)\n"        "  -e <endpoint> (specify endpoint for some commands)\n"        "  -t <timeout> (specify USB timeout in milliseconds)\n"        "  -c <configuration> (device configuration to choose)\n"        "  -i <interface> (configuration interface to claim)\n"        "  -w (suppress USB warnings, default is verbose)\n"        "\n"        "Commands are:\n"        "  list (list all matching devices by name)\n"        "  control in|out <type> <recipient> <request> <value> <index> (send control request)\n"        "  interrupt in|out (send or receive interrupt data)\n"        "  bulk in|out (send or receive bulk data)\n"        "For valid enum values for <type> and <recipient> pass \"x\" for the value.\n"        "Objective Development's free VID/PID pairs are:\n"        "  5824/1500 for vendor class devices\n"        "  5824/1503 for HID class devices excluding mice and keyboards\n"        "  5824/1505 for CDC-ACM class devices\n"        "  5824/1508 for MIDI class devices\n"        , DEFAULT_USB_VID, DEFAULT_USB_PID    );}static int  vendorID = DEFAULT_USB_VID;static int  productID = DEFAULT_USB_PID;static char *vendorNamePattern = "*";static char *productNamePattern = "*";static char *serialPattern = "*";static char *sendBytes = NULL;static int  sendByteCount;static char *outputFile = NULL;static int  endpoint = 0;static int  outputFormatIsBinary = 0;static int  showWarnings = 1;static int  usbTimeout = 5000;static int  usbCount = 128;static int  usbConfiguration = 1;static int  usbInterface = 0;static int  usbDirection, usbType, usbRecipient, usbRequest, usbValue, usbIndex; /* arguments of control transfer *//* ------------------------------------------------------------------------- *//* ASCII to integer (number parsing) which allows hex (0x prefix), * octal (0 prefix) and decimal (1-9 prefix) input. */static int  myAtoi(char *text){long    l;char    *endPtr;    if(strcmp(text, "*") == 0)        return 0;    l = strtol(text, &endPtr, 0);    if(endPtr == text){        fprintf(stderr, "warning: can't parse numeric parameter ->%s<-, defaults to 0.\n", text);        l = 0;    }else if(*endPtr != 0){        fprintf(stderr, "warning: numeric parameter ->%s<- only partially parsed.\n", text);    }    return l;}static int  parseEnum(char *text, ...){va_list vlist;char    *entries[64];int     i, numEntries;    va_start(vlist, text);    for(i = 0; i < 64; i++){        entries[i] = va_arg(vlist, char *);        if(entries[i] == NULL)            break;    }    numEntries = i;    va_end(vlist);    for(i = 0; i < numEntries; i++){        if(strcasecmp(text, entries[i]) == 0)            return i;    }    if(isdigit(*text)){        return myAtoi(text);    }    fprintf(stderr, "Enum value \"%s\" not allowed. Allowed values are:\n", text);    for(i = 0; i < numEntries; i++){        fprintf(stderr, "  %s\n", entries[i]);    }    exit(1);}/* ------------------------------------------------------------------------- */#define ACTION_LIST         0#define ACTION_CONTROL      1#define ACTION_INTERRUPT    2#define ACTION_BULK         3int main(int argc, char **argv){usb_dev_handle  *handle = NULL;int             opt, len, action, argcnt;char            *myName = argv[0], *s, *rxBuffer = NULL;FILE            *fp;    while((opt = getopt(argc, argv, "?hv:p:V:P:S:d:D:O:e:n:tbw")) != -1){        switch(opt){        case 'h':        case '?':   /* -h or -? (print this help and exit) */            usage(myName);            exit(1);        case 'v':   /* -v <vendor-id> (defaults to 0x%x, can be '*' for any VID) */            vendorID = myAtoi(optarg);            break;        case 'p':   /* -p <product-id> (defaults to 0x%x, can be '*' for any PID) */            productID = myAtoi(optarg);            break;        case 'V':   /* -V <vendor-name-pattern> (shell style matching, defaults to '*') */            vendorNamePattern = optarg;            break;        case 'P':   /* -P <product-name-pattern> (shell style matching, defaults to '*') */            productNamePattern = optarg;            break;        case 'S':   /* -S <serial-pattern> (shell style matching, defaults to '*') */            serialPattern = optarg;            break;        case 'd':   /* -d <databytes> (data bytes for requests given on command line) */            while((s = strtok(optarg, ", ")) != NULL){                optarg = NULL;                if(sendBytes != NULL){                    sendBytes = realloc(sendBytes, sendByteCount + 1);                }else{                    sendBytes = malloc(sendByteCount + 1);                }                sendBytes[sendByteCount++] = myAtoi(s);            }            break;        case 'D':   /* -D <file> (data bytes for request taken from file) */            if((fp = fopen(optarg, "rb")) == NULL){                fprintf(stderr, "error opening %s: %s\n", optarg, strerror(errno));                exit(1);            }            fseek(fp, 0, SEEK_END);            len = ftell(fp);            fseek(fp, 0, SEEK_SET);            if(sendBytes != NULL){                sendBytes = realloc(sendBytes, sendByteCount + len);            }else{                sendBytes = malloc(sendByteCount + len);            }            fread(sendBytes + sendByteCount, 1, len, fp);   /* would need error checking */            sendByteCount += len;            fclose(fp);            break;        case 'O':   /* -O <file> (write received data bytes to file) */            outputFile = optarg;            break;        case 'e':   /* -e <endpoint> (specify endpoint for some commands) */            endpoint = myAtoi(optarg);            break;        case 't':   /* -t <timeout> (specify USB timeout in milliseconds) */            usbTimeout = myAtoi(optarg);            break;        case 'b':   /* -b (binary output format, default is hex) */            outputFormatIsBinary = 1;            break;        case 'n':   /* -n <count> (maximum number of bytes to receive) */            usbCount = myAtoi(optarg);            break;        case 'c':   /* -c <configuration> (device configuration to choose) */            usbConfiguration = myAtoi(optarg);            break;        case 'i':   /* -i <interface> (configuration interface to claim) */            usbInterface = myAtoi(optarg);            break;        case 'w':   /* -w (suppress USB warnings, default is verbose) */            showWarnings = 0;            break;        default:            fprintf(stderr, "Option -%c unknown\n", opt);            exit(1);        }    }    argc -= optind;    argv += optind;    if(argc < 1){        usage(myName);        exit(1);    }    argcnt = 2;    if(strcasecmp(argv[0], "list") == 0){        action = ACTION_LIST;        argcnt = 1;    }else if(strcasecmp(argv[0], "control") == 0){        action = ACTION_CONTROL;        argcnt = 7;    }else if(strcasecmp(argv[0], "interrupt") == 0){        action = ACTION_INTERRUPT;    }else if(strcasecmp(argv[0], "bulk") == 0){        action = ACTION_BULK;    }else{        fprintf(stderr, "command %s not known\n", argv[0]);        usage(myName);        exit(1);    }    if(argc < argcnt){        fprintf(stderr, "Not enough arguments.\n");        usage(myName);        exit(1);    }    if(argc > argcnt){        fprintf(stderr, "Warning: only %d arguments expected, rest ignored.\n", argcnt);    }    usb_init();    if(usbOpenDevice(&handle, vendorID, vendorNamePattern, productID, productNamePattern, serialPattern, action == ACTION_LIST ? stdout : NULL, showWarnings ? stderr : NULL) != 0){        fprintf(stderr, "Could not find USB device with VID=0x%x PID=0x%x Vname=%s Pname=%s Serial=%s\n", vendorID, productID, vendorNamePattern, productNamePattern, serialPattern);        exit(1);    }    if(action == ACTION_LIST)        exit(0);                /* we've done what we were asked to do already */    usbDirection = parseEnum(argv[1], "out", "in", NULL);    if(usbDirection){   /* IN transfer */        rxBuffer = malloc(usbCount);    }    if(action == ACTION_CONTROL){        int requestType;        usbType = parseEnum(argv[2], "standard", "class", "vendor", "reserved", NULL);        usbRecipient = parseEnum(argv[3], "device", "interface", "endpoint", "other", NULL);        usbRequest = myAtoi(argv[4]);        usbValue = myAtoi(argv[5]);        usbIndex = myAtoi(argv[6]);        requestType = ((usbDirection & 1) << 7) | ((usbType & 3) << 5) | (usbRecipient & 0x1f);        if(usbDirection){   /* IN transfer */            len = usb_control_msg(handle, requestType, usbRequest, usbValue, usbIndex, rxBuffer, usbCount, usbTimeout);        }else{              /* OUT transfer */            len = usb_control_msg(handle, requestType, usbRequest, usbValue, usbIndex, sendBytes, sendByteCount, usbTimeout);        }    }else{  /* must be ACTION_INTERRUPT or ACTION_BULK */        int retries = 1;        if(usb_set_configuration(handle, usbConfiguration) && showWarnings){            fprintf(stderr, "Warning: could not set configuration: %s\n", usb_strerror());        }        /* now try to claim the interface and detach the kernel HID driver on         * linux and other operating systems which support the call.         */        while((len = usb_claim_interface(handle, usbInterface)) != 0 && retries-- > 0){#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP            if(usb_detach_kernel_driver_np(handle, 0) < 0 && showWarnings){                fprintf(stderr, "Warning: could not detach kernel driver: %s\n", usb_strerror());            }#endif        }        if(len != 0 && showWarnings)            fprintf(stderr, "Warning: could not claim interface: %s\n", usb_strerror());        if(action == ACTION_INTERRUPT){            if(usbDirection){   /* IN transfer */                len = usb_interrupt_read(handle, endpoint, rxBuffer, usbCount, usbTimeout);            }else{                len = usb_interrupt_write(handle, endpoint, sendBytes, sendByteCount, usbTimeout);            }        }else{            if(usbDirection){   /* IN transfer */                len = usb_bulk_read(handle, endpoint, rxBuffer, usbCount, usbTimeout);            }else{                len = usb_bulk_write(handle, endpoint, sendBytes, sendByteCount, usbTimeout);            }        }    }    if(len < 0){        fprintf(stderr, "USB error: %s\n", usb_strerror());        exit(1);    }    if(usbDirection == 0)   /* OUT */        printf("%d bytes sent.\n", len);    if(rxBuffer != NULL){        FILE *fp = stdout;        if(outputFile != NULL){            fp = fopen(outputFile, outputFormatIsBinary ? "wb" : "w");            if(fp == NULL){                fprintf(stderr, "Error writing \"%s\": %s\n", outputFile, strerror(errno));                exit(1);            }        }        if(outputFormatIsBinary){            fwrite(rxBuffer, 1, len, fp);        }else{            int i;            for(i = 0; i < len; i++){                if(i != 0){                    if(i % 16 == 0){                        fprintf(fp, "\n");                    }else{                        fprintf(fp, " ");                    }                }                fprintf(fp, "0x%02x", rxBuffer[i] & 0xff);            }            if(i != 0)                fprintf(fp, "\n");        }    }    usb_close(handle);    if(rxBuffer != NULL)        free(rxBuffer);    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -