aboutsummaryrefslogtreecommitdiffstats
path: root/libs-host/opendevice.c
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/opendevice.c
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/opendevice.c')
-rw-r--r--libs-host/opendevice.c203
1 files changed, 203 insertions, 0 deletions
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;
+}
+
+/* ------------------------------------------------------------------------- */