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