xref: /aosp_15_r20/external/libusb/libusb/os/windows_common.h (revision 86b64dcb59b3a0b37502ecd56e119234366a6f7e)
1 /*
2  * Windows backend common header for libusb 1.0
3  *
4  * This file brings together header code common between
5  * the desktop Windows backends.
6  * Copyright © 2012-2013 RealVNC Ltd.
7  * Copyright © 2009-2012 Pete Batard <[email protected]>
8  * Copyright © 2014-2020 Chris Dickens <[email protected]>
9  * With contributions from Michael Plante, Orin Eman et al.
10  * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer
11  * Major code testing contribution by Xiaofan Chen
12  *
13  * This library is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU Lesser General Public
15  * License as published by the Free Software Foundation; either
16  * version 2.1 of the License, or (at your option) any later version.
17  *
18  * This library is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21  * Lesser General Public License for more details.
22  *
23  * You should have received a copy of the GNU Lesser General Public
24  * License along with this library; if not, write to the Free Software
25  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26  */
27 
28 #ifndef LIBUSB_WINDOWS_COMMON_H
29 #define LIBUSB_WINDOWS_COMMON_H
30 
31 #include <stdbool.h>
32 
33 /*
34  * Workaround for the mess that exists with the DWORD and ULONG types.
35  * Visual Studio unconditionally defines these types as 'unsigned long'
36  * and a long is always 32-bits, even on 64-bit builds. GCC on the other
37  * hand varies the width of a long, matching it to the build. To make
38  * matters worse, the platform headers for these GCC builds define a
39  * DWORD/ULONG to be 'unsigned long' on 32-bit builds and 'unsigned int'
40  * on 64-bit builds. This creates a great deal of warnings for compilers
41  * that support printf format checking since it will never actually be
42  * an unsigned long.
43  */
44 #if defined(_MSC_VER)
45 #define ULONG_CAST(x)	(x)
46 #else
47 #define ULONG_CAST(x)	((unsigned long)(x))
48 #endif
49 
50 #if defined(__CYGWIN__)
51 #define _stricmp strcasecmp
52 #define _strdup strdup
53 // _beginthreadex is MSVCRT => unavailable for cygwin. Fallback to using CreateThread
54 #define _beginthreadex(a, b, c, d, e, f) CreateThread(a, b, (LPTHREAD_START_ROUTINE)c, d, e, (LPDWORD)f)
55 #else
56 #include <process.h>
57 #endif
58 
59 #define safe_free(p) do {if (p != NULL) {free((void *)p); p = NULL;}} while (0)
60 
61 /*
62  * API macros - leveraged from libusb-win32 1.x
63  */
64 #define DLL_STRINGIFY(s) #s
65 
66 /*
67  * Macros for handling DLL themselves
68  */
69 #define DLL_HANDLE_NAME(name) __dll_##name##_handle
70 
71 #define DLL_DECLARE_HANDLE(name)					\
72 	static HMODULE DLL_HANDLE_NAME(name)
73 
74 #define DLL_GET_HANDLE(ctx, name)					\
75 	do {								\
76 		DLL_HANDLE_NAME(name) = load_system_library(ctx,	\
77 				DLL_STRINGIFY(name));			\
78 		if (!DLL_HANDLE_NAME(name))				\
79 			return false;					\
80 	} while (0)
81 
82 #define DLL_FREE_HANDLE(name)						\
83 	do {								\
84 		if (DLL_HANDLE_NAME(name)) {				\
85 			FreeLibrary(DLL_HANDLE_NAME(name));		\
86 			DLL_HANDLE_NAME(name) = NULL;			\
87 		}							\
88 	} while (0)
89 
90 /*
91  * Macros for handling functions within a DLL
92  */
93 #define DLL_FUNC_NAME(name) __dll_##name##_func_t
94 
95 #define DLL_DECLARE_FUNC_PREFIXNAME(api, ret, prefixname, name, args)	\
96 	typedef ret (api * DLL_FUNC_NAME(name))args;			\
97 	static DLL_FUNC_NAME(name) prefixname
98 
99 #define DLL_DECLARE_FUNC(api, ret, name, args)				\
100 	DLL_DECLARE_FUNC_PREFIXNAME(api, ret, name, name, args)
101 #define DLL_DECLARE_FUNC_PREFIXED(api, ret, prefix, name, args)		\
102 	DLL_DECLARE_FUNC_PREFIXNAME(api, ret, prefix##name, name, args)
103 
104 #define DLL_LOAD_FUNC_PREFIXNAME(dll, prefixname, name, ret_on_failure)	\
105 	do {								\
106 		HMODULE h = DLL_HANDLE_NAME(dll);			\
107 		prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h,	\
108 				DLL_STRINGIFY(name));			\
109 		if (prefixname)						\
110 			break;						\
111 		prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h,	\
112 				DLL_STRINGIFY(name) DLL_STRINGIFY(A));	\
113 		if (prefixname)						\
114 			break;						\
115 		prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h,	\
116 				DLL_STRINGIFY(name) DLL_STRINGIFY(W));	\
117 		if (prefixname)						\
118 			break;						\
119 		if (ret_on_failure)					\
120 			return false;					\
121 	} while (0)
122 
123 #define DLL_LOAD_FUNC(dll, name, ret_on_failure)			\
124 	DLL_LOAD_FUNC_PREFIXNAME(dll, name, name, ret_on_failure)
125 #define DLL_LOAD_FUNC_PREFIXED(dll, prefix, name, ret_on_failure)	\
126 	DLL_LOAD_FUNC_PREFIXNAME(dll, prefix##name, name, ret_on_failure)
127 
128 // https://msdn.microsoft.com/en-us/library/windows/hardware/ff539136(v=vs.85).aspx
129 #if !defined(USBD_SUCCESS)
130 typedef LONG USBD_STATUS;
131 
132 #define USBD_SUCCESS(Status)		((USBD_STATUS)(Status) >= 0)
133 
134 #define USBD_STATUS_STALL_PID		((USBD_STATUS)0xC0000004L)
135 #define USBD_STATUS_ENDPOINT_HALTED	((USBD_STATUS)0xC0000030L)
136 #define USBD_STATUS_TIMEOUT		((USBD_STATUS)0xC0006000L)
137 #define USBD_STATUS_DEVICE_GONE		((USBD_STATUS)0xC0007000L)
138 #define USBD_STATUS_CANCELED		((USBD_STATUS)0xC0010000L)
139 #endif
140 
141 // error code added with Windows SDK 10.0.18362
142 #ifndef ERROR_NO_SUCH_DEVICE
143 #define ERROR_NO_SUCH_DEVICE	433L
144 #endif
145 
146 /* Windows versions */
147 enum windows_version {
148 	WINDOWS_UNDEFINED,
149 	WINDOWS_2000,
150 	WINDOWS_XP,
151 	WINDOWS_2003,	// Also XP x64
152 	WINDOWS_VISTA,
153 	WINDOWS_7,
154 	WINDOWS_8,
155 	WINDOWS_8_1,
156 	WINDOWS_10,
157 	WINDOWS_11,
158 	WINDOWS_12_OR_LATER
159 };
160 
161 extern enum windows_version windows_version;
162 
163 #include <pshpack1.h>
164 
165 typedef struct USB_DEVICE_DESCRIPTOR {
166 	UCHAR  bLength;
167 	UCHAR  bDescriptorType;
168 	USHORT bcdUSB;
169 	UCHAR  bDeviceClass;
170 	UCHAR  bDeviceSubClass;
171 	UCHAR  bDeviceProtocol;
172 	UCHAR  bMaxPacketSize0;
173 	USHORT idVendor;
174 	USHORT idProduct;
175 	USHORT bcdDevice;
176 	UCHAR  iManufacturer;
177 	UCHAR  iProduct;
178 	UCHAR  iSerialNumber;
179 	UCHAR  bNumConfigurations;
180 } USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR;
181 
182 typedef struct USB_CONFIGURATION_DESCRIPTOR {
183 	UCHAR  bLength;
184 	UCHAR  bDescriptorType;
185 	USHORT wTotalLength;
186 	UCHAR  bNumInterfaces;
187 	UCHAR  bConfigurationValue;
188 	UCHAR  iConfiguration;
189 	UCHAR  bmAttributes;
190 	UCHAR  MaxPower;
191 } USB_CONFIGURATION_DESCRIPTOR, *PUSB_CONFIGURATION_DESCRIPTOR;
192 
193 #include <poppack.h>
194 
195 #define MAX_DEVICE_ID_LEN	200
196 
197 typedef struct USB_DK_DEVICE_ID {
198 	WCHAR DeviceID[MAX_DEVICE_ID_LEN];
199 	WCHAR InstanceID[MAX_DEVICE_ID_LEN];
200 } USB_DK_DEVICE_ID, *PUSB_DK_DEVICE_ID;
201 
202 typedef struct USB_DK_DEVICE_INFO {
203 	USB_DK_DEVICE_ID ID;
204 	ULONG64 FilterID;
205 	ULONG64 Port;
206 	ULONG64 Speed;
207 	USB_DEVICE_DESCRIPTOR DeviceDescriptor;
208 } USB_DK_DEVICE_INFO, *PUSB_DK_DEVICE_INFO;
209 
210 typedef struct USB_DK_ISO_TRANSFER_RESULT {
211 	ULONG64 ActualLength;
212 	ULONG64 TransferResult;
213 } USB_DK_ISO_TRANSFER_RESULT, *PUSB_DK_ISO_TRANSFER_RESULT;
214 
215 typedef struct USB_DK_GEN_TRANSFER_RESULT {
216 	ULONG64 BytesTransferred;
217 	ULONG64 UsbdStatus; // USBD_STATUS code
218 } USB_DK_GEN_TRANSFER_RESULT, *PUSB_DK_GEN_TRANSFER_RESULT;
219 
220 typedef struct USB_DK_TRANSFER_RESULT {
221 	USB_DK_GEN_TRANSFER_RESULT GenResult;
222 	PVOID64 IsochronousResultsArray; // array of USB_DK_ISO_TRANSFER_RESULT
223 } USB_DK_TRANSFER_RESULT, *PUSB_DK_TRANSFER_RESULT;
224 
225 typedef struct USB_DK_TRANSFER_REQUEST {
226 	ULONG64 EndpointAddress;
227 	PVOID64 Buffer;
228 	ULONG64 BufferLength;
229 	ULONG64 TransferType;
230 	ULONG64 IsochronousPacketsArraySize;
231 	PVOID64 IsochronousPacketsArray;
232 	USB_DK_TRANSFER_RESULT Result;
233 } USB_DK_TRANSFER_REQUEST, *PUSB_DK_TRANSFER_REQUEST;
234 
235 struct usbdk_device_priv {
236 	USB_DK_DEVICE_ID ID;
237 	PUSB_CONFIGURATION_DESCRIPTOR *config_descriptors;
238 	HANDLE redirector_handle;
239 	HANDLE system_handle;
240 	uint8_t active_configuration;
241 };
242 
243 struct winusb_device_priv {
244 	bool initialized;
245 	bool root_hub;
246 	uint8_t active_config;
247 	uint8_t depth; // distance to HCD
248 	const struct windows_usb_api_backend *apib;
249 	char *dev_id;
250 	char *path;  // device interface path
251 	int sub_api; // for WinUSB-like APIs
252 	struct {
253 		char *path; // each interface needs a device interface path,
254 		const struct windows_usb_api_backend *apib; // an API backend (multiple drivers support),
255 		int sub_api;
256 		int8_t nb_endpoints; // and a set of endpoint addresses (USB_MAXENDPOINTS)
257 		uint8_t *endpoint;
258 		int current_altsetting;
259 		bool restricted_functionality;  // indicates if the interface functionality is restricted
260 						// by Windows (eg. HID keyboards or mice cannot do R/W)
261 		uint8_t num_associated_interfaces; // If non-zero, the interface is part of a grouped
262 		                                   // set of associated interfaces (defined by an IAD)
263 						   // and this is the number of interfaces within the
264 						   // associated group (bInterfaceCount in IAD).
265 		uint8_t first_associated_interface; // For associated interfaces, this is the index of
266 						    // the first interface (bFirstInterface in IAD) for
267 		                                    // the grouped set of associated interfaces.
268 	} usb_interface[USB_MAXINTERFACES];
269 	struct hid_device_priv *hid;
270 	PUSB_CONFIGURATION_DESCRIPTOR *config_descriptor; // list of pointers to the cached config descriptors
271 	GUID class_guid; // checked for change during re-enumeration
272 };
273 
274 struct usbdk_device_handle_priv {
275 	// Not currently used
276 	char dummy;
277 };
278 
279 enum WINUSB_ZLP {
280 	WINUSB_ZLP_UNSET = 0,
281 	WINUSB_ZLP_OFF = 1,
282 	WINUSB_ZLP_ON = 2
283 };
284 
285 struct winusb_device_handle_priv {
286 	int active_interface;
287 	struct {
288 		HANDLE dev_handle; // WinUSB needs an extra handle for the file
289 		HANDLE api_handle; // used by the API to communicate with the device
290 		uint8_t zlp[USB_MAXENDPOINTS]; // Current per-endpoint SHORT_PACKET_TERMINATE status (enum WINUSB_ZLP)
291 	} interface_handle[USB_MAXINTERFACES];
292 	int autoclaim_count[USB_MAXINTERFACES]; // For auto-release
293 };
294 
295 struct usbdk_transfer_priv {
296 	USB_DK_TRANSFER_REQUEST request;
297 	PULONG64 IsochronousPacketsArray;
298 	PUSB_DK_ISO_TRANSFER_RESULT IsochronousResultsArray;
299 };
300 
301 struct winusb_transfer_priv {
302 	uint8_t interface_number;
303 
304 	uint8_t *hid_buffer; // 1 byte extended data buffer, required for HID
305 	uint8_t *hid_dest;   // transfer buffer destination, required for HID
306 	size_t hid_expected_size;
307 
308 	// For isochronous transfers with LibUSBk driver:
309 	void *iso_context;
310 
311 	// For isochronous transfers with Microsoft WinUSB driver:
312 	void *isoch_buffer_handle; // The isoch_buffer_handle to free at the end of the transfer
313 	BOOL iso_break_stream;	// Whether the isoch. stream was to be continued in the last call of libusb_submit_transfer.
314 							// As we this structure is zeroed out upon initialization, we need to use inverse logic here.
315 	libusb_transfer_cb_fn iso_user_callback; // Original transfer callback of the user. Might be used for isochronous transfers.
316 };
317 
318 struct windows_backend {
319 	int (*init)(struct libusb_context *ctx);
320 	void (*exit)(struct libusb_context *ctx);
321 	int (*get_device_list)(struct libusb_context *ctx,
322 		struct discovered_devs **discdevs);
323 	int (*open)(struct libusb_device_handle *dev_handle);
324 	void (*close)(struct libusb_device_handle *dev_handle);
325 	int (*get_active_config_descriptor)(struct libusb_device *device,
326 		void *buffer, size_t len);
327 	int (*get_config_descriptor)(struct libusb_device *device,
328 		uint8_t config_index, void *buffer, size_t len);
329 	int (*get_config_descriptor_by_value)(struct libusb_device *device,
330 		uint8_t bConfigurationValue, void **buffer);
331 	int (*get_configuration)(struct libusb_device_handle *dev_handle, uint8_t *config);
332 	int (*set_configuration)(struct libusb_device_handle *dev_handle, uint8_t config);
333 	int (*claim_interface)(struct libusb_device_handle *dev_handle, uint8_t interface_number);
334 	int (*release_interface)(struct libusb_device_handle *dev_handle, uint8_t interface_number);
335 	int (*set_interface_altsetting)(struct libusb_device_handle *dev_handle,
336 		uint8_t interface_number, uint8_t altsetting);
337 	int (*clear_halt)(struct libusb_device_handle *dev_handle,
338 		unsigned char endpoint);
339 	int (*reset_device)(struct libusb_device_handle *dev_handle);
340 	void (*destroy_device)(struct libusb_device *dev);
341 	int (*submit_transfer)(struct usbi_transfer *itransfer);
342 	int (*cancel_transfer)(struct usbi_transfer *itransfer);
343 	void (*clear_transfer_priv)(struct usbi_transfer *itransfer);
344 	enum libusb_transfer_status (*copy_transfer_data)(struct usbi_transfer *itransfer, DWORD length);
345 };
346 
347 struct windows_context_priv {
348 	const struct windows_backend *backend;
349 	HANDLE completion_port;
350 	HANDLE completion_port_thread;
351 };
352 
353 union windows_device_priv {
354 	struct usbdk_device_priv usbdk_priv;
355 	struct winusb_device_priv winusb_priv;
356 };
357 
358 struct windows_device_handle_priv {
359 	struct list_head active_transfers;
360 	union {
361 		struct usbdk_device_handle_priv usbdk_priv;
362 		struct winusb_device_handle_priv winusb_priv;
363 	};
364 };
365 
366 struct windows_transfer_priv {
367 	OVERLAPPED overlapped;
368 	HANDLE handle;
369 	struct list_head list;
370 	union {
371 		struct usbdk_transfer_priv usbdk_priv;
372 		struct winusb_transfer_priv winusb_priv;
373 	};
374 };
375 
get_usbdk_device_handle_priv(struct libusb_device_handle * dev_handle)376 static inline struct usbdk_device_handle_priv *get_usbdk_device_handle_priv(struct libusb_device_handle *dev_handle)
377 {
378 	struct windows_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
379 	return &handle_priv->usbdk_priv;
380 }
381 
get_winusb_device_handle_priv(struct libusb_device_handle * dev_handle)382 static inline struct winusb_device_handle_priv *get_winusb_device_handle_priv(struct libusb_device_handle *dev_handle)
383 {
384 	struct windows_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
385 	return &handle_priv->winusb_priv;
386 }
387 
get_transfer_priv_overlapped(struct usbi_transfer * itransfer)388 static inline OVERLAPPED *get_transfer_priv_overlapped(struct usbi_transfer *itransfer)
389 {
390 	struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
391 	return &transfer_priv->overlapped;
392 }
393 
set_transfer_priv_handle(struct usbi_transfer * itransfer,HANDLE handle)394 static inline void set_transfer_priv_handle(struct usbi_transfer *itransfer, HANDLE handle)
395 {
396 	struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
397 	transfer_priv->handle = handle;
398 }
399 
get_usbdk_transfer_priv(struct usbi_transfer * itransfer)400 static inline struct usbdk_transfer_priv *get_usbdk_transfer_priv(struct usbi_transfer *itransfer)
401 {
402 	struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
403 	return &transfer_priv->usbdk_priv;
404 }
405 
get_winusb_transfer_priv(struct usbi_transfer * itransfer)406 static inline struct winusb_transfer_priv *get_winusb_transfer_priv(struct usbi_transfer *itransfer)
407 {
408 	struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
409 	return &transfer_priv->winusb_priv;
410 }
411 
412 extern const struct windows_backend usbdk_backend;
413 extern const struct windows_backend winusb_backend;
414 
415 HMODULE load_system_library(struct libusb_context *ctx, const char *name);
416 unsigned long htab_hash(const char *str);
417 enum libusb_transfer_status usbd_status_to_libusb_transfer_status(USBD_STATUS status);
418 void windows_force_sync_completion(struct usbi_transfer *itransfer, ULONG size);
419 
420 #if defined(ENABLE_LOGGING)
421 const char *windows_error_str(DWORD error_code);
422 #endif
423 
424 #endif
425