/* * 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 #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; } /* * ------------------------------------------------------------------------- */