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