lowlevel.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /*
  2. * Copyright 2012-2013 Luke Dashjr
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms of the GNU General Public License as published by the Free
  6. * Software Foundation; either version 3 of the License, or (at your option)
  7. * any later version. See COPYING for more details.
  8. */
  9. #include "config.h"
  10. #include <stdint.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <utlist.h>
  14. #include "logging.h"
  15. #include "lowlevel.h"
  16. static struct lowlevel_device_info *devinfo_list;
  17. void lowlevel_devinfo_semicpy(struct lowlevel_device_info * const dst, const struct lowlevel_device_info * const src)
  18. {
  19. #define COPYSTR(key) BFGINIT(dst->key, maybe_strdup(src->key))
  20. COPYSTR(manufacturer);
  21. COPYSTR(product);
  22. COPYSTR(serial);
  23. COPYSTR(path);
  24. COPYSTR(devid);
  25. BFGINIT(dst->vid, src->vid);
  26. BFGINIT(dst->pid, src->pid);
  27. }
  28. void lowlevel_devinfo_free(struct lowlevel_device_info * const info)
  29. {
  30. if (info->ref--)
  31. return;
  32. if (info->lowl->devinfo_free)
  33. info->lowl->devinfo_free(info);
  34. free(info->manufacturer);
  35. free(info->product);
  36. free(info->serial);
  37. free(info->path);
  38. free(info->devid);
  39. free(info);
  40. }
  41. struct lowlevel_device_info *lowlevel_ref(const struct lowlevel_device_info * const cinfo)
  42. {
  43. struct lowlevel_device_info * const info = (void*)cinfo;
  44. ++info->ref;
  45. return info;
  46. }
  47. void lowlevel_scan_free()
  48. {
  49. if (!devinfo_list)
  50. return;
  51. struct lowlevel_device_info *info, *tmp;
  52. LL_FOREACH_SAFE(devinfo_list, info, tmp)
  53. {
  54. LL_DELETE(devinfo_list, info);
  55. lowlevel_devinfo_free(info);
  56. }
  57. }
  58. struct lowlevel_device_info *lowlevel_scan()
  59. {
  60. struct lowlevel_device_info *devinfo_mid_list;
  61. lowlevel_scan_free();
  62. #ifdef HAVE_LIBUSB
  63. devinfo_mid_list = lowl_usb.devinfo_scan();
  64. LL_CONCAT(devinfo_list, devinfo_mid_list);
  65. #endif
  66. #ifdef USE_X6500
  67. devinfo_mid_list = lowl_ft232r.devinfo_scan();
  68. LL_CONCAT(devinfo_list, devinfo_mid_list);
  69. #endif
  70. #ifdef NEED_BFG_LOWL_HID
  71. devinfo_mid_list = lowl_hid.devinfo_scan();
  72. LL_CONCAT(devinfo_list, devinfo_mid_list);
  73. #endif
  74. #ifdef USE_NANOFURY
  75. devinfo_mid_list = lowl_mcp2210.devinfo_scan();
  76. LL_CONCAT(devinfo_list, devinfo_mid_list);
  77. #endif
  78. #ifdef HAVE_FPGAUTILS
  79. devinfo_mid_list = lowl_vcom.devinfo_scan();
  80. LL_CONCAT(devinfo_list, devinfo_mid_list);
  81. #endif
  82. LL_FOREACH(devinfo_list, devinfo_mid_list)
  83. {
  84. applog(LOG_DEBUG, "%s: Found %s device at %s (path=%s, vid=%04x, pid=%04x, manuf=%s, prod=%s, serial=%s)",
  85. __func__,
  86. devinfo_mid_list->lowl->dname,
  87. devinfo_mid_list->devid,
  88. devinfo_mid_list->path,
  89. (unsigned)devinfo_mid_list->vid, (unsigned)devinfo_mid_list->pid,
  90. devinfo_mid_list->manufacturer, devinfo_mid_list->product, devinfo_mid_list->serial);
  91. }
  92. return devinfo_list;
  93. }
  94. bool _lowlevel_match_product(const struct lowlevel_device_info * const info, const char ** const needles)
  95. {
  96. if (!info->product)
  97. return false;
  98. for (int i = 0; needles[i]; ++i)
  99. if (!strstr(info->product, needles[i]))
  100. return false;
  101. return true;
  102. }
  103. bool lowlevel_match_id(const struct lowlevel_device_info * const info, const struct lowlevel_driver * const lowl, const int32_t vid, const int32_t pid)
  104. {
  105. if (info->lowl != lowl)
  106. return false;
  107. if (vid != -1 && vid != info->vid)
  108. return false;
  109. if (pid != -1 && pid != info->pid)
  110. return false;
  111. return true;
  112. }
  113. #define DETECT_BEGIN \
  114. struct lowlevel_device_info *info, *tmp; \
  115. int found = 0; \
  116. \
  117. LL_FOREACH_SAFE(devinfo_list, info, tmp) \
  118. { \
  119. // END DETECT_BEGIN
  120. #define DETECT_END \
  121. if (!cb(info, userp)) \
  122. continue; \
  123. LL_DELETE(devinfo_list, info); \
  124. ++found; \
  125. } \
  126. return found; \
  127. // END DETECT_END
  128. int _lowlevel_detect(lowl_found_devinfo_func_t cb, const char *serial, const char **product_needles, void * const userp)
  129. {
  130. DETECT_BEGIN
  131. if (serial && ((!info->serial) || strcmp(serial, info->serial)))
  132. continue;
  133. if (product_needles[0] && !_lowlevel_match_product(info, product_needles))
  134. continue;
  135. DETECT_END
  136. }
  137. int lowlevel_detect_id(const lowl_found_devinfo_func_t cb, void * const userp, const struct lowlevel_driver * const lowl, const int32_t vid, const int32_t pid)
  138. {
  139. DETECT_BEGIN
  140. if (!lowlevel_match_id(info, lowl, vid, pid))
  141. continue;
  142. DETECT_END
  143. }