| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923 | 
							- /*******************************************************
 
-  HIDAPI - Multi-Platform library for
 
-  communication with HID devices.
 
-  Alan Ott
 
-  Signal 11 Software
 
-  8/22/2009
 
-  Copyright 2009, All Rights Reserved.
 
-  
 
-  At the discretion of the user of this library,
 
-  this software may be licensed under the terms of the
 
-  GNU General Public License v3, a BSD-Style license, or the
 
-  original HIDAPI license as outlined in the LICENSE.txt,
 
-  LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
 
-  files located at the root of the source distribution.
 
-  These files may also be found in the public source
 
-  code repository located at:
 
-         http://github.com/signal11/hidapi .
 
- ********************************************************/
 
- #include <windows.h>
 
- #ifndef _NTDEF_
 
- typedef LONG NTSTATUS;
 
- #endif
 
- #ifdef __MINGW32__
 
- #include <ntdef.h>
 
- #include <winbase.h>
 
- #endif
 
- #ifdef __CYGWIN__
 
- #include <ntdef.h>
 
- #define _wcsdup wcsdup
 
- #endif
 
- /*#define HIDAPI_USE_DDK*/
 
- #ifdef __cplusplus
 
- extern "C" {
 
- #endif
 
- 	#include <setupapi.h>
 
- 	#include <winioctl.h>
 
- 	#ifdef HIDAPI_USE_DDK
 
- 		#include <hidsdi.h>
 
- 	#endif
 
- 	/* Copied from inc/ddk/hidclass.h, part of the Windows DDK. */
 
- 	#define HID_OUT_CTL_CODE(id)  \
 
- 		CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
 
- 	#define IOCTL_HID_GET_FEATURE                   HID_OUT_CTL_CODE(100)
 
- #ifdef __cplusplus
 
- } /* extern "C" */
 
- #endif
 
- #include <stdio.h>
 
- #include <stdlib.h>
 
- #include "hidapi.h"
 
- #ifdef _MSC_VER
 
- 	/* Thanks Microsoft, but I know how to use strncpy(). */
 
- 	#pragma warning(disable:4996)
 
- #endif
 
- #ifdef __cplusplus
 
- extern "C" {
 
- #endif
 
- #ifndef HIDAPI_USE_DDK
 
- 	/* Since we're not building with the DDK, and the HID header
 
- 	   files aren't part of the SDK, we have to define all this
 
- 	   stuff here. In lookup_functions(), the function pointers
 
- 	   defined below are set. */
 
- 	typedef struct _HIDD_ATTRIBUTES{
 
- 		ULONG Size;
 
- 		USHORT VendorID;
 
- 		USHORT ProductID;
 
- 		USHORT VersionNumber;
 
- 	} HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES;
 
- 	typedef USHORT USAGE;
 
- 	typedef struct _HIDP_CAPS {
 
- 		USAGE Usage;
 
- 		USAGE UsagePage;
 
- 		USHORT InputReportByteLength;
 
- 		USHORT OutputReportByteLength;
 
- 		USHORT FeatureReportByteLength;
 
- 		USHORT Reserved[17];
 
- 		USHORT fields_not_used_by_hidapi[10];
 
- 	} HIDP_CAPS, *PHIDP_CAPS;
 
- 	typedef void* PHIDP_PREPARSED_DATA;
 
- 	#define HIDP_STATUS_SUCCESS 0x110000
 
- 	typedef BOOLEAN (__stdcall *HidD_GetAttributes_)(HANDLE device, PHIDD_ATTRIBUTES attrib);
 
- 	typedef BOOLEAN (__stdcall *HidD_GetSerialNumberString_)(HANDLE device, PVOID buffer, ULONG buffer_len);
 
- 	typedef BOOLEAN (__stdcall *HidD_GetManufacturerString_)(HANDLE handle, PVOID buffer, ULONG buffer_len);
 
- 	typedef BOOLEAN (__stdcall *HidD_GetProductString_)(HANDLE handle, PVOID buffer, ULONG buffer_len);
 
- 	typedef BOOLEAN (__stdcall *HidD_SetFeature_)(HANDLE handle, PVOID data, ULONG length);
 
- 	typedef BOOLEAN (__stdcall *HidD_GetFeature_)(HANDLE handle, PVOID data, ULONG length);
 
- 	typedef BOOLEAN (__stdcall *HidD_GetIndexedString_)(HANDLE handle, ULONG string_index, PVOID buffer, ULONG buffer_len);
 
- 	typedef BOOLEAN (__stdcall *HidD_GetPreparsedData_)(HANDLE handle, PHIDP_PREPARSED_DATA *preparsed_data);
 
- 	typedef BOOLEAN (__stdcall *HidD_FreePreparsedData_)(PHIDP_PREPARSED_DATA preparsed_data);
 
- 	typedef NTSTATUS (__stdcall *HidP_GetCaps_)(PHIDP_PREPARSED_DATA preparsed_data, HIDP_CAPS *caps);
 
- 	static HidD_GetAttributes_ HidD_GetAttributes;
 
- 	static HidD_GetSerialNumberString_ HidD_GetSerialNumberString;
 
- 	static HidD_GetManufacturerString_ HidD_GetManufacturerString;
 
- 	static HidD_GetProductString_ HidD_GetProductString;
 
- 	static HidD_SetFeature_ HidD_SetFeature;
 
- 	static HidD_GetFeature_ HidD_GetFeature;
 
- 	static HidD_GetIndexedString_ HidD_GetIndexedString;
 
- 	static HidD_GetPreparsedData_ HidD_GetPreparsedData;
 
- 	static HidD_FreePreparsedData_ HidD_FreePreparsedData;
 
- 	static HidP_GetCaps_ HidP_GetCaps;
 
- 	static HMODULE lib_handle = NULL;
 
- 	static BOOLEAN initialized = FALSE;
 
- #endif /* HIDAPI_USE_DDK */
 
- struct hid_device_ {
 
- 		HANDLE device_handle;
 
- 		BOOL blocking;
 
- 		USHORT output_report_length;
 
- 		size_t input_report_length;
 
- 		void *last_error_str;
 
- 		DWORD last_error_num;
 
- 		BOOL read_pending;
 
- 		char *read_buf;
 
- 		OVERLAPPED ol;
 
- };
 
- static hid_device *new_hid_device()
 
- {
 
- 	hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device));
 
