haiku_usb_raw.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /*
  2. * Haiku Backend for libusb
  3. * Copyright © 2014 Akshay Jaggi <akshay1994.leo@gmail.com>
  4. *
  5. * This library is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Lesser General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2.1 of the License, or (at your option) any later version.
  9. *
  10. * This library is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public
  16. * License along with this library; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  18. */
  19. #include <unistd.h>
  20. #include <string.h>
  21. #include <stdlib.h>
  22. #include <new>
  23. #include <vector>
  24. #include "haiku_usb.h"
  25. USBRoster gUsbRoster;
  26. int32 gInitCount = 0;
  27. static int haiku_get_config_descriptor(struct libusb_device *, uint8_t,
  28. void *, size_t);
  29. static int
  30. haiku_init(struct libusb_context *ctx)
  31. {
  32. UNUSED(ctx);
  33. if (atomic_add(&gInitCount, 1) == 0)
  34. return gUsbRoster.Start();
  35. return LIBUSB_SUCCESS;
  36. }
  37. static void
  38. haiku_exit(struct libusb_context *ctx)
  39. {
  40. UNUSED(ctx);
  41. if (atomic_add(&gInitCount, -1) == 1)
  42. gUsbRoster.Stop();
  43. }
  44. static int
  45. haiku_open(struct libusb_device_handle *dev_handle)
  46. {
  47. USBDevice *dev = *((USBDevice **)usbi_get_device_priv(dev_handle->dev));
  48. USBDeviceHandle *handle = new(std::nothrow) USBDeviceHandle(dev);
  49. if (handle == NULL)
  50. return LIBUSB_ERROR_NO_MEM;
  51. if (handle->InitCheck() == false) {
  52. delete handle;
  53. return LIBUSB_ERROR_NO_DEVICE;
  54. }
  55. *((USBDeviceHandle **)usbi_get_device_handle_priv(dev_handle)) = handle;
  56. return LIBUSB_SUCCESS;
  57. }
  58. static void
  59. haiku_close(struct libusb_device_handle *dev_handle)
  60. {
  61. USBDeviceHandle **pHandle = (USBDeviceHandle **)usbi_get_device_handle_priv(dev_handle);
  62. USBDeviceHandle *handle = *pHandle;
  63. if (handle == NULL)
  64. return;
  65. delete handle;
  66. *pHandle = NULL;
  67. }
  68. static int
  69. haiku_get_active_config_descriptor(struct libusb_device *device, void *buffer, size_t len)
  70. {
  71. USBDevice *dev = *((USBDevice **)usbi_get_device_priv(device));
  72. return haiku_get_config_descriptor(device, dev->ActiveConfigurationIndex(), buffer, len);
  73. }
  74. static int
  75. haiku_get_config_descriptor(struct libusb_device *device, uint8_t config_index, void *buffer, size_t len)
  76. {
  77. USBDevice *dev = *((USBDevice **)usbi_get_device_priv(device));
  78. const usb_configuration_descriptor *config = dev->ConfigurationDescriptor(config_index);
  79. if (config == NULL) {
  80. usbi_err(DEVICE_CTX(device), "failed getting configuration descriptor");
  81. return LIBUSB_ERROR_IO;
  82. }
  83. if (len > config->total_length) {
  84. len = config->total_length;
  85. }
  86. memcpy(buffer, config, len);
  87. return len;
  88. }
  89. static int
  90. haiku_set_configuration(struct libusb_device_handle *dev_handle, int config)
  91. {
  92. USBDeviceHandle *handle= *((USBDeviceHandle **)usbi_get_device_handle_priv(dev_handle));
  93. if (config <= 0)
  94. return LIBUSB_ERROR_NOT_SUPPORTED; // cannot unconfigure
  95. return handle->SetConfiguration((uint8)config);
  96. }
  97. static int
  98. haiku_claim_interface(struct libusb_device_handle *dev_handle, uint8_t interface_number)
  99. {
  100. USBDeviceHandle *handle = *((USBDeviceHandle **)usbi_get_device_handle_priv(dev_handle));
  101. return handle->ClaimInterface(interface_number);
  102. }
  103. static int
  104. haiku_set_altsetting(struct libusb_device_handle *dev_handle, uint8_t interface_number, uint8_t altsetting)
  105. {
  106. USBDeviceHandle *handle = *((USBDeviceHandle **)usbi_get_device_handle_priv(dev_handle));
  107. return handle->SetAltSetting(interface_number, altsetting);
  108. }
  109. static int
  110. haiku_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
  111. {
  112. USBDeviceHandle *handle = *((USBDeviceHandle **)usbi_get_device_handle_priv(dev_handle));
  113. return handle->ClearHalt(endpoint);
  114. }
  115. static int
  116. haiku_release_interface(struct libusb_device_handle *dev_handle, uint8_t interface_number)
  117. {
  118. USBDeviceHandle *handle = *((USBDeviceHandle **)usbi_get_device_handle_priv(dev_handle));
  119. haiku_set_altsetting(dev_handle, interface_number, 0);
  120. return handle->ReleaseInterface(interface_number);
  121. }
  122. static int
  123. haiku_submit_transfer(struct usbi_transfer *itransfer)
  124. {
  125. struct libusb_transfer *fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
  126. USBDeviceHandle *fDeviceHandle = *((USBDeviceHandle **)usbi_get_device_handle_priv(fLibusbTransfer->dev_handle));
  127. return fDeviceHandle->SubmitTransfer(itransfer);
  128. }
  129. static int
  130. haiku_cancel_transfer(struct usbi_transfer *itransfer)
  131. {
  132. struct libusb_transfer *fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
  133. USBDeviceHandle *fDeviceHandle = *((USBDeviceHandle **)usbi_get_device_handle_priv(fLibusbTransfer->dev_handle));
  134. return fDeviceHandle->CancelTransfer(*((USBTransfer **)usbi_get_transfer_priv(itransfer)));
  135. }
  136. static int
  137. haiku_handle_transfer_completion(struct usbi_transfer *itransfer)
  138. {
  139. USBTransfer **pTransfer = (USBTransfer **)usbi_get_transfer_priv(itransfer);
  140. USBTransfer *transfer = *pTransfer;
  141. usbi_mutex_lock(&itransfer->lock);
  142. if (transfer->IsCancelled()) {
  143. delete transfer;
  144. *pTransfer = NULL;
  145. usbi_mutex_unlock(&itransfer->lock);
  146. if (itransfer->transferred < 0)
  147. itransfer->transferred = 0;
  148. return usbi_handle_transfer_cancellation(itransfer);
  149. }
  150. libusb_transfer_status status = LIBUSB_TRANSFER_COMPLETED;
  151. if (itransfer->transferred < 0) {
  152. usbi_err(ITRANSFER_CTX(itransfer), "error in transfer");
  153. status = LIBUSB_TRANSFER_ERROR;
  154. itransfer->transferred = 0;
  155. }
  156. delete transfer;
  157. *pTransfer = NULL;
  158. usbi_mutex_unlock(&itransfer->lock);
  159. return usbi_handle_transfer_completion(itransfer, status);
  160. }
  161. const struct usbi_os_backend usbi_backend = {
  162. /*.name =*/ "Haiku usbfs",
  163. /*.caps =*/ 0,
  164. /*.init =*/ haiku_init,
  165. /*.exit =*/ haiku_exit,
  166. /*.set_option =*/ NULL,
  167. /*.get_device_list =*/ NULL,
  168. /*.hotplug_poll =*/ NULL,
  169. /*.wrap_sys_device =*/ NULL,
  170. /*.open =*/ haiku_open,
  171. /*.close =*/ haiku_close,
  172. /*.get_active_config_descriptor =*/ haiku_get_active_config_descriptor,
  173. /*.get_config_descriptor =*/ haiku_get_config_descriptor,
  174. /*.get_config_descriptor_by_value =*/ NULL,
  175. /*.get_configuration =*/ NULL,
  176. /*.set_configuration =*/ haiku_set_configuration,
  177. /*.claim_interface =*/ haiku_claim_interface,
  178. /*.release_interface =*/ haiku_release_interface,
  179. /*.set_interface_altsetting =*/ haiku_set_altsetting,
  180. /*.clear_halt =*/ haiku_clear_halt,
  181. /*.reset_device =*/ NULL,
  182. /*.alloc_streams =*/ NULL,
  183. /*.free_streams =*/ NULL,
  184. /*.dev_mem_alloc =*/ NULL,
  185. /*.dev_mem_free =*/ NULL,
  186. /*.kernel_driver_active =*/ NULL,
  187. /*.detach_kernel_driver =*/ NULL,
  188. /*.attach_kernel_driver =*/ NULL,
  189. /*.destroy_device =*/ NULL,
  190. /*.submit_transfer =*/ haiku_submit_transfer,
  191. /*.cancel_transfer =*/ haiku_cancel_transfer,
  192. /*.clear_transfer_priv =*/ NULL,
  193. /*.handle_events =*/ NULL,
  194. /*.handle_transfer_completion =*/ haiku_handle_transfer_completion,
  195. /*.context_priv_size =*/ 0,
  196. /*.device_priv_size =*/ sizeof(USBDevice *),
  197. /*.device_handle_priv_size =*/ sizeof(USBDeviceHandle *),
  198. /*.transfer_priv_size =*/ sizeof(USBTransfer *),
  199. };