1 /*******************************************************
2  HIDAPI - Multi-Platform library for
3  communication with HID devices.
4 
5  Alan Ott
6  Signal 11 Software
7 
8  8/22/2009
9 
10  Copyright 2009, All Rights Reserved.
11 
12  At the discretion of the user of this library,
13  this software may be licensed under the terms of the
14  GNU General Public License v3, a BSD-Style license, or the
15  original HIDAPI license as outlined in the LICENSE.txt,
16  LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
17  files located at the root of the source distribution.
18  These files may also be found in the public source
19  code repository located at:
20         https://github.com/libusb/hidapi .
21 ********************************************************/
22 #include "../../SDL_internal.h"
23 
24 #ifdef SDL_JOYSTICK_HIDAPI
25 
26 #include <windows.h>
27 
28 #if 0 /* can cause redefinition errors on some toolchains */
29 #ifdef __MINGW32__
30 #include <ntdef.h>
31 #include <winbase.h>
32 #endif
33 
34 #ifdef __CYGWIN__
35 #include <ntdef.h>
36 #define _wcsdup wcsdup
37 #endif
38 #endif /* */
39 
40 #ifndef _NTDEF_
41 typedef LONG NTSTATUS;
42 #endif
43 
44 /* SDL C runtime functions */
45 #include "SDL_stdinc.h"
46 
47 #define calloc SDL_calloc
48 #define free SDL_free
49 #define malloc SDL_malloc
50 #define memcpy SDL_memcpy
51 #define memset SDL_memset
52 #define strcmp SDL_strcmp
53 #define strlen SDL_strlen
54 #define strncpy SDL_strlcpy
55 #define strstr SDL_strstr
56 #define strtol SDL_strtol
57 #define wcscmp SDL_wcscmp
58 #define _wcsdup SDL_wcsdup
59 
60 /* The maximum number of characters that can be passed into the
61    HidD_Get*String() functions without it failing.*/
62 #define MAX_STRING_WCHARS 0xFFF
63 
64 /*#define HIDAPI_USE_DDK*/
65 
66 /* The timeout in milliseconds for waiting on WriteFile to
67    complete in hid_write. The longest observed time to do a output
68    report that we've seen is ~200-250ms so let's double that */
69 #define HID_WRITE_TIMEOUT_MILLISECONDS 500
70 
71 /* We will only enumerate devices that match these usages */
72 #define USAGE_PAGE_GENERIC_DESKTOP 0x0001
73 #define USAGE_JOYSTICK 0x0004
74 #define USAGE_GAMEPAD 0x0005
75 #define USAGE_MULTIAXISCONTROLLER 0x0008
76 #define USB_VENDOR_VALVE 0x28de
77 
78 #ifdef __cplusplus
79 extern "C" {
80 #endif
81 	#include <setupapi.h>
82 	#include <winioctl.h>
83 	#ifdef HIDAPI_USE_DDK
84 		#include <hidsdi.h>
85 	#endif
86 
87 	/* Copied from inc/ddk/hidclass.h, part of the Windows DDK. */
88 	#define HID_OUT_CTL_CODE(id)  \
89 		CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
90 	#define IOCTL_HID_GET_FEATURE                   HID_OUT_CTL_CODE(100)
91 
92 #ifdef __cplusplus
93 } /* extern "C" */
94 #endif
95 
96 #include <stdio.h>
97 #include <stdlib.h>
98 
99 
100 #include "../hidapi/hidapi.h"
101 
102 #undef MIN
103 #define MIN(x,y) ((x) < (y)? (x): (y))
104 
105 #ifdef _MSC_VER
106 	/* Thanks Microsoft, but I know how to use strncpy(). */
107 	#pragma warning(disable:4996)
108 #endif
109 
110 #ifdef __cplusplus
111 extern "C" {
112 #endif
113 
114 #ifndef HIDAPI_USE_DDK
115 	/* Since we're not building with the DDK, and the HID header
116 	   files aren't part of the SDK, we have to define all this
117 	   stuff here. In lookup_functions(), the function pointers
118 	   defined below are set. */
119 	typedef struct _HIDD_ATTRIBUTES{
120 		ULONG Size;
121 		USHORT VendorID;
122 		USHORT ProductID;
123 		USHORT VersionNumber;
124 	} HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES;
125 
126 	typedef USHORT USAGE;
127 	typedef struct _HIDP_CAPS {
128 		USAGE Usage;
129 		USAGE UsagePage;
130 		USHORT InputReportByteLength;
131 		USHORT OutputReportByteLength;
132 		USHORT FeatureReportByteLength;
133 		USHORT Reserved[17];
134 		USHORT fields_not_used_by_hidapi[10];
135 	} HIDP_CAPS, *PHIDP_CAPS;
136 	typedef void* PHIDP_PREPARSED_DATA;
137 	#define HIDP_STATUS_SUCCESS 0x110000
138 
139 	typedef BOOLEAN (__stdcall *HidD_GetAttributes_)(HANDLE device, PHIDD_ATTRIBUTES attrib);
140 	typedef BOOLEAN (__stdcall *HidD_GetSerialNumberString_)(HANDLE device, PVOID buffer, ULONG buffer_len);
141 	typedef BOOLEAN (__stdcall *HidD_GetManufacturerString_)(HANDLE handle, PVOID buffer, ULONG buffer_len);
142 	typedef BOOLEAN (__stdcall *HidD_GetProductString_)(HANDLE handle, PVOID buffer, ULONG buffer_len);
143 	typedef BOOLEAN (__stdcall *HidD_SetFeature_)(HANDLE handle, PVOID data, ULONG length);
144 	typedef BOOLEAN (__stdcall *HidD_GetFeature_)(HANDLE handle, PVOID data, ULONG length);
145 	typedef BOOLEAN (__stdcall *HidD_GetIndexedString_)(HANDLE handle, ULONG string_index, PVOID buffer, ULONG buffer_len);
146 	typedef BOOLEAN (__stdcall *HidD_GetPreparsedData_)(HANDLE handle, PHIDP_PREPARSED_DATA *preparsed_data);
147 	typedef BOOLEAN (__stdcall *HidD_FreePreparsedData_)(PHIDP_PREPARSED_DATA preparsed_data);
148 	typedef NTSTATUS (__stdcall *HidP_GetCaps_)(PHIDP_PREPARSED_DATA preparsed_data, HIDP_CAPS *caps);
149 	typedef BOOLEAN (__stdcall *HidD_SetNumInputBuffers_)(HANDLE handle, ULONG number_buffers);
150 	typedef BOOLEAN(__stdcall *HidD_SetOutputReport_ )(HANDLE handle, PVOID buffer, ULONG buffer_len);
151 	static HidD_GetAttributes_ HidD_GetAttributes;
152 	static HidD_GetSerialNumberString_ HidD_GetSerialNumberString;
153 	static HidD_GetManufacturerString_ HidD_GetManufacturerString;
154 	static HidD_GetProductString_ HidD_GetProductString;
155 	static HidD_SetFeature_ HidD_SetFeature;
156 	static HidD_GetFeature_ HidD_GetFeature;
157 	static HidD_GetIndexedString_ HidD_GetIndexedString;
158 	static HidD_GetPreparsedData_ HidD_GetPreparsedData;
159 	static HidD_FreePreparsedData_ HidD_FreePreparsedData;
160 	static HidP_GetCaps_ HidP_GetCaps;
161 	static HidD_SetNumInputBuffers_ HidD_SetNumInputBuffers;
162 	static HidD_SetOutputReport_ HidD_SetOutputReport;
163 
164 	static HMODULE lib_handle = NULL;
165 	static BOOLEAN initialized = FALSE;
166 #endif /* HIDAPI_USE_DDK */
167 
168 struct hid_device_ {
169 		HANDLE device_handle;
170 		BOOL blocking;
171 		USHORT output_report_length;
172 		size_t input_report_length;
173 		void *last_error_str;
174 		DWORD last_error_num;
175 		BOOL read_pending;
176 		char *read_buf;
177 		OVERLAPPED ol;
178 		OVERLAPPED write_ol;
179 };
180 
new_hid_device()181 static hid_device *new_hid_device()
182 {
183 	hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device));
184 	dev->device_handle = INVALID_HANDLE_VALUE;
185 	dev->blocking = TRUE;
186 	dev->output_report_length = 0;
187 	dev->input_report_length = 0;
188 	dev->last_error_str = NULL;
189 	dev->last_error_num = 0;
190 	dev->read_pending = FALSE;
191 	dev->read_buf = NULL;
192 	memset(&dev->ol, 0, sizeof(dev->ol));
193 	dev->ol.hEvent = CreateEvent(NULL, FALSE, FALSE /*initial state f=nonsignaled*/, NULL);
194 	memset(&dev->write_ol, 0, sizeof(dev->write_ol));
195 	dev->write_ol.hEvent = CreateEvent(NULL, FALSE, FALSE /*initial state f=nonsignaled*/, NULL);
196 
197 	return dev;
198 }
199 
free_hid_device(hid_device * dev)200 static void free_hid_device(hid_device *dev)
201 {
202 	CloseHandle(dev->ol.hEvent);
203 	CloseHandle(dev->write_ol.hEvent);
204 	CloseHandle(dev->device_handle);
205 	LocalFree(dev->last_error_str);
206 	free(dev->read_buf);
207 	free(dev);
208 }
209 
register_error(hid_device * device,const char * op)210 static void register_error(hid_device *device, const char *op)
211 {
212 	WCHAR *ptr, *msg;
213 
214 	DWORD count = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
215 		FORMAT_MESSAGE_FROM_SYSTEM |
216 		FORMAT_MESSAGE_IGNORE_INSERTS,
217 		NULL,
218 		GetLastError(),
219 		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
220 		(LPWSTR)&msg, 0/*sz*/,
221 		NULL);
222 	if (!count)
223 		return;
224 
225 	/* Get rid of the CR and LF that FormatMessage() sticks at the
226 	   end of the message. Thanks Microsoft! */
227 	ptr = msg;
228 	while (*ptr) {
229 		if (*ptr == '\r') {
230 			*ptr = 0x0000;
231 			break;
232 		}
233 		ptr++;
234 	}
235 
236 	/* Store the message off in the Device entry so that
237 	   the hid_error() function can pick it up. */
238 	LocalFree(device->last_error_str);
239 	device->last_error_str = msg;
240 }
241 
242 #ifndef HIDAPI_USE_DDK
lookup_functions()243 static int lookup_functions()
244 {
245 	lib_handle = LoadLibraryA("hid.dll");
246 	if (lib_handle) {
247 #define RESOLVE(x) x = (x##_)GetProcAddress(lib_handle, #x); if (!x) return -1;
248 		RESOLVE(HidD_GetAttributes);
249 		RESOLVE(HidD_GetSerialNumberString);
250 		RESOLVE(HidD_GetManufacturerString);
251 		RESOLVE(HidD_GetProductString);
252 		RESOLVE(HidD_SetFeature);
253 		RESOLVE(HidD_GetFeature);
254 		RESOLVE(HidD_GetIndexedString);
255 		RESOLVE(HidD_GetPreparsedData);
256 		RESOLVE(HidD_FreePreparsedData);
257 		RESOLVE(HidP_GetCaps);
258 		RESOLVE(HidD_SetNumInputBuffers);
259 		RESOLVE(HidD_SetOutputReport);
260 #undef RESOLVE
261 	}
262 	else
263 		return -1;
264 
265 	return 0;
266 }
267 #endif
268 
open_device(const char * path,BOOL enumerate,BOOL bExclusive)269 static HANDLE open_device(const char *path, BOOL enumerate, BOOL bExclusive )
270 {
271 	HANDLE handle;
272 	// Opening with access 0 causes keyboards to stop responding in some system configurations
273 	// http://steamcommunity.com/discussions/forum/1/1843493219428923893
274 	// Thanks to co-wie (Ka-wei Low <kawei@mac.com>) for help narrowing down the problem on his system
275 	//DWORD desired_access = (enumerate)? 0: (GENERIC_WRITE | GENERIC_READ);
276 	DWORD desired_access = ( GENERIC_WRITE | GENERIC_READ );
277 	DWORD share_mode = bExclusive ? 0 : ( FILE_SHARE_READ | FILE_SHARE_WRITE );
278 
279 	handle = CreateFileA(path,
280 		desired_access,
281 		share_mode,
282 		NULL,
283 		OPEN_EXISTING,
284 		FILE_FLAG_OVERLAPPED,/*FILE_ATTRIBUTE_NORMAL,*/
285 		0);
286 
287 	return handle;
288 }
289 
hid_init(void)290 int HID_API_EXPORT hid_init(void)
291 {
292 #ifndef HIDAPI_USE_DDK
293 	if (!initialized) {
294 		if (lookup_functions() < 0) {
295 			hid_exit();
296 			return -1;
297 		}
298 		initialized = TRUE;
299 	}
300 #endif
301 	return 0;
302 }
303 
hid_exit(void)304 int HID_API_EXPORT hid_exit(void)
305 {
306 #ifndef HIDAPI_USE_DDK
307 	if (lib_handle)
308 		FreeLibrary(lib_handle);
309 	lib_handle = NULL;
310 	initialized = FALSE;
311 #endif
312 	return 0;
313 }
314 
hid_blacklist(unsigned short vendor_id,unsigned short product_id)315 int hid_blacklist(unsigned short vendor_id, unsigned short product_id)
316 {
317     size_t i;
318     static const struct { unsigned short vid; unsigned short pid; } known_bad[] = {
319         /* Causes deadlock when asking for device details... */
320         { 0x1B1C, 0x1B3D },  /* Corsair Gaming keyboard */
321         { 0x1532, 0x0109 },  /* Razer Lycosa Gaming keyboard */
322         { 0x1532, 0x010B },  /* Razer Arctosa Gaming keyboard */
323         { 0x045E, 0x0822 },  /* Microsoft Precision Mouse */
324 
325         /* Turns into an Android controller when enumerated... */
326         { 0x0738, 0x2217 }   /* SPEEDLINK COMPETITION PRO */
327     };
328 
329     for (i = 0; i < SDL_arraysize(known_bad); i++) {
330         if ((vendor_id == known_bad[i].vid) && (product_id == known_bad[i].pid)) {
331             return 1;
332         }
333     }
334 
335     return 0;
336 }
337 
hid_enumerate(unsigned short vendor_id,unsigned short product_id)338 struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id)
339 {
340 	BOOL res;
341 	struct hid_device_info *root = NULL; /* return object */
342 	struct hid_device_info *cur_dev = NULL;
343 
344 	/* Windows objects for interacting with the driver. */
345 	GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, {0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30} };
346 	SP_DEVINFO_DATA devinfo_data;
347 	SP_DEVICE_INTERFACE_DATA device_interface_data;
348 	SP_DEVICE_INTERFACE_DETAIL_DATA_A *device_interface_detail_data = NULL;
349 	HDEVINFO device_info_set = INVALID_HANDLE_VALUE;
350 	int device_index = 0;
351 
352 	if (hid_init() < 0)
353 		return NULL;
354 
355 	/* Initialize the Windows objects. */
356 	memset(&devinfo_data, 0x0, sizeof(devinfo_data));
357 	devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA);
358 	device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
359 
360 	/* Get information for all the devices belonging to the HID class. */
361 	device_info_set = SetupDiGetClassDevsA(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
362 
363 	/* Iterate over each device in the HID class, looking for the right one. */
364 
365 	for (;;) {
366 		HANDLE write_handle = INVALID_HANDLE_VALUE;
367 		DWORD required_size = 0;
368 		HIDD_ATTRIBUTES attrib;
369 
370 		res = SetupDiEnumDeviceInterfaces(device_info_set,
371 			NULL,
372 			&InterfaceClassGuid,
373 			device_index,
374 			&device_interface_data);
375 
376 		if (!res) {
377 			/* A return of FALSE from this function means that
378 			   there are no more devices. */
379 			break;
380 		}
381 
382 		/* Call with 0-sized detail size, and let the function
383 		   tell us how long the detail struct needs to be. The
384 		   size is put in &required_size. */
385 		res = SetupDiGetDeviceInterfaceDetailA(device_info_set,
386 			&device_interface_data,
387 			NULL,
388 			0,
389 			&required_size,
390 			NULL);
391 
392 		/* Allocate a long enough structure for device_interface_detail_data. */
393 		device_interface_detail_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_A*) malloc(required_size);
394 		device_interface_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
395 
396 		/* Get the detailed data for this device. The detail data gives us
397 		   the device path for this device, which is then passed into
398 		   CreateFile() to get a handle to the device. */
399 		res = SetupDiGetDeviceInterfaceDetailA(device_info_set,
400 			&device_interface_data,
401 			device_interface_detail_data,
402 			required_size,
403 			NULL,
404 			NULL);
405 
406 		if (!res) {
407 			/* register_error(dev, "Unable to call SetupDiGetDeviceInterfaceDetail");
408 			   Continue to the next device. */
409 			goto cont;
410 		}
411 
412 		/* Make sure this device is of Setup Class "HIDClass" and has a
413 		   driver bound to it. */
414 		/* In the main HIDAPI tree this is a loop which will erroneously open
415 			devices that aren't HID class. Please preserve this delta if we ever
416 			update to take new changes */
417 		{
418 			char driver_name[256];
419 
420 			/* Populate devinfo_data. This function will return failure
421 			   when there are no more interfaces left. */
422 			res = SetupDiEnumDeviceInfo(device_info_set, device_index, &devinfo_data);
423 
424 			if (!res)
425 				goto cont;
426 
427 			res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data,
428 			               SPDRP_CLASS, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL);
429 			if (!res)
430 				goto cont;
431 
432 			if (strcmp(driver_name, "HIDClass") == 0) {
433 				/* See if there's a driver bound. */
434 				res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data,
435 				           SPDRP_DRIVER, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL);
436 				if (!res)
437 					goto cont;
438 			}
439 			else
440 			{
441 				goto cont;
442 			}
443 		}
444 
445 		//wprintf(L"HandleName: %s\n", device_interface_detail_data->DevicePath);
446 
447 		/* Open a handle to the device */
448 		write_handle = open_device(device_interface_detail_data->DevicePath, TRUE, FALSE);
449 
450 		/* Check validity of write_handle. */
451 		if (write_handle == INVALID_HANDLE_VALUE) {
452 			/* Unable to open the device. */
453 			//register_error(dev, "CreateFile");
454 			goto cont;
455 		}
456 
457 
458 		/* Get the Vendor ID and Product ID for this device. */
459 		attrib.Size = sizeof(HIDD_ATTRIBUTES);
460 		HidD_GetAttributes(write_handle, &attrib);
461 		//wprintf(L"Product/Vendor: %x %x\n", attrib.ProductID, attrib.VendorID);
462 
463 		/* Check the VID/PID to see if we should add this
464 		   device to the enumeration list. */
465 		if ((vendor_id == 0x0 || attrib.VendorID == vendor_id) &&
466 		    (product_id == 0x0 || attrib.ProductID == product_id) &&
467 			!hid_blacklist(attrib.VendorID, attrib.ProductID)) {
468 
469 			#define WSTR_LEN 512
470 			const char *str;
471 			struct hid_device_info *tmp;
472 			PHIDP_PREPARSED_DATA pp_data = NULL;
473 			HIDP_CAPS caps;
474 			BOOLEAN hidp_res;
475 			NTSTATUS nt_res;
476 			wchar_t wstr[WSTR_LEN]; /* TODO: Determine Size */
477 			size_t len;
478 
479 			/* Get the Usage Page and Usage for this device. */
480 			hidp_res = HidD_GetPreparsedData(write_handle, &pp_data);
481 			if (hidp_res) {
482 				nt_res = HidP_GetCaps(pp_data, &caps);
483 				HidD_FreePreparsedData(pp_data);
484 				if (nt_res != HIDP_STATUS_SUCCESS) {
485 					goto cont_close;
486 				}
487 			}
488 			else {
489 				goto cont_close;
490 			}
491 
492 			/* SDL Modification: Ignore the device if it's not a gamepad. This limits compatibility
493 			   risk from devices that may respond poorly to our string queries below. */
494 			if (attrib.VendorID != USB_VENDOR_VALVE) {
495 				if (caps.UsagePage != USAGE_PAGE_GENERIC_DESKTOP) {
496 					goto cont_close;
497 				}
498 				if (caps.Usage != USAGE_JOYSTICK && caps.Usage != USAGE_GAMEPAD && caps.Usage != USAGE_MULTIAXISCONTROLLER) {
499 					goto cont_close;
500 				}
501 			}
502 
503 			/* VID/PID match. Create the record. */
504 			tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info));
505 			if (cur_dev) {
506 				cur_dev->next = tmp;
507 			}
508 			else {
509 				root = tmp;
510 			}
511 			cur_dev = tmp;
512 
513 			/* Fill out the record */
514 			cur_dev->usage_page = caps.UsagePage;
515 			cur_dev->usage = caps.Usage;
516 			cur_dev->next = NULL;
517 			str = device_interface_detail_data->DevicePath;
518 			if (str) {
519 				len = strlen(str);
520 				cur_dev->path = (char*) calloc(len+1, sizeof(char));
521 				strncpy(cur_dev->path, str, len+1);
522 				cur_dev->path[len] = '\0';
523 			}
524 			else
525 				cur_dev->path = NULL;
526 
527 			/* Serial Number */
528 			hidp_res = HidD_GetSerialNumberString(write_handle, wstr, sizeof(wstr));
529 			wstr[WSTR_LEN-1] = 0x0000;
530 			if (hidp_res) {
531 				cur_dev->serial_number = _wcsdup(wstr);
532 			}
533 
534 			/* Manufacturer String */
535 			hidp_res = HidD_GetManufacturerString(write_handle, wstr, sizeof(wstr));
536 			wstr[WSTR_LEN-1] = 0x0000;
537 			if (hidp_res) {
538 				cur_dev->manufacturer_string = _wcsdup(wstr);
539 			}
540 
541 			/* Product String */
542 			hidp_res = HidD_GetProductString(write_handle, wstr, sizeof(wstr));
543 			wstr[WSTR_LEN-1] = 0x0000;
544 			if (hidp_res) {
545 				cur_dev->product_string = _wcsdup(wstr);
546 			}
547 
548 			/* VID/PID */
549 			cur_dev->vendor_id = attrib.VendorID;
550 			cur_dev->product_id = attrib.ProductID;
551 
552 			/* Release Number */
553 			cur_dev->release_number = attrib.VersionNumber;
554 
555 			/* Interface Number. It can sometimes be parsed out of the path
556 			   on Windows if a device has multiple interfaces. See
557 			   http://msdn.microsoft.com/en-us/windows/hardware/gg487473 or
558 			   search for "Hardware IDs for HID Devices" at MSDN. If it's not
559 			   in the path, it's set to -1. */
560 			cur_dev->interface_number = -1;
561 			if (cur_dev->path) {
562 				char *interface_component = strstr(cur_dev->path, "&mi_");
563 				if (interface_component) {
564 					char *hex_str = interface_component + 4;
565 					char *endptr = NULL;
566 					cur_dev->interface_number = strtol(hex_str, &endptr, 16);
567 					if (endptr == hex_str) {
568 						/* The parsing failed. Set interface_number to -1. */
569 						cur_dev->interface_number = -1;
570 					}
571 				}
572 			}
573 		}
574 
575 cont_close:
576 		CloseHandle(write_handle);
577 cont:
578 		/* We no longer need the detail data. It can be freed */
579 		free(device_interface_detail_data);
580 
581 		device_index++;
582 
583 	}
584 
585 	/* Close the device information handle. */
586 	SetupDiDestroyDeviceInfoList(device_info_set);
587 
588 	return root;
589 
590 }
591 
hid_free_enumeration(struct hid_device_info * devs)592 void  HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs)
593 {
594 	/* TODO: Merge this with the Linux version. This function is platform-independent. */
595 	struct hid_device_info *d = devs;
596 	while (d) {
597 		struct hid_device_info *next = d->next;
598 		free(d->path);
599 		free(d->serial_number);
600 		free(d->manufacturer_string);
601 		free(d->product_string);
602 		free(d);
603 		d = next;
604 	}
605 }
606 
607 
hid_open(unsigned short vendor_id,unsigned short product_id,const wchar_t * serial_number)608 HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
609 {
610 	/* TODO: Merge this functions with the Linux version. This function should be platform independent. */
611 	struct hid_device_info *devs, *cur_dev;
612 	const char *path_to_open = NULL;
613 	hid_device *handle = NULL;
614 
615 	devs = hid_enumerate(vendor_id, product_id);
616 	cur_dev = devs;
617 	while (cur_dev) {
618 		if (cur_dev->vendor_id == vendor_id &&
619 		    cur_dev->product_id == product_id) {
620 			if (serial_number) {
621 				if (wcscmp(serial_number, cur_dev->serial_number) == 0) {
622 					path_to_open = cur_dev->path;
623 					break;
624 				}
625 			}
626 			else {
627 				path_to_open = cur_dev->path;
628 				break;
629 			}
630 		}
631 		cur_dev = cur_dev->next;
632 	}
633 
634 	if (path_to_open) {
635 		/* Open the device */
636 		handle = hid_open_path(path_to_open, 0);
637 	}
638 
639 	hid_free_enumeration(devs);
640 
641 	return handle;
642 }
643 
hid_open_path(const char * path,int bExclusive)644 HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path, int bExclusive)
645 {
646 	hid_device *dev;
647 	HIDP_CAPS caps;
648 	PHIDP_PREPARSED_DATA pp_data = NULL;
649 	BOOLEAN res;
650 	NTSTATUS nt_res;
651 
652 	if (hid_init() < 0) {
653 		return NULL;
654 	}
655 
656 	dev = new_hid_device();
657 
658 	/* Open a handle to the device */
659 	dev->device_handle = open_device(path, FALSE, bExclusive);
660 
661 	/* Check validity of write_handle. */
662 	if (dev->device_handle == INVALID_HANDLE_VALUE) {
663 		/* Unable to open the device. */
664 		register_error(dev, "CreateFile");
665 		goto err;
666 	}
667 
668 	/* Set the Input Report buffer size to 64 reports. */
669 	res = HidD_SetNumInputBuffers(dev->device_handle, 64);
670 	if (!res) {
671 		register_error(dev, "HidD_SetNumInputBuffers");
672 		goto err;
673 	}
674 
675 	/* Get the Input Report length for the device. */
676 	res = HidD_GetPreparsedData(dev->device_handle, &pp_data);
677 	if (!res) {
678 		register_error(dev, "HidD_GetPreparsedData");
679 		goto err;
680 	}
681 	nt_res = HidP_GetCaps(pp_data, &caps);
682 	if (nt_res != HIDP_STATUS_SUCCESS) {
683 		register_error(dev, "HidP_GetCaps");
684 		goto err_pp_data;
685 	}
686 	dev->output_report_length = caps.OutputReportByteLength;
687 	dev->input_report_length = caps.InputReportByteLength;
688 	HidD_FreePreparsedData(pp_data);
689 
690 	dev->read_buf = (char*) malloc(dev->input_report_length);
691 
692 	return dev;
693 
694 err_pp_data:
695 		HidD_FreePreparsedData(pp_data);
696 err:
697 		free_hid_device(dev);
698 		return NULL;
699 }
700 
hid_write_output_report(hid_device * dev,const unsigned char * data,size_t length)701 int HID_API_EXPORT HID_API_CALL hid_write_output_report(hid_device *dev, const unsigned char *data, size_t length)
702 {
703 	BOOL res;
704 	res = HidD_SetOutputReport(dev->device_handle, (void *)data, (ULONG)length);
705 	if (res)
706 		return (int)length;
707 	else
708 		return -1;
709 }
710 
hid_write_timeout(hid_device * dev,const unsigned char * data,size_t length,int milliseconds)711 static int hid_write_timeout(hid_device *dev, const unsigned char *data, size_t length, int milliseconds)
712 {
713 	DWORD bytes_written;
714 	BOOL res;
715 	size_t stashed_length = length;
716 	unsigned char *buf;
717 
718 	/* Make sure the right number of bytes are passed to WriteFile. Windows
719 	   expects the number of bytes which are in the _longest_ report (plus
720 	   one for the report number) bytes even if the data is a report
721 	   which is shorter than that. Windows gives us this value in
722 	   caps.OutputReportByteLength. If a user passes in fewer bytes than this,
723 	   create a temporary buffer which is the proper size. */
724 	if (length >= dev->output_report_length) {
725 		/* The user passed the right number of bytes. Use the buffer as-is. */
726 		buf = (unsigned char *) data;
727 	} else {
728 		/* Create a temporary buffer and copy the user's data
729 		   into it, padding the rest with zeros. */
730 		buf = (unsigned char *) malloc(dev->output_report_length);
731 		memcpy(buf, data, length);
732 		memset(buf + length, 0, dev->output_report_length - length);
733 		length = dev->output_report_length;
734 	}
735 	if (length > 512)
736 	{
737 		return hid_write_output_report( dev, data, stashed_length );
738 	}
739 	else
740 	{
741 		res = WriteFile( dev->device_handle, buf, ( DWORD ) length, NULL, &dev->write_ol );
742 		if (!res) {
743 			if (GetLastError() != ERROR_IO_PENDING) {
744 				/* WriteFile() failed. Return error. */
745 				register_error(dev, "WriteFile");
746 				bytes_written = (DWORD) -1;
747 				goto end_of_function;
748 			}
749 		}
750 
751 		/* Wait here until the write is done. This makes
752 		hid_write() synchronous. */
753 		res = WaitForSingleObject(dev->write_ol.hEvent, milliseconds);
754 		if (res != WAIT_OBJECT_0)
755 		{
756 			// There was a Timeout.
757 			bytes_written = (DWORD) -1;
758 			register_error(dev, "WriteFile/WaitForSingleObject Timeout");
759 			goto end_of_function;
760 		}
761 
762 		res = GetOverlappedResult(dev->device_handle, &dev->write_ol, &bytes_written, FALSE/*F=don't_wait*/);
763 		if (!res) {
764 			/* The Write operation failed. */
765 			register_error(dev, "WriteFile");
766 			bytes_written = (DWORD) -1;
767 			goto end_of_function;
768 		}
769 	}
770 end_of_function:
771 	if (buf != data)
772 		free(buf);
773 
774 	return bytes_written;
775 }
776 
hid_write(hid_device * dev,const unsigned char * data,size_t length)777 int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length)
778 {
779 	return hid_write_timeout(dev, data, length, HID_WRITE_TIMEOUT_MILLISECONDS);
780 }
781 
hid_read_timeout(hid_device * dev,unsigned char * data,size_t length,int milliseconds)782 int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
783 {
784 	DWORD bytes_read = 0;
785 	size_t copy_len = 0;
786 	BOOL res;
787 
788 	/* Copy the handle for convenience. */
789 	HANDLE ev = dev->ol.hEvent;
790 
791 	if (!dev->read_pending) {
792 		/* Start an Overlapped I/O read. */
793 		dev->read_pending = TRUE;
794 		memset(dev->read_buf, 0, dev->input_report_length);
795 		ResetEvent(ev);
796 		res = ReadFile(dev->device_handle, dev->read_buf, (DWORD)dev->input_report_length, &bytes_read, &dev->ol);
797 
798 		if (!res) {
799 			if (GetLastError() != ERROR_IO_PENDING) {
800 				/* ReadFile() has failed.
801 				   Clean up and return error. */
802 				CancelIo(dev->device_handle);
803 				dev->read_pending = FALSE;
804 				goto end_of_function;
805 			}
806 		}
807 	}
808 
809 	if (milliseconds >= 0) {
810 		/* See if there is any data yet. */
811 		res = WaitForSingleObject(ev, milliseconds);
812 		if (res != WAIT_OBJECT_0) {
813 			/* There was no data this time. Return zero bytes available,
814 			   but leave the Overlapped I/O running. */
815 			return 0;
816 		}
817 	}
818 
819 	/* Either WaitForSingleObject() told us that ReadFile has completed, or
820 	   we are in non-blocking mode. Get the number of bytes read. The actual
821 	   data has been copied to the data[] array which was passed to ReadFile(). */
822 	res = GetOverlappedResult(dev->device_handle, &dev->ol, &bytes_read, TRUE/*wait*/);
823 
824 	/* Set pending back to false, even if GetOverlappedResult() returned error. */
825 	dev->read_pending = FALSE;
826 
827 	if (res && bytes_read > 0) {
828 		if (dev->read_buf[0] == 0x0) {
829 			/* If report numbers aren't being used, but Windows sticks a report
830 			   number (0x0) on the beginning of the report anyway. To make this
831 			   work like the other platforms, and to make it work more like the
832 			   HID spec, we'll skip over this byte. */
833 			bytes_read--;
834 			copy_len = length > bytes_read ? bytes_read : length;
835 			memcpy(data, dev->read_buf+1, copy_len);
836 		}
837 		else {
838 			/* Copy the whole buffer, report number and all. */
839 			copy_len = length > bytes_read ? bytes_read : length;
840 			memcpy(data, dev->read_buf, copy_len);
841 		}
842 	}
843 
844 end_of_function:
845 	if (!res) {
846 		register_error(dev, "GetOverlappedResult");
847 		return -1;
848 	}
849 
850 	return (int)copy_len;
851 }
852 
hid_read(hid_device * dev,unsigned char * data,size_t length)853 int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, size_t length)
854 {
855 	return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0);
856 }
857 
hid_set_nonblocking(hid_device * dev,int nonblock)858 int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonblock)
859 {
860 	dev->blocking = !nonblock;
861 	return 0; /* Success */
862 }
863 
hid_send_feature_report(hid_device * dev,const unsigned char * data,size_t length)864 int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length)
865 {
866 	BOOL res = HidD_SetFeature(dev->device_handle, (PVOID)data, (ULONG)length);
867 	if (!res) {
868 		register_error(dev, "HidD_SetFeature");
869 		return -1;
870 	}
871 
872 	return (int)length;
873 }
874 
875 
hid_get_feature_report(hid_device * dev,unsigned char * data,size_t length)876 int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length)
877 {
878 	BOOL res;
879 #if 0
880 	res = HidD_GetFeature(dev->device_handle, (PVOID)data, (ULONG)length);
881 	if (!res) {
882 		register_error(dev, "HidD_GetFeature");
883 		return -1;
884 	}
885 	return 0; /* HidD_GetFeature() doesn't give us an actual length, unfortunately */
886 #else
887 	DWORD bytes_returned;
888 
889 	OVERLAPPED ol;
890 	memset(&ol, 0, sizeof(ol));
891 
892 	res = DeviceIoControl(dev->device_handle,
893 		IOCTL_HID_GET_FEATURE,
894 		data, (DWORD)length,
895 		data, (DWORD)length,
896 		&bytes_returned, &ol);
897 
898 	if (!res) {
899 		if (GetLastError() != ERROR_IO_PENDING) {
900 			/* DeviceIoControl() failed. Return error. */
901 			register_error(dev, "Send Feature Report DeviceIoControl");
902 			return -1;
903 		}
904 	}
905 
906 	/* Wait here until the write is done. This makes
907 	   hid_get_feature_report() synchronous. */
908 	res = GetOverlappedResult(dev->device_handle, &ol, &bytes_returned, TRUE/*wait*/);
909 	if (!res) {
910 		/* The operation failed. */
911 		register_error(dev, "Send Feature Report GetOverLappedResult");
912 		return -1;
913 	}
914 
915 	/* bytes_returned does not include the first byte which contains the
916 	   report ID. The data buffer actually contains one more byte than
917 	   bytes_returned. */
918 	bytes_returned++;
919 
920 
921 	return bytes_returned;
922 #endif
923 }
924 
hid_close(hid_device * dev)925 void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev)
926 {
927 	if (!dev)
928 		return;
929 	CancelIo(dev->device_handle);
930 	free_hid_device(dev);
931 }
932 
hid_get_manufacturer_string(hid_device * dev,wchar_t * string,size_t maxlen)933 int HID_API_EXPORT_CALL HID_API_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen)
934 {
935 	BOOL res;
936 
937 	res = HidD_GetManufacturerString(dev->device_handle, string, (ULONG)(sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS)));
938 	if (!res) {
939 		register_error(dev, "HidD_GetManufacturerString");
940 		return -1;
941 	}
942 
943 	return 0;
944 }
945 
hid_get_product_string(hid_device * dev,wchar_t * string,size_t maxlen)946 int HID_API_EXPORT_CALL HID_API_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen)
947 {
948 	BOOL res;
949 
950 	res = HidD_GetProductString(dev->device_handle, string, (ULONG)(sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS)));
951 	if (!res) {
952 		register_error(dev, "HidD_GetProductString");
953 		return -1;
954 	}
955 
956 	return 0;
957 }
958 
hid_get_serial_number_string(hid_device * dev,wchar_t * string,size_t maxlen)959 int HID_API_EXPORT_CALL HID_API_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen)
960 {
961 	BOOL res;
962 
963 	res = HidD_GetSerialNumberString(dev->device_handle, string, (ULONG)(sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS)));
964 	if (!res) {
965 		register_error(dev, "HidD_GetSerialNumberString");
966 		return -1;
967 	}
968 
969 	return 0;
970 }
971 
hid_get_indexed_string(hid_device * dev,int string_index,wchar_t * string,size_t maxlen)972 int HID_API_EXPORT_CALL HID_API_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen)
973 {
974 	BOOL res;
975 
976 	res = HidD_GetIndexedString(dev->device_handle, string_index, string, (ULONG)(sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS)));
977 	if (!res) {
978 		register_error(dev, "HidD_GetIndexedString");
979 		return -1;
980 	}
981 
982 	return 0;
983 }
984 
hid_error(hid_device * dev)985 HID_API_EXPORT const wchar_t * HID_API_CALL  hid_error(hid_device *dev)
986 {
987 	return (wchar_t*)dev->last_error_str;
988 }
989 
990 
991 #if 0
992 
993 /*#define PICPGM*/
994 /*#define S11*/
995 #define P32
996 #ifdef S11
997   unsigned short VendorID = 0xa0a0;
998 	unsigned short ProductID = 0x0001;
999 #endif
1000 
1001 #ifdef P32
1002   unsigned short VendorID = 0x04d8;
1003 	unsigned short ProductID = 0x3f;
1004 #endif
1005 
1006 #ifdef PICPGM
1007   unsigned short VendorID = 0x04d8;
1008   unsigned short ProductID = 0x0033;
1009 #endif
1010 
1011 int __cdecl main(int argc, char* argv[])
1012 {
1013 	int res;
1014 	unsigned char buf[65];
1015 
1016 	UNREFERENCED_PARAMETER(argc);
1017 	UNREFERENCED_PARAMETER(argv);
1018 
1019 	/* Set up the command buffer. */
1020 	memset(buf,0x00,sizeof(buf));
1021 	buf[0] = 0;
1022 	buf[1] = 0x81;
1023 
1024 
1025 	/* Open the device. */
1026 	int handle = open(VendorID, ProductID, L"12345");
1027 	if (handle < 0)
1028 		printf("unable to open device\n");
1029 
1030 
1031 	/* Toggle LED (cmd 0x80) */
1032 	buf[1] = 0x80;
1033 	res = write(handle, buf, 65);
1034 	if (res < 0)
1035 		printf("Unable to write()\n");
1036 
1037 	/* Request state (cmd 0x81) */
1038 	buf[1] = 0x81;
1039 	write(handle, buf, 65);
1040 	if (res < 0)
1041 		printf("Unable to write() (2)\n");
1042 
1043 	/* Read requested state */
1044 	read(handle, buf, 65);
1045 	if (res < 0)
1046 		printf("Unable to read()\n");
1047 
1048 	/* Print out the returned buffer. */
1049 	for (int i = 0; i < 4; i++)
1050 		printf("buf[%d]: %d\n", i, buf[i]);
1051 
1052 	return 0;
1053 }
1054 #endif
1055 
1056 #ifdef __cplusplus
1057 } /* extern "C" */
1058 #endif
1059 
1060 #endif /* SDL_JOYSTICK_HIDAPI */
1061