- 	dev->device_handle = INVALID_HANDLE_VALUE;
 
- 	dev->blocking = TRUE;
 
- 	dev->output_report_length = 0;
 
- 	dev->input_report_length = 0;
 
- 	dev->last_error_str = NULL;
 
- 	dev->last_error_num = 0;
 
- 	dev->read_pending = FALSE;
 
- 	dev->read_buf = NULL;
 
- 	memset(&dev->ol, 0, sizeof(dev->ol));
 
- 	dev->ol.hEvent = CreateEvent(NULL, FALSE, FALSE /*inital state f=nonsignaled*/, NULL);
 
- 	return dev;
 
- }
 
- static void free_hid_device(hid_device *dev)
 
- {
 
- 	CloseHandle(dev->ol.hEvent);
 
- 	CloseHandle(dev->device_handle);
 
- 	LocalFree(dev->last_error_str);
 
- 	free(dev->read_buf);
 
- 	free(dev);
 
- }
 
- static void register_error(hid_device *device, const char *op)
 
- {
 
- 	WCHAR *ptr, *msg;
 
- 	FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
 
- 		FORMAT_MESSAGE_FROM_SYSTEM |
 
- 		FORMAT_MESSAGE_IGNORE_INSERTS,
 
- 		NULL,
 
- 		GetLastError(),
 
- 		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
 
- 		(LPVOID)&msg, 0/*sz*/,
 
- 		NULL);
 
- 	
 
- 	/* Get rid of the CR and LF that FormatMessage() sticks at the
 
- 	   end of the message. Thanks Microsoft! */
 
- 	ptr = msg;
 
- 	while (*ptr) {
 
- 		if (*ptr == '\r') {
 
- 			*ptr = 0x0000;
 
- 			break;
 
- 		}
 
- 		ptr++;
 
- 	}
 
- 	/* Store the message off in the Device entry so that
 
- 	   the hid_error() function can pick it up. */
 
- 	LocalFree(device->last_error_str);
 
- 	device->last_error_str = msg;
 
- }
 
- #ifndef HIDAPI_USE_DDK
 
- static int lookup_functions()
 
