opendevice.c 12 KB

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