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 
23 #include "debug.h"
24 
25 #include "hid_win.h"
26 
27 #undef MIN
28 #define MIN(x,y) ((x) < (y)? (x): (y))
29 
30 #ifdef _MSC_VER
31 	/* Thanks Microsoft, but I know how to use strncpy(). */
32 	#pragma warning(disable:4996)
33 #endif
34 
errtext(std::string s)35 void errtext(std::string s)
36 {
37 	FILE *erf = fopen("erf.txt", "a");
38 	fprintf(erf, "%s\n", s.c_str());
39 	fclose(erf);
40 }
41 
wchar2str(const char * where,wchar_t * WC)42 std::string wchar2str( const char *where, wchar_t *WC )
43 {
44 	size_t count = wcstombs(NULL, WC, 1024);
45 	char MB[count + 1];
46 	memset(MB, 0, count + 1);
47 	int ret = wcstombs(MB, WC, count);
48 
49 	if (ret == -1) {
50 		LOG_DEBUG("Cannot convert %s: %ls", where, WC);
51 		return "";
52 	}
53 	return MB;
54 }
55 
56 hid_api_version api_version = {
57 	HID_API_VERSION_MAJOR,
58 	HID_API_VERSION_MINOR,
59 	HID_API_VERSION_PATCH
60 };
61 
register_error(const char * op)62 void hid_device::register_error(const char *op)
63 {
64 	WCHAR *ptr, *msg;
65 	(void)op; // unreferenced  param
66 	FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
67 		FORMAT_MESSAGE_FROM_SYSTEM |
68 		FORMAT_MESSAGE_IGNORE_INSERTS,
69 		NULL,
70 		GetLastError(),
71 		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
72 		(LPWSTR)&msg, 0/*sz*/,
73 		NULL);
74 
75 	/* Get rid of the CR and LF that FormatMessage() sticks at the
76 	   end of the message. Thanks Microsoft! */
77 	ptr = msg;
78 	while (*ptr) {
79 		if (*ptr == '\r') {
80 			*ptr = 0x0000;
81 			break;
82 		}
83 		ptr++;
84 	}
85 
86 	/* Store the message off in the Device entry so that
87 	   the hid_error() function can pick it up. */
88 	LocalFree(last_error_str);
89 	last_error_str = msg;
90 }
91 
open_device(const char * path,BOOL open_rw)92 HANDLE open_device(const char *path, BOOL open_rw)
93 {
94 	HANDLE handle;
95 	DWORD desired_access = (open_rw)? (GENERIC_WRITE | GENERIC_READ): GENERIC_READ;
96 	DWORD share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
97 
98 	handle = CreateFileA(path,
99 		desired_access,
100 		share_mode,
101 		NULL,
102 		OPEN_EXISTING,
103 		FILE_ATTRIBUTE_NORMAL, //FILE_FLAG_OVERLAPPED,/*FILE_ATTRIBUTE_NORMAL,*/
104 		NULL);
105 
106 	return handle;
107 }
108 
hid_version()109 const struct hid_api_version*  hid_version()
110 {
111 	return &api_version;
112 }
113 
hid_version_str()114 const char*  hid_version_str()
115 {
116 	return HID_API_VERSION_STR;
117 }
118 
hid_init(void)119 int  hid_init(void)
120 {
121 	/*
122 #ifndef HIDAPI_USE_DDK
123 	if (!initialized) {
124 		if (lookup_functions() < 0) {
125 			hid_exit();
126 			return -1;
127 		}
128 		initialized = TRUE;
129 	}
130 #endif
131 */
132 //	initialized = TRUE;
133 	return 0;
134 }
135 
hid_exit(void)136 int  hid_exit(void)
137 {
138 //#ifndef HIDAPI_USE_DDK
139 //	if (lib_handle)
140 //		FreeLibrary(lib_handle);
141 //	lib_handle = NULL;
142 //	initialized = FALSE;
143 //#endif
144 	return 0;
145 }
146 
hid_enumerate(unsigned short vendor_id,unsigned short product_id)147 hid_device_info  *  hid_enumerate(unsigned short vendor_id, unsigned short product_id)
148 {
149 	BOOL res;
150 	hid_device_info *root = NULL; /* return object */
151 	hid_device_info *cur_dev = NULL;
152 
153 	/* Hard-coded GUID retreived by HidD_GetHidGuid */
154 	GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, {0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30} };
155 
156 	/* Windows objects for interacting with the driver. */
157 	SP_DEVINFO_DATA devinfo_data;
158 	SP_DEVICE_INTERFACE_DATA device_interface_data;
159 	SP_DEVICE_INTERFACE_DETAIL_DATA_A *device_interface_detail_data = NULL;
160 	HDEVINFO device_info_set = INVALID_HANDLE_VALUE;
161 	char driver_name[256];
162 	int device_index = 0;
163 
164 	if (hid_init() < 0)
165 		return NULL;
166 
167 	/* Initialize the Windows objects. */
168 	memset(&devinfo_data, 0x0, sizeof(devinfo_data));
169 	devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA);
170 	device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
171 
172 	/* Get information for all the devices belonging to the HID class. */
173 	device_info_set = SetupDiGetClassDevsA(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
174 
175 	/* Iterate over each device in the HID class, looking for the right one. */
176 
177 	for (;;) {
178 		HANDLE query_handle = INVALID_HANDLE_VALUE;
179 		DWORD required_size = 0;
180 		HIDD_ATTRIBUTES attrib;
181 
182 		res = SetupDiEnumDeviceInterfaces(device_info_set,
183 			NULL,
184 			&InterfaceClassGuid,
185 			device_index,
186 			&device_interface_data);
187 
188 		if (!res) {
189 			/* A return of FALSE from this function means that
190 			   there are no more devices. */
191 			break;
192 		}
193 
194 		/* Call with 0-sized detail size, and let the function
195 		   tell us how long the detail struct needs to be. The
196 		   size is put in &required_size. */
197 		res = SetupDiGetDeviceInterfaceDetailA(device_info_set,
198 			&device_interface_data,
199 			NULL,
200 			0,
201 			&required_size,
202 			NULL);
203 
204 		/* Allocate a long enough structure for device_interface_detail_data. */
205 		device_interface_detail_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_A*) malloc(required_size);
206 		device_interface_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
207 
208 		/* Get the detailed data for this device. The detail data gives us
209 		   the device path for this device, which is then passed into
210 		   CreateFile() to get a handle to the device. */
211 		res = SetupDiGetDeviceInterfaceDetailA(device_info_set,
212 			&device_interface_data,
213 			device_interface_detail_data,
214 			required_size,
215 			NULL,
216 			NULL);
217 
218 		if (!res) {
219 			/* register_error("Unable to call SetupDiGetDeviceInterfaceDetail");
220 			   Continue to the next device. */
221 			goto cont;
222 		}
223 
224 		/* Populate devinfo_data. This function will return failure
225 		   when the device with such index doesn't exist. We've already checked it does. */
226 		res = SetupDiEnumDeviceInfo(device_info_set, device_index, &devinfo_data);
227 		if (!res)
228 			goto cont;
229 
230 
231 		/* Make sure this device has a driver bound to it. */
232 		res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data,
233 			   SPDRP_DRIVER, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL);
234 		if (!res)
235 			goto cont;
236 
237 		//wprintf(L"HandleName: %s\n", device_interface_detail_data->DevicePath);
238 
239 		/* Open a handle to the device */
240 		query_handle = open_device(device_interface_detail_data->DevicePath, FALSE);
241 
242 		/* Check validity of query_handle. */
243 		if (query_handle == INVALID_HANDLE_VALUE) {
244 			/* Unable to open the device. */
245 			//register_error("CreateFile");
246 			goto cont_close;
247 		}
248 
249 
250 		/* Get the Vendor ID and Product ID for this device. */
251 		attrib.Size = sizeof(HIDD_ATTRIBUTES);
252 		HidD_GetAttributes(query_handle, &attrib);
253 		//wprintf(L"Product/Vendor: %x %x\n", attrib.ProductID, attrib.VendorID);
254 
255 		/* Check the VID/PID to see if we should add this
256 		   device to the enumeration list. */
257 		if ((vendor_id == 0x0 || attrib.VendorID == vendor_id) &&
258 		    (product_id == 0x0 || attrib.ProductID == product_id)) {
259 
260 			#define WSTR_LEN 512
261 			const char *str;
262 			hid_device_info *tmp;
263 			PHIDP_PREPARSED_DATA pp_data = NULL;
264 			HIDP_CAPS caps;
265 			NTSTATUS nt_res;
266 
267 			/* VID/PID match. Create the record. */
268 			tmp = new hid_device_info;
269 			if (cur_dev) {
270 				cur_dev->next = tmp;
271 			}
272 			else {
273 				root = tmp;
274 			}
275 			cur_dev = tmp;
276 
277 			/* Get the Usage Page and Usage for this device. */
278 			res = HidD_GetPreparsedData(query_handle, &pp_data);
279 			if (res) {
280 				nt_res = HidP_GetCaps(pp_data, &caps);
281 				if (nt_res == HIDP_STATUS_SUCCESS) {
282 					cur_dev->usage_page = caps.UsagePage;
283 					cur_dev->usage = caps.Usage;
284 				}
285 
286 				HidD_FreePreparsedData(pp_data);
287 			}
288 
289 			/* Fill out the record */
290 			cur_dev->next = NULL;
291 			str = device_interface_detail_data->DevicePath;
292 			if (str) {
293 				cur_dev->path = str;
294 			}
295 			else
296 				cur_dev->path.clear();
297 
298 			/* Serial Number */
299 			static wchar_t WC[1024];
300 			memset(WC, 0, sizeof(wchar_t) * 1024);
301 			cur_dev->str_serial_number.clear();
302 			res = HidD_GetSerialNumberString(query_handle, WC, 1024);
303 			if (res) cur_dev->str_serial_number = wchar2str("HidD_GetSerialNumberString", WC);;
304 
305 			/* Manufacturer String */
306 			memset(WC, 0, sizeof(wchar_t) * 1024);
307 			cur_dev->str_manufacturer_string.clear();
308 			res = HidD_GetManufacturerString(query_handle, WC, 1024);
309 			if (res) cur_dev->str_manufacturer_string = wchar2str("HidD_GetManufacturerString", WC);;
310 
311 			/* Product String */
312 			memset(WC, 0, sizeof(wchar_t) * 1024);
313 			cur_dev->str_product_string.clear();
314 			res = HidD_GetProductString(query_handle, WC, 1024);
315 			if (res) cur_dev->str_product_string = wchar2str("HidD_GetProductString", WC);;
316 
317 			/* VID/PID */
318 			cur_dev->vendor_id = attrib.VendorID;
319 			cur_dev->product_id = attrib.ProductID;
320 
321 			/* Release Number */
322 			cur_dev->release_number = attrib.VersionNumber;
323 
324 			/* Interface Number. It can sometimes be parsed out of the path
325 			   on Windows if a device has multiple interfaces. See
326 			   http://msdn.microsoft.com/en-us/windows/hardware/gg487473 or
327 			   search for "Hardware IDs for HID Devices" at MSDN. If it's not
328 			   in the path, it's set to -1. */
329 			cur_dev->interface_number = -1;
330 //			if (!cur_dev->path.empty()) {
331 //				char *interface_component = strstr(cur_dev->path, "&mi_");
332 //				if (interface_component) {
333 //					char *hex_str = interface_component + 4;
334 //					char *endptr = NULL;
335 //					cur_dev->interface_number = strtol(hex_str, &endptr, 16);
336 //					if (endptr == hex_str) {
337 //						/* The parsing failed. Set interface_number to -1. */
338 //						cur_dev->interface_number = -1;
339 //					}
340 //				}
341 //			}
342 		}
343 
344 cont_close:
345 		CloseHandle(query_handle);
346 cont:
347 		/* We no longer need the detail data. It can be freed */
348 		free(device_interface_detail_data);
349 
350 		device_index++;
351 
352 	}
353 
354 	/* Close the device information handle. */
355 	SetupDiDestroyDeviceInfoList(device_info_set);
356 
357 	return root;
358 
359 }
360 
hid_free_enumeration(hid_device_info * devs)361 void    hid_free_enumeration(hid_device_info *devs)
362 {
363 	/* TODO: Merge this with the Linux version. This function is platform-independent. */
364 	hid_device_info *d = devs;
365 	while (d) {
366 		hid_device_info *next = d->next;
367 //		free(d->path);
368 //		free(d->serial_number);
369 //		free(d->manufacturer_string);
370 //		free(d->product_string);
371 		delete d;
372 		d = next;
373 	}
374 }
375 
hid_open(unsigned short vendor_id,unsigned short product_id,std::string serial_number)376 hid_device *  hid_open(unsigned short vendor_id, unsigned short product_id, std::string serial_number)
377 {
378 	/* TODO: Merge this functions with the Linux version. This function should be platform independent. */
379 	hid_device_info *devs, *cur_dev;
380 	std::string path_to_open;
381 	hid_device *handle = NULL;
382 
383 	path_to_open.clear();
384 
385 	devs = hid_enumerate(vendor_id, product_id);
386 	cur_dev = devs;
387 	while (cur_dev) {
388 		if (cur_dev->vendor_id == vendor_id &&
389 		    cur_dev->product_id == product_id) {
390 			if (!cur_dev->str_serial_number.empty()) {
391 				if (cur_dev->str_serial_number == serial_number) {
392 					path_to_open = cur_dev->path;
393 					break;
394 				}
395 			}
396 			else {
397 				path_to_open = cur_dev->path;
398 				break;
399 			}
400 		}
401 		cur_dev = cur_dev->next;
402 	}
403 
404 	if (!path_to_open.empty()) {
405 		/* Open the device */
406 		handle = hid_open_path(path_to_open);
407 	}
408 
409 	hid_free_enumeration(devs);
410 
411 	return handle;
412 }
413 
hid_open_path(std::string path)414 hid_device *  hid_open_path(std::string path)
415 {
416 	hid_device *dev;
417 	HIDP_CAPS caps;
418 	PHIDP_PREPARSED_DATA pp_data = NULL;
419 	BOOLEAN res;
420 	NTSTATUS nt_res;
421 
422 	if (hid_init() < 0) {
423 		return NULL;
424 	}
425 
426 	dev = new hid_device;
427 
428 	/* Open a handle to the device */
429 	dev->device_handle = open_device(path.c_str(), TRUE);
430 
431 	/* Check validity of write_handle. */
432 	if (dev->device_handle == INVALID_HANDLE_VALUE) {
433 		/* System devices, such as keyboards and mice, cannot be opened in
434 		   read-write mode, because the system takes exclusive control over
435 		   them.  This is to prevent keyloggers.  However, feature reports
436 		   can still be sent and received.  Retry opening the device, but
437 		   without read/write access. */
438 		dev->device_handle = open_device(path.c_str(), FALSE);
439 
440 		/* Check the validity of the limited device_handle. */
441 		if (dev->device_handle == INVALID_HANDLE_VALUE) {
442 			/* Unable to open the device, even without read-write mode. */
443 			dev->register_error("CreateFile");
444 errtext("CreateFile for ro failed: INVALID_HANDLE");
445 			goto err;
446 		} else
447 errtext("CreateFile for ro OK");
448 	} else
449 errtext("CreateFile for r/w OK");
450 
451 	/* Set the Input Report buffer size to 64 reports. */
452 	res = HidD_SetNumInputBuffers(dev->device_handle, 64);
453 	if (!res) {
454 		dev->register_error("HidD_SetNumInputBuffers");
455 		goto err;
456 	}
457 
458 	/* Get the Input Report length for the device. */
459 	res = HidD_GetPreparsedData(dev->device_handle, &pp_data);
460 	if (!res) {
461 		dev->register_error("HidD_GetPreparsedData");
462 		goto err;
463 	}
464 	nt_res = HidP_GetCaps(pp_data, &caps);
465 	if (nt_res != HIDP_STATUS_SUCCESS) {
466 		dev->register_error("HidP_GetCaps");
467 		goto err_pp_data;
468 	}
469 	dev->output_report_length = caps.OutputReportByteLength;
470 	dev->input_report_length = caps.InputReportByteLength;
471 	dev->feature_report_length = caps.FeatureReportByteLength;
472 	HidD_FreePreparsedData(pp_data);
473 
474 	dev->read_buf = (char*) malloc(dev->input_report_length);
475 
476 	return dev;
477 
478 err_pp_data:
479 		HidD_FreePreparsedData(pp_data);
480 err:
481 		return NULL;
482 }
483 
hid_write(const unsigned char * data,size_t length)484 int  hid_device::hid_write(const unsigned char *data, size_t length)
485 {
486 	DWORD bytes_written = 0;
487 	int function_result = -1;
488 	BOOL res;
489 	BOOL overlapped = FALSE;
490 
491 	unsigned char *buf;
492 
493 	/* Make sure the right number of bytes are passed to WriteFile. Windows
494 	   expects the number of bytes which are in the _longest_ report (plus
495 	   one for the report number) bytes even if the data is a report
496 	   which is shorter than that. Windows gives us this value in
497 	   caps.OutputReportByteLength. If a user passes in fewer bytes than this,
498 	   use cached temporary buffer which is the proper size. */
499 	if (length >= output_report_length) {
500 		/* The user passed the right number of bytes. Use the buffer as-is. */
501 		buf = (unsigned char *) data;
502 	} else {
503 		if (write_buf == NULL)
504 			write_buf = (unsigned char *) malloc(output_report_length);
505 		buf = write_buf;
506 		memcpy(buf, data, length);
507 		memset(buf + length, 0, output_report_length - length);
508 		length = output_report_length;
509 	}
510 
511 	res = WriteFile(device_handle, buf, (DWORD) length, NULL, &write_ol);
512 
513 	if (!res) {
514 		if (GetLastError() != ERROR_IO_PENDING) {
515 			/* WriteFile() failed. Return error. */
516 			register_error("WriteFile");
517 			goto end_of_function;
518 		}
519 		overlapped = TRUE;
520 	}
521 
522 	if (overlapped) {
523 		/* Wait for the transaction to complete. This makes
524 		   hid_write() synchronous. */
525 		res = WaitForSingleObject(write_ol.hEvent, 1000);
526 		if (res != WAIT_OBJECT_0) {
527 			/* There was a Timeout. */
528 			register_error("WriteFile/WaitForSingleObject Timeout");
529 			goto end_of_function;
530 		}
531 
532 		/* Get the result. */
533 		res = GetOverlappedResult(device_handle, &write_ol, &bytes_written, FALSE/*wait*/);
534 		if (res) {
535 			function_result = bytes_written;
536 		}
537 		else {
538 			/* The Write operation failed. */
539 			register_error("WriteFile");
540 			goto end_of_function;
541 		}
542 	}
543 
544 end_of_function:
545 	return function_result;
546 }
547 
548 
hid_read_timeout(unsigned char * data,size_t length,int milliseconds)549 int hid_device::hid_read_timeout(unsigned char *data, size_t length, int milliseconds)
550 {
551 	DWORD bytes_read = 0;
552 	size_t copy_len = 0;
553 	BOOL res = FALSE;
554 	BOOL overlapped = FALSE;
555 
556 	/* Copy the handle for convenience. */
557 	HANDLE ev = ol.hEvent;
558 
559 	if (!read_pending) {
560 		/* Start an Overlapped I/O read. */
561 		read_pending = TRUE;
562 		memset(read_buf, 0, input_report_length);
563 		ResetEvent(ev);
564 		res = ReadFile(device_handle, read_buf, (DWORD) input_report_length, &bytes_read, &ol);
565 
566 		if (!res) {
567 			if (GetLastError() != ERROR_IO_PENDING) {
568 				/* ReadFile() has failed.
569 				   Clean up and return error. */
570 				CancelIo(device_handle);
571 				read_pending = FALSE;
572 				goto end_of_function;
573 			}
574 			overlapped = TRUE;
575 		}
576 	}
577 	else {
578 		overlapped = TRUE;
579 	}
580 
581 	if (overlapped) {
582 		if (milliseconds >= 0) {
583 			/* See if there is any data yet. */
584 			res = WaitForSingleObject(ev, milliseconds);
585 			if (res != WAIT_OBJECT_0) {
586 				/* There was no data this time. Return zero bytes available,
587 				   but leave the Overlapped I/O running. */
588 				return 0;
589 			}
590 		}
591 
592 		/* Either WaitForSingleObject() told us that ReadFile has completed, or
593 		   we are in non-blocking mode. Get the number of bytes read. The actual
594 		   data has been copied to the data[] array which was passed to ReadFile(). */
595 		res = GetOverlappedResult(device_handle, &ol, &bytes_read, TRUE/*wait*/);
596 	}
597 	/* Set pending back to false, even if GetOverlappedResult() returned error. */
598 	read_pending = FALSE;
599 
600 	if (res && bytes_read > 0) {
601 		if (read_buf[0] == 0x0) {
602 			/* If report numbers aren't being used, but Windows sticks a report
603 			   number (0x0) on the beginning of the report anyway. To make this
604 			   work like the other platforms, and to make it work more like the
605 			   HID spec, we'll skip over this byte. */
606 			bytes_read--;
607 			copy_len = length > bytes_read ? bytes_read : length;
608 			memcpy(data, read_buf+1, copy_len);
609 		}
610 		else {
611 			/* Copy the whole buffer, report number and all. */
612 			copy_len = length > bytes_read ? bytes_read : length;
613 			memcpy(data, read_buf, copy_len);
614 		}
615 	}
616 
617 end_of_function:
618 	if (!res) {
619 		register_error("GetOverlappedResult");
620 		return -1;
621 	}
622 
623 	return (int) copy_len;
624 }
625 
hid_read(unsigned char * data,size_t length)626 int hid_device::hid_read(unsigned char *data, size_t length)
627 {
628 	return hid_read_timeout(data, length, (blocking)? -1: 0);
629 }
630 
hid_set_nonblocking(int nonblock)631 int hid_device::hid_set_nonblocking(int nonblock)
632 {
633 	blocking = !nonblock;
634 	return 0; /* Success */
635 }
636 
hid_send_feature_report(const unsigned char * data,size_t length)637 int hid_device::hid_send_feature_report(const unsigned char *data, size_t length)
638 {
639 	BOOL res = FALSE;
640 	unsigned char *buf;
641 	size_t length_to_send;
642 
643 	/* Windows expects at least caps.FeatureReportByteLength bytes passed
644 	   to HidD_SetFeature(), even if the report is shorter. Any less sent and
645 	   the function fails with error ERROR_INVALID_PARAMETER set. Any more
646 	   and HidD_SetFeature() silently truncates the data sent in the report
647 	   to caps.FeatureReportByteLength. */
648 	if (length >= feature_report_length) {
649 		buf = (unsigned char *) data;
650 		length_to_send = length;
651 	} else {
652 		if (feature_buf == NULL)
653 			feature_buf = (unsigned char *) malloc(feature_report_length);
654 		buf = feature_buf;
655 		memcpy(buf, data, length);
656 		memset(buf + length, 0, feature_report_length - length);
657 		length_to_send = feature_report_length;
658 	}
659 
660 	res = HidD_SetFeature(device_handle, (PVOID)buf, (DWORD) length_to_send);
661 
662 	if (!res) {
663 		register_error("HidD_SetFeature");
664 		return -1;
665 	}
666 
667 	return (int) length;
668 }
669 
670 
hid_get_feature_report(unsigned char * data,size_t length)671 int hid_device::hid_get_feature_report(unsigned char *data, size_t length)
672 {
673 	BOOL res;
674 #if 0
675 	res = HidD_GetFeature(device_handle, data, length);
676 	if (!res) {
677 		register_error("HidD_GetFeature");
678 		return -1;
679 	}
680 	return 0; /* HidD_GetFeature() doesn't give us an actual length, unfortunately */
681 #else
682 	DWORD bytes_returned;
683 
684 	OVERLAPPED ol;
685 	memset(&ol, 0, sizeof(ol));
686 
687 	res = DeviceIoControl(device_handle,
688 		IOCTL_HID_GET_FEATURE,
689 		data, (DWORD) length,
690 		data, (DWORD) length,
691 		&bytes_returned, &ol);
692 
693 	if (!res) {
694 		if (GetLastError() != ERROR_IO_PENDING) {
695 			/* DeviceIoControl() failed. Return error. */
696 			register_error("Send Feature Report DeviceIoControl");
697 			return -1;
698 		}
699 	}
700 
701 	/* Wait here until the write is done. This makes
702 	   hid_get_feature_report() synchronous. */
703 	res = GetOverlappedResult(device_handle, &ol, &bytes_returned, TRUE/*wait*/);
704 	if (!res) {
705 		/* The operation failed. */
706 		register_error("Send Feature Report GetOverLappedResult");
707 		return -1;
708 	}
709 
710 	/* bytes_returned does not include the first byte which contains the
711 	   report ID. The data buffer actually contains one more byte than
712 	   bytes_returned. */
713 	bytes_returned++;
714 
715 	return bytes_returned;
716 #endif
717 }
718 
719 
hid_get_input_report(unsigned char * data,size_t length)720 int hid_device::hid_get_input_report(unsigned char *data, size_t length)
721 {
722 	BOOL res;
723 #if 0
724 	res = HidD_GetInputReport(device_handle, data, length);
725 	if (!res) {
726 		register_error("HidD_GetInputReport");
727 		return -1;
728 	}
729 	return length;
730 #else
731 	DWORD bytes_returned;
732 
733 	OVERLAPPED ol;
734 	memset(&ol, 0, sizeof(ol));
735 
736 	res = DeviceIoControl(device_handle,
737 		IOCTL_HID_GET_INPUT_REPORT,
738 		data, (DWORD) length,
739 		data, (DWORD) length,
740 		&bytes_returned, &ol);
741 
742 	if (!res) {
743 		if (GetLastError() != ERROR_IO_PENDING) {
744 			/* DeviceIoControl() failed. Return error. */
745 			register_error("Send Input Report DeviceIoControl");
746 			return -1;
747 		}
748 	}
749 
750 	/* Wait here until the write is done. This makes
751 	   hid_get_feature_report() synchronous. */
752 	res = GetOverlappedResult(device_handle, &ol, &bytes_returned, TRUE/*wait*/);
753 	if (!res) {
754 		/* The operation failed. */
755 		register_error("Send Input Report GetOverLappedResult");
756 		return -1;
757 	}
758 
759 	/* bytes_returned does not include the first byte which contains the
760 	   report ID. The data buffer actually contains one more byte than
761 	   bytes_returned. */
762 	bytes_returned++;
763 
764 	return bytes_returned;
765 #endif
766 }
767 
hid_close()768 void hid_device::hid_close()
769 {
770 	CancelIo(device_handle);
771 }
772 
hid_get_manufacturer_string()773 std::string hid_device::hid_get_manufacturer_string()
774 {
775 	BOOL res;
776 	wchar_t WC[256];
777 
778 	res = HidD_GetManufacturerString(device_handle, WC, 256);
779 	if (!res) {
780 		register_error("HidD_GetManufacturerString");
781 		return "";
782 	}
783 	return  wchar2str("HidD_GetManufacturerString", WC);
784 }
785 
hid_get_product_string()786 std::string hid_device::hid_get_product_string()
787 {
788 	BOOL res;
789 	wchar_t WC[256];
790 	res = HidD_GetProductString(device_handle, WC, 256);
791 	if (!res) {
792 		register_error("HidD_GetProductString");
793 		return "";
794 	}
795 	return wchar2str("HidD_GetProductString", WC);
796 }
797 
hid_get_serial_number_string()798 std::string hid_device::hid_get_serial_number_string()
799 {
800 	BOOL res;
801 	wchar_t WC[256];
802 
803 	res = HidD_GetSerialNumberString(device_handle, WC, 256);
804 	if (!res) {
805 		register_error("HidD_GetSerialNumberString");
806 		return "";
807 	}
808 	return wchar2str("HidD_GetSerialNumberString", WC);
809 }
810 
hid_get_indexed_string(int string_index,std::string string,size_t maxlen)811 int hid_device::hid_get_indexed_string(int string_index, std::string string, size_t maxlen)
812 {
813 	BOOL res;
814 	wchar_t WC[maxlen+1];
815 	res = HidD_GetIndexedString(device_handle, string_index, WC, maxlen);
816 	if (!res) {
817 		register_error("HidD_GetIndexedString");
818 		string = "";
819 		return -1;
820 	}
821 	string = wchar2str("HidD_Get_IndexedString", WC);
822 	return 0;
823 }
824 
825 
hid_error()826 const char * hid_device::hid_error()
827 {
828 	return "hid_error for global errors is not implemented yet";
829 }
830 
831