- {
 
- 	lib_handle = LoadLibraryA("hid.dll");
 
- 	if (lib_handle) {
 
- #define RESOLVE(x) x = (x##_)GetProcAddress(lib_handle, #x); if (!x) return -1;
 
- 		RESOLVE(HidD_GetAttributes);
 
- 		RESOLVE(HidD_GetSerialNumberString);
 
- 		RESOLVE(HidD_GetManufacturerString);
 
- 		RESOLVE(HidD_GetProductString);
 
- 		RESOLVE(HidD_SetFeature);
 
- 		RESOLVE(HidD_GetFeature);
 
- 		RESOLVE(HidD_GetIndexedString);
 
- 		RESOLVE(HidD_GetPreparsedData);
 
- 		RESOLVE(HidD_FreePreparsedData);
 
- 		RESOLVE(HidP_GetCaps);
 
- #undef RESOLVE
 
- 	}
 
- 	else
 
- 		return -1;
 
- 	return 0;
 
- }
 
- #endif
 
- static HANDLE open_device(const char *path, BOOL enumerate)
 
- {
 
- 	HANDLE handle;
 
- 	DWORD desired_access = (enumerate)? 0: (GENERIC_WRITE | GENERIC_READ);
 
- 	DWORD share_mode = (enumerate)?
 
- 	                      FILE_SHARE_READ|FILE_SHARE_WRITE:
 
- 	                      FILE_SHARE_READ;
 
- 	handle = CreateFileA(path,
 
- 		desired_access,
 
- 		share_mode,
 
- 		NULL,
 
- 		OPEN_EXISTING,
 
- 		FILE_FLAG_OVERLAPPED,/*FILE_ATTRIBUTE_NORMAL,*/
 
- 		0);
 
- 	return handle;
 
- }
 
- int HID_API_EXPORT hid_init(void)
 
- {
 
- #ifndef HIDAPI_USE_DDK
 
- 	if (!initialized) {
 
- 		if (lookup_functions() < 0) {
 
- 			hid_exit();
 
- 			return -1;
 
- 		}
 
- 		initialized = TRUE;
 
- 	}
 
- #endif
 
- 	return 0;
 
- }
 
- int HID_API_EXPORT hid_exit(void)
 
- {
 
- #ifndef HIDAPI_USE_DDK
 
- 	if (lib_handle)
 
- 		FreeLibrary(lib_handle);
 
- 	lib_handle = NULL;
 
- 	initialized = FALSE;
 
- #endif
 
- 	return 0;
 
- }
 
- struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id)
 
- {
 
- 	BOOL res;
 
- 	struct hid_device_info *root = NULL; /* return object */
 
- 	struct hid_device_info *cur_dev = NULL;
 
- 	/* Windows objects for interacting with the driver. */
 
- 	GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, {0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30} };
 
- 	SP_DEVINFO_DATA devinfo_data;
 
- 	SP_DEVICE_INTERFACE_DATA device_interface_data;
 
- 	SP_DEVICE_INTERFACE_DETAIL_DATA_A *device_interface_detail_data = NULL;
 
- 	HDEVINFO device_info_set = INVALID_HANDLE_VALUE;
 
- 	int device_index = 0;
 
- 	int i;
 
- 	if (hid_init() < 0)
 
- 		return NULL;
 
- 	/* Initialize the Windows objects. */
 
- 	memset(&devinfo_data, 0x0, sizeof(devinfo_data));
 
- 	devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA);
 
- 	device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
 
- 	/* Get information for all the devices belonging to the HID class. */
 
