opendevice.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. /*
  2. * =====================================================================================
  3. *
  4. * ________ .__ __ ________ ____ ________
  5. * \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
  6. * / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
  7. * / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
  8. * \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
  9. * \__> \/ \/ \/ \/ \/
  10. *
  11. * www.optixx.org
  12. *
  13. *
  14. * Version: 1.0
  15. * Created: 07/21/2009 03:32:16 PM
  16. * Author: david@optixx.org
  17. * Based on: custom-class, a basic USB example
  18. * Author: Christian Starkjohann
  19. * =====================================================================================
  20. */
  21. #include <stdio.h>
  22. #include "opendevice.h"
  23. /*
  24. * -------------------------------------------------------------------------
  25. */
  26. #define MATCH_SUCCESS 1
  27. #define MATCH_FAILED 0
  28. #define MATCH_ABORT -1
  29. /*
  30. * private interface: match text and p, return MATCH_SUCCESS, MATCH_FAILED, or
  31. * MATCH_ABORT.
  32. */
  33. static int _shellStyleMatch(char *text, char *p)
  34. {
  35. int last,
  36. matched,
  37. reverse;
  38. for (; *p; text++, p++) {
  39. if (*text == 0 && *p != '*')
  40. return MATCH_ABORT;
  41. switch (*p) {
  42. case '\\':
  43. /*
  44. * Literal match with following character.
  45. */
  46. p++;
  47. /*
  48. * FALLTHROUGH
  49. */
  50. default:
  51. if (*text != *p)
  52. return MATCH_FAILED;
  53. continue;
  54. case '?':
  55. /*
  56. * Match anything.
  57. */
  58. continue;
  59. case '*':
  60. while (*++p == '*')
  61. /*
  62. * Consecutive stars act just like one.
  63. */
  64. continue;
  65. if (*p == 0)
  66. /*
  67. * Trailing star matches everything.
  68. */
  69. return MATCH_SUCCESS;
  70. while (*text)
  71. if ((matched = _shellStyleMatch(text++, p)) != MATCH_FAILED)
  72. return matched;
  73. return MATCH_ABORT;
  74. case '[':
  75. reverse = p[1] == '^';
  76. if (reverse) /* Inverted character class. */
  77. p++;
  78. matched = MATCH_FAILED;
  79. if (p[1] == ']' || p[1] == '-')
  80. if (*++p == *text)
  81. matched = MATCH_SUCCESS;
  82. for (last = *p; *++p && *p != ']'; last = *p)
  83. if (*p == '-' && p[1] != ']' ? *text <= *++p
  84. && *text >= last : *text == *p)
  85. matched = MATCH_SUCCESS;
  86. if (matched == reverse)
  87. return MATCH_FAILED;
  88. continue;
  89. }
  90. }
  91. return *text == 0;
  92. }
  93. /*
  94. * public interface for shell style matching: returns 0 if fails, 1 if matches
  95. */
  96. static int shellStyleMatch(char *text, char *pattern)
  97. {
  98. if (pattern == NULL) /* NULL pattern is synonymous to "*" */
  99. return 1;
  100. return _shellStyleMatch(text, pattern) == MATCH_SUCCESS;
  101. }
  102. /*
  103. * -------------------------------------------------------------------------
  104. */
  105. int usbGetStringAscii(usb_dev_handle * dev, int index, char *buf, int buflen)
  106. {
  107. char buffer[256];
  108. int rval,
  109. i;
  110. if ((rval = usb_get_string_simple(dev, index, buf, buflen)) >= 0) /* use
  111. * libusb
  112. * version
  113. * if
  114. * it
  115. * works
  116. */
  117. return rval;
  118. if ((rval =
  119. usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,
  120. (USB_DT_STRING << 8) + index, 0x0409, buffer,
  121. sizeof(buffer), 5000)) < 0)
  122. return rval;
  123. if (buffer[1] != USB_DT_STRING) {
  124. *buf = 0;
  125. return 0;
  126. }
  127. if ((unsigned char) buffer[0] < rval)
  128. rval = (unsigned char) buffer[0];
  129. rval /= 2;
  130. /*
  131. * lossy conversion to ISO Latin1:
  132. */
  133. for (i = 1; i < rval; i++) {
  134. if (i > buflen) /* destination buffer overflow */
  135. break;
  136. buf[i - 1] = buffer[2 * i];
  137. if (buffer[2 * i + 1] != 0) /* outside of ISO Latin1 range */
  138. buf[i - 1] = '?';
  139. }
  140. buf[i - 1] = 0;
  141. return i - 1;
  142. }
  143. /*
  144. * -------------------------------------------------------------------------
  145. */
  146. int usbOpenDevice(usb_dev_handle ** device, int vendorID,
  147. char *vendorNamePattern, int productID,
  148. char *productNamePattern, char *serialNamePattern,
  149. FILE * printMatchingDevicesFp, FILE * warningsFp)
  150. {
  151. struct usb_bus *bus;
  152. struct usb_device *dev;
  153. usb_dev_handle *handle = NULL;
  154. int errorCode = USBOPEN_ERR_NOTFOUND;
  155. usb_find_busses();
  156. usb_find_devices();
  157. for (bus = usb_get_busses(); bus; bus = bus->next) {
  158. for (dev = bus->devices; dev; dev = dev->next) { /* iterate over
  159. * all devices
  160. * on all
  161. * busses */
  162. if ((vendorID == 0 || dev->descriptor.idVendor == vendorID)
  163. && (productID == 0 || dev->descriptor.idProduct == productID)) {
  164. char vendor[256],
  165. product[256],
  166. serial[256];
  167. int len;
  168. handle = usb_open(dev); /* we need to open the device in order
  169. * to query strings */
  170. if (!handle) {
  171. errorCode = USBOPEN_ERR_ACCESS;
  172. if (warningsFp != NULL)
  173. fprintf(warningsFp,
  174. "Warning: cannot open VID=0x%04x PID=0x%04x: %s\n",
  175. dev->descriptor.idVendor,
  176. dev->descriptor.idProduct, usb_strerror());
  177. continue;
  178. }
  179. /*
  180. * now check whether the names match:
  181. */
  182. len = vendor[0] = 0;
  183. if (dev->descriptor.iManufacturer > 0) {
  184. len =
  185. usbGetStringAscii(handle, dev->descriptor.iManufacturer,
  186. vendor, sizeof(vendor));
  187. }
  188. if (len < 0) {
  189. errorCode = USBOPEN_ERR_ACCESS;
  190. if (warningsFp != NULL)
  191. fprintf(warningsFp,
  192. "Warning: cannot query manufacturer for VID=0x%04x PID=0x%04x: %s\n",
  193. dev->descriptor.idVendor,
  194. dev->descriptor.idProduct, usb_strerror());
  195. } else {
  196. errorCode = USBOPEN_ERR_NOTFOUND;
  197. /*
  198. * printf("seen device from vendor ->%s<-\n", vendor);
  199. */
  200. if (shellStyleMatch(vendor, vendorNamePattern)) {
  201. len = product[0] = 0;
  202. if (dev->descriptor.iProduct > 0) {
  203. len =
  204. usbGetStringAscii(handle,
  205. dev->descriptor.iProduct,
  206. product, sizeof(product));
  207. }
  208. if (len < 0) {
  209. errorCode = USBOPEN_ERR_ACCESS;
  210. if (warningsFp != NULL)
  211. fprintf(warningsFp,
  212. "Warning: cannot query product for VID=0x%04x PID=0x%04x: %s\n",
  213. dev->descriptor.idVendor,
  214. dev->descriptor.idProduct,
  215. usb_strerror());
  216. } else {
  217. errorCode = USBOPEN_ERR_NOTFOUND;
  218. /*
  219. * printf("seen product ->%s<-\n", product);
  220. */
  221. if (shellStyleMatch(product, productNamePattern)) {
  222. len = serial[0] = 0;
  223. if (dev->descriptor.iSerialNumber > 0) {
  224. len =
  225. usbGetStringAscii(handle,
  226. dev->descriptor.
  227. iSerialNumber, serial,
  228. sizeof(serial));
  229. }
  230. if (len < 0) {
  231. errorCode = USBOPEN_ERR_ACCESS;
  232. if (warningsFp != NULL)
  233. fprintf(warningsFp,
  234. "Warning: cannot query serial for VID=0x%04x PID=0x%04x: %s\n",
  235. dev->descriptor.idVendor,
  236. dev->descriptor.idProduct,
  237. usb_strerror());
  238. }
  239. if (shellStyleMatch(serial, serialNamePattern)) {
  240. if (printMatchingDevicesFp != NULL) {
  241. if (serial[0] == 0) {
  242. fprintf(printMatchingDevicesFp,
  243. "VID=0x%04x PID=0x%04x vendor=\"%s\" product=\"%s\"\n",
  244. dev->descriptor.idVendor,
  245. dev->descriptor.idProduct,
  246. vendor, product);
  247. } else {
  248. fprintf(printMatchingDevicesFp,
  249. "VID=0x%04x PID=0x%04x vendor=\"%s\" product=\"%s\" serial=\"%s\"\n",
  250. dev->descriptor.idVendor,
  251. dev->descriptor.idProduct,
  252. vendor, product, serial);
  253. }
  254. } else {
  255. break;
  256. }
  257. }
  258. }
  259. }
  260. }
  261. }
  262. usb_close(handle);
  263. handle = NULL;
  264. }
  265. }
  266. if (handle) /* we have found a deice */
  267. break;
  268. }
  269. if (handle != NULL) {
  270. errorCode = 0;
  271. *device = handle;
  272. }
  273. if (printMatchingDevicesFp != NULL) /* never return an error for listing
  274. * only */
  275. errorCode = 0;
  276. return errorCode;
  277. }
  278. /*
  279. * -------------------------------------------------------------------------
  280. */