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