- 	device_info_set = SetupDiGetClassDevsA(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
 
- 	
 
- 	/* Iterate over each device in the HID class, looking for the right one. */
 
- 	
 
- 	for (;;) {
 
- 		HANDLE write_handle = INVALID_HANDLE_VALUE;
 
- 		DWORD required_size = 0;
 
- 		HIDD_ATTRIBUTES attrib;
 
- 		res = SetupDiEnumDeviceInterfaces(device_info_set,
 
- 			NULL,
 
- 			&InterfaceClassGuid,
 
- 			device_index,
 
- 			&device_interface_data);
 
- 		
 
- 		if (!res) {
 
- 			/* A return of FALSE from this function means that
 
- 			   there are no more devices. */
 
- 			break;
 
- 		}
 
- 		/* Call with 0-sized detail size, and let the function
 
- 		   tell us how long the detail struct needs to be. The
 
- 		   size is put in &required_size. */
 
- 		res = SetupDiGetDeviceInterfaceDetailA(device_info_set,
 
- 			&device_interface_data,
 
- 			NULL,
 
- 			0,
 
- 			&required_size,
 
- 			NULL);
 
- 		/* Allocate a long enough structure for device_interface_detail_data. */
 
- 		device_interface_detail_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_A*) malloc(required_size);
 
- 		device_interface_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
 
- 		/* Get the detailed data for this device. The detail data gives us
 
- 		   the device path for this device, which is then passed into
 
- 		   CreateFile() to get a handle to the device. */
 
- 		res = SetupDiGetDeviceInterfaceDetailA(device_info_set,
 
- 			&device_interface_data,
 
- 			device_interface_detail_data,
 
- 			required_size,
 
- 			NULL,
 
- 			NULL);
 
- 		if (!res) {
 
- 			/* register_error(dev, "Unable to call SetupDiGetDeviceInterfaceDetail");
 
- 			   Continue to the next device. */
 
- 			goto cont;
 
- 		}
 
- 		/* Make sure this device is of Setup Class "HIDClass" and has a
 
- 		   driver bound to it. */
 
- 		for (i = 0; ; i++) {
 
- 			char driver_name[256];
 
- 			/* Populate devinfo_data. This function will return failure
 
- 			   when there are no more interfaces left. */
 
- 			res = SetupDiEnumDeviceInfo(device_info_set, i, &devinfo_data);
 
- 			if (!res)
 
- 				goto cont;
 
- 			res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data,
 
- 			               SPDRP_CLASS, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL);
 
- 			if (!res)
 
- 				goto cont;
 
- 			if (strcmp(driver_name, "HIDClass") == 0) {
 
- 				/* See if there's a driver bound. */
 
- 				res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data,
 
- 				           SPDRP_DRIVER, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL);
 
- 				if (res)
 
- 					break;
 
- 			}
 
- 		}
 
- 		//wprintf(L"HandleName: %s\n", device_interface_detail_data->DevicePath);
 
- 		/* Open a handle to the device */
 
- 		write_handle = open_device(device_interface_detail_data->DevicePath, TRUE);
 
- 		/* Check validity of write_handle. */
 
- 		if (write_handle == INVALID_HANDLE_VALUE) {
 
- 			/* Unable to open the device. */
 
- 			//register_error(dev, "CreateFile");
 
- 			goto cont_close;
 
- 		}		
 
- 		/* Get the Vendor ID and Product ID for this device. */
 
- 		attrib.Size = sizeof(HIDD_ATTRIBUTES);
 
- 		HidD_GetAttributes(write_handle, &attrib);
 
- 		//wprintf(L"Product/Vendor: %x %x\n", attrib.ProductID, attrib.VendorID);
 
- 		/* Check the VID/PID to see if we should add this
 
- 		   device to the enumeration list. */
 
- 		if ((vendor_id == 0x0 || attrib.VendorID == vendor_id) &&
 
- 		    (product_id == 0x0 || attrib.ProductID == product_id)) {
 
- 			#define WSTR_LEN 512
 
- 			const char *str;
 
- 			struct hid_device_info *tmp;
 
- 			PHIDP_PREPARSED_DATA pp_data = NULL;
 
- 			HIDP_CAPS caps;
 
- 			BOOLEAN res;
 
- 			NTSTATUS nt_res;
 
- 			wchar_t wstr[WSTR_LEN]; /* TODO: Determine Size */
 
- 			size_t len;
 
- 			/* VID/PID match. Create the record. */
 
- 			tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info));
 
- 			if (cur_dev) {
 
- 				cur_dev->next = tmp;
 
- 			}
 
- 			else {
 
- 				root = tmp;
 
- 			}
 
- 			cur_dev = tmp;
 
- 			/* Get the Usage Page and Usage for this device. */
 
- 			res = HidD_GetPreparsedData(write_handle, &pp_data);
 
- 			if (res) {
 
- 				nt_res = HidP_GetCaps(pp_data, &caps);
 
- 				if (nt_res == HIDP_STATUS_SUCCESS) {
 
- 					cur_dev->usage_page = caps.UsagePage;
 
- 					cur_dev->usage = caps.Usage;
 
- 				}
 
- 				HidD_FreePreparsedData(pp_data);
 
- 			}
 
- 			
 
- 			/* Fill out the record */
 
- 			cur_dev->next = NULL;
 
- 			str = device_interface_detail_data->DevicePath;
 
- 			if (str) {
 
- 				len = strlen(str);
 
- 				cur_dev->path = (char*) calloc(len+1, sizeof(char));
 
- 				strncpy(cur_dev->path, str, len+1);
 
- 				cur_dev->path[len] = '\0';
 
- 			}
 
