123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724 |
- /*
- * windows UsbDk backend for libusb 1.0
- * Copyright © 2014 Red Hat, Inc.
- * Authors:
- * Dmitry Fleytman <dmitry@daynix.com>
- * Pavel Gurvich <pavel@daynix.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
- #include <config.h>
- #include <windows.h>
- #include <stdio.h>
- #include "libusbi.h"
- #include "windows_usbdk.h"
- #if !defined(STATUS_SUCCESS)
- typedef LONG NTSTATUS;
- #define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
- #endif
- #if !defined(STATUS_CANCELLED)
- #define STATUS_CANCELLED ((NTSTATUS)0xC0000120L)
- #endif
- #if !defined(STATUS_REQUEST_CANCELED)
- #define STATUS_REQUEST_CANCELED ((NTSTATUS)0xC0000703L)
- #endif
- static struct {
- HMODULE module;
- USBDK_GET_DEVICES_LIST GetDevicesList;
- USBDK_RELEASE_DEVICES_LIST ReleaseDevicesList;
- USBDK_START_REDIRECT StartRedirect;
- USBDK_STOP_REDIRECT StopRedirect;
- USBDK_GET_CONFIGURATION_DESCRIPTOR GetConfigurationDescriptor;
- USBDK_RELEASE_CONFIGURATION_DESCRIPTOR ReleaseConfigurationDescriptor;
- USBDK_READ_PIPE ReadPipe;
- USBDK_WRITE_PIPE WritePipe;
- USBDK_ABORT_PIPE AbortPipe;
- USBDK_RESET_PIPE ResetPipe;
- USBDK_SET_ALTSETTING SetAltsetting;
- USBDK_RESET_DEVICE ResetDevice;
- USBDK_GET_REDIRECTOR_SYSTEM_HANDLE GetRedirectorSystemHandle;
- } usbdk_helper;
- static FARPROC get_usbdk_proc_addr(struct libusb_context *ctx, LPCSTR api_name)
- {
- FARPROC api_ptr = GetProcAddress(usbdk_helper.module, api_name);
- if (api_ptr == NULL)
- usbi_err(ctx, "UsbDkHelper API %s not found: %s", api_name, windows_error_str(0));
- return api_ptr;
- }
- static void unload_usbdk_helper_dll(void)
- {
- if (usbdk_helper.module != NULL) {
- FreeLibrary(usbdk_helper.module);
- usbdk_helper.module = NULL;
- }
- }
- static int load_usbdk_helper_dll(struct libusb_context *ctx)
- {
- usbdk_helper.module = load_system_library(ctx, "UsbDkHelper");
- if (usbdk_helper.module == NULL) {
- usbi_err(ctx, "Failed to load UsbDkHelper.dll: %s", windows_error_str(0));
- return LIBUSB_ERROR_NOT_FOUND;
- }
- usbdk_helper.GetDevicesList = (USBDK_GET_DEVICES_LIST)get_usbdk_proc_addr(ctx, "UsbDk_GetDevicesList");
- if (usbdk_helper.GetDevicesList == NULL)
- goto error_unload;
- usbdk_helper.ReleaseDevicesList = (USBDK_RELEASE_DEVICES_LIST)get_usbdk_proc_addr(ctx, "UsbDk_ReleaseDevicesList");
- if (usbdk_helper.ReleaseDevicesList == NULL)
- goto error_unload;
- usbdk_helper.StartRedirect = (USBDK_START_REDIRECT)get_usbdk_proc_addr(ctx, "UsbDk_StartRedirect");
- if (usbdk_helper.StartRedirect == NULL)
- goto error_unload;
- usbdk_helper.StopRedirect = (USBDK_STOP_REDIRECT)get_usbdk_proc_addr(ctx, "UsbDk_StopRedirect");
- if (usbdk_helper.StopRedirect == NULL)
- goto error_unload;
- usbdk_helper.GetConfigurationDescriptor = (USBDK_GET_CONFIGURATION_DESCRIPTOR)get_usbdk_proc_addr(ctx, "UsbDk_GetConfigurationDescriptor");
- if (usbdk_helper.GetConfigurationDescriptor == NULL)
- goto error_unload;
- usbdk_helper.ReleaseConfigurationDescriptor = (USBDK_RELEASE_CONFIGURATION_DESCRIPTOR)get_usbdk_proc_addr(ctx, "UsbDk_ReleaseConfigurationDescriptor");
- if (usbdk_helper.ReleaseConfigurationDescriptor == NULL)
- goto error_unload;
- usbdk_helper.ReadPipe = (USBDK_READ_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_ReadPipe");
- if (usbdk_helper.ReadPipe == NULL)
- goto error_unload;
- usbdk_helper.WritePipe = (USBDK_WRITE_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_WritePipe");
- if (usbdk_helper.WritePipe == NULL)
- goto error_unload;
- usbdk_helper.AbortPipe = (USBDK_ABORT_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_AbortPipe");
- if (usbdk_helper.AbortPipe == NULL)
- goto error_unload;
- usbdk_helper.ResetPipe = (USBDK_RESET_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_ResetPipe");
- if (usbdk_helper.ResetPipe == NULL)
- goto error_unload;
- usbdk_helper.SetAltsetting = (USBDK_SET_ALTSETTING)get_usbdk_proc_addr(ctx, "UsbDk_SetAltsetting");
- if (usbdk_helper.SetAltsetting == NULL)
- goto error_unload;
- usbdk_helper.ResetDevice = (USBDK_RESET_DEVICE)get_usbdk_proc_addr(ctx, "UsbDk_ResetDevice");
- if (usbdk_helper.ResetDevice == NULL)
- goto error_unload;
- usbdk_helper.GetRedirectorSystemHandle = (USBDK_GET_REDIRECTOR_SYSTEM_HANDLE)get_usbdk_proc_addr(ctx, "UsbDk_GetRedirectorSystemHandle");
- if (usbdk_helper.GetRedirectorSystemHandle == NULL)
- goto error_unload;
- return LIBUSB_SUCCESS;
- error_unload:
- FreeLibrary(usbdk_helper.module);
- usbdk_helper.module = NULL;
- return LIBUSB_ERROR_NOT_FOUND;
- }
- typedef SC_HANDLE (WINAPI *POPENSCMANAGERA)(LPCSTR, LPCSTR, DWORD);
- typedef SC_HANDLE (WINAPI *POPENSERVICEA)(SC_HANDLE, LPCSTR, DWORD);
- typedef BOOL (WINAPI *PCLOSESERVICEHANDLE)(SC_HANDLE);
- static int usbdk_init(struct libusb_context *ctx)
- {
- POPENSCMANAGERA pOpenSCManagerA;
- POPENSERVICEA pOpenServiceA;
- PCLOSESERVICEHANDLE pCloseServiceHandle;
- SC_HANDLE managerHandle;
- SC_HANDLE serviceHandle;
- HMODULE h;
- h = load_system_library(ctx, "Advapi32");
- if (h == NULL) {
- usbi_warn(ctx, "failed to open Advapi32\n");
- return LIBUSB_ERROR_OTHER;
- }
- pOpenSCManagerA = (POPENSCMANAGERA)GetProcAddress(h, "OpenSCManagerA");
- if (pOpenSCManagerA == NULL) {
- usbi_warn(ctx, "failed to find %s in Advapi32\n", "OpenSCManagerA");
- goto error_free_library;
- }
- pOpenServiceA = (POPENSERVICEA)GetProcAddress(h, "OpenServiceA");
- if (pOpenServiceA == NULL) {
- usbi_warn(ctx, "failed to find %s in Advapi32\n", "OpenServiceA");
- goto error_free_library;
- }
- pCloseServiceHandle = (PCLOSESERVICEHANDLE)GetProcAddress(h, "CloseServiceHandle");
- if (pCloseServiceHandle == NULL) {
- usbi_warn(ctx, "failed to find %s in Advapi32\n", "CloseServiceHandle");
- goto error_free_library;
- }
- managerHandle = pOpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
- if (managerHandle == NULL) {
- usbi_warn(ctx, "failed to open service control manager: %s", windows_error_str(0));
- goto error_free_library;
- }
- serviceHandle = pOpenServiceA(managerHandle, "UsbDk", GENERIC_READ);
- pCloseServiceHandle(managerHandle);
- if (serviceHandle == NULL) {
- if (GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST)
- usbi_warn(ctx, "failed to open UsbDk service: %s", windows_error_str(0));
- FreeLibrary(h);
- return LIBUSB_ERROR_NOT_FOUND;
- }
- pCloseServiceHandle(serviceHandle);
- FreeLibrary(h);
- return load_usbdk_helper_dll(ctx);
- error_free_library:
- FreeLibrary(h);
- return LIBUSB_ERROR_OTHER;
- }
- static void usbdk_exit(struct libusb_context *ctx)
- {
- UNUSED(ctx);
- unload_usbdk_helper_dll();
- }
- static int usbdk_get_session_id_for_device(struct libusb_context *ctx,
- PUSB_DK_DEVICE_ID id, unsigned long *session_id)
- {
- char dev_identity[ARRAYSIZE(id->DeviceID) + ARRAYSIZE(id->InstanceID) + 1];
- if (snprintf(dev_identity, sizeof(dev_identity), "%S%S", id->DeviceID, id->InstanceID) == -1) {
- usbi_warn(ctx, "cannot form device identity");
- return LIBUSB_ERROR_NOT_SUPPORTED;
- }
- *session_id = htab_hash(dev_identity);
- return LIBUSB_SUCCESS;
- }
- static void usbdk_release_config_descriptors(struct usbdk_device_priv *priv, uint8_t count)
- {
- uint8_t i;
- for (i = 0; i < count; i++)
- usbdk_helper.ReleaseConfigurationDescriptor(priv->config_descriptors[i]);
- free(priv->config_descriptors);
- priv->config_descriptors = NULL;
- }
- static int usbdk_cache_config_descriptors(struct libusb_context *ctx,
- struct usbdk_device_priv *priv, PUSB_DK_DEVICE_INFO info)
- {
- uint8_t i;
- USB_DK_CONFIG_DESCRIPTOR_REQUEST Request;
- Request.ID = info->ID;
- priv->config_descriptors = calloc(info->DeviceDescriptor.bNumConfigurations, sizeof(PUSB_CONFIGURATION_DESCRIPTOR));
- if (priv->config_descriptors == NULL) {
- usbi_err(ctx, "failed to allocate configuration descriptors holder");
- return LIBUSB_ERROR_NO_MEM;
- }
- for (i = 0; i < info->DeviceDescriptor.bNumConfigurations; i++) {
- ULONG Length;
- Request.Index = i;
- if (!usbdk_helper.GetConfigurationDescriptor(&Request, &priv->config_descriptors[i], &Length)) {
- usbi_err(ctx, "failed to retrieve configuration descriptors");
- usbdk_release_config_descriptors(priv, i);
- return LIBUSB_ERROR_OTHER;
- }
- }
- return LIBUSB_SUCCESS;
- }
- static inline int usbdk_device_priv_init(struct libusb_context *ctx, struct libusb_device *dev, PUSB_DK_DEVICE_INFO info)
- {
- struct usbdk_device_priv *priv = usbi_get_device_priv(dev);
- priv->ID = info->ID;
- priv->active_configuration = 0;
- return usbdk_cache_config_descriptors(ctx, priv, info);
- }
- static void usbdk_device_init(struct libusb_device *dev, PUSB_DK_DEVICE_INFO info)
- {
- dev->bus_number = (uint8_t)info->FilterID;
- dev->port_number = (uint8_t)info->Port;
- dev->parent_dev = NULL;
- // Addresses in libusb are 1-based
- dev->device_address = (uint8_t)(info->Port + 1);
- static_assert(sizeof(dev->device_descriptor) == sizeof(info->DeviceDescriptor),
- "mismatch between libusb and OS device descriptor sizes");
- memcpy(&dev->device_descriptor, &info->DeviceDescriptor, LIBUSB_DT_DEVICE_SIZE);
- usbi_localize_device_descriptor(&dev->device_descriptor);
- switch (info->Speed) {
- case LowSpeed:
- dev->speed = LIBUSB_SPEED_LOW;
- break;
- case FullSpeed:
- dev->speed = LIBUSB_SPEED_FULL;
- break;
- case HighSpeed:
- dev->speed = LIBUSB_SPEED_HIGH;
- break;
- case SuperSpeed:
- dev->speed = LIBUSB_SPEED_SUPER;
- break;
- case NoSpeed:
- default:
- dev->speed = LIBUSB_SPEED_UNKNOWN;
- break;
- }
- }
- static int usbdk_get_device_list(struct libusb_context *ctx, struct discovered_devs **_discdevs)
- {
- int r = LIBUSB_SUCCESS;
- ULONG i;
- struct discovered_devs *discdevs = NULL;
- ULONG dev_number;
- PUSB_DK_DEVICE_INFO devices;
- if (!usbdk_helper.GetDevicesList(&devices, &dev_number))
- return LIBUSB_ERROR_OTHER;
- for (i = 0; i < dev_number; i++) {
- unsigned long session_id;
- struct libusb_device *dev = NULL;
- if (usbdk_get_session_id_for_device(ctx, &devices[i].ID, &session_id))
- continue;
- dev = usbi_get_device_by_session_id(ctx, session_id);
- if (dev == NULL) {
- dev = usbi_alloc_device(ctx, session_id);
- if (dev == NULL) {
- usbi_err(ctx, "failed to allocate a new device structure");
- continue;
- }
- usbdk_device_init(dev, &devices[i]);
- if (usbdk_device_priv_init(ctx, dev, &devices[i]) != LIBUSB_SUCCESS) {
- libusb_unref_device(dev);
- continue;
- }
- }
- discdevs = discovered_devs_append(*_discdevs, dev);
- libusb_unref_device(dev);
- if (!discdevs) {
- usbi_err(ctx, "cannot append new device to list");
- r = LIBUSB_ERROR_NO_MEM;
- goto func_exit;
- }
- *_discdevs = discdevs;
- }
- func_exit:
- usbdk_helper.ReleaseDevicesList(devices);
- return r;
- }
- static int usbdk_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, void *buffer, size_t len)
- {
- struct usbdk_device_priv *priv = usbi_get_device_priv(dev);
- PUSB_CONFIGURATION_DESCRIPTOR config_header;
- size_t size;
- config_header = (PUSB_CONFIGURATION_DESCRIPTOR)priv->config_descriptors[config_index];
- size = min(config_header->wTotalLength, len);
- memcpy(buffer, config_header, size);
- return (int)size;
- }
- static int usbdk_get_config_descriptor_by_value(struct libusb_device *dev, uint8_t bConfigurationValue,
- void **buffer)
- {
- struct usbdk_device_priv *priv = usbi_get_device_priv(dev);
- PUSB_CONFIGURATION_DESCRIPTOR config_header;
- uint8_t index;
- for (index = 0; index < dev->device_descriptor.bNumConfigurations; index++) {
- config_header = priv->config_descriptors[index];
- if (config_header->bConfigurationValue == bConfigurationValue) {
- *buffer = priv->config_descriptors[index];
- return (int)config_header->wTotalLength;
- }
- }
- return LIBUSB_ERROR_NOT_FOUND;
- }
- static int usbdk_get_active_config_descriptor(struct libusb_device *dev, void *buffer, size_t len)
- {
- struct usbdk_device_priv *priv = usbi_get_device_priv(dev);
- return usbdk_get_config_descriptor(dev, priv->active_configuration, buffer, len);
- }
- static int usbdk_open(struct libusb_device_handle *dev_handle)
- {
- struct libusb_device *dev = dev_handle->dev;
- struct libusb_context *ctx = DEVICE_CTX(dev);
- struct windows_context_priv *priv = usbi_get_context_priv(ctx);
- struct usbdk_device_priv *device_priv = usbi_get_device_priv(dev);
- device_priv->redirector_handle = usbdk_helper.StartRedirect(&device_priv->ID);
- if (device_priv->redirector_handle == INVALID_HANDLE_VALUE) {
- usbi_err(ctx, "Redirector startup failed");
- device_priv->redirector_handle = NULL;
- return LIBUSB_ERROR_OTHER;
- }
- device_priv->system_handle = usbdk_helper.GetRedirectorSystemHandle(device_priv->redirector_handle);
- if (CreateIoCompletionPort(device_priv->system_handle, priv->completion_port, (ULONG_PTR)dev_handle, 0) == NULL) {
- usbi_err(ctx, "failed to associate handle to I/O completion port: %s", windows_error_str(0));
- usbdk_helper.StopRedirect(device_priv->redirector_handle);
- device_priv->system_handle = NULL;
- device_priv->redirector_handle = NULL;
- return LIBUSB_ERROR_OTHER;
- }
- return LIBUSB_SUCCESS;
- }
- static void usbdk_close(struct libusb_device_handle *dev_handle)
- {
- struct usbdk_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
- if (!usbdk_helper.StopRedirect(priv->redirector_handle))
- usbi_err(HANDLE_CTX(dev_handle), "Redirector shutdown failed");
- priv->system_handle = NULL;
- priv->redirector_handle = NULL;
- }
- static int usbdk_get_configuration(struct libusb_device_handle *dev_handle, uint8_t *config)
- {
- struct usbdk_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
- *config = priv->active_configuration;
- return LIBUSB_SUCCESS;
- }
- static int usbdk_set_configuration(struct libusb_device_handle *dev_handle, uint8_t config)
- {
- UNUSED(dev_handle);
- UNUSED(config);
- return LIBUSB_SUCCESS;
- }
- static int usbdk_claim_interface(struct libusb_device_handle *dev_handle, uint8_t iface)
- {
- UNUSED(dev_handle);
- UNUSED(iface);
- return LIBUSB_SUCCESS;
- }
- static int usbdk_set_interface_altsetting(struct libusb_device_handle *dev_handle, uint8_t iface, uint8_t altsetting)
- {
- struct usbdk_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
- if (!usbdk_helper.SetAltsetting(priv->redirector_handle, iface, altsetting)) {
- usbi_err(HANDLE_CTX(dev_handle), "SetAltsetting failed: %s", windows_error_str(0));
- return LIBUSB_ERROR_NO_DEVICE;
- }
- return LIBUSB_SUCCESS;
- }
- static int usbdk_release_interface(struct libusb_device_handle *dev_handle, uint8_t iface)
- {
- UNUSED(dev_handle);
- UNUSED(iface);
- return LIBUSB_SUCCESS;
- }
- static int usbdk_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
- {
- struct usbdk_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
- if (!usbdk_helper.ResetPipe(priv->redirector_handle, endpoint)) {
- usbi_err(HANDLE_CTX(dev_handle), "ResetPipe failed: %s", windows_error_str(0));
- return LIBUSB_ERROR_NO_DEVICE;
- }
- return LIBUSB_SUCCESS;
- }
- static int usbdk_reset_device(struct libusb_device_handle *dev_handle)
- {
- struct usbdk_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
- if (!usbdk_helper.ResetDevice(priv->redirector_handle)) {
- usbi_err(HANDLE_CTX(dev_handle), "ResetDevice failed: %s", windows_error_str(0));
- return LIBUSB_ERROR_NO_DEVICE;
- }
- return LIBUSB_SUCCESS;
- }
- static void usbdk_destroy_device(struct libusb_device *dev)
- {
- struct usbdk_device_priv *priv = usbi_get_device_priv(dev);
- if (priv->config_descriptors != NULL)
- usbdk_release_config_descriptors(priv, dev->device_descriptor.bNumConfigurations);
- }
- static void usbdk_clear_transfer_priv(struct usbi_transfer *itransfer)
- {
- struct usbdk_transfer_priv *transfer_priv = get_usbdk_transfer_priv(itransfer);
- struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) {
- safe_free(transfer_priv->IsochronousPacketsArray);
- safe_free(transfer_priv->IsochronousResultsArray);
- }
- }
- static int usbdk_do_control_transfer(struct usbi_transfer *itransfer)
- {
- struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- struct usbdk_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
- struct usbdk_transfer_priv *transfer_priv = get_usbdk_transfer_priv(itransfer);
- OVERLAPPED *overlapped = get_transfer_priv_overlapped(itransfer);
- TransferResult transResult;
- transfer_priv->request.Buffer = (PVOID64)transfer->buffer;
- transfer_priv->request.BufferLength = transfer->length;
- transfer_priv->request.TransferType = ControlTransferType;
- set_transfer_priv_handle(itransfer, priv->system_handle);
- if (transfer->buffer[0] & LIBUSB_ENDPOINT_IN)
- transResult = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, overlapped);
- else
- transResult = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, overlapped);
- switch (transResult) {
- case TransferSuccess:
- windows_force_sync_completion(itransfer, (ULONG)transfer_priv->request.Result.GenResult.BytesTransferred);
- break;
- case TransferSuccessAsync:
- break;
- case TransferFailure:
- usbi_err(TRANSFER_CTX(transfer), "ControlTransfer failed: %s", windows_error_str(0));
- return LIBUSB_ERROR_IO;
- }
- return LIBUSB_SUCCESS;
- }
- static int usbdk_do_bulk_transfer(struct usbi_transfer *itransfer)
- {
- struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- struct usbdk_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
- struct usbdk_transfer_priv *transfer_priv = get_usbdk_transfer_priv(itransfer);
- OVERLAPPED *overlapped = get_transfer_priv_overlapped(itransfer);
- TransferResult transferRes;
- transfer_priv->request.Buffer = (PVOID64)transfer->buffer;
- transfer_priv->request.BufferLength = transfer->length;
- transfer_priv->request.EndpointAddress = transfer->endpoint;
- switch (transfer->type) {
- case LIBUSB_TRANSFER_TYPE_BULK:
- transfer_priv->request.TransferType = BulkTransferType;
- break;
- case LIBUSB_TRANSFER_TYPE_INTERRUPT:
- transfer_priv->request.TransferType = InterruptTransferType;
- break;
- }
- set_transfer_priv_handle(itransfer, priv->system_handle);
- if (IS_XFERIN(transfer))
- transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, overlapped);
- else
- transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, overlapped);
- switch (transferRes) {
- case TransferSuccess:
- windows_force_sync_completion(itransfer, (ULONG)transfer_priv->request.Result.GenResult.BytesTransferred);
- break;
- case TransferSuccessAsync:
- break;
- case TransferFailure:
- usbi_err(TRANSFER_CTX(transfer), "ReadPipe/WritePipe failed: %s", windows_error_str(0));
- return LIBUSB_ERROR_IO;
- }
- return LIBUSB_SUCCESS;
- }
- static int usbdk_do_iso_transfer(struct usbi_transfer *itransfer)
- {
- struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- struct usbdk_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
- struct usbdk_transfer_priv *transfer_priv = get_usbdk_transfer_priv(itransfer);
- OVERLAPPED *overlapped = get_transfer_priv_overlapped(itransfer);
- TransferResult transferRes;
- int i;
- transfer_priv->request.Buffer = (PVOID64)transfer->buffer;
- transfer_priv->request.BufferLength = transfer->length;
- transfer_priv->request.EndpointAddress = transfer->endpoint;
- transfer_priv->request.TransferType = IsochronousTransferType;
- transfer_priv->request.IsochronousPacketsArraySize = transfer->num_iso_packets;
- transfer_priv->IsochronousPacketsArray = malloc(transfer->num_iso_packets * sizeof(ULONG64));
- transfer_priv->request.IsochronousPacketsArray = (PVOID64)transfer_priv->IsochronousPacketsArray;
- if (!transfer_priv->IsochronousPacketsArray) {
- usbi_err(TRANSFER_CTX(transfer), "Allocation of IsochronousPacketsArray failed");
- return LIBUSB_ERROR_NO_MEM;
- }
- transfer_priv->IsochronousResultsArray = malloc(transfer->num_iso_packets * sizeof(USB_DK_ISO_TRANSFER_RESULT));
- transfer_priv->request.Result.IsochronousResultsArray = (PVOID64)transfer_priv->IsochronousResultsArray;
- if (!transfer_priv->IsochronousResultsArray) {
- usbi_err(TRANSFER_CTX(transfer), "Allocation of isochronousResultsArray failed");
- return LIBUSB_ERROR_NO_MEM;
- }
- for (i = 0; i < transfer->num_iso_packets; i++)
- transfer_priv->IsochronousPacketsArray[i] = transfer->iso_packet_desc[i].length;
- set_transfer_priv_handle(itransfer, priv->system_handle);
- if (IS_XFERIN(transfer))
- transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, overlapped);
- else
- transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, overlapped);
- switch (transferRes) {
- case TransferSuccess:
- windows_force_sync_completion(itransfer, (ULONG)transfer_priv->request.Result.GenResult.BytesTransferred);
- break;
- case TransferSuccessAsync:
- break;
- case TransferFailure:
- return LIBUSB_ERROR_IO;
- }
- return LIBUSB_SUCCESS;
- }
- static int usbdk_submit_transfer(struct usbi_transfer *itransfer)
- {
- struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- switch (transfer->type) {
- case LIBUSB_TRANSFER_TYPE_CONTROL:
- return usbdk_do_control_transfer(itransfer);
- case LIBUSB_TRANSFER_TYPE_BULK:
- case LIBUSB_TRANSFER_TYPE_INTERRUPT:
- if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET))
- return LIBUSB_ERROR_NOT_SUPPORTED; //TODO: Check whether we can support this in UsbDk
- return usbdk_do_bulk_transfer(itransfer);
- case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
- return usbdk_do_iso_transfer(itransfer);
- default:
- // Should not get here since windows_submit_transfer() validates
- // the transfer->type field
- usbi_err(TRANSFER_CTX(transfer), "unsupported endpoint type %d", transfer->type);
- return LIBUSB_ERROR_NOT_SUPPORTED;
- }
- }
- static enum libusb_transfer_status usbdk_copy_transfer_data(struct usbi_transfer *itransfer, DWORD length)
- {
- struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- struct usbdk_transfer_priv *transfer_priv = get_usbdk_transfer_priv(itransfer);
- UNUSED(length);
- if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) {
- ULONG64 i;
- for (i = 0; i < transfer_priv->request.IsochronousPacketsArraySize; i++) {
- struct libusb_iso_packet_descriptor *lib_desc = &transfer->iso_packet_desc[i];
- switch (transfer_priv->IsochronousResultsArray[i].TransferResult) {
- case STATUS_SUCCESS:
- case STATUS_CANCELLED:
- case STATUS_REQUEST_CANCELED:
- lib_desc->status = LIBUSB_TRANSFER_COMPLETED; // == ERROR_SUCCESS
- break;
- default:
- lib_desc->status = LIBUSB_TRANSFER_ERROR; // ERROR_UNKNOWN_EXCEPTION;
- break;
- }
- lib_desc->actual_length = (unsigned int)transfer_priv->IsochronousResultsArray[i].ActualLength;
- }
- }
- itransfer->transferred += (int)transfer_priv->request.Result.GenResult.BytesTransferred;
- return usbd_status_to_libusb_transfer_status((USBD_STATUS)transfer_priv->request.Result.GenResult.UsbdStatus);
- }
- const struct windows_backend usbdk_backend = {
- usbdk_init,
- usbdk_exit,
- usbdk_get_device_list,
- usbdk_open,
- usbdk_close,
- usbdk_get_active_config_descriptor,
- usbdk_get_config_descriptor,
- usbdk_get_config_descriptor_by_value,
- usbdk_get_configuration,
- usbdk_set_configuration,
- usbdk_claim_interface,
- usbdk_release_interface,
- usbdk_set_interface_altsetting,
- usbdk_clear_halt,
- usbdk_reset_device,
- usbdk_destroy_device,
- usbdk_submit_transfer,
- NULL, /* cancel_transfer */
- usbdk_clear_transfer_priv,
- usbdk_copy_transfer_data,
- };
|