diff options
author | Christian Starkjohann <cs+github@obdev.at> | 2008-04-17 19:00:20 +0000 |
---|---|---|
committer | Christian Starkjohann <cs+github@obdev.at> | 2008-04-17 19:00:20 +0000 |
commit | 95ca3f5bd696b5450820929e1b1a444d02f0bd1e (patch) | |
tree | 70ac0161a0e4548acaf2f89d2ecb77132579ff7a /examples/usbtool | |
parent | 2f465daef9e6c5a6b7bda3074c050cd7e8515770 (diff) | |
download | v-usb-95ca3f5bd696b5450820929e1b1a444d02f0bd1e.tar.gz v-usb-95ca3f5bd696b5450820929e1b1a444d02f0bd1e.tar.bz2 v-usb-95ca3f5bd696b5450820929e1b1a444d02f0bd1e.zip |
- imported new files into project
Diffstat (limited to 'examples/usbtool')
-rw-r--r-- | examples/usbtool/Makefile | 48 | ||||
-rw-r--r-- | examples/usbtool/Makefile.windows | 18 | ||||
-rw-r--r-- | examples/usbtool/Readme.txt | 209 | ||||
-rwxr-xr-x | examples/usbtool/make-files.sh | 16 | ||||
-rw-r--r-- | examples/usbtool/usbtool.c | 356 |
5 files changed, 647 insertions, 0 deletions
diff --git a/examples/usbtool/Makefile b/examples/usbtool/Makefile new file mode 100644 index 0000000..f79fc03 --- /dev/null +++ b/examples/usbtool/Makefile @@ -0,0 +1,48 @@ +# Name: Makefile +# Project: usbtool +# 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) or proprietary (CommercialLicense.txt) +# This Revision: $Id$ + + +# Concigure the following definitions according to your system. +# This Makefile has been tested on Mac OS X, Linux and Windows. + +# Use the following 3 lines on Unix (uncomment the framework on Mac OS X): +USBFLAGS = `libusb-config --cflags` +USBLIBS = `libusb-config --libs` +EXE_SUFFIX = + +# Use the following 3 lines on Windows and comment out the 3 above. You may +# have to change the include paths to where you installed libusb-win32 +#USBFLAGS = -I/usr/local/include +#USBLIBS = -L/usr/local/lib -lusb +#EXE_SUFFIX = .exe + +NAME = usbtool + +OBJECTS = opendevice.o $(NAME).o + +CC = gcc +CFLAGS = $(USBFLAGS) -O -g -Wall +LIBS = $(USBLIBS) + +PROGRAM = $(NAME)$(EXE_SUFFIX) + + +all: $(PROGRAM) + +.c.o: + $(CC) $(CFLAGS) -c $< + +$(PROGRAM): $(OBJECTS) + $(CC) -o $(PROGRAM) $(OBJECTS) $(LIBS) + +strip: $(PROGRAM) + strip $(PROGRAM) + +clean: + rm -f *.o $(PROGRAM) diff --git a/examples/usbtool/Makefile.windows b/examples/usbtool/Makefile.windows new file mode 100644 index 0000000..1c4aaa1 --- /dev/null +++ b/examples/usbtool/Makefile.windows @@ -0,0 +1,18 @@ +# Name: Makefile.windows +# Project: usbtool +# 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) or proprietary (CommercialLicense.txt) +# This Revision: $Id$ + +# You may use this file with +# make -f Makefile.windows +# on Windows with MinGW instead of editing the main Makefile. + +include Makefile + +USBFLAGS = -I/usr/local/mingw/include +USBLIBS = -L/usr/local/mingw/lib -lusb +EXE_SUFFIX = .exe diff --git a/examples/usbtool/Readme.txt b/examples/usbtool/Readme.txt new file mode 100644 index 0000000..33f527c --- /dev/null +++ b/examples/usbtool/Readme.txt @@ -0,0 +1,209 @@ +This is the Readme file for usbtool, a general purpose command line utility +which can send USB requests to arbitrary devices. Usbtool is based on libusb. + + +WHAT IS USBTOOL GOOD FOR? +========================= +When you implement a communication protocol like USB, you must usually write +two programs: one on each end of the communication. For USB, this means that +you must write a firmware for the device and driver software for the host. + +Usbtool can save you the work of writing the host software, at least during +firmware development and testing. Usbtool can send control-in and -out +requests to arbitrary devices and send and receive data on interrupt- and +bulk-endpoints. + +Usbtool is not only a useful developer tool, it's also an example for using +libusb for communication with the device. + + +SYNOPSIS +======== + usbtool [options] <command> + + +COMMANDS +======== + list + This command prints a list of devices found on all available USB busses. + Options -v, -V, -p and -P can be used to filter the list. + + control in|out <type> <recipient> <request> <value> <index> + Sends a control-in or control-out request to the device. The request + parameters are: + type ........ Type of request, can be "standard", "class", "vendor" or + "reserved". The type determines which software module in + the device is responsible for answering the request: + Standard requests are answered by the driver, class + requests by the class implementation (e.g. HID, CDC) and + vendor requests by custom code. + recipient ... Recipient of the request in the device. Can be "device", + "interface", "endpoint" or "other". For standard and + class requests, the specification defines a recipient for + each request. For vendor requests, choose whatever your + code expects. + request ..... 8 bit numeric value identifying the request. + value ....... 16 bit numeric value passed to the device. + index ....... another 16 bit numeric value passed to the device. + Use options -v, -V, -p and -P to single out a particular device. Use + options -d or -D to to send data in an OUT request. Use options -n, -O + and -b to determine what to do with data received in an IN request. + + interrupt in|out + Sends or receives data on an interrupt-out resp. -in endpoint. + Use options -v, -V, -p and -P to single out a particular device. Use + options -d or -D to to send data to an OUT endpoint. Use options -n, -O + and -b to determine what to do with data received from an IN endpoint. + Use option -e to set the endpoint number, -c to choose a configuration + -i to claim a particular interface. + + bulk in|out + Same as "interrupt in" and "interrupt out", but for bulk endpoints. + + +OPTIONS +======= +Most options have already been mentioned at the commands which use them. +here is a complete list: + + -h or -? + Prints a short help. + + -v <vendor-id> + Numeric vendor ID, can be "*" to allow any VID. Take only devices with + matching vendor ID into account. + + -p <product-id> + Numeric product ID, can be "*" to allow any PID. Take only devices with + matching product ID into account. + + -V <vendor-name-pattern> + Shell style matching pattern for vendor name. Take only devices into + account which have a vendor name that matches this pattern. + + -P <product-name-pattern> + Shell style matching pattern for product name. Take only devices into + account which have a product name that matches this pattern. + + -S <serial-pattern> + Shell style matching pattern for serial number. Take only devices into + account which have a serial number that matches this pattern. + + -d <databytes> + Data bytes to send to the device, comma separated list of numeric values. + E.g.: "1,2,3,4,5". + + -D <file> + Binary data sent to the device should be taken from this file. + + -O <file> + Write received data bytes to the given file. Format is either hex or + binary, depending on the -b flag. By default, received data is printed + to standard output. + + -b + Request binary output format for files and standard output. Default is + a hexadecimal listing. + + -n <count> + Numeric value: Maximum number of bytes to receive. This value is passed + directly to the libusb API functions. + + -e <endpoint> + Numeric value: Endpoint number for interrupt and bulk commands. + + -t <timeout> + Numeric value: Timeout in milliseconds for the request. This value is + passed directly to the libusb API functions. + + -c <configuration> + Numeric value: Interrupt and bulk endpoints can usually only be used if + a configuration and an interface has been chosen. Use -c and -i to + specify configuration and interface values. + + -i <interface> + Numeric value: Interrupt and bulk endpoints can usually only be used if + a configuration and an interface has been chosen. Use -c and -i to + specify configuration and interface values. + + -w + Usbtool may be too verbose with warnings for some applications. Use this + option to suppress USB warnings. + + +NUMERIC VALUES +============== +All numeric values can be given in hexadecimal, decimal or octal. Hex values +are identified by their 0x or 0X prefix, octal values by a leading "0" (the +digit zero) and decimal values because they start with a non-zero digit. An +optional sign character is allowed. The special value "*" is translated to +zero and stands for "any value" in some contexts. + + +SHELL STYLE MATCHING PATTERNS +============================= +Some options take shell style matching patterns as an argument. This refers +to Unix shells and their file wildcard operations: + + "*" (asterisk character) matches any number (0 to infinite) of any + characters. + + "?" matches exactly one arbitrary character. + + A list of characters in square brackets (e.g. "[abc]") matches any of the + characters in the list. If a dash ("-") is in the list, it must be the + first or the last character. If a caret ("^") is in the list, it must + not be the first character. A closing square bracket ("]") must be the + first character in the list. A range of characters can be specified in + the way "[a-z]". This matches all characters with numeric representation + (usually ASCII) starting with "a" and ending with "z". The entire + construct matches only one character. + + A list of characters in square brackets starting with a caret ("^"), e.g. + ("[^abc]") matches any character NOT in the list. The other rules are as + above. + + "\" (backslash) followed by any character matches that following + character. This can be used to escape "*", "?", "[" and "\". + + +BUILDING USBTOOL +================ +Usbtool uses libusb on Unix and libusb-win32 on Windows. These libraries can +be obtained from http://libusb.sourceforge.net/ and +http://libusb-win32.sourceforge.net/ respectively. On Unix, a simple "make" +should compile the sources (although you may have to edit Makefile to +include or remove additional libraries). On Windows, we recommend that you +use MinGW and MSYS. See the top level Readme file for details. Edit +Makefile.windows according to your library installation paths and build with +"make -f Makefile.windows". + + +EXAMPLES +======== +To list all devices connected to your computer, do + + usbtool -w list + +To check whether our selection options single out the desired device, use eg. + + usbtool -w -P LEDControl list + +This command shows all LEDControl devices connected or prints nothing if +none is found. LEDControl is the device from the "custom-class" example. + +You can also send commands to the LEDControl device using usbtool. From +the file requests.h in custom-class/firmware, we know that the set-status +request has numeric value 1 and the get-status request is 2. See this file +for details of the protocol used. We can therefore query the status with + + usbtool -w -P LEDControl control in vendor device 2 0 0 + +This command prints 0x00 if the LED is off or 0x01 if it is on. To turn the +LED on, use + + usbtool -w -P LEDControl control out vendor device 1 1 0 + +and to turn it off, use + + usbtool -w -P LEDControl control out vendor device 1 0 0 + + +---------------------------------------------------------------------------- +(c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH. +http://www.obdev.at/ diff --git a/examples/usbtool/make-files.sh b/examples/usbtool/make-files.sh new file mode 100755 index 0000000..0ba183e --- /dev/null +++ b/examples/usbtool/make-files.sh @@ -0,0 +1,16 @@ +#!/bin/sh +# Author: Christian Starkjohann +# Creation Date: 2008-04-17 +# Tabsize: 4 +# Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH +# License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt) +# This Revision: $Id$ + + +if [ "$1" = remove ]; then + make clean + rm -f opendevice.[ch] + exit +fi + +cp ../../libs-host/opendevice.[ch] . diff --git a/examples/usbtool/usbtool.c b/examples/usbtool/usbtool.c new file mode 100644 index 0000000..fe29a06 --- /dev/null +++ b/examples/usbtool/usbtool.c @@ -0,0 +1,356 @@ +/* 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) or proprietary (CommercialLicense.txt) + * This Revision: $Id$ + */ + +/* +General Description: +This command line tool can perform various USB requests at arbitrary +USB devices. It is intended as universal host side tool for experimentation +and debugging purposes. It must be linked with libusb, a library for accessing +the 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 3 + +int 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; +} |