rb-blink1 0.0.1

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