summaryrefslogtreecommitdiffstats
path: root/commandline
diff options
context:
space:
mode:
authorJenna Fox <a@creativepony.com>2012-09-23 16:10:31 +1000
committerJenna Fox <a@creativepony.com>2012-09-23 16:10:31 +1000
commit0b63b7b37c027ae58fa29698c5181ecf212f961b (patch)
treecbd2711939c9c29be8ca9b0840aeb9f38978265d /commandline
parent824c303782a62b57b6525875b3c2dee81056baa4 (diff)
downloadmicronucleus-0b63b7b37c027ae58fa29698c5181ecf212f961b.tar.gz
micronucleus-0b63b7b37c027ae58fa29698c5181ecf212f961b.tar.bz2
micronucleus-0b63b7b37c027ae58fa29698c5181ecf212f961b.zip
bring in slightly modified version of bootloadHID host programming app by objective development - including delays tiny85 requires (though they could be tuned to be a bit shorter for quicker programming later)
Diffstat (limited to 'commandline')
-rw-r--r--commandline/Makefile46
-rw-r--r--commandline/Makefile.windows18
-rwxr-xr-xcommandline/bootloadHIDbin0 -> 15040 bytes
-rwxr-xr-xcommandline/hidsdi.h50
-rw-r--r--commandline/main.c272
-rw-r--r--commandline/main.obin0 -> 6116 bytes
-rw-r--r--commandline/usb-libusb.c203
-rwxr-xr-xcommandline/usb-windows.c180
-rw-r--r--commandline/usbcalls.c20
-rw-r--r--commandline/usbcalls.h81
-rw-r--r--commandline/usbcalls.obin0 -> 4012 bytes
11 files changed, 870 insertions, 0 deletions
diff --git a/commandline/Makefile b/commandline/Makefile
new file mode 100644
index 0000000..5c8f81a
--- /dev/null
+++ b/commandline/Makefile
@@ -0,0 +1,46 @@
+# Name: Makefile
+# Project: Automator
+# Author: Christian Starkjohann
+# Creation Date: 2006-02-01
+# Tabsize: 4
+# Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH
+# License: Proprietary, free under certain conditions. See Documentation.
+# This Revision: $Id: Makefile 281 2007-03-20 13:22:10Z cs $
+
+# Please read the definitions below and edit them as appropriate for your
+# system:
+
+# Use the following 3 lines on Unix and 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:
+#USBFLAGS=
+#USBLIBS= -lhid -lusb -lsetupapi
+#EXE_SUFFIX= .exe
+
+CC= gcc
+CXX= g++
+CFLAGS= -O2 -Wall $(USBFLAGS)
+LIBS= $(USBLIBS)
+ARCH_COMPILE=
+ARCH_LINK=
+
+OBJ= main.o usbcalls.o
+PROGRAM= bootloadHID$(EXE_SUFFIX)
+
+all: $(PROGRAM)
+
+$(PROGRAM): $(OBJ)
+ $(CC) $(ARCH_LINK) $(CFLAGS) -o $(PROGRAM) $(OBJ) $(LIBS)
+
+
+strip: $(PROGRAM)
+ strip $(PROGRAM)
+
+clean:
+ rm -f $(OBJ) $(PROGRAM)
+
+.c.o:
+ $(CC) $(ARCH_COMPILE) $(CFLAGS) -c $*.c -o $*.o
diff --git a/commandline/Makefile.windows b/commandline/Makefile.windows
new file mode 100644
index 0000000..16f3ba8
--- /dev/null
+++ b/commandline/Makefile.windows
@@ -0,0 +1,18 @@
+# Name: Makefile.windows
+# Project: Automator
+# Author: Christian Starkjohann
+# Creation Date: 2006-02-20
+# Tabsize: 4
+# Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH
+# License: Proprietary, free under certain conditions. See Documentation.
+# 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=
+USBLIBS= -lhid -lusb -lsetupapi
+EXE_SUFFIX= .exe
diff --git a/commandline/bootloadHID b/commandline/bootloadHID
new file mode 100755
index 0000000..db51c59
--- /dev/null
+++ b/commandline/bootloadHID
Binary files differ
diff --git a/commandline/hidsdi.h b/commandline/hidsdi.h
new file mode 100755
index 0000000..cabb995
--- /dev/null
+++ b/commandline/hidsdi.h
@@ -0,0 +1,50 @@
+/* Name: hidsdi.h
+ * Project: usbcalls library
+ * Author: Christian Starkjohann
+ * Creation Date: 2006-02-02
+ * Tabsize: 4
+ * Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: Proprietary, free under certain conditions. See Documentation.
+ * This Revision: $Id: hidsdi.h 281 2007-03-20 13:22:10Z cs $
+ */
+
+/*
+General Description
+This file is a replacement for hidsdi.h from the Windows DDK. It defines some
+of the types and function prototypes of this header for our project. If you
+have the Windows DDK version of this file or a version shipped with MinGW, use
+that instead.
+*/
+
+#ifndef _HIDSDI_H
+#define _HIDSDI_H
+
+#include <pshpack4.h>
+
+#include <ddk/hidusage.h>
+#include <ddk/hidpi.h>
+
+typedef struct{
+ ULONG Size;
+ USHORT VendorID;
+ USHORT ProductID;
+ USHORT VersionNumber;
+}HIDD_ATTRIBUTES;
+
+void __stdcall HidD_GetHidGuid(OUT LPGUID hidGuid);
+
+BOOLEAN __stdcall HidD_GetAttributes(IN HANDLE device, OUT HIDD_ATTRIBUTES *attributes);
+
+BOOLEAN __stdcall HidD_GetManufacturerString(IN HANDLE device, OUT void *buffer, IN ULONG bufferLen);
+BOOLEAN __stdcall HidD_GetProductString(IN HANDLE device, OUT void *buffer, IN ULONG bufferLen);
+BOOLEAN __stdcall HidD_GetSerialNumberString(IN HANDLE device, OUT void *buffer, IN ULONG bufferLen);
+
+BOOLEAN __stdcall HidD_GetFeature(IN HANDLE device, OUT void *reportBuffer, IN ULONG bufferLen);
+BOOLEAN __stdcall HidD_SetFeature(IN HANDLE device, IN void *reportBuffer, IN ULONG bufferLen);
+
+BOOLEAN __stdcall HidD_GetNumInputBuffers(IN HANDLE device, OUT ULONG *numBuffers);
+BOOLEAN __stdcall HidD_SetNumInputBuffers(IN HANDLE device, OUT ULONG numBuffers);
+
+#include <poppack.h>
+
+#endif
diff --git a/commandline/main.c b/commandline/main.c
new file mode 100644
index 0000000..1b507d3
--- /dev/null
+++ b/commandline/main.c
@@ -0,0 +1,272 @@
+/* Name: main.c
+ * Project: AVR bootloader HID
+ * Author: Christian Starkjohann
+ * Creation Date: 2007-03-19
+ * Tabsize: 4
+ * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: Proprietary, free under certain conditions. See Documentation.
+ * This Revision: $Id: main.c 787 2010-05-30 20:54:25Z cs $
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "usbcalls.h"
+
+#define IDENT_VENDOR_NUM 0x16c0
+#define IDENT_VENDOR_STRING "obdev.at"
+#define IDENT_PRODUCT_NUM 1503
+#define IDENT_PRODUCT_STRING "HIDBoot"
+
+// extra delays before more USB requests for tiny85 compatibility
+#define TINY85_POSTWRITE_DELAY 8000
+#define TINY85_FIRSTWRITE_DELAY 500000
+
+/* ------------------------------------------------------------------------- */
+
+static char dataBuffer[65536 + 256]; /* buffer for file data */
+static int startAddress, endAddress;
+static char leaveBootLoader = 0;
+
+/* ------------------------------------------------------------------------- */
+
+static int parseUntilColon(FILE *fp)
+{
+int c;
+
+ do{
+ c = getc(fp);
+ }while(c != ':' && c != EOF);
+ return c;
+}
+
+static int parseHex(FILE *fp, int numDigits)
+{
+int i;
+char temp[9];
+
+ for(i = 0; i < numDigits; i++)
+ temp[i] = getc(fp);
+ temp[i] = 0;
+ return strtol(temp, NULL, 16);
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int parseIntelHex(char *hexfile, char buffer[65536 + 256], int *startAddr, int *endAddr)
+{
+int address, base, d, segment, i, lineLen, sum;
+FILE *input;
+
+ input = fopen(hexfile, "r");
+ if(input == NULL){
+ fprintf(stderr, "error opening %s: %s\n", hexfile, strerror(errno));
+ return 1;
+ }
+ while(parseUntilColon(input) == ':'){
+ sum = 0;
+ sum += lineLen = parseHex(input, 2);
+ base = address = parseHex(input, 4);
+ sum += address >> 8;
+ sum += address;
+ sum += segment = parseHex(input, 2); /* segment value? */
+ if(segment != 0) /* ignore lines where this byte is not 0 */
+ continue;
+ for(i = 0; i < lineLen ; i++){
+ d = parseHex(input, 2);
+ buffer[address++] = d;
+ sum += d;
+ }
+ sum += parseHex(input, 2);
+ if((sum & 0xff) != 0){
+ fprintf(stderr, "Warning: Checksum error between address 0x%x and 0x%x\n", base, address);
+ }
+ if(*startAddr > base)
+ *startAddr = base;
+ if(*endAddr < address)
+ *endAddr = address;
+ }
+ fclose(input);
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+char *usbErrorMessage(int errCode)
+{
+static char buffer[80];
+
+ switch(errCode){
+ case USB_ERROR_ACCESS: return "Access to device denied";
+ case USB_ERROR_NOTFOUND: return "The specified device was not found";
+ case USB_ERROR_BUSY: return "The device is used by another application";
+ case USB_ERROR_IO: return "Communication error with device";
+ default:
+ sprintf(buffer, "Unknown USB error %d", errCode);
+ return buffer;
+ }
+ return NULL; /* not reached */
+}
+
+static int getUsbInt(char *buffer, int numBytes)
+{
+int shift = 0, value = 0, i;
+
+ for(i = 0; i < numBytes; i++){
+ value |= ((int)*buffer & 0xff) << shift;
+ shift += 8;
+ buffer++;
+ }
+ return value;
+}
+
+static void setUsbInt(char *buffer, int value, int numBytes)
+{
+int i;
+
+ for(i = 0; i < numBytes; i++){
+ *buffer++ = value;
+ value >>= 8;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+typedef struct deviceInfo{
+ char reportId;
+ char pageSize[2]; // TODO: change this to one byte?
+ char flashSize[4]; // TODO: change this to two bytes?
+}deviceInfo_t;
+
+typedef struct deviceData{
+ char reportId;
+ char address[3];
+ char data[128];
+}deviceData_t;
+
+static int uploadData(char *dataBuffer, int startAddr, int endAddr)
+{
+usbDevice_t *dev = NULL;
+int err = 0, len, mask, pageSize, deviceSize;
+union{
+ char bytes[1];
+ deviceInfo_t info;
+ deviceData_t data;
+} buffer;
+unsigned char firstWrite = 1; // track first page write request, accept extra delay
+
+ if((err = usbOpenDevice(&dev, IDENT_VENDOR_NUM, IDENT_VENDOR_STRING, IDENT_PRODUCT_NUM, IDENT_PRODUCT_STRING, 1)) != 0){
+ fprintf(stderr, "Error opening HIDBoot device: %s\n", usbErrorMessage(err));
+ goto errorOccurred;
+ }
+ len = sizeof(buffer);
+ if(endAddr > startAddr){ // we need to upload data
+ if((err = usbGetReport(dev, USB_HID_REPORT_TYPE_FEATURE, 1, buffer.bytes, &len)) != 0){
+ fprintf(stderr, "Error reading page size: %s\n", usbErrorMessage(err));
+ goto errorOccurred;
+ }
+ if(len < sizeof(buffer.info)){
+ fprintf(stderr, "Not enough bytes in device info report (%d instead of %d)\n", len, (int)sizeof(buffer.info));
+ err = -1;
+ goto errorOccurred;
+ }
+ pageSize = getUsbInt(buffer.info.pageSize, 2);
+ deviceSize = getUsbInt(buffer.info.flashSize, 4);
+ printf("Page size = %d (0x%x)\n", pageSize, pageSize);
+ printf("Device size = %d (0x%x)\n", deviceSize, deviceSize);
+ if(endAddr > deviceSize){
+ fprintf(stderr, "Data (%d bytes) exceeds remaining flash size!\n", endAddr);
+ err = -1;
+ goto errorOccurred;
+ }
+ if(pageSize < 128){
+ mask = 127;
+ }else{
+ mask = pageSize - 1;
+ }
+ startAddr &= ~mask; /* round down */
+ endAddr = (endAddr + mask) & ~mask; /* round up */
+ printf("Uploading %d (0x%x) bytes starting at %d (0x%x)\n", endAddr - startAddr, endAddr - startAddr, startAddr, startAddr);
+ while(startAddr < endAddr){
+ buffer.data.reportId = 2;
+ memcpy(buffer.data.data, dataBuffer + startAddr, 128);
+ setUsbInt(buffer.data.address, startAddr, 3);
+ printf("\r0x%05x ... 0x%05x", startAddr, startAddr + (int)sizeof(buffer.data.data));
+ fflush(stdout);
+ if((err = usbSetReport(dev, USB_HID_REPORT_TYPE_FEATURE, buffer.bytes, sizeof(buffer.data))) != 0){
+ fprintf(stderr, "Error uploading data block: %s\n", usbErrorMessage(err));
+ goto errorOccurred;
+ }
+ startAddr += sizeof(buffer.data.data);
+
+ // special tiny85 chillout session - chip freezes after write, so we
+ // need to make sure we don't send it any requests while it's busy
+ // erasing or writing
+ if (firstWrite) usleep(TINY85_FIRSTWRITE_DELAY); // progmem erase extra time
+ usleep(TINY85_POSTWRITE_DELAY); // regular page write duration
+ firstWrite = 0;
+ }
+ printf("\n");
+ }
+ if(leaveBootLoader){
+ /* and now leave boot loader: */
+ buffer.info.reportId = 1;
+ usbSetReport(dev, USB_HID_REPORT_TYPE_FEATURE, buffer.bytes, sizeof(buffer.info));
+ /* Ignore errors here. If the device reboots before we poll the response,
+ * this request fails.
+ */
+ }
+errorOccurred:
+ if(dev != NULL)
+ usbCloseDevice(dev);
+ return err;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void printUsage(char *pname)
+{
+ fprintf(stderr, "usage: %s [-r] [<intel-hexfile>]\n", pname);
+}
+
+int main(int argc, char **argv)
+{
+char *file = NULL;
+
+ if(argc < 2){
+ printUsage(argv[0]);
+ return 1;
+ }
+ if(strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0){
+ printUsage(argv[0]);
+ return 1;
+ }
+ if(strcmp(argv[1], "-r") == 0){
+ leaveBootLoader = 1;
+ if(argc >= 3){
+ file = argv[2];
+ }
+ }else{
+ file = argv[1];
+ }
+ startAddress = sizeof(dataBuffer);
+ endAddress = 0;
+ if(file != NULL){ // an upload file was given, load the data
+ memset(dataBuffer, -1, sizeof(dataBuffer));
+ if(parseIntelHex(file, dataBuffer, &startAddress, &endAddress))
+ return 1;
+ if(startAddress >= endAddress){
+ fprintf(stderr, "No data in input file, exiting.\n");
+ return 0;
+ }
+ }
+ // if no file was given, endAddress is less than startAddress and no data is uploaded
+ if(uploadData(dataBuffer, startAddress, endAddress))
+ return 1;
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+
diff --git a/commandline/main.o b/commandline/main.o
new file mode 100644
index 0000000..709f98e
--- /dev/null
+++ b/commandline/main.o
Binary files differ
diff --git a/commandline/usb-libusb.c b/commandline/usb-libusb.c
new file mode 100644
index 0000000..886da3b
--- /dev/null
+++ b/commandline/usb-libusb.c
@@ -0,0 +1,203 @@
+/* Name: usb-libusb.c
+ * Project: usbcalls library
+ * Author: Christian Starkjohann
+ * Creation Date: 2006-02-02
+ * Tabsize: 4
+ * Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: Proprietary, free under certain conditions. See Documentation.
+ * This Revision: $Id: usb-libusb.c 323 2007-03-29 17:25:03Z cs $
+ */
+
+/*
+General Description:
+This module implements USB HID report receiving/sending based on libusb. It
+does not read and parse the report descriptor. You must therefore be careful
+to pass correctly formatted data blocks of correct size. In order to be
+compatible with the Windows implementation, we add a zero report ID for all
+reports which don't have an ID. Since we don't parse the descriptor, the caller
+must tell us whether report IDs are used or not in usbOpenDevice().
+
+The implementation of dummy report IDs is a hack. Whether they are used is
+stored in a global variable, not in the device structure (just laziness, don't
+want to allocate memory for that). If you open more than one device and the
+devices differ in report ID usage, you must change the code.
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <usb.h>
+
+#define usbDevice usb_dev_handle /* use libusb's device structure */
+#include "usbcalls.h"
+
+/* ------------------------------------------------------------------------- */
+
+#define USBRQ_HID_GET_REPORT 0x01
+#define USBRQ_HID_SET_REPORT 0x09
+
+static int usesReportIDs;
+
+/* ------------------------------------------------------------------------- */
+
+static int usbGetStringAscii(usb_dev_handle *dev, int index, int langid, char *buf, int buflen)
+{
+char buffer[256];
+int rval, i;
+
+ if((rval = usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) + index, langid, buffer, sizeof(buffer), 1000)) < 0)
+ return rval;
+ if(buffer[1] != USB_DT_STRING)
+ 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(usbDevice_t **device, int vendor, char *vendorName, int product, char *productName, int _usesReportIDs)
+{
+struct usb_bus *bus;
+struct usb_device *dev;
+usb_dev_handle *handle = NULL;
+int errorCode = USB_ERROR_NOTFOUND;
+static int didUsbInit = 0;
+
+ if(!didUsbInit){
+ usb_init();
+ didUsbInit = 1;
+ }
+ usb_find_busses();
+ usb_find_devices();
+ for(bus=usb_get_busses(); bus; bus=bus->next){
+ for(dev=bus->devices; dev; dev=dev->next){
+ if(dev->descriptor.idVendor == vendor && dev->descriptor.idProduct == product){
+ char string[256];
+ int len;
+ handle = usb_open(dev); /* we need to open the device in order to query strings */
+ if(!handle){
+ errorCode = USB_ERROR_ACCESS;
+ fprintf(stderr, "Warning: cannot open USB device: %s\n", usb_strerror());
+ continue;
+ }
+ if(vendorName == NULL && productName == NULL){ /* name does not matter */
+ break;
+ }
+ /* now check whether the names match: */
+ len = usbGetStringAscii(handle, dev->descriptor.iManufacturer, 0x0409, string, sizeof(string));
+ if(len < 0){
+ errorCode = USB_ERROR_IO;
+ fprintf(stderr, "Warning: cannot query manufacturer for device: %s\n", usb_strerror());
+ }else{
+ errorCode = USB_ERROR_NOTFOUND;
+ /* fprintf(stderr, "seen device from vendor ->%s<-\n", string); */
+ if(strcmp(string, vendorName) == 0){
+ len = usbGetStringAscii(handle, dev->descriptor.iProduct, 0x0409, string, sizeof(string));
+ if(len < 0){
+ errorCode = USB_ERROR_IO;
+ fprintf(stderr, "Warning: cannot query product for device: %s\n", usb_strerror());
+ }else{
+ errorCode = USB_ERROR_NOTFOUND;
+ /* fprintf(stderr, "seen product ->%s<-\n", string); */
+ if(strcmp(string, productName) == 0)
+ break;
+ }
+ }
+ }
+ usb_close(handle);
+ handle = NULL;
+ }
+ }
+ if(handle)
+ break;
+ }
+ if(handle != NULL){
+ int rval, retries = 3;
+ if(usb_set_configuration(handle, 1)){
+ 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((rval = usb_claim_interface(handle, 0)) != 0 && retries-- > 0){
+#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
+ if(usb_detach_kernel_driver_np(handle, 0) < 0){
+ fprintf(stderr, "Warning: could not detach kernel HID driver: %s\n", usb_strerror());
+ }
+#endif
+ }
+#ifndef __APPLE__
+ if(rval != 0)
+ fprintf(stderr, "Warning: could not claim interface\n");
+#endif
+/* Continue anyway, even if we could not claim the interface. Control transfers
+ * should still work.
+ */
+ errorCode = 0;
+ *device = handle;
+ usesReportIDs = _usesReportIDs;
+ }
+ return errorCode;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void usbCloseDevice(usbDevice_t *device)
+{
+ if(device != NULL)
+ usb_close(device);
+}
+
+/* ------------------------------------------------------------------------- */
+
+int usbSetReport(usbDevice_t *device, int reportType, char *buffer, int len)
+{
+int bytesSent;
+
+ if(!usesReportIDs){
+ buffer++; /* skip dummy report ID */
+ len--;
+ }
+ bytesSent = usb_control_msg(device, USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_ENDPOINT_OUT, USBRQ_HID_SET_REPORT, reportType << 8 | buffer[0], 0, buffer, len, 5000);
+ if(bytesSent != len){
+ if(bytesSent < 0)
+ fprintf(stderr, "Error sending message: %s\n", usb_strerror());
+ return USB_ERROR_IO;
+ }
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int usbGetReport(usbDevice_t *device, int reportType, int reportNumber, char *buffer, int *len)
+{
+int bytesReceived, maxLen = *len;
+
+ if(!usesReportIDs){
+ buffer++; /* make room for dummy report ID */
+ maxLen--;
+ }
+ bytesReceived = usb_control_msg(device, USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_ENDPOINT_IN, USBRQ_HID_GET_REPORT, reportType << 8 | reportNumber, 0, buffer, maxLen, 5000);
+ if(bytesReceived < 0){
+ fprintf(stderr, "Error sending message: %s\n", usb_strerror());
+ return USB_ERROR_IO;
+ }
+ *len = bytesReceived;
+ if(!usesReportIDs){
+ buffer[-1] = reportNumber; /* add dummy report ID */
+ *len++;
+ }
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+
diff --git a/commandline/usb-windows.c b/commandline/usb-windows.c
new file mode 100755
index 0000000..fac3b02
--- /dev/null
+++ b/commandline/usb-windows.c
@@ -0,0 +1,180 @@
+/* Name: usb-windows.c
+ * Project: usbcalls library
+ * Author: Christian Starkjohann
+ * Creation Date: 2006-02-02
+ * Tabsize: 4
+ * Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: Proprietary, free under certain conditions. See Documentation.
+ * This Revision: $Id: usb-windows.c 281 2007-03-20 13:22:10Z cs $
+ */
+
+/*
+General Description:
+This module implements USB HID report receiving and sending with native
+Windows API functions. If you compile with MinGW, no software from Microsoft
+(no DDK) is needed. We supply the missing types and function prototypes in
+hidsdi.h.
+*/
+
+#include <stdio.h>
+#include <windows.h>
+#include <setupapi.h>
+#include "hidsdi.h"
+#include <ddk/hidpi.h>
+
+#include "usbcalls.h"
+
+#ifdef DEBUG
+#define DEBUG_PRINT(arg) printf arg
+#else
+#define DEBUG_PRINT(arg)
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static void convertUniToAscii(char *buffer)
+{
+unsigned short *uni = (void *)buffer;
+char *ascii = buffer;
+
+ while(*uni != 0){
+ if(*uni >= 256){
+ *ascii++ = '?';
+ }else{
+ *ascii++ = *uni++;
+ }
+ }
+ *ascii++ = 0;
+}
+
+int usbOpenDevice(usbDevice_t **device, int vendor, char *vendorName, int product, char *productName, int usesReportIDs)
+{
+GUID hidGuid; /* GUID for HID driver */
+HDEVINFO deviceInfoList;
+SP_DEVICE_INTERFACE_DATA deviceInfo;
+SP_DEVICE_INTERFACE_DETAIL_DATA *deviceDetails = NULL;
+DWORD size;
+int i, openFlag = 0; /* may be FILE_FLAG_OVERLAPPED */
+int errorCode = USB_ERROR_NOTFOUND;
+HANDLE handle = INVALID_HANDLE_VALUE;
+HIDD_ATTRIBUTES deviceAttributes;
+
+ HidD_GetHidGuid(&hidGuid);
+ deviceInfoList = SetupDiGetClassDevs(&hidGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
+ deviceInfo.cbSize = sizeof(deviceInfo);
+ for(i=0;;i++){
+ if(handle != INVALID_HANDLE_VALUE){
+ CloseHandle(handle);
+ handle = INVALID_HANDLE_VALUE;
+ }
+ if(!SetupDiEnumDeviceInterfaces(deviceInfoList, 0, &hidGuid, i, &deviceInfo))
+ break; /* no more entries */
+ /* first do a dummy call just to determine the actual size required */
+ SetupDiGetDeviceInterfaceDetail(deviceInfoList, &deviceInfo, NULL, 0, &size, NULL);
+ if(deviceDetails != NULL)
+ free(deviceDetails);
+ deviceDetails = malloc(size);
+ deviceDetails->cbSize = sizeof(*deviceDetails);
+ /* this call is for real: */
+ SetupDiGetDeviceInterfaceDetail(deviceInfoList, &deviceInfo, deviceDetails, size, &size, NULL);
+ DEBUG_PRINT(("checking HID path \"%s\"\n", deviceDetails->DevicePath));
+ /* attempt opening for R/W -- we don't care about devices which can't be accessed */
+ handle = CreateFile(deviceDetails->DevicePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, openFlag, NULL);
+ if(handle == INVALID_HANDLE_VALUE){
+ DEBUG_PRINT(("opening failed: %d\n", (int)GetLastError()));
+ /* errorCode = USB_ERROR_ACCESS; opening will always fail for mouse -- ignore */
+ continue;
+ }
+ deviceAttributes.Size = sizeof(deviceAttributes);
+ HidD_GetAttributes(handle, &deviceAttributes);
+ DEBUG_PRINT(("device attributes: vid=%d pid=%d\n", deviceAttributes.VendorID, deviceAttributes.ProductID));
+ if(deviceAttributes.VendorID != vendor || deviceAttributes.ProductID != product)
+ continue; /* ignore this device */
+ errorCode = USB_ERROR_NOTFOUND;
+ if(vendorName != NULL && productName != NULL){
+ char buffer[512];
+ if(!HidD_GetManufacturerString(handle, buffer, sizeof(buffer))){
+ DEBUG_PRINT(("error obtaining vendor name\n"));
+ errorCode = USB_ERROR_IO;
+ continue;
+ }
+ convertUniToAscii(buffer);
+ DEBUG_PRINT(("vendorName = \"%s\"\n", buffer));
+ if(strcmp(vendorName, buffer) != 0)
+ continue;
+ if(!HidD_GetProductString(handle, buffer, sizeof(buffer))){
+ DEBUG_PRINT(("error obtaining product name\n"));
+ errorCode = USB_ERROR_IO;
+ continue;
+ }
+ convertUniToAscii(buffer);
+ DEBUG_PRINT(("productName = \"%s\"\n", buffer));
+ if(strcmp(productName, buffer) != 0)
+ continue;
+ }
+ break; /* we have found the device we are looking for! */
+ }
+ SetupDiDestroyDeviceInfoList(deviceInfoList);
+ if(deviceDetails != NULL)
+ free(deviceDetails);
+ if(handle != INVALID_HANDLE_VALUE){
+ *device = (usbDevice_t *)handle;
+ errorCode = 0;
+ }
+ return errorCode;
+}
+
+/* ------------------------------------------------------------------------ */
+
+void usbCloseDevice(usbDevice_t *device)
+{
+ CloseHandle((HANDLE)device);
+}
+
+/* ------------------------------------------------------------------------ */
+
+int usbSetReport(usbDevice_t *device, int reportType, char *buffer, int len)
+{
+HANDLE handle = (HANDLE)device;
+BOOLEAN rval = 0;
+DWORD bytesWritten;
+
+ switch(reportType){
+ case USB_HID_REPORT_TYPE_INPUT:
+ break;
+ case USB_HID_REPORT_TYPE_OUTPUT:
+ rval = WriteFile(handle, buffer, len, &bytesWritten, NULL);
+ break;
+ case USB_HID_REPORT_TYPE_FEATURE:
+ rval = HidD_SetFeature(handle, buffer, len);
+ break;
+ }
+ return rval == 0 ? USB_ERROR_IO : 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+int usbGetReport(usbDevice_t *device, int reportType, int reportNumber, char *buffer, int *len)
+{
+HANDLE handle = (HANDLE)device;
+BOOLEAN rval = 0;
+DWORD bytesRead;
+
+ switch(reportType){
+ case USB_HID_REPORT_TYPE_INPUT:
+ buffer[0] = reportNumber;
+ rval = ReadFile(handle, buffer, *len, &bytesRead, NULL);
+ if(rval)
+ *len = bytesRead;
+ break;
+ case USB_HID_REPORT_TYPE_OUTPUT:
+ break;
+ case USB_HID_REPORT_TYPE_FEATURE:
+ buffer[0] = reportNumber;
+ rval = HidD_GetFeature(handle, buffer, *len);
+ break;
+ }
+ return rval == 0 ? USB_ERROR_IO : 0;
+}
+
+/* ------------------------------------------------------------------------ */
diff --git a/commandline/usbcalls.c b/commandline/usbcalls.c
new file mode 100644
index 0000000..f8a1857
--- /dev/null
+++ b/commandline/usbcalls.c
@@ -0,0 +1,20 @@
+/* Name: usbcalls.c
+ * Project: usbcalls library
+ * Author: Christian Starkjohann
+ * Creation Date: 2006-02-02
+ * Tabsize: 4
+ * Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: Proprietary, free under certain conditions. See Documentation.
+ * This Revision: $Id: usbcalls.c 281 2007-03-20 13:22:10Z cs $
+ */
+
+/* This file includes the appropriate implementation based on platform
+ * specific defines.
+ */
+
+#if defined(WIN32)
+# include "usb-windows.c"
+#else
+/* e.g. defined(__APPLE__) */
+# include "usb-libusb.c"
+#endif
diff --git a/commandline/usbcalls.h b/commandline/usbcalls.h
new file mode 100644
index 0000000..3f329b2
--- /dev/null
+++ b/commandline/usbcalls.h
@@ -0,0 +1,81 @@
+/* Name: usbcalls.h
+ * Project: usbcalls library
+ * Author: Christian Starkjohann
+ * Creation Date: 2006-02-02
+ * Tabsize: 4
+ * Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: Proprietary, free under certain conditions. See Documentation.
+ * This Revision: $Id: usbcalls.h 281 2007-03-20 13:22:10Z cs $
+ */
+
+#ifndef __usbcalls_h_INCLUDED__
+#define __usbcalls_h_INCLUDED__
+
+/*
+General Description:
+This module implements an abstraction layer for access to USB/HID communication
+functions. An implementation based on libusb (portable to Linux, FreeBSD and
+Mac OS X) and a native implementation for Windows are provided.
+*/
+
+/* ------------------------------------------------------------------------ */
+
+#define USB_HID_REPORT_TYPE_INPUT 1
+#define USB_HID_REPORT_TYPE_OUTPUT 2
+#define USB_HID_REPORT_TYPE_FEATURE 3
+/* Numeric constants for 'reportType' parameters */
+
+#define USB_ERROR_NONE 0
+#define USB_ERROR_ACCESS 1
+#define USB_ERROR_NOTFOUND 2
+#define USB_ERROR_BUSY 16
+#define USB_ERROR_IO 5
+/* These are the error codes which can be returned by functions of this
+ * module.
+ */
+
+/* ------------------------------------------------------------------------ */
+
+typedef struct usbDevice usbDevice_t;
+/* This type represents a USB device internally. Only opaque pointers to this
+ * type are available outside the module implementation.
+ */
+
+/* ------------------------------------------------------------------------ */
+
+int usbOpenDevice(usbDevice_t **device, int vendor, char *vendorName, int product, char *productName, int usesReportIDs);
+/* This function opens a USB device. 'vendor' and 'product' are the numeric
+ * Vendor-ID and Product-ID of the device we want to open. If 'vendorName' and
+ * 'productName' are both not NULL, only devices with matching manufacturer-
+ * and product name strings are accepted. If the device uses report IDs,
+ * 'usesReportIDs' must be set to a non-zero value.
+ * Returns: If a matching device has been found, USB_ERROR_NONE is returned and
+ * '*device' is set to an opaque pointer representing the device. The device
+ * must be closed with usbCloseDevice(). If the device has not been found or
+ * opening failed, an error code is returned.
+ */
+void usbCloseDevice(usbDevice_t *device);
+/* Every device opened with usbOpenDevice() must be closed with this function.
+ */
+int usbSetReport(usbDevice_t *device, int reportType, char *buffer, int len);
+/* This function sends a report to the device. 'reportType' specifies the type
+ * of report (see USB_HID_REPORT_TYPE* constants). The report ID must be in the
+ * first byte of buffer and the length 'len' of the report is specified
+ * including this report ID. If no report IDs are used, buffer[0] must be set
+ * to 0 (dummy report ID).
+ * Returns: 0 on success, an error code otherwise.
+ */
+int usbGetReport(usbDevice_t *device, int reportType, int reportID, char *buffer, int *len);
+/* This function obtains a report from the device. 'reportType' specifies the
+ * type of report (see USB_HID_REPORT_TYPE* constants). The requested report ID
+ * is passed in 'reportID'. The caller must pass a buffer of the size of the
+ * expected report in 'buffer' and initialize the variable in '*len' to the
+ * total size of this buffer. Upon successful return, the report (prefixed with
+ * a report ID) is in 'buffer' and the actual length of the report is returned
+ * in '*len'.
+ * Returns: 0 on success, an error code otherwise.
+ */
+
+/* ------------------------------------------------------------------------ */
+
+#endif /* __usbcalls_h_INCLUDED__ */
diff --git a/commandline/usbcalls.o b/commandline/usbcalls.o
new file mode 100644
index 0000000..4a43f0f
--- /dev/null
+++ b/commandline/usbcalls.o
Binary files differ