- 			else
 
- 				cur_dev->path = NULL;
 
- 			/* Serial Number */
 
- 			res = HidD_GetSerialNumberString(write_handle, wstr, sizeof(wstr));
 
- 			wstr[WSTR_LEN-1] = 0x0000;
 
- 			if (res) {
 
- 				cur_dev->serial_number = _wcsdup(wstr);
 
- 			}
 
- 			/* Manufacturer String */
 
- 			res = HidD_GetManufacturerString(write_handle, wstr, sizeof(wstr));
 
- 			wstr[WSTR_LEN-1] = 0x0000;
 
- 			if (res) {
 
- 				cur_dev->manufacturer_string = _wcsdup(wstr);
 
- 			}
 
- 			/* Product String */
 
- 			res = HidD_GetProductString(write_handle, wstr, sizeof(wstr));
 
- 			wstr[WSTR_LEN-1] = 0x0000;
 
- 			if (res) {
 
- 				cur_dev->product_string = _wcsdup(wstr);
 
- 			}
 
- 			/* VID/PID */
 
- 			cur_dev->vendor_id = attrib.VendorID;
 
- 			cur_dev->product_id = attrib.ProductID;
 
- 			/* Release Number */
 
- 			cur_dev->release_number = attrib.VersionNumber;
 
- 			/* Interface Number. It can sometimes be parsed out of the path
 
- 			   on Windows if a device has multiple interfaces. See
 
- 			   http://msdn.microsoft.com/en-us/windows/hardware/gg487473 or
 
- 			   search for "Hardware IDs for HID Devices" at MSDN. If it's not
 
- 			   in the path, it's set to -1. */
 
- 			cur_dev->interface_number = -1;
 
- 			if (cur_dev->path) {
 
- 				char *interface_component = strstr(cur_dev->path, "&mi_");
 
- 				if (interface_component) {
 
- 					char *hex_str = interface_component + 4;
 
- 					char *endptr = NULL;
 
- 					cur_dev->interface_number = strtol(hex_str, &endptr, 16);
 
- 					if (endptr == hex_str) {
 
- 						/* The parsing failed. Set interface_number to -1. */
 
- 						cur_dev->interface_number = -1;
 
- 					}
 
- 				}
 
- 			}
 
- 		}
 
- cont_close:
 
- 		CloseHandle(write_handle);
 
- cont:
 
- 		/* We no longer need the detail data. It can be freed */
 
- 		free(device_interface_detail_data);
 
- 		device_index++;
 
- 	}
 
- 	/* Close the device information handle. */
 
- 	SetupDiDestroyDeviceInfoList(device_info_set);
 
- 	return root;
 
- }
 
- void  HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs)
 
- {
 
- 	/* TODO: Merge this with the Linux version. This function is platform-independent. */
 
- 	struct hid_device_info *d = devs;
 
- 	while (d) {
 
- 		struct hid_device_info *next = d->next;
 
- 		free(d->path);
 
- 		free(d->serial_number);
 
- 		free(d->manufacturer_string);
 
- 		free(d->product_string);
 
- 		free(d);
 
- 		d = next;
 
- 	}
 
- }
 
- HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
 
- {
 
- 	/* TODO: Merge this functions with the Linux version. This function should be platform independent. */
 
- 	struct hid_device_info *devs, *cur_dev;
 
- 	const char *path_to_open = NULL;
 
- 	hid_device *handle = NULL;
 
- 	
 
- 	devs = hid_enumerate(vendor_id, product_id);
 
- 	cur_dev = devs;
 
- 	while (cur_dev) {
 
- 		if (cur_dev->vendor_id == vendor_id &&
 
- 		    cur_dev->product_id == product_id) {
 
- 			if (serial_number) {
 
- 				if (wcscmp(serial_number, cur_dev->serial_number) == 0) {
 
- 					path_to_open = cur_dev->path;
 
- 					break;
 
- 				}
 
- 			}
 
- 			else {
 
- 				path_to_open = cur_dev->path;
 
- 				break;
 
- 			}
 
- 		}
 
- 		cur_dev = cur_dev->next;
 
- 	}
 
- 	if (path_to_open) {
 
- 		/* Open the device */
 
- 		handle = hid_open_path(path_to_open);
 
- 	}
 
- 	hid_free_enumeration(devs);
 
- 	
 
- 	return handle;
 
- }
 
- HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path)
 
