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