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