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