gobot.io/x/gobot@v1.16.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  /* ------------------------------------------------------------------------- */