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