- {
 
- 	hid_device *dev;
 
- 	HIDP_CAPS caps;
 
- 	PHIDP_PREPARSED_DATA pp_data = NULL;
 
- 	BOOLEAN res;
 
- 	NTSTATUS nt_res;
 
- 	if (hid_init() < 0) {
 
- 		return NULL;
 
- 	}
 
- 	dev = new_hid_device();
 
- 	/* Open a handle to the device */
 
- 	dev->device_handle = open_device(path, FALSE);
 
- 	/* Check validity of write_handle. */
 
- 	if (dev->device_handle == INVALID_HANDLE_VALUE) {
 
- 		/* Unable to open the device. */
 
- 		register_error(dev, "CreateFile");
 
- 		goto err;
 
- 	}
 
- 	/* Get the Input Report length for the device. */
 
- 	res = HidD_GetPreparsedData(dev->device_handle, &pp_data);
 
- 	if (!res) {
 
- 		register_error(dev, "HidD_GetPreparsedData");
 
- 		goto err;
 
- 	}
 
- 	nt_res = HidP_GetCaps(pp_data, &caps);
 
- 	if (nt_res != HIDP_STATUS_SUCCESS) {
 
- 		register_error(dev, "HidP_GetCaps");	
 
- 		goto err_pp_data;
 
- 	}
 
- 	dev->output_report_length = caps.OutputReportByteLength;
 
- 	dev->input_report_length = caps.InputReportByteLength;
 
- 	HidD_FreePreparsedData(pp_data);
 
- 	dev->read_buf = (char*) malloc(dev->input_report_length);
 
- 	return dev;
 
- err_pp_data:
 
- 		HidD_FreePreparsedData(pp_data);
 
- err:	
 
- 		free_hid_device(dev);
 
- 		return NULL;
 
- }
 
- int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length)
 
- {
 
- 	DWORD bytes_written;
 
- 	BOOL res;
 
- 	OVERLAPPED ol;
 
- 	unsigned char *buf;
 
- 	memset(&ol, 0, sizeof(ol));
 
- 	/* Make sure the right number of bytes are passed to WriteFile. Windows
 
- 	   expects the number of bytes which are in the _longest_ report (plus
 
- 	   one for the report number) bytes even if the data is a report
 
- 	   which is shorter than that. Windows gives us this value in
 
- 	   caps.OutputReportByteLength. If a user passes in fewer bytes than this,
 
- 	   create a temporary buffer which is the proper size. */
 
- 	if (length >= dev->output_report_length) {
 
- 		/* The user passed the right number of bytes. Use the buffer as-is. */
 
- 		buf = (unsigned char *) data;
 
- 	} else {
 
- 		/* Create a temporary buffer and copy the user's data
 
- 		   into it, padding the rest with zeros. */
 
- 		buf = (unsigned char *) malloc(dev->output_report_length);
 
- 		memcpy(buf, data, length);
 
- 		memset(buf + length, 0, dev->output_report_length - length);
 
- 		length = dev->output_report_length;
 
- 	}
 
- 	res = WriteFile(dev->device_handle, buf, length, NULL, &ol);
 
- 	
 
- 	if (!res) {
 
- 		if (GetLastError() != ERROR_IO_PENDING) {
 
- 			/* WriteFile() failed. Return error. */
 
- 			register_error(dev, "WriteFile");
 
- 			bytes_written = -1;
 
- 			goto end_of_function;
 
- 		}
 
- 	}
 
- 	/* Wait here until the write is done. This makes
 
- 	   hid_write() synchronous. */
 
- 	res = GetOverlappedResult(dev->device_handle, &ol, &bytes_written, TRUE/*wait*/);
 
- 	if (!res) {
 
- 		/* The Write operation failed. */
 
- 		register_error(dev, "WriteFile");
 
- 		bytes_written = -1;
 
- 		goto end_of_function;
 
- 	}
 
- end_of_function:
 
- 	if (buf != data)
 
- 		free(buf);
 
- 	return bytes_written;
 
- }
 
- int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
 
