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