windows_usbdk.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724
  1. /*
  2. * windows UsbDk backend for libusb 1.0
  3. * Copyright © 2014 Red Hat, Inc.
  4. * Authors:
  5. * Dmitry Fleytman <dmitry@daynix.com>
  6. * Pavel Gurvich <pavel@daynix.com>
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2.1 of the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this library; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. */
  22. #include <config.h>
  23. #include <windows.h>
  24. #include <stdio.h>
  25. #include "libusbi.h"
  26. #include "windows_usbdk.h"
  27. #if !defined(STATUS_SUCCESS)
  28. typedef LONG NTSTATUS;
  29. #define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
  30. #endif
  31. #if !defined(STATUS_CANCELLED)
  32. #define STATUS_CANCELLED ((NTSTATUS)0xC0000120L)
  33. #endif
  34. #if !defined(STATUS_REQUEST_CANCELED)
  35. #define STATUS_REQUEST_CANCELED ((NTSTATUS)0xC0000703L)
  36. #endif
  37. static struct {
  38. HMODULE module;
  39. USBDK_GET_DEVICES_LIST GetDevicesList;
  40. USBDK_RELEASE_DEVICES_LIST ReleaseDevicesList;
  41. USBDK_START_REDIRECT StartRedirect;
  42. USBDK_STOP_REDIRECT StopRedirect;
  43. USBDK_GET_CONFIGURATION_DESCRIPTOR GetConfigurationDescriptor;
  44. USBDK_RELEASE_CONFIGURATION_DESCRIPTOR ReleaseConfigurationDescriptor;
  45. USBDK_READ_PIPE ReadPipe;
  46. USBDK_WRITE_PIPE WritePipe;
  47. USBDK_ABORT_PIPE AbortPipe;
  48. USBDK_RESET_PIPE ResetPipe;
  49. USBDK_SET_ALTSETTING SetAltsetting;
  50. USBDK_RESET_DEVICE ResetDevice;
  51. USBDK_GET_REDIRECTOR_SYSTEM_HANDLE GetRedirectorSystemHandle;
  52. } usbdk_helper;
  53. static FARPROC get_usbdk_proc_addr(struct libusb_context *ctx, LPCSTR api_name)
  54. {
  55. FARPROC api_ptr = GetProcAddress(usbdk_helper.module, api_name);
  56. if (api_ptr == NULL)
  57. usbi_err(ctx, "UsbDkHelper API %s not found: %s", api_name, windows_error_str(0));
  58. return api_ptr;
  59. }
  60. static void unload_usbdk_helper_dll(void)
  61. {
  62. if (usbdk_helper.module != NULL) {
  63. FreeLibrary(usbdk_helper.module);
  64. usbdk_helper.module = NULL;
  65. }
  66. }
  67. static int load_usbdk_helper_dll(struct libusb_context *ctx)
  68. {
  69. usbdk_helper.module = load_system_library(ctx, "UsbDkHelper");
  70. if (usbdk_helper.module == NULL) {
  71. usbi_err(ctx, "Failed to load UsbDkHelper.dll: %s", windows_error_str(0));
  72. return LIBUSB_ERROR_NOT_FOUND;
  73. }
  74. usbdk_helper.GetDevicesList = (USBDK_GET_DEVICES_LIST)get_usbdk_proc_addr(ctx, "UsbDk_GetDevicesList");
  75. if (usbdk_helper.GetDevicesList == NULL)
  76. goto error_unload;
  77. usbdk_helper.ReleaseDevicesList = (USBDK_RELEASE_DEVICES_LIST)get_usbdk_proc_addr(ctx, "UsbDk_ReleaseDevicesList");
  78. if (usbdk_helper.ReleaseDevicesList == NULL)
  79. goto error_unload;
  80. usbdk_helper.StartRedirect = (USBDK_START_REDIRECT)get_usbdk_proc_addr(ctx, "UsbDk_StartRedirect");
  81. if (usbdk_helper.StartRedirect == NULL)
  82. goto error_unload;
  83. usbdk_helper.StopRedirect = (USBDK_STOP_REDIRECT)get_usbdk_proc_addr(ctx, "UsbDk_StopRedirect");
  84. if (usbdk_helper.StopRedirect == NULL)
  85. goto error_unload;
  86. usbdk_helper.GetConfigurationDescriptor = (USBDK_GET_CONFIGURATION_DESCRIPTOR)get_usbdk_proc_addr(ctx, "UsbDk_GetConfigurationDescriptor");
  87. if (usbdk_helper.GetConfigurationDescriptor == NULL)
  88. goto error_unload;
  89. usbdk_helper.ReleaseConfigurationDescriptor = (USBDK_RELEASE_CONFIGURATION_DESCRIPTOR)get_usbdk_proc_addr(ctx, "UsbDk_ReleaseConfigurationDescriptor");
  90. if (usbdk_helper.ReleaseConfigurationDescriptor == NULL)
  91. goto error_unload;
  92. usbdk_helper.ReadPipe = (USBDK_READ_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_ReadPipe");
  93. if (usbdk_helper.ReadPipe == NULL)
  94. goto error_unload;
  95. usbdk_helper.WritePipe = (USBDK_WRITE_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_WritePipe");
  96. if (usbdk_helper.WritePipe == NULL)
  97. goto error_unload;
  98. usbdk_helper.AbortPipe = (USBDK_ABORT_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_AbortPipe");
  99. if (usbdk_helper.AbortPipe == NULL)
  100. goto error_unload;
  101. usbdk_helper.ResetPipe = (USBDK_RESET_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_ResetPipe");
  102. if (usbdk_helper.ResetPipe == NULL)
  103. goto error_unload;
  104. usbdk_helper.SetAltsetting = (USBDK_SET_ALTSETTING)get_usbdk_proc_addr(ctx, "UsbDk_SetAltsetting");
  105. if (usbdk_helper.SetAltsetting == NULL)
  106. goto error_unload;
  107. usbdk_helper.ResetDevice = (USBDK_RESET_DEVICE)get_usbdk_proc_addr(ctx, "UsbDk_ResetDevice");
  108. if (usbdk_helper.ResetDevice == NULL)
  109. goto error_unload;
  110. usbdk_helper.GetRedirectorSystemHandle = (USBDK_GET_REDIRECTOR_SYSTEM_HANDLE)get_usbdk_proc_addr(ctx, "UsbDk_GetRedirectorSystemHandle");
  111. if (usbdk_helper.GetRedirectorSystemHandle == NULL)
  112. goto error_unload;
  113. return LIBUSB_SUCCESS;
  114. error_unload:
  115. FreeLibrary(usbdk_helper.module);
  116. usbdk_helper.module = NULL;
  117. return LIBUSB_ERROR_NOT_FOUND;
  118. }
  119. typedef SC_HANDLE (WINAPI *POPENSCMANAGERA)(LPCSTR, LPCSTR, DWORD);
  120. typedef SC_HANDLE (WINAPI *POPENSERVICEA)(SC_HANDLE, LPCSTR, DWORD);
  121. typedef BOOL (WINAPI *PCLOSESERVICEHANDLE)(SC_HANDLE);
  122. static int usbdk_init(struct libusb_context *ctx)
  123. {
  124. POPENSCMANAGERA pOpenSCManagerA;
  125. POPENSERVICEA pOpenServiceA;
  126. PCLOSESERVICEHANDLE pCloseServiceHandle;
  127. SC_HANDLE managerHandle;
  128. SC_HANDLE serviceHandle;
  129. HMODULE h;
  130. h = load_system_library(ctx, "Advapi32");
  131. if (h == NULL) {
  132. usbi_warn(ctx, "failed to open Advapi32\n");
  133. return LIBUSB_ERROR_OTHER;
  134. }
  135. pOpenSCManagerA = (POPENSCMANAGERA)GetProcAddress(h, "OpenSCManagerA");
  136. if (pOpenSCManagerA == NULL) {
  137. usbi_warn(ctx, "failed to find %s in Advapi32\n", "OpenSCManagerA");
  138. goto error_free_library;
  139. }
  140. pOpenServiceA = (POPENSERVICEA)GetProcAddress(h, "OpenServiceA");
  141. if (pOpenServiceA == NULL) {
  142. usbi_warn(ctx, "failed to find %s in Advapi32\n", "OpenServiceA");
  143. goto error_free_library;
  144. }
  145. pCloseServiceHandle = (PCLOSESERVICEHANDLE)GetProcAddress(h, "CloseServiceHandle");
  146. if (pCloseServiceHandle == NULL) {
  147. usbi_warn(ctx, "failed to find %s in Advapi32\n", "CloseServiceHandle");
  148. goto error_free_library;
  149. }
  150. managerHandle = pOpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
  151. if (managerHandle == NULL) {
  152. usbi_warn(ctx, "failed to open service control manager: %s", windows_error_str(0));
  153. goto error_free_library;
  154. }
  155. serviceHandle = pOpenServiceA(managerHandle, "UsbDk", GENERIC_READ);
  156. pCloseServiceHandle(managerHandle);
  157. if (serviceHandle == NULL) {
  158. if (GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST)
  159. usbi_warn(ctx, "failed to open UsbDk service: %s", windows_error_str(0));
  160. FreeLibrary(h);
  161. return LIBUSB_ERROR_NOT_FOUND;
  162. }
  163. pCloseServiceHandle(serviceHandle);
  164. FreeLibrary(h);
  165. return load_usbdk_helper_dll(ctx);
  166. error_free_library:
  167. FreeLibrary(h);
  168. return LIBUSB_ERROR_OTHER;
  169. }
  170. static void usbdk_exit(struct libusb_context *ctx)
  171. {
  172. UNUSED(ctx);
  173. unload_usbdk_helper_dll();
  174. }
  175. static int usbdk_get_session_id_for_device(struct libusb_context *ctx,
  176. PUSB_DK_DEVICE_ID id, unsigned long *session_id)
  177. {
  178. char dev_identity[ARRAYSIZE(id->DeviceID) + ARRAYSIZE(id->InstanceID) + 1];
  179. if (snprintf(dev_identity, sizeof(dev_identity), "%S%S", id->DeviceID, id->InstanceID) == -1) {
  180. usbi_warn(ctx, "cannot form device identity");
  181. return LIBUSB_ERROR_NOT_SUPPORTED;
  182. }
  183. *session_id = htab_hash(dev_identity);
  184. return LIBUSB_SUCCESS;
  185. }
  186. static void usbdk_release_config_descriptors(struct usbdk_device_priv *priv, uint8_t count)
  187. {
  188. uint8_t i;
  189. for (i = 0; i < count; i++)
  190. usbdk_helper.ReleaseConfigurationDescriptor(priv->config_descriptors[i]);
  191. free(priv->config_descriptors);
  192. priv->config_descriptors = NULL;
  193. }
  194. static int usbdk_cache_config_descriptors(struct libusb_context *ctx,
  195. struct usbdk_device_priv *priv, PUSB_DK_DEVICE_INFO info)
  196. {
  197. uint8_t i;
  198. USB_DK_CONFIG_DESCRIPTOR_REQUEST Request;
  199. Request.ID = info->ID;
  200. priv->config_descriptors = calloc(info->DeviceDescriptor.bNumConfigurations, sizeof(PUSB_CONFIGURATION_DESCRIPTOR));
  201. if (priv->config_descriptors == NULL) {
  202. usbi_err(ctx, "failed to allocate configuration descriptors holder");
  203. return LIBUSB_ERROR_NO_MEM;
  204. }
  205. for (i = 0; i < info->DeviceDescriptor.bNumConfigurations; i++) {
  206. ULONG Length;
  207. Request.Index = i;
  208. if (!usbdk_helper.GetConfigurationDescriptor(&Request, &priv->config_descriptors[i], &Length)) {
  209. usbi_err(ctx, "failed to retrieve configuration descriptors");
  210. usbdk_release_config_descriptors(priv, i);
  211. return LIBUSB_ERROR_OTHER;
  212. }
  213. }
  214. return LIBUSB_SUCCESS;
  215. }
  216. static inline int usbdk_device_priv_init(struct libusb_context *ctx, struct libusb_device *dev, PUSB_DK_DEVICE_INFO info)
  217. {
  218. struct usbdk_device_priv *priv = usbi_get_device_priv(dev);
  219. priv->ID = info->ID;
  220. priv->active_configuration = 0;
  221. return usbdk_cache_config_descriptors(ctx, priv, info);
  222. }
  223. static void usbdk_device_init(struct libusb_device *dev, PUSB_DK_DEVICE_INFO info)
  224. {
  225. dev->bus_number = (uint8_t)info->FilterID;
  226. dev->port_number = (uint8_t)info->Port;
  227. dev->parent_dev = NULL;
  228. // Addresses in libusb are 1-based
  229. dev->device_address = (uint8_t)(info->Port + 1);
  230. static_assert(sizeof(dev->device_descriptor) == sizeof(info->DeviceDescriptor),
  231. "mismatch between libusb and OS device descriptor sizes");
  232. memcpy(&dev->device_descriptor, &info->DeviceDescriptor, LIBUSB_DT_DEVICE_SIZE);
  233. usbi_localize_device_descriptor(&dev->device_descriptor);
  234. switch (info->Speed) {
  235. case LowSpeed:
  236. dev->speed = LIBUSB_SPEED_LOW;
  237. break;
  238. case FullSpeed:
  239. dev->speed = LIBUSB_SPEED_FULL;
  240. break;
  241. case HighSpeed:
  242. dev->speed = LIBUSB_SPEED_HIGH;
  243. break;
  244. case SuperSpeed:
  245. dev->speed = LIBUSB_SPEED_SUPER;
  246. break;
  247. case NoSpeed:
  248. default:
  249. dev->speed = LIBUSB_SPEED_UNKNOWN;
  250. break;
  251. }
  252. }
  253. static int usbdk_get_device_list(struct libusb_context *ctx, struct discovered_devs **_discdevs)
  254. {
  255. int r = LIBUSB_SUCCESS;
  256. ULONG i;
  257. struct discovered_devs *discdevs = NULL;
  258. ULONG dev_number;
  259. PUSB_DK_DEVICE_INFO devices;
  260. if (!usbdk_helper.GetDevicesList(&devices, &dev_number))
  261. return LIBUSB_ERROR_OTHER;
  262. for (i = 0; i < dev_number; i++) {
  263. unsigned long session_id;
  264. struct libusb_device *dev = NULL;
  265. if (usbdk_get_session_id_for_device(ctx, &devices[i].ID, &session_id))
  266. continue;
  267. dev = usbi_get_device_by_session_id(ctx, session_id);
  268. if (dev == NULL) {
  269. dev = usbi_alloc_device(ctx, session_id);
  270. if (dev == NULL) {
  271. usbi_err(ctx, "failed to allocate a new device structure");
  272. continue;
  273. }
  274. usbdk_device_init(dev, &devices[i]);
  275. if (usbdk_device_priv_init(ctx, dev, &devices[i]) != LIBUSB_SUCCESS) {
  276. libusb_unref_device(dev);
  277. continue;
  278. }
  279. }
  280. discdevs = discovered_devs_append(*_discdevs, dev);
  281. libusb_unref_device(dev);
  282. if (!discdevs) {
  283. usbi_err(ctx, "cannot append new device to list");
  284. r = LIBUSB_ERROR_NO_MEM;
  285. goto func_exit;
  286. }
  287. *_discdevs = discdevs;
  288. }
  289. func_exit:
  290. usbdk_helper.ReleaseDevicesList(devices);
  291. return r;
  292. }
  293. static int usbdk_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, void *buffer, size_t len)
  294. {
  295. struct usbdk_device_priv *priv = usbi_get_device_priv(dev);
  296. PUSB_CONFIGURATION_DESCRIPTOR config_header;
  297. size_t size;
  298. config_header = (PUSB_CONFIGURATION_DESCRIPTOR)priv->config_descriptors[config_index];
  299. size = min(config_header->wTotalLength, len);
  300. memcpy(buffer, config_header, size);
  301. return (int)size;
  302. }
  303. static int usbdk_get_config_descriptor_by_value(struct libusb_device *dev, uint8_t bConfigurationValue,
  304. void **buffer)
  305. {
  306. struct usbdk_device_priv *priv = usbi_get_device_priv(dev);
  307. PUSB_CONFIGURATION_DESCRIPTOR config_header;
  308. uint8_t index;
  309. for (index = 0; index < dev->device_descriptor.bNumConfigurations; index++) {
  310. config_header = priv->config_descriptors[index];
  311. if (config_header->bConfigurationValue == bConfigurationValue) {
  312. *buffer = priv->config_descriptors[index];
  313. return (int)config_header->wTotalLength;
  314. }
  315. }
  316. return LIBUSB_ERROR_NOT_FOUND;
  317. }
  318. static int usbdk_get_active_config_descriptor(struct libusb_device *dev, void *buffer, size_t len)
  319. {
  320. struct usbdk_device_priv *priv = usbi_get_device_priv(dev);
  321. return usbdk_get_config_descriptor(dev, priv->active_configuration, buffer, len);
  322. }
  323. static int usbdk_open(struct libusb_device_handle *dev_handle)
  324. {
  325. struct libusb_device *dev = dev_handle->dev;
  326. struct libusb_context *ctx = DEVICE_CTX(dev);
  327. struct windows_context_priv *priv = usbi_get_context_priv(ctx);
  328. struct usbdk_device_priv *device_priv = usbi_get_device_priv(dev);
  329. device_priv->redirector_handle = usbdk_helper.StartRedirect(&device_priv->ID);
  330. if (device_priv->redirector_handle == INVALID_HANDLE_VALUE) {
  331. usbi_err(ctx, "Redirector startup failed");
  332. device_priv->redirector_handle = NULL;
  333. return LIBUSB_ERROR_OTHER;
  334. }
  335. device_priv->system_handle = usbdk_helper.GetRedirectorSystemHandle(device_priv->redirector_handle);
  336. if (CreateIoCompletionPort(device_priv->system_handle, priv->completion_port, (ULONG_PTR)dev_handle, 0) == NULL) {
  337. usbi_err(ctx, "failed to associate handle to I/O completion port: %s", windows_error_str(0));
  338. usbdk_helper.StopRedirect(device_priv->redirector_handle);
  339. device_priv->system_handle = NULL;
  340. device_priv->redirector_handle = NULL;
  341. return LIBUSB_ERROR_OTHER;
  342. }
  343. return LIBUSB_SUCCESS;
  344. }
  345. static void usbdk_close(struct libusb_device_handle *dev_handle)
  346. {
  347. struct usbdk_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
  348. if (!usbdk_helper.StopRedirect(priv->redirector_handle))
  349. usbi_err(HANDLE_CTX(dev_handle), "Redirector shutdown failed");
  350. priv->system_handle = NULL;
  351. priv->redirector_handle = NULL;
  352. }
  353. static int usbdk_get_configuration(struct libusb_device_handle *dev_handle, uint8_t *config)
  354. {
  355. struct usbdk_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
  356. *config = priv->active_configuration;
  357. return LIBUSB_SUCCESS;
  358. }
  359. static int usbdk_set_configuration(struct libusb_device_handle *dev_handle, uint8_t config)
  360. {
  361. UNUSED(dev_handle);
  362. UNUSED(config);
  363. return LIBUSB_SUCCESS;
  364. }
  365. static int usbdk_claim_interface(struct libusb_device_handle *dev_handle, uint8_t iface)
  366. {
  367. UNUSED(dev_handle);
  368. UNUSED(iface);
  369. return LIBUSB_SUCCESS;
  370. }
  371. static int usbdk_set_interface_altsetting(struct libusb_device_handle *dev_handle, uint8_t iface, uint8_t altsetting)
  372. {
  373. struct usbdk_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
  374. if (!usbdk_helper.SetAltsetting(priv->redirector_handle, iface, altsetting)) {
  375. usbi_err(HANDLE_CTX(dev_handle), "SetAltsetting failed: %s", windows_error_str(0));
  376. return LIBUSB_ERROR_NO_DEVICE;
  377. }
  378. return LIBUSB_SUCCESS;
  379. }
  380. static int usbdk_release_interface(struct libusb_device_handle *dev_handle, uint8_t iface)
  381. {
  382. UNUSED(dev_handle);
  383. UNUSED(iface);
  384. return LIBUSB_SUCCESS;
  385. }
  386. static int usbdk_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
  387. {
  388. struct usbdk_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
  389. if (!usbdk_helper.ResetPipe(priv->redirector_handle, endpoint)) {
  390. usbi_err(HANDLE_CTX(dev_handle), "ResetPipe failed: %s", windows_error_str(0));
  391. return LIBUSB_ERROR_NO_DEVICE;
  392. }
  393. return LIBUSB_SUCCESS;
  394. }
  395. static int usbdk_reset_device(struct libusb_device_handle *dev_handle)
  396. {
  397. struct usbdk_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
  398. if (!usbdk_helper.ResetDevice(priv->redirector_handle)) {
  399. usbi_err(HANDLE_CTX(dev_handle), "ResetDevice failed: %s", windows_error_str(0));
  400. return LIBUSB_ERROR_NO_DEVICE;
  401. }
  402. return LIBUSB_SUCCESS;
  403. }
  404. static void usbdk_destroy_device(struct libusb_device *dev)
  405. {
  406. struct usbdk_device_priv *priv = usbi_get_device_priv(dev);
  407. if (priv->config_descriptors != NULL)
  408. usbdk_release_config_descriptors(priv, dev->device_descriptor.bNumConfigurations);
  409. }
  410. static void usbdk_clear_transfer_priv(struct usbi_transfer *itransfer)
  411. {
  412. struct usbdk_transfer_priv *transfer_priv = get_usbdk_transfer_priv(itransfer);
  413. struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
  414. if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) {
  415. safe_free(transfer_priv->IsochronousPacketsArray);
  416. safe_free(transfer_priv->IsochronousResultsArray);
  417. }
  418. }
  419. static int usbdk_do_control_transfer(struct usbi_transfer *itransfer)
  420. {
  421. struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
  422. struct usbdk_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
  423. struct usbdk_transfer_priv *transfer_priv = get_usbdk_transfer_priv(itransfer);
  424. OVERLAPPED *overlapped = get_transfer_priv_overlapped(itransfer);
  425. TransferResult transResult;
  426. transfer_priv->request.Buffer = (PVOID64)transfer->buffer;
  427. transfer_priv->request.BufferLength = transfer->length;
  428. transfer_priv->request.TransferType = ControlTransferType;
  429. set_transfer_priv_handle(itransfer, priv->system_handle);
  430. if (transfer->buffer[0] & LIBUSB_ENDPOINT_IN)
  431. transResult = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, overlapped);
  432. else
  433. transResult = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, overlapped);
  434. switch (transResult) {
  435. case TransferSuccess:
  436. windows_force_sync_completion(itransfer, (ULONG)transfer_priv->request.Result.GenResult.BytesTransferred);
  437. break;
  438. case TransferSuccessAsync:
  439. break;
  440. case TransferFailure:
  441. usbi_err(TRANSFER_CTX(transfer), "ControlTransfer failed: %s", windows_error_str(0));
  442. return LIBUSB_ERROR_IO;
  443. }
  444. return LIBUSB_SUCCESS;
  445. }
  446. static int usbdk_do_bulk_transfer(struct usbi_transfer *itransfer)
  447. {
  448. struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
  449. struct usbdk_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
  450. struct usbdk_transfer_priv *transfer_priv = get_usbdk_transfer_priv(itransfer);
  451. OVERLAPPED *overlapped = get_transfer_priv_overlapped(itransfer);
  452. TransferResult transferRes;
  453. transfer_priv->request.Buffer = (PVOID64)transfer->buffer;
  454. transfer_priv->request.BufferLength = transfer->length;
  455. transfer_priv->request.EndpointAddress = transfer->endpoint;
  456. switch (transfer->type) {
  457. case LIBUSB_TRANSFER_TYPE_BULK:
  458. transfer_priv->request.TransferType = BulkTransferType;
  459. break;
  460. case LIBUSB_TRANSFER_TYPE_INTERRUPT:
  461. transfer_priv->request.TransferType = InterruptTransferType;
  462. break;
  463. }
  464. set_transfer_priv_handle(itransfer, priv->system_handle);
  465. if (IS_XFERIN(transfer))
  466. transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, overlapped);
  467. else
  468. transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, overlapped);
  469. switch (transferRes) {
  470. case TransferSuccess:
  471. windows_force_sync_completion(itransfer, (ULONG)transfer_priv->request.Result.GenResult.BytesTransferred);
  472. break;
  473. case TransferSuccessAsync:
  474. break;
  475. case TransferFailure:
  476. usbi_err(TRANSFER_CTX(transfer), "ReadPipe/WritePipe failed: %s", windows_error_str(0));
  477. return LIBUSB_ERROR_IO;
  478. }
  479. return LIBUSB_SUCCESS;
  480. }
  481. static int usbdk_do_iso_transfer(struct usbi_transfer *itransfer)
  482. {
  483. struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
  484. struct usbdk_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
  485. struct usbdk_transfer_priv *transfer_priv = get_usbdk_transfer_priv(itransfer);
  486. OVERLAPPED *overlapped = get_transfer_priv_overlapped(itransfer);
  487. TransferResult transferRes;
  488. int i;
  489. transfer_priv->request.Buffer = (PVOID64)transfer->buffer;
  490. transfer_priv->request.BufferLength = transfer->length;
  491. transfer_priv->request.EndpointAddress = transfer->endpoint;
  492. transfer_priv->request.TransferType = IsochronousTransferType;
  493. transfer_priv->request.IsochronousPacketsArraySize = transfer->num_iso_packets;
  494. transfer_priv->IsochronousPacketsArray = malloc(transfer->num_iso_packets * sizeof(ULONG64));
  495. transfer_priv->request.IsochronousPacketsArray = (PVOID64)transfer_priv->IsochronousPacketsArray;
  496. if (!transfer_priv->IsochronousPacketsArray) {
  497. usbi_err(TRANSFER_CTX(transfer), "Allocation of IsochronousPacketsArray failed");
  498. return LIBUSB_ERROR_NO_MEM;
  499. }
  500. transfer_priv->IsochronousResultsArray = malloc(transfer->num_iso_packets * sizeof(USB_DK_ISO_TRANSFER_RESULT));
  501. transfer_priv->request.Result.IsochronousResultsArray = (PVOID64)transfer_priv->IsochronousResultsArray;
  502. if (!transfer_priv->IsochronousResultsArray) {
  503. usbi_err(TRANSFER_CTX(transfer), "Allocation of isochronousResultsArray failed");
  504. return LIBUSB_ERROR_NO_MEM;
  505. }
  506. for (i = 0; i < transfer->num_iso_packets; i++)
  507. transfer_priv->IsochronousPacketsArray[i] = transfer->iso_packet_desc[i].length;
  508. set_transfer_priv_handle(itransfer, priv->system_handle);
  509. if (IS_XFERIN(transfer))
  510. transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, overlapped);
  511. else
  512. transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, overlapped);
  513. switch (transferRes) {
  514. case TransferSuccess:
  515. windows_force_sync_completion(itransfer, (ULONG)transfer_priv->request.Result.GenResult.BytesTransferred);
  516. break;
  517. case TransferSuccessAsync:
  518. break;
  519. case TransferFailure:
  520. return LIBUSB_ERROR_IO;
  521. }
  522. return LIBUSB_SUCCESS;
  523. }
  524. static int usbdk_submit_transfer(struct usbi_transfer *itransfer)
  525. {
  526. struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
  527. switch (transfer->type) {
  528. case LIBUSB_TRANSFER_TYPE_CONTROL:
  529. return usbdk_do_control_transfer(itransfer);
  530. case LIBUSB_TRANSFER_TYPE_BULK:
  531. case LIBUSB_TRANSFER_TYPE_INTERRUPT:
  532. if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET))
  533. return LIBUSB_ERROR_NOT_SUPPORTED; //TODO: Check whether we can support this in UsbDk
  534. return usbdk_do_bulk_transfer(itransfer);
  535. case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
  536. return usbdk_do_iso_transfer(itransfer);
  537. default:
  538. // Should not get here since windows_submit_transfer() validates
  539. // the transfer->type field
  540. usbi_err(TRANSFER_CTX(transfer), "unsupported endpoint type %d", transfer->type);
  541. return LIBUSB_ERROR_NOT_SUPPORTED;
  542. }
  543. }
  544. static enum libusb_transfer_status usbdk_copy_transfer_data(struct usbi_transfer *itransfer, DWORD length)
  545. {
  546. struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
  547. struct usbdk_transfer_priv *transfer_priv = get_usbdk_transfer_priv(itransfer);
  548. UNUSED(length);
  549. if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) {
  550. ULONG64 i;
  551. for (i = 0; i < transfer_priv->request.IsochronousPacketsArraySize; i++) {
  552. struct libusb_iso_packet_descriptor *lib_desc = &transfer->iso_packet_desc[i];
  553. switch (transfer_priv->IsochronousResultsArray[i].TransferResult) {
  554. case STATUS_SUCCESS:
  555. case STATUS_CANCELLED:
  556. case STATUS_REQUEST_CANCELED:
  557. lib_desc->status = LIBUSB_TRANSFER_COMPLETED; // == ERROR_SUCCESS
  558. break;
  559. default:
  560. lib_desc->status = LIBUSB_TRANSFER_ERROR; // ERROR_UNKNOWN_EXCEPTION;
  561. break;
  562. }
  563. lib_desc->actual_length = (unsigned int)transfer_priv->IsochronousResultsArray[i].ActualLength;
  564. }
  565. }
  566. itransfer->transferred += (int)transfer_priv->request.Result.GenResult.BytesTransferred;
  567. return usbd_status_to_libusb_transfer_status((USBD_STATUS)transfer_priv->request.Result.GenResult.UsbdStatus);
  568. }
  569. const struct windows_backend usbdk_backend = {
  570. usbdk_init,
  571. usbdk_exit,
  572. usbdk_get_device_list,
  573. usbdk_open,
  574. usbdk_close,
  575. usbdk_get_active_config_descriptor,
  576. usbdk_get_config_descriptor,
  577. usbdk_get_config_descriptor_by_value,
  578. usbdk_get_configuration,
  579. usbdk_set_configuration,
  580. usbdk_claim_interface,
  581. usbdk_release_interface,
  582. usbdk_set_interface_altsetting,
  583. usbdk_clear_halt,
  584. usbdk_reset_device,
  585. usbdk_destroy_device,
  586. usbdk_submit_transfer,
  587. NULL, /* cancel_transfer */
  588. usbdk_clear_transfer_priv,
  589. usbdk_copy_transfer_data,
  590. };