- {
 
- 	DWORD bytes_read = 0;
 
- 	BOOL res;
 
- 	/* Copy the handle for convenience. */
 
- 	HANDLE ev = dev->ol.hEvent;
 
- 	if (!dev->read_pending) {
 
- 		/* Start an Overlapped I/O read. */
 
- 		dev->read_pending = TRUE;
 
- 		memset(dev->read_buf, 0, dev->input_report_length);
 
- 		ResetEvent(ev);
 
- 		res = ReadFile(dev->device_handle, dev->read_buf, dev->input_report_length, &bytes_read, &dev->ol);
 
- 		
 
- 		if (!res) {
 
- 			if (GetLastError() != ERROR_IO_PENDING) {
 
- 				/* ReadFile() has failed.
 
- 				   Clean up and return error. */
 
- 				CancelIo(dev->device_handle);
 
- 				dev->read_pending = FALSE;
 
- 				goto end_of_function;
 
- 			}
 
- 		}
 
- 	}
 
- 	if (milliseconds >= 0) {
 
- 		/* See if there is any data yet. */
 
- 		res = WaitForSingleObject(ev, milliseconds);
 
- 		if (res != WAIT_OBJECT_0) {
 
- 			/* There was no data this time. Return zero bytes available,
 
- 			   but leave the Overlapped I/O running. */
 
- 			return 0;
 
- 		}
 
- 	}
 
- 	/* Either WaitForSingleObject() told us that ReadFile has completed, or
 
- 	   we are in non-blocking mode. Get the number of bytes read. The actual
 
- 	   data has been copied to the data[] array which was passed to ReadFile(). */
 
- 	res = GetOverlappedResult(dev->device_handle, &dev->ol, &bytes_read, TRUE/*wait*/);
 
- 	
 
- 	/* Set pending back to false, even if GetOverlappedResult() returned error. */
 
- 	dev->read_pending = FALSE;
 
- 	if (res && bytes_read > 0) {
 
- 		if (dev->read_buf[0] == 0x0) {
 
- 			/* If report numbers aren't being used, but Windows sticks a report
 
- 			   number (0x0) on the beginning of the report anyway. To make this
 
- 			   work like the other platforms, and to make it work more like the
 
- 			   HID spec, we'll skip over this byte. */
 
- 			size_t copy_len;
 
- 			bytes_read--;
 
- 			copy_len = length > bytes_read ? bytes_read : length;
 
- 			memcpy(data, dev->read_buf+1, copy_len);
 
- 		}
 
- 		else {
 
- 			/* Copy the whole buffer, report number and all. */
 
- 			size_t copy_len = length > bytes_read ? bytes_read : length;
 
- 			memcpy(data, dev->read_buf, copy_len);
 
- 		}
 
- 	}
 
- 	
 
- end_of_function:
 
- 	if (!res) {
 
- 		register_error(dev, "GetOverlappedResult");
 
- 		return -1;
 
- 	}
 
- 	
 
- 	return bytes_read;
 
- }
 
- int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, size_t length)
 
- {
 
- 	return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0);
 
- }
 
- int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonblock)
 
- {
 
- 	dev->blocking = !nonblock;
 
- 	return 0; /* Success */
 
- }
 
- int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length)
 
- {
 
- 	BOOL res = HidD_SetFeature(dev->device_handle, (PVOID)data, length);
 
- 	if (!res) {
 
- 		register_error(dev, "HidD_SetFeature");
 
- 		return -1;
 
- 	}
 
- 	return length;
 
- }
 
- int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length)
 
- {
 
- 	BOOL res;
 
- #if 0
 
- 	res = HidD_GetFeature(dev->device_handle, data, length);
 
- 	if (!res) {
 
- 		register_error(dev, "HidD_GetFeature");
 
- 		return -1;
 
- 	}
 
- 	return 0; /* HidD_GetFeature() doesn't give us an actual length, unfortunately */
 
- #else
 
- 	DWORD bytes_returned;
 
- 	OVERLAPPED ol;
 
- 	memset(&ol, 0, sizeof(ol));
 
- 	res = DeviceIoControl(dev->device_handle,
 
- 		IOCTL_HID_GET_FEATURE,
 
- 		data, length,
 
- 		data, length,
 
- 		&bytes_returned, &ol);
 
- 	if (!res) {
 
- 		if (GetLastError() != ERROR_IO_PENDING) {
 
- 			/* DeviceIoControl() failed. Return error. */
 
- 			register_error(dev, "Send Feature Report DeviceIoControl");
 
- 			return -1;
 
- 		}
 
- 	}
 
- 	/* Wait here until the write is done. This makes
 
- 	   hid_get_feature_report() synchronous. */
 
- 	res = GetOverlappedResult(dev->device_handle, &ol, &bytes_returned, TRUE/*wait*/);
 
- 	if (!res) {
 
- 		/* The operation failed. */
 
- 		register_error(dev, "Send Feature Report GetOverLappedResult");
 
- 		return -1;
 
- 	}
 
- 	return bytes_returned;
 
- #endif
 
- }
 
