opendevice.c 8.5 KB

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