usbhid.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. /*******************************************************************************
  2. Copyright 2019 Yepkit Lda (www.yepkit.com)
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. *******************************************************************************/
  13. #include "usbhid.h"
  14. #include <libusb.h>
  15. #include <cstdlib>
  16. #include <string.h>
  17. #include <string>
  18. #include <iostream>
  19. UsbHid::UsbHid()
  20. {
  21. usb_context = NULL;
  22. }
  23. struct hid_device_info *UsbHid::enumerate(unsigned int vendor_id, unsigned int product_id)
  24. {
  25. libusb_device **devs;
  26. libusb_device *dev;
  27. libusb_device_handle *handle;
  28. ssize_t num_devs;
  29. int i = 0;
  30. struct hid_device_info *root = NULL; // Return object. The first device found.
  31. struct hid_device_info *cur_dev = NULL;
  32. if(init() < 0)
  33. return NULL;
  34. num_devs = libusb_get_device_list(usb_context, &devs);
  35. if (num_devs < 0)
  36. return NULL;
  37. while ((dev = devs[i++]) != NULL) {
  38. struct libusb_device_descriptor desc;
  39. int res = libusb_get_device_descriptor(dev, &desc);
  40. if ((desc.idVendor == vendor_id) && (desc.idProduct == product_id)) {
  41. struct hid_device_info *tmp;
  42. // VID/PID match. Create the record.
  43. tmp = (struct hid_device_info*) std::calloc(1, sizeof(struct hid_device_info));
  44. if (cur_dev)
  45. cur_dev->next = tmp;
  46. else
  47. root = tmp;
  48. cur_dev = tmp;
  49. // Fill out the record.
  50. cur_dev->next = NULL;
  51. res = libusb_open(dev, &handle);
  52. if (res >= 0) {
  53. /* Serial Number */
  54. if (desc.iSerialNumber > 0)
  55. cur_dev->serial_number_ascii = get_usb_string_ascii(handle, desc.iSerialNumber);
  56. /* Manufacturer and Product strings */
  57. if (desc.iManufacturer > 0)
  58. cur_dev->manufacturer_string_ascii = get_usb_string_ascii(handle, desc.iManufacturer);
  59. if (desc.iProduct > 0)
  60. cur_dev->product_string_ascii = get_usb_string_ascii(handle, desc.iProduct);
  61. }
  62. libusb_close(handle);
  63. }
  64. }
  65. libusb_free_device_list(devs, 1);
  66. return root;
  67. }
  68. void UsbHid::free_enumeration(struct hid_device_info *devs)
  69. {
  70. struct hid_device_info *d = devs;
  71. while (d) {
  72. struct hid_device_info *next = d->next;
  73. //free(d->path);
  74. free(d->serial_number_ascii);
  75. free(d->manufacturer_string_ascii);
  76. free(d->product_string_ascii);
  77. free(d);
  78. d = next;
  79. }
  80. }
  81. int UsbHid::init()
  82. {
  83. if (!usb_context) {
  84. // Init Libusb
  85. if (libusb_init(&usb_context))
  86. return -1;
  87. }
  88. return 0;
  89. }
  90. char *UsbHid::get_usb_string_ascii(libusb_device_handle *dev, uint8_t idx)
  91. {
  92. unsigned char buf[512];
  93. int len;
  94. wchar_t *str = NULL;
  95. // Get the string from libusb.
  96. //len = libusb_get_string_descriptor(dev, idx, 0x0409, (unsigned char*)buf, sizeof(buf));
  97. len = libusb_get_string_descriptor_ascii(dev, idx, (unsigned char*)buf, sizeof(buf));
  98. if (len < 0)
  99. return NULL;
  100. return (char *)strdup((const char *)buf);
  101. }
  102. int UsbHid::open(unsigned int vendor_id, unsigned int product_id, char *serial)
  103. {
  104. libusb_device **devs;
  105. libusb_device *dev;
  106. libusb_device_handle *handle;
  107. ssize_t num_devs;
  108. int i = 0;
  109. std::string str1, str2;
  110. if (serial != NULL)
  111. str1 = serial;
  112. if(init() < 0)
  113. return -1;
  114. num_devs = libusb_get_device_list(usb_context, &devs);
  115. if (num_devs < 0)
  116. return -1;
  117. //std::cout << "num_devs = " << num_devs << "\n";
  118. while ((dev = devs[i++]) != NULL) {
  119. struct libusb_device_descriptor desc;
  120. int res = libusb_get_device_descriptor(dev, &desc);
  121. if ((desc.idVendor == vendor_id) && (desc.idProduct == product_id)) {
  122. res = libusb_open(dev, &open_device.handle);
  123. //std::cout << "res = libusb_open = " << res << "\n";
  124. if (res >= 0) {
  125. if (serial == NULL) { // Without serial number
  126. struct libusb_device_descriptor desc;
  127. struct libusb_config_descriptor *conf_desc = NULL;
  128. int f,j,k;
  129. libusb_get_device_descriptor(dev, &desc);
  130. if (libusb_get_active_config_descriptor(dev, &conf_desc) < 0) {
  131. std::cout << "cannot get active descriptor\n";
  132. libusb_free_device_list(devs, 1);
  133. libusb_close(open_device.handle);
  134. return -1;
  135. }
  136. //std::cout << "conf_desc->bNumInterfaces = " << (unsigned int)conf_desc->bNumInterfaces << "\n";
  137. for (j = 0; j < conf_desc->bNumInterfaces; j++) {
  138. const struct libusb_interface *intf = &conf_desc->interface[j];
  139. for (k = 0; k < intf->num_altsetting; k++) {
  140. const struct libusb_interface_descriptor *intf_desc;
  141. intf_desc = &intf->altsetting[k];
  142. if (intf_desc->bInterfaceClass == LIBUSB_CLASS_HID) {
  143. //std::cout << "intf_desc->bInterfaceNumber = " << (unsigned int)intf_desc->bInterfaceNumber << "\n";
  144. open_device.interface = intf_desc->bInterfaceNumber;
  145. //std::cout << "intf_desc->bNumEndpoints = " << (unsigned int)intf_desc->bNumEndpoints << "\n";
  146. // Find the INPUT and OUTPUT endpoints. An OUTPUT endpoint is not required.
  147. for (f = 0; f < intf_desc->bNumEndpoints; f++) {
  148. //std::cout << "f = " << f << "\n";
  149. const struct libusb_endpoint_descriptor *ep = &intf_desc->endpoint[f];
  150. /* Determine the type and direction of this
  151. endpoint. */
  152. int is_interrupt =
  153. (ep->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK)
  154. == LIBUSB_TRANSFER_TYPE_INTERRUPT;
  155. int is_output =
  156. (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK)
  157. == LIBUSB_ENDPOINT_OUT;
  158. int is_input =
  159. (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK)
  160. == LIBUSB_ENDPOINT_IN;
  161. /* Decide whether to use it for input or output. */
  162. if (open_device.input_endpoint == 0 &&
  163. is_interrupt && is_input) {
  164. /* Use this endpoint for INPUT */
  165. open_device.input_endpoint = ep->bEndpointAddress;
  166. open_device.input_ep_max_packet_size = ep->wMaxPacketSize;
  167. }
  168. if (open_device.output_endpoint == 0 &&
  169. is_interrupt && is_output) {
  170. /* Use this endpoint for OUTPUT */
  171. open_device.output_endpoint = ep->bEndpointAddress;
  172. }
  173. }
  174. }
  175. }
  176. }
  177. res = libusb_claim_interface(open_device.handle, open_device.interface);
  178. if (res < 0) {
  179. //try detach kernel driver
  180. int detached = 0;
  181. res = libusb_kernel_driver_active(open_device.handle, open_device.interface);
  182. if (res == 1) {
  183. res = libusb_detach_kernel_driver(open_device.handle, open_device.interface);
  184. if (res < 0)
  185. std::cout << "Couldn't detach kernel driver, even though a kernel driver was attached.\n";
  186. else
  187. detached = 1;
  188. }
  189. res = libusb_claim_interface(open_device.handle, open_device.interface);
  190. if (res < 0) {
  191. std::cout << "cannot claim interface\n";
  192. libusb_free_device_list(devs, 1);
  193. libusb_free_config_descriptor(conf_desc);
  194. libusb_close(open_device.handle);
  195. return -1;
  196. }
  197. }
  198. //std::cout << "debug claim interface: " << res << "\n";
  199. /* Store off the string descriptor indexes */
  200. open_device.manufacturer_index = desc.iManufacturer;
  201. open_device.product_index = desc.iProduct;
  202. open_device.serial_index = desc.iSerialNumber;
  203. libusb_free_device_list(devs, 1);
  204. libusb_free_config_descriptor(conf_desc);
  205. return 0; //Success
  206. } else if (desc.iSerialNumber > 0) { // With serial number
  207. str2 = get_usb_string_ascii(open_device.handle, desc.iSerialNumber);
  208. if ( str1.compare(str2) == 0 ) {
  209. //std::cout << "Serial found\n";
  210. struct libusb_device_descriptor desc;
  211. struct libusb_config_descriptor *conf_desc = NULL;
  212. int f,j,k;
  213. libusb_get_device_descriptor(dev, &desc);
  214. if (libusb_get_active_config_descriptor(dev, &conf_desc) < 0) {
  215. std::cout << "cannot get active descriptor\n";
  216. libusb_free_device_list(devs, 1);
  217. libusb_close(open_device.handle);
  218. return -1;
  219. }
  220. //std::cout << "conf_desc->bNumInterfaces = " << (unsigned int)conf_desc->bNumInterfaces << "\n";
  221. for (j = 0; j < conf_desc->bNumInterfaces; j++) {
  222. const struct libusb_interface *intf = &conf_desc->interface[j];
  223. for (k = 0; k < intf->num_altsetting; k++) {
  224. const struct libusb_interface_descriptor *intf_desc;
  225. intf_desc = &intf->altsetting[k];
  226. if (intf_desc->bInterfaceClass == LIBUSB_CLASS_HID) {
  227. //std::cout << "intf_desc->bInterfaceNumber = " << (unsigned int)intf_desc->bInterfaceNumber << "\n";
  228. open_device.interface = intf_desc->bInterfaceNumber;
  229. //std::cout << "intf_desc->bNumEndpoints = " << (unsigned int)intf_desc->bNumEndpoints << "\n";
  230. // Find the INPUT and OUTPUT endpoints. An OUTPUT endpoint is not required.
  231. for (f = 0; f < intf_desc->bNumEndpoints; f++) {
  232. //std::cout << "f = " << f << "\n";
  233. const struct libusb_endpoint_descriptor *ep = &intf_desc->endpoint[f];
  234. /* Determine the type and direction of this
  235. endpoint. */
  236. int is_interrupt =
  237. (ep->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK)
  238. == LIBUSB_TRANSFER_TYPE_INTERRUPT;
  239. int is_output =
  240. (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK)
  241. == LIBUSB_ENDPOINT_OUT;
  242. int is_input =
  243. (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK)
  244. == LIBUSB_ENDPOINT_IN;
  245. /* Decide whether to use it for input or output. */
  246. if (open_device.input_endpoint == 0 &&
  247. is_interrupt && is_input) {
  248. /* Use this endpoint for INPUT */
  249. open_device.input_endpoint = ep->bEndpointAddress;
  250. open_device.input_ep_max_packet_size = ep->wMaxPacketSize;
  251. }
  252. if (open_device.output_endpoint == 0 &&
  253. is_interrupt && is_output) {
  254. /* Use this endpoint for OUTPUT */
  255. open_device.output_endpoint = ep->bEndpointAddress;
  256. }
  257. }
  258. }
  259. }
  260. }
  261. /*
  262. int detached = 0;
  263. res = libusb_kernel_driver_active(open_device.handle, open_device.interface);
  264. if (res == 1) {
  265. res = libusb_detach_kernel_driver(open_device.handle, open_device.interface);
  266. if (res < 0)
  267. std::cout << "Couldn't detach kernel driver, even though a kernel driver was attached.\n";
  268. else
  269. detached = 1;
  270. }
  271. */
  272. res = libusb_claim_interface(open_device.handle, open_device.interface);
  273. if (res < 0) {
  274. //try detach kernel driver
  275. int detached = 0;
  276. res = libusb_kernel_driver_active(open_device.handle, open_device.interface);
  277. if (res == 1) {
  278. res = libusb_detach_kernel_driver(open_device.handle, open_device.interface);
  279. if (res < 0)
  280. std::cout << "Couldn't detach kernel driver, even though a kernel driver was attached.\n";
  281. else
  282. detached = 1;
  283. }
  284. res = libusb_claim_interface(open_device.handle, open_device.interface);
  285. if (res < 0) {
  286. std::cout << "cannot claim interface\n";
  287. libusb_free_device_list(devs, 1);
  288. libusb_free_config_descriptor(conf_desc);
  289. libusb_close(open_device.handle);
  290. return -1;
  291. }
  292. }
  293. //std::cout << "debug claim interface: " << res << "\n";
  294. /* Store off the string descriptor indexes */
  295. open_device.manufacturer_index = desc.iManufacturer;
  296. open_device.product_index = desc.iProduct;
  297. open_device.serial_index = desc.iSerialNumber;
  298. libusb_free_device_list(devs, 1);
  299. libusb_free_config_descriptor(conf_desc);
  300. return 0; //Success
  301. }
  302. }
  303. }
  304. libusb_close(open_device.handle);
  305. }
  306. }
  307. libusb_free_device_list(devs, 1);
  308. return -1;
  309. }
  310. void UsbHid::close() {
  311. libusb_close(open_device.handle);
  312. }
  313. int UsbHid::write(unsigned char *data, size_t length)
  314. {
  315. int res;
  316. /* Use the interrupt out endpoint */
  317. int actual_length;
  318. res = libusb_interrupt_transfer(open_device.handle,
  319. open_device.output_endpoint,
  320. (unsigned char*)data,
  321. length,
  322. &actual_length, 1000);
  323. //std::cout << "Interrupt transfer used\n";
  324. if (res < 0)
  325. return -1;
  326. return actual_length;
  327. }
  328. int UsbHid::read(unsigned char *data, int length)
  329. {
  330. int res;
  331. int report_number = data[0];
  332. int skipped_report_id = 0;
  333. int actual_length;
  334. res = libusb_interrupt_transfer(open_device.handle,
  335. open_device.input_endpoint,
  336. data,
  337. length,
  338. &actual_length, 5000);
  339. //std::cout << "read res = " << res << "\n";
  340. if (res < 0)
  341. return -1;
  342. return actual_length;
  343. }