- void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev)
 
- {
 
- 	if (!dev)
 
- 		return;
 
- 	CancelIo(dev->device_handle);
 
- 	free_hid_device(dev);
 
- }
 
- int HID_API_EXPORT_CALL HID_API_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen)
 
- {
 
- 	BOOL res;
 
- 	res = HidD_GetManufacturerString(dev->device_handle, string, sizeof(wchar_t) * maxlen);
 
- 	if (!res) {
 
- 		register_error(dev, "HidD_GetManufacturerString");
 
- 		return -1;
 
- 	}
 
- 	return 0;
 
- }
 
- int HID_API_EXPORT_CALL HID_API_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen)
 
- {
 
- 	BOOL res;
 
- 	res = HidD_GetProductString(dev->device_handle, string, sizeof(wchar_t) * maxlen);
 
- 	if (!res) {
 
- 		register_error(dev, "HidD_GetProductString");
 
- 		return -1;
 
- 	}
 
- 	return 0;
 
- }
 
- int HID_API_EXPORT_CALL HID_API_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen)
 
- {
 
- 	BOOL res;
 
- 	res = HidD_GetSerialNumberString(dev->device_handle, string, sizeof(wchar_t) * maxlen);
 
- 	if (!res) {
 
- 		register_error(dev, "HidD_GetSerialNumberString");
 
- 		return -1;
 
- 	}
 
- 	return 0;
 
- }
 
- int HID_API_EXPORT_CALL HID_API_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen)
 
- {
 
- 	BOOL res;
 
- 	res = HidD_GetIndexedString(dev->device_handle, string_index, string, sizeof(wchar_t) * maxlen);
 
- 	if (!res) {
 
- 		register_error(dev, "HidD_GetIndexedString");
 
- 		return -1;
 
- 	}
 
- 	return 0;
 
- }
 
- HID_API_EXPORT const wchar_t * HID_API_CALL  hid_error(hid_device *dev)
 
- {
 
- 	return (wchar_t*)dev->last_error_str;
 
- }
 
- /*#define PICPGM*/
 
- /*#define S11*/
 
- #define P32
 
- #ifdef S11 
 
-   unsigned short VendorID = 0xa0a0;
 
- 	unsigned short ProductID = 0x0001;
 
- #endif
 
- #ifdef P32
 
-   unsigned short VendorID = 0x04d8;
 
- 	unsigned short ProductID = 0x3f;
 
- #endif
 
- #ifdef PICPGM
 
-   unsigned short VendorID = 0x04d8;
 
-   unsigned short ProductID = 0x0033;
 
- #endif
 
- #if 0
 
- int __cdecl main(int argc, char* argv[])
 
- {
 
- 	int res;
 
- 	unsigned char buf[65];
 
- 	UNREFERENCED_PARAMETER(argc);
 
- 	UNREFERENCED_PARAMETER(argv);
 
- 	/* Set up the command buffer. */
 
- 	memset(buf,0x00,sizeof(buf));
 
- 	buf[0] = 0;
 
- 	buf[1] = 0x81;
 
- 	
 
- 	/* Open the device. */
 
- 	int handle = open(VendorID, ProductID, L"12345");
 
- 	if (handle < 0)
 
- 		printf("unable to open device\n");
 
- 	/* Toggle LED (cmd 0x80) */
 
- 	buf[1] = 0x80;
 
- 	res = write(handle, buf, 65);
 
- 	if (res < 0)
 
- 		printf("Unable to write()\n");
 
- 	/* Request state (cmd 0x81) */
 
- 	buf[1] = 0x81;
 
- 	write(handle, buf, 65);
 
- 	if (res < 0)
 
- 		printf("Unable to write() (2)\n");
 
- 	/* Read requested state */
 
- 	read(handle, buf, 65);
 
- 	if (res < 0)
 
- 		printf("Unable to read()\n");
 
- 	/* Print out the returned buffer. */
 
- 	for (int i = 0; i < 4; i++)
 
- 		printf("buf[%d]: %d\n", i, buf[i]);
 
- 	return 0;
 
- }
 
- #endif
 
- #ifdef __cplusplus
 
- } /* extern "C" */
 
- #endif
 
 
  |