gobot.io/x/gobot/v2@v2.1.0/platforms/digispark/opendevice.c (about) 1 /* Name: opendevice.c 2 * Project: V-USB host-side library 3 * Author: Christian Starkjohann 4 * Creation Date: 2008-04-10 5 * Tabsize: 4 6 * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH 7 * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) 8 * This Revision: $Id: opendevice.c 740 2009-04-13 18:23:31Z cs $ 9 */ 10 11 /* 12 General Description: 13 The functions in this module can be used to find and open a device based on 14 libusb or libusb-win32. 15 */ 16 17 #include <stdio.h> 18 #include "opendevice.h" 19 20 /* ------------------------------------------------------------------------- */ 21 22 #define MATCH_SUCCESS 1 23 #define MATCH_FAILED 0 24 #define MATCH_ABORT -1 25 26 /* private interface: match text and p, return MATCH_SUCCESS, MATCH_FAILED, or MATCH_ABORT. */ 27 static int _shellStyleMatch(char *text, char *p) 28 { 29 int last, matched, reverse; 30 31 for(; *p; text++, p++){ 32 if(*text == 0 && *p != '*') 33 return MATCH_ABORT; 34 switch(*p){ 35 case '\\': 36 /* Literal match with following character. */ 37 p++; 38 /* FALLTHROUGH */ 39 default: 40 if(*text != *p) 41 return MATCH_FAILED; 42 continue; 43 case '?': 44 /* Match anything. */ 45 continue; 46 case '*': 47 while(*++p == '*') 48 /* Consecutive stars act just like one. */ 49 continue; 50 if(*p == 0) 51 /* Trailing star matches everything. */ 52 return MATCH_SUCCESS; 53 while(*text) 54 if((matched = _shellStyleMatch(text++, p)) != MATCH_FAILED) 55 return matched; 56 return MATCH_ABORT; 57 case '[': 58 reverse = p[1] == '^'; 59 if(reverse) /* Inverted character class. */ 60 p++; 61 matched = MATCH_FAILED; 62 if(p[1] == ']' || p[1] == '-') 63 if(*++p == *text) 64 matched = MATCH_SUCCESS; 65 for(last = *p; *++p && *p != ']'; last = *p) 66 if (*p == '-' && p[1] != ']' ? *text <= *++p && *text >= last : *text == *p) 67 matched = MATCH_SUCCESS; 68 if(matched == reverse) 69 return MATCH_FAILED; 70 continue; 71 } 72 } 73 return *text == 0; 74 } 75 76 /* public interface for shell style matching: returns 0 if fails, 1 if matches */ 77 static int shellStyleMatch(char *text, char *pattern) 78 { 79 if(pattern == NULL) /* NULL pattern is synonymous to "*" */ 80 return 1; 81 return _shellStyleMatch(text, pattern) == MATCH_SUCCESS; 82 } 83 84 /* ------------------------------------------------------------------------- */ 85 86 int usbGetStringAscii(usb_dev_handle *dev, int index, char *buf, int buflen) 87 { 88 char buffer[256]; 89 int rval, i; 90 91 if((rval = usb_get_string_simple(dev, index, buf, buflen)) >= 0) /* use libusb version if it works */ 92 return rval; 93 if((rval = usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) + index, 0x0409, buffer, sizeof(buffer), 5000)) < 0) 94 return rval; 95 if(buffer[1] != USB_DT_STRING){ 96 *buf = 0; 97 return 0; 98 } 99 if((unsigned char)buffer[0] < rval) 100 rval = (unsigned char)buffer[0]; 101 rval /= 2; 102 /* lossy conversion to ISO Latin1: */ 103 for(i=1;i<rval;i++){ 104 if(i > buflen) /* destination buffer overflow */ 105 break; 106 buf[i-1] = buffer[2 * i]; 107 if(buffer[2 * i + 1] != 0) /* outside of ISO Latin1 range */ 108 buf[i-1] = '?'; 109 } 110 buf[i-1] = 0; 111 return i-1; 112 } 113 114 /* ------------------------------------------------------------------------- */ 115 116 int usbOpenDevice(usb_dev_handle **device, int vendorID, char *vendorNamePattern, int productID, char *productNamePattern, char *serialNamePattern, FILE *printMatchingDevicesFp, FILE *warningsFp) 117 { 118 struct usb_bus *bus; 119 struct usb_device *dev; 120 usb_dev_handle *handle = NULL; 121 int errorCode = USBOPEN_ERR_NOTFOUND; 122 123 usb_find_busses(); 124 usb_find_devices(); 125 for(bus = usb_get_busses(); bus; bus = bus->next){ 126 for(dev = bus->devices; dev; dev = dev->next){ /* iterate over all devices on all busses */ 127 if((vendorID == 0 || dev->descriptor.idVendor == vendorID) 128 && (productID == 0 || dev->descriptor.idProduct == productID)){ 129 char vendor[256], product[256], serial[256]; 130 int len; 131 handle = usb_open(dev); /* we need to open the device in order to query strings */ 132 if(!handle){ 133 errorCode = USBOPEN_ERR_ACCESS; 134 if(warningsFp != NULL) 135 fprintf(warningsFp, "Warning: cannot open VID=0x%04x PID=0x%04x: %s\n", dev->descriptor.idVendor, dev->descriptor.idProduct, usb_strerror()); 136 continue; 137 } 138 /* now check whether the names match: */ 139 len = vendor[0] = 0; 140 if(dev->descriptor.iManufacturer > 0){ 141 len = usbGetStringAscii(handle, dev->descriptor.iManufacturer, vendor, sizeof(vendor)); 142 } 143 if(len < 0){ 144 errorCode = USBOPEN_ERR_ACCESS; 145 if(warningsFp != NULL) 146 fprintf(warningsFp, "Warning: cannot query manufacturer for VID=0x%04x PID=0x%04x: %s\n", dev->descriptor.idVendor, dev->descriptor.idProduct, usb_strerror()); 147 }else{ 148 errorCode = USBOPEN_ERR_NOTFOUND; 149 /* printf("seen device from vendor ->%s<-\n", vendor); */ 150 if(shellStyleMatch(vendor, vendorNamePattern)){ 151 len = product[0] = 0; 152 if(dev->descriptor.iProduct > 0){ 153 len = usbGetStringAscii(handle, dev->descriptor.iProduct, product, sizeof(product)); 154 } 155 if(len < 0){ 156 errorCode = USBOPEN_ERR_ACCESS; 157 if(warningsFp != NULL) 158 fprintf(warningsFp, "Warning: cannot query product for VID=0x%04x PID=0x%04x: %s\n", dev->descriptor.idVendor, dev->descriptor.idProduct, usb_strerror()); 159 }else{ 160 errorCode = USBOPEN_ERR_NOTFOUND; 161 /* printf("seen product ->%s<-\n", product); */ 162 if(shellStyleMatch(product, productNamePattern)){ 163 len = serial[0] = 0; 164 if(dev->descriptor.iSerialNumber > 0){ 165 len = usbGetStringAscii(handle, dev->descriptor.iSerialNumber, serial, sizeof(serial)); 166 } 167 if(len < 0){ 168 errorCode = USBOPEN_ERR_ACCESS; 169 if(warningsFp != NULL) 170 fprintf(warningsFp, "Warning: cannot query serial for VID=0x%04x PID=0x%04x: %s\n", dev->descriptor.idVendor, dev->descriptor.idProduct, usb_strerror()); 171 } 172 if(shellStyleMatch(serial, serialNamePattern)){ 173 if(printMatchingDevicesFp != NULL){ 174 if(serial[0] == 0){ 175 fprintf(printMatchingDevicesFp, "VID=0x%04x PID=0x%04x vendor=\"%s\" product=\"%s\"\n", dev->descriptor.idVendor, dev->descriptor.idProduct, vendor, product); 176 }else{ 177 fprintf(printMatchingDevicesFp, "VID=0x%04x PID=0x%04x vendor=\"%s\" product=\"%s\" serial=\"%s\"\n", dev->descriptor.idVendor, dev->descriptor.idProduct, vendor, product, serial); 178 } 179 }else{ 180 break; 181 } 182 } 183 } 184 } 185 } 186 } 187 usb_close(handle); 188 handle = NULL; 189 } 190 } 191 if(handle) /* we have found a deice */ 192 break; 193 } 194 if(handle != NULL){ 195 errorCode = 0; 196 *device = handle; 197 } 198 if(printMatchingDevicesFp != NULL) /* never return an error for listing only */ 199 errorCode = 0; 200 return errorCode; 201 } 202 203 /* ------------------------------------------------------------------------- */