aboutsummaryrefslogtreecommitdiffstats
path: root/libs-host
diff options
context:
space:
mode:
authorChristian Starkjohann <cs+github@obdev.at>2008-04-17 19:00:20 +0000
committerChristian Starkjohann <cs+github@obdev.at>2008-04-17 19:00:20 +0000
commit95ca3f5bd696b5450820929e1b1a444d02f0bd1e (patch)
tree70ac0161a0e4548acaf2f89d2ecb77132579ff7a /libs-host
parent2f465daef9e6c5a6b7bda3074c050cd7e8515770 (diff)
downloadv-usb-95ca3f5bd696b5450820929e1b1a444d02f0bd1e.tar.gz
v-usb-95ca3f5bd696b5450820929e1b1a444d02f0bd1e.tar.bz2
v-usb-95ca3f5bd696b5450820929e1b1a444d02f0bd1e.zip
- imported new files into project
Diffstat (limited to 'libs-host')
-rw-r--r--libs-host/Readme.txt26
-rw-r--r--libs-host/hiddata.c317
-rw-r--r--libs-host/hiddata.h71
-rw-r--r--libs-host/hidsdi.h49
-rw-r--r--libs-host/opendevice.c203
-rw-r--r--libs-host/opendevice.h77
6 files changed, 743 insertions, 0 deletions
diff --git a/libs-host/Readme.txt b/libs-host/Readme.txt
new file mode 100644
index 0000000..5117d18
--- /dev/null
+++ b/libs-host/Readme.txt
@@ -0,0 +1,26 @@
+This is the Readme file for the libs-host directory. This directory contains
+code snippets which may be useful for host side USB software.
+
+
+WHAT IS INCLUDED IN THIS DIRECTORY?
+===================================
+
+opendevice.c and opendevice.h
+ This module contains a function to find and open a device given its
+ numeric IDs (VID, PID), names (vendor name and product name) and serial
+ number. It is based on libusb/libusb-win32 and returns a libusb device
+ handle. See opendevice.h for an API documentation.
+
+hiddata.c and hiddata.h
+ This module contains functions for data transfer over HID feature reports.
+ It is based on libusb on Unix and native Windows functions on Windows. No
+ driver DLL is needed on Windows. See hiddata.h for an API documentation.
+
+hidsdi.h
+ This DDK header file is missing in the free MinGW version of the Windows
+ DDK. Use this version if you get an "include file not found" error.
+
+
+----------------------------------------------------------------------------
+(c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH.
+http://www.obdev.at/
diff --git a/libs-host/hiddata.c b/libs-host/hiddata.c
new file mode 100644
index 0000000..3e884e8
--- /dev/null
+++ b/libs-host/hiddata.c
@@ -0,0 +1,317 @@
+/* Name: hiddata.c
+ * Author: Christian Starkjohann
+ * Creation Date: 2008-04-11
+ * Tabsize: 4
+ * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
+ * This Revision: $Id$
+ */
+
+#include <stdio.h>
+#include "hiddata.h"
+
+/* ######################################################################## */
+#if defined(WIN32) /* ##################################################### */
+/* ######################################################################## */
+
+#include <windows.h>
+#include <setupapi.h>
+#include "hidsdi.h"
+#include <ddk/hidpi.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 usbhidOpenDevice(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 = USBOPEN_ERR_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 = USBOPEN_ERR_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 = USBOPEN_ERR_NOTFOUND;
+ if(vendorName != NULL && productName != NULL){
+ char buffer[512];
+ if(!HidD_GetManufacturerString(handle, buffer, sizeof(buffer))){
+ DEBUG_PRINT(("error obtaining vendor name\n"));
+ errorCode = USBOPEN_ERR_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 = USBOPEN_ERR_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 usbhidCloseDevice(usbDevice_t *device)
+{
+ CloseHandle((HANDLE)device);
+}
+
+/* ------------------------------------------------------------------------ */
+
+int usbhidSetReport(usbDevice_t *device, char *buffer, int len)
+{
+BOOLEAN rval;
+
+ rval = HidD_SetFeature((HANDLE)device, buffer, len);
+ return rval == 0 ? USBOPEN_ERR_IO : 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+int usbhidGetReport(usbDevice_t *device, int reportNumber, char *buffer, int *len)
+{
+BOOLEAN rval = 0;
+
+ buffer[0] = reportNumber;
+ rval = HidD_GetFeature((HANDLE)device, buffer, *len);
+ return rval == 0 ? USBOPEN_ERR_IO : 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* ######################################################################## */
+#else /* defined WIN32 #################################################### */
+/* ######################################################################## */
+
+#include <string.h>
+#include <usb.h>
+
+#define usbDevice usb_dev_handle /* use libusb's device structure */
+
+/* ------------------------------------------------------------------------- */
+
+#define USBRQ_HID_GET_REPORT 0x01
+#define USBRQ_HID_SET_REPORT 0x09
+
+#define USB_HID_REPORT_TYPE_FEATURE 3
+
+
+static int usesReportIDs;
+
+/* ------------------------------------------------------------------------- */
+
+static int usbhidGetStringAscii(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 usbhidOpenDevice(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 = USBOPEN_ERR_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 = USBOPEN_ERR_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 = usbhidGetStringAscii(handle, dev->descriptor.iManufacturer, string, sizeof(string));
+ if(len < 0){
+ errorCode = USBOPEN_ERR_IO;
+ fprintf(stderr, "Warning: cannot query manufacturer for device: %s\n", usb_strerror());
+ }else{
+ errorCode = USBOPEN_ERR_NOTFOUND;
+ /* fprintf(stderr, "seen device from vendor ->%s<-\n", string); */
+ if(strcmp(string, vendorName) == 0){
+ len = usbhidGetStringAscii(handle, dev->descriptor.iProduct, string, sizeof(string));
+ if(len < 0){
+ errorCode = USBOPEN_ERR_IO;
+ fprintf(stderr, "Warning: cannot query product for device: %s\n", usb_strerror());
+ }else{
+ errorCode = USBOPEN_ERR_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){
+ errorCode = 0;
+ *device = (void *)handle;
+ usesReportIDs = _usesReportIDs;
+ }
+ return errorCode;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void usbhidCloseDevice(usbDevice_t *device)
+{
+ if(device != NULL)
+ usb_close((void *)device);
+}
+
+/* ------------------------------------------------------------------------- */
+
+int usbhidSetReport(usbDevice_t *device, char *buffer, int len)
+{
+int bytesSent;
+
+ if(!usesReportIDs){
+ buffer++; /* skip dummy report ID */
+ len--;
+ }
+ bytesSent = usb_control_msg((void *)device, USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_ENDPOINT_OUT, USBRQ_HID_SET_REPORT, USB_HID_REPORT_TYPE_FEATURE << 8 | (buffer[0] & 0xff), 0, buffer, len, 5000);
+ if(bytesSent != len){
+ if(bytesSent < 0)
+ fprintf(stderr, "Error sending message: %s\n", usb_strerror());
+ return USBOPEN_ERR_IO;
+ }
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int usbhidGetReport(usbDevice_t *device, int reportNumber, char *buffer, int *len)
+{
+int bytesReceived, maxLen = *len;
+
+ if(!usesReportIDs){
+ buffer++; /* make room for dummy report ID */
+ maxLen--;
+ }
+ bytesReceived = usb_control_msg((void *)device, USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_ENDPOINT_IN, USBRQ_HID_GET_REPORT, USB_HID_REPORT_TYPE_FEATURE << 8 | reportNumber, 0, buffer, maxLen, 5000);
+ if(bytesReceived < 0){
+ fprintf(stderr, "Error sending message: %s\n", usb_strerror());
+ return USBOPEN_ERR_IO;
+ }
+ *len = bytesReceived;
+ if(!usesReportIDs){
+ buffer[-1] = reportNumber; /* add dummy report ID */
+ *len++;
+ }
+ return 0;
+}
+
+/* ######################################################################## */
+#endif /* defined WIN32 ################################################### */
+/* ######################################################################## */
diff --git a/libs-host/hiddata.h b/libs-host/hiddata.h
new file mode 100644
index 0000000..e362730
--- /dev/null
+++ b/libs-host/hiddata.h
@@ -0,0 +1,71 @@
+/* Name: hiddata.h
+ * Author: Christian Starkjohann
+ * Creation Date: 2008-04-11
+ * Tabsize: 4
+ * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
+ * This Revision: $Id$
+ */
+
+#ifndef __HIDDATA_H_INCLUDED__
+#define __HIDDATA_H_INCLUDED__
+
+/*
+General Description:
+This module implements an abstraction layer for data transfer over HID feature
+requests. The implementation uses native Windows functions on Windows so that
+no driver installation is required and libusb on Unix. You must link the
+appropriate libraries in either case: "-lhid -lusb -lsetupapi" on Windows and
+`libusb-config --libs` on Unix.
+*/
+
+/* ------------------------------------------------------------------------ */
+
+#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 */
+
+/* ------------------------------------------------------------------------ */
+
+typedef struct usbDevice usbDevice_t;
+/* Opaque data type representing the USB device. This can be a Windows handle
+ * or a libusb handle, depending on the backend implementation.
+ */
+
+/* ------------------------------------------------------------------------ */
+
+int usbhidOpenDevice(usbDevice_t **device, int vendorID, char *vendorName, int productID, char *productName, int usesReportIDs);
+/* This function opens a USB device. 'vendorID' and 'productID' 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, USBOPEN_SUCCESS is returned
+ * and '*device' is set to an opaque pointer representing the device. The
+ * device must be closed with usbhidCloseDevice(). If the device has not been
+ * found or opening failed, an error code is returned.
+ */
+void usbhidCloseDevice(usbDevice_t *device);
+/* Every device opened with usbhidOpenDevice() must be closed with this function.
+ */
+int usbhidSetReport(usbDevice_t *device, char *buffer, int len);
+/* This function sends a feature report to the device. 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 usbhidGetReport(usbDevice_t *device, int reportID, char *buffer, int *len);
+/* This function obtains a feature report from the device. 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 pointed to by
+ * 'len' to the total size of this buffer. Upon successful return, the report
+ * (prefixed with the 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 /* __HIDDATA_H_INCLUDED__ */
diff --git a/libs-host/hidsdi.h b/libs-host/hidsdi.h
new file mode 100644
index 0000000..840afcb
--- /dev/null
+++ b/libs-host/hidsdi.h
@@ -0,0 +1,49 @@
+/* Name: hidsdi.h
+ * Author: Christian Starkjohann
+ * Creation Date: 2006-02-02
+ * Tabsize: 4
+ * Copyright: (c) 2006-2008 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
+ * This Revision: $Id$
+ */
+
+/*
+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/libs-host/opendevice.c b/libs-host/opendevice.c
new file mode 100644
index 0000000..cd41c15
--- /dev/null
+++ b/libs-host/opendevice.c
@@ -0,0 +1,203 @@
+/* Name: opendevice.c
+ * Project: AVR-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) or proprietary (CommercialLicense.txt)
+ * This Revision: $Id$
+ */
+
+/*
+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;
+}
+
+/* ------------------------------------------------------------------------- */
diff --git a/libs-host/opendevice.h b/libs-host/opendevice.h
new file mode 100644
index 0000000..046392e
--- /dev/null
+++ b/libs-host/opendevice.h
@@ -0,0 +1,77 @@
+/* Name: opendevice.h
+ * Project: AVR-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) or proprietary (CommercialLicense.txt)
+ * This Revision: $Id$
+ */
+
+/*
+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.
+*/
+
+#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 USBID-License.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__ */