Initial commit of the VUSB custom request client.
This commit is contained in:
parent
1c740255d5
commit
ef1aa32741
6 changed files with 481 additions and 0 deletions
48
client/Makefile
Normal file
48
client/Makefile
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
# Name: Makefile
|
||||||
|
# Project: hid-custom-rq example
|
||||||
|
# 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: Makefile 692 2008-11-07 15:07:40Z cs $
|
||||||
|
|
||||||
|
|
||||||
|
# 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 = set-led
|
||||||
|
|
||||||
|
OBJECTS = opendevice.o $(NAME).o
|
||||||
|
|
||||||
|
CC = gcc
|
||||||
|
CFLAGS = $(CPPFLAGS) $(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)
|
18
client/Makefile.windows
Normal file
18
client/Makefile.windows
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# Name: Makefile.windows
|
||||||
|
# Project: hid-custom-rq example
|
||||||
|
# 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$
|
||||||
|
|
||||||
|
# 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
|
203
client/opendevice.c
Normal file
203
client/opendevice.c
Normal file
|
@ -0,0 +1,203 @@
|
||||||
|
/* Name: opendevice.c
|
||||||
|
* Project: V-USB host-side library
|
||||||
|
* Author: Christian Starkjohann
|
||||||
|
* Creation Date: 2008-04-10
|
||||||
|
* 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: opendevice.c 740 2009-04-13 18:23:31Z cs $
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
General Description:
|
||||||
|
The functions in this module can be used to find and open a device based on
|
||||||
|
libusb or libusb-win32.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "opendevice.h"
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#define MATCH_SUCCESS 1
|
||||||
|
#define MATCH_FAILED 0
|
||||||
|
#define MATCH_ABORT -1
|
||||||
|
|
||||||
|
/* private interface: match text and p, return MATCH_SUCCESS, MATCH_FAILED, or MATCH_ABORT. */
|
||||||
|
static int _shellStyleMatch(char *text, char *p)
|
||||||
|
{
|
||||||
|
int last, matched, reverse;
|
||||||
|
|
||||||
|
for(; *p; text++, p++){
|
||||||
|
if(*text == 0 && *p != '*')
|
||||||
|
return MATCH_ABORT;
|
||||||
|
switch(*p){
|
||||||
|
case '\\':
|
||||||
|
/* Literal match with following character. */
|
||||||
|
p++;
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
default:
|
||||||
|
if(*text != *p)
|
||||||
|
return MATCH_FAILED;
|
||||||
|
continue;
|
||||||
|
case '?':
|
||||||
|
/* Match anything. */
|
||||||
|
continue;
|
||||||
|
case '*':
|
||||||
|
while(*++p == '*')
|
||||||
|
/* Consecutive stars act just like one. */
|
||||||
|
continue;
|
||||||
|
if(*p == 0)
|
||||||
|
/* Trailing star matches everything. */
|
||||||
|
return MATCH_SUCCESS;
|
||||||
|
while(*text)
|
||||||
|
if((matched = _shellStyleMatch(text++, p)) != MATCH_FAILED)
|
||||||
|
return matched;
|
||||||
|
return MATCH_ABORT;
|
||||||
|
case '[':
|
||||||
|
reverse = p[1] == '^';
|
||||||
|
if(reverse) /* Inverted character class. */
|
||||||
|
p++;
|
||||||
|
matched = MATCH_FAILED;
|
||||||
|
if(p[1] == ']' || p[1] == '-')
|
||||||
|
if(*++p == *text)
|
||||||
|
matched = MATCH_SUCCESS;
|
||||||
|
for(last = *p; *++p && *p != ']'; last = *p)
|
||||||
|
if (*p == '-' && p[1] != ']' ? *text <= *++p && *text >= last : *text == *p)
|
||||||
|
matched = MATCH_SUCCESS;
|
||||||
|
if(matched == reverse)
|
||||||
|
return MATCH_FAILED;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *text == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* public interface for shell style matching: returns 0 if fails, 1 if matches */
|
||||||
|
static int shellStyleMatch(char *text, char *pattern)
|
||||||
|
{
|
||||||
|
if(pattern == NULL) /* NULL pattern is synonymous to "*" */
|
||||||
|
return 1;
|
||||||
|
return _shellStyleMatch(text, pattern) == MATCH_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
int usbGetStringAscii(usb_dev_handle *dev, int index, char *buf, int buflen)
|
||||||
|
{
|
||||||
|
char buffer[256];
|
||||||
|
int rval, i;
|
||||||
|
|
||||||
|
if((rval = usb_get_string_simple(dev, index, buf, buflen)) >= 0) /* use libusb version if it works */
|
||||||
|
return rval;
|
||||||
|
if((rval = usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) + index, 0x0409, buffer, sizeof(buffer), 5000)) < 0)
|
||||||
|
return rval;
|
||||||
|
if(buffer[1] != USB_DT_STRING){
|
||||||
|
*buf = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if((unsigned char)buffer[0] < rval)
|
||||||
|
rval = (unsigned char)buffer[0];
|
||||||
|
rval /= 2;
|
||||||
|
/* lossy conversion to ISO Latin1: */
|
||||||
|
for(i=1;i<rval;i++){
|
||||||
|
if(i > buflen) /* destination buffer overflow */
|
||||||
|
break;
|
||||||
|
buf[i-1] = buffer[2 * i];
|
||||||
|
if(buffer[2 * i + 1] != 0) /* outside of ISO Latin1 range */
|
||||||
|
buf[i-1] = '?';
|
||||||
|
}
|
||||||
|
buf[i-1] = 0;
|
||||||
|
return i-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
int usbOpenDevice(usb_dev_handle **device, int vendorID, char *vendorNamePattern, int productID, char *productNamePattern, char *serialNamePattern, FILE *printMatchingDevicesFp, FILE *warningsFp)
|
||||||
|
{
|
||||||
|
struct usb_bus *bus;
|
||||||
|
struct usb_device *dev;
|
||||||
|
usb_dev_handle *handle = NULL;
|
||||||
|
int errorCode = USBOPEN_ERR_NOTFOUND;
|
||||||
|
|
||||||
|
usb_find_busses();
|
||||||
|
usb_find_devices();
|
||||||
|
for(bus = usb_get_busses(); bus; bus = bus->next){
|
||||||
|
for(dev = bus->devices; dev; dev = dev->next){ /* iterate over all devices on all busses */
|
||||||
|
if((vendorID == 0 || dev->descriptor.idVendor == vendorID)
|
||||||
|
&& (productID == 0 || dev->descriptor.idProduct == productID)){
|
||||||
|
char vendor[256], product[256], serial[256];
|
||||||
|
int len;
|
||||||
|
handle = usb_open(dev); /* we need to open the device in order to query strings */
|
||||||
|
if(!handle){
|
||||||
|
errorCode = USBOPEN_ERR_ACCESS;
|
||||||
|
if(warningsFp != NULL)
|
||||||
|
fprintf(warningsFp, "Warning: cannot open VID=0x%04x PID=0x%04x: %s\n", dev->descriptor.idVendor, dev->descriptor.idProduct, usb_strerror());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* now check whether the names match: */
|
||||||
|
len = vendor[0] = 0;
|
||||||
|
if(dev->descriptor.iManufacturer > 0){
|
||||||
|
len = usbGetStringAscii(handle, dev->descriptor.iManufacturer, vendor, sizeof(vendor));
|
||||||
|
}
|
||||||
|
if(len < 0){
|
||||||
|
errorCode = USBOPEN_ERR_ACCESS;
|
||||||
|
if(warningsFp != NULL)
|
||||||
|
fprintf(warningsFp, "Warning: cannot query manufacturer for VID=0x%04x PID=0x%04x: %s\n", dev->descriptor.idVendor, dev->descriptor.idProduct, usb_strerror());
|
||||||
|
}else{
|
||||||
|
errorCode = USBOPEN_ERR_NOTFOUND;
|
||||||
|
/* printf("seen device from vendor ->%s<-\n", vendor); */
|
||||||
|
if(shellStyleMatch(vendor, vendorNamePattern)){
|
||||||
|
len = product[0] = 0;
|
||||||
|
if(dev->descriptor.iProduct > 0){
|
||||||
|
len = usbGetStringAscii(handle, dev->descriptor.iProduct, product, sizeof(product));
|
||||||
|
}
|
||||||
|
if(len < 0){
|
||||||
|
errorCode = USBOPEN_ERR_ACCESS;
|
||||||
|
if(warningsFp != NULL)
|
||||||
|
fprintf(warningsFp, "Warning: cannot query product for VID=0x%04x PID=0x%04x: %s\n", dev->descriptor.idVendor, dev->descriptor.idProduct, usb_strerror());
|
||||||
|
}else{
|
||||||
|
errorCode = USBOPEN_ERR_NOTFOUND;
|
||||||
|
/* printf("seen product ->%s<-\n", product); */
|
||||||
|
if(shellStyleMatch(product, productNamePattern)){
|
||||||
|
len = serial[0] = 0;
|
||||||
|
if(dev->descriptor.iSerialNumber > 0){
|
||||||
|
len = usbGetStringAscii(handle, dev->descriptor.iSerialNumber, serial, sizeof(serial));
|
||||||
|
}
|
||||||
|
if(len < 0){
|
||||||
|
errorCode = USBOPEN_ERR_ACCESS;
|
||||||
|
if(warningsFp != NULL)
|
||||||
|
fprintf(warningsFp, "Warning: cannot query serial for VID=0x%04x PID=0x%04x: %s\n", dev->descriptor.idVendor, dev->descriptor.idProduct, usb_strerror());
|
||||||
|
}
|
||||||
|
if(shellStyleMatch(serial, serialNamePattern)){
|
||||||
|
if(printMatchingDevicesFp != NULL){
|
||||||
|
if(serial[0] == 0){
|
||||||
|
fprintf(printMatchingDevicesFp, "VID=0x%04x PID=0x%04x vendor=\"%s\" product=\"%s\"\n", dev->descriptor.idVendor, dev->descriptor.idProduct, vendor, product);
|
||||||
|
}else{
|
||||||
|
fprintf(printMatchingDevicesFp, "VID=0x%04x PID=0x%04x vendor=\"%s\" product=\"%s\" serial=\"%s\"\n", dev->descriptor.idVendor, dev->descriptor.idProduct, vendor, product, serial);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
usb_close(handle);
|
||||||
|
handle = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(handle) /* we have found a deice */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(handle != NULL){
|
||||||
|
errorCode = 0;
|
||||||
|
*device = handle;
|
||||||
|
}
|
||||||
|
if(printMatchingDevicesFp != NULL) /* never return an error for listing only */
|
||||||
|
errorCode = 0;
|
||||||
|
return errorCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
77
client/opendevice.h
Normal file
77
client/opendevice.h
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/* Name: opendevice.h
|
||||||
|
* Project: V-USB host-side library
|
||||||
|
* Author: Christian Starkjohann
|
||||||
|
* Creation Date: 2008-04-10
|
||||||
|
* 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: opendevice.h 755 2009-08-03 17:01:21Z cs $
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
General Description:
|
||||||
|
This module offers additional functionality for host side drivers based on
|
||||||
|
libusb or libusb-win32. It includes a function to find and open a device
|
||||||
|
based on numeric IDs and textual description. It also includes a function to
|
||||||
|
obtain textual descriptions from a device.
|
||||||
|
|
||||||
|
To use this functionality, simply copy opendevice.c and opendevice.h into your
|
||||||
|
project and add them to your Makefile. You may modify and redistribute these
|
||||||
|
files according to the GNU General Public License (GPL) version 2 or 3.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __OPENDEVICE_H_INCLUDED__
|
||||||
|
#define __OPENDEVICE_H_INCLUDED__
|
||||||
|
|
||||||
|
#include <usb.h> /* this is libusb, see http://libusb.sourceforge.net/ */
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int usbGetStringAscii(usb_dev_handle *dev, int index, char *buf, int buflen);
|
||||||
|
/* This function gets a string descriptor from the device. 'index' is the
|
||||||
|
* string descriptor index. The string is returned in ISO Latin 1 encoding in
|
||||||
|
* 'buf' and it is terminated with a 0-character. The buffer size must be
|
||||||
|
* passed in 'buflen' to prevent buffer overflows. A libusb device handle
|
||||||
|
* must be given in 'dev'.
|
||||||
|
* Returns: The length of the string (excluding the terminating 0) or
|
||||||
|
* a negative number in case of an error. If there was an error, use
|
||||||
|
* usb_strerror() to obtain the error message.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int usbOpenDevice(usb_dev_handle **device, int vendorID, char *vendorNamePattern, int productID, char *productNamePattern, char *serialNamePattern, FILE *printMatchingDevicesFp, FILE *warningsFp);
|
||||||
|
/* This function iterates over all devices on all USB busses and searches for
|
||||||
|
* a device. Matching is done first by means of Vendor- and Product-ID (passed
|
||||||
|
* in 'vendorID' and 'productID'. An ID of 0 matches any numeric ID (wildcard).
|
||||||
|
* When a device matches by its IDs, matching by names is performed. Name
|
||||||
|
* matching can be done on textual vendor name ('vendorNamePattern'), product
|
||||||
|
* name ('productNamePattern') and serial number ('serialNamePattern'). A
|
||||||
|
* device matches only if all non-null pattern match. If you don't care about
|
||||||
|
* a string, pass NULL for the pattern. Patterns are Unix shell style pattern:
|
||||||
|
* '*' stands for 0 or more characters, '?' for one single character, a list
|
||||||
|
* of characters in square brackets for a single character from the list
|
||||||
|
* (dashes are allowed to specify a range) and if the lis of characters begins
|
||||||
|
* with a caret ('^'), it matches one character which is NOT in the list.
|
||||||
|
* Other parameters to the function: If 'warningsFp' is not NULL, warning
|
||||||
|
* messages are printed to this file descriptor with fprintf(). If
|
||||||
|
* 'printMatchingDevicesFp' is not NULL, no device is opened but matching
|
||||||
|
* devices are printed to the given file descriptor with fprintf().
|
||||||
|
* If a device is opened, the resulting USB handle is stored in '*device'. A
|
||||||
|
* pointer to a "usb_dev_handle *" type variable must be passed here.
|
||||||
|
* Returns: 0 on success, an error code (see defines below) on failure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* usbOpenDevice() error codes: */
|
||||||
|
#define USBOPEN_SUCCESS 0 /* no error */
|
||||||
|
#define USBOPEN_ERR_ACCESS 1 /* not enough permissions to open device */
|
||||||
|
#define USBOPEN_ERR_IO 2 /* I/O error */
|
||||||
|
#define USBOPEN_ERR_NOTFOUND 3 /* device not found */
|
||||||
|
|
||||||
|
|
||||||
|
/* Obdev's free USB IDs, see USB-IDs-for-free.txt for details */
|
||||||
|
|
||||||
|
#define USB_VID_OBDEV_SHARED 5824 /* obdev's shared vendor ID */
|
||||||
|
#define USB_PID_OBDEV_SHARED_CUSTOM 1500 /* shared PID for custom class devices */
|
||||||
|
#define USB_PID_OBDEV_SHARED_HID 1503 /* shared PID for HIDs except mice & keyboards */
|
||||||
|
#define USB_PID_OBDEV_SHARED_CDCACM 1505 /* shared PID for CDC Modem devices */
|
||||||
|
#define USB_PID_OBDEV_SHARED_MIDI 1508 /* shared PID for MIDI class devices */
|
||||||
|
|
||||||
|
#endif /* __OPENDEVICE_H_INCLUDED__ */
|
BIN
client/set-led
Normal file
BIN
client/set-led
Normal file
Binary file not shown.
135
client/set-led.c
Normal file
135
client/set-led.c
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
/* Name: set-led.c
|
||||||
|
* Project: hid-custom-rq example
|
||||||
|
* Author: Christian Starkjohann
|
||||||
|
* Creation Date: 2008-04-10
|
||||||
|
* 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: set-led.c 692 2008-11-07 15:07:40Z cs $
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
General Description:
|
||||||
|
This is the host-side driver for the custom-class example device. It searches
|
||||||
|
the USB for the LEDControl device and sends the requests understood by this
|
||||||
|
device.
|
||||||
|
This program must be linked with libusb on Unix and libusb-win32 on Windows.
|
||||||
|
See http://libusb.sourceforge.net/ or http://libusb-win32.sourceforge.net/
|
||||||
|
respectively.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <usb.h> /* this is libusb */
|
||||||
|
#include "opendevice.h" /* common code moved to separate module */
|
||||||
|
|
||||||
|
#include "../firmware/requests.h" /* custom request numbers */
|
||||||
|
#include "../firmware/usbconfig.h" /* device's VID/PID and names */
|
||||||
|
|
||||||
|
static void usage(char *name)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "usage:\n");
|
||||||
|
fprintf(stderr, " %s on ....... turn on LED\n", name);
|
||||||
|
fprintf(stderr, " %s off ...... turn off LED\n", name);
|
||||||
|
fprintf(stderr, " %s status ... ask current status of LED\n", name);
|
||||||
|
#if ENABLE_TEST
|
||||||
|
fprintf(stderr, " %s test ..... run driver reliability test\n", name);
|
||||||
|
#endif /* ENABLE_TEST */
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
usb_dev_handle *handle = NULL;
|
||||||
|
const unsigned char rawVid[2] = {USB_CFG_VENDOR_ID}, rawPid[2] = {USB_CFG_DEVICE_ID};
|
||||||
|
char vendor[] = {USB_CFG_VENDOR_NAME, 0}, product[] = {USB_CFG_DEVICE_NAME, 0};
|
||||||
|
char buffer[4];
|
||||||
|
int cnt, vid, pid, isOn;
|
||||||
|
|
||||||
|
usb_init();
|
||||||
|
if(argc < 2){ /* we need at least one argument */
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
/* compute VID/PID from usbconfig.h so that there is a central source of information */
|
||||||
|
vid = rawVid[1] * 256 + rawVid[0];
|
||||||
|
pid = rawPid[1] * 256 + rawPid[0];
|
||||||
|
/* The following function is in opendevice.c: */
|
||||||
|
if(usbOpenDevice(&handle, vid, vendor, pid, product, NULL, NULL, NULL) != 0){
|
||||||
|
fprintf(stderr, "Could not find USB device \"%s\" with vid=0x%x pid=0x%x\n", product, vid, pid);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
/* Since we use only control endpoint 0, we don't need to choose a
|
||||||
|
* configuration and interface. Reading device descriptor and setting a
|
||||||
|
* configuration and interface is done through endpoint 0 after all.
|
||||||
|
* However, newer versions of Linux require that we claim an interface
|
||||||
|
* even for endpoint 0. Enable the following code if your operating system
|
||||||
|
* needs it: */
|
||||||
|
#if 0
|
||||||
|
int retries = 1, usbConfiguration = 1, usbInterface = 0;
|
||||||
|
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
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(strcasecmp(argv[1], "status") == 0){
|
||||||
|
cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_GET_STATUS, 0, 0, buffer, sizeof(buffer), 5000);
|
||||||
|
if(cnt < 1){
|
||||||
|
if(cnt < 0){
|
||||||
|
fprintf(stderr, "USB error: %s\n", usb_strerror());
|
||||||
|
}else{
|
||||||
|
fprintf(stderr, "only %d bytes received.\n", cnt);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
printf("LED is %s\n", buffer[0] ? "on" : "off");
|
||||||
|
}
|
||||||
|
}else if((isOn = (strcasecmp(argv[1], "on") == 0)) || strcasecmp(argv[1], "off") == 0){
|
||||||
|
cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, CUSTOM_RQ_SET_STATUS, isOn, 0, buffer, 0, 5000);
|
||||||
|
if(cnt < 0){
|
||||||
|
fprintf(stderr, "USB error: %s\n", usb_strerror());
|
||||||
|
}
|
||||||
|
#if ENABLE_TEST
|
||||||
|
}else if(strcasecmp(argv[1], "test") == 0){
|
||||||
|
int i;
|
||||||
|
srandomdev();
|
||||||
|
for(i = 0; i < 50000; i++){
|
||||||
|
int value = random() & 0xffff, index = random() & 0xffff;
|
||||||
|
int rxValue, rxIndex;
|
||||||
|
if((i+1) % 100 == 0){
|
||||||
|
fprintf(stderr, "\r%05d", i+1);
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
|
cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_ECHO, value, index, buffer, sizeof(buffer), 5000);
|
||||||
|
if(cnt < 0){
|
||||||
|
fprintf(stderr, "\nUSB error in iteration %d: %s\n", i, usb_strerror());
|
||||||
|
break;
|
||||||
|
}else if(cnt != 4){
|
||||||
|
fprintf(stderr, "\nerror in iteration %d: %d bytes received instead of 4\n", i, cnt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rxValue = ((int)buffer[0] & 0xff) | (((int)buffer[1] & 0xff) << 8);
|
||||||
|
rxIndex = ((int)buffer[2] & 0xff) | (((int)buffer[3] & 0xff) << 8);
|
||||||
|
if(rxValue != value || rxIndex != index){
|
||||||
|
fprintf(stderr, "\ndata error in iteration %d:\n", i);
|
||||||
|
fprintf(stderr, "rxValue = 0x%04x value = 0x%04x\n", rxValue, value);
|
||||||
|
fprintf(stderr, "rxIndex = 0x%04x index = 0x%04x\n", rxIndex, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(stderr, "\nTest completed.\n");
|
||||||
|
#endif /* ENABLE_TEST */
|
||||||
|
}else{
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
usb_close(handle);
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in a new issue