rb-blink1 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/ext/blink1/blink1-lib.c +106 -74
- data/ext/blink1/blink1-lib.h +9 -7
- data/ext/blink1/blink1.c +15 -0
- data/ext/blink1/hid.c.libusb +108 -109
- data/ext/blink1/hid.c.mac +115 -160
- data/ext/blink1/hid.c.windows +115 -112
- data/ext/blink1/hidapi.h +3 -2
- data/ext/blink1/osccal.h +7 -7
- data/ext/blink1/usbconfig.h +3 -3
- data/lib/blink1.rb +5 -5
- data/lib/blink1/version.rb +1 -1
- data/spec/blink1_spec.rb +11 -3
- data/spec/spec_helper.rb +7 -1
- metadata +2 -2
data/ext/blink1/hid.c.windows
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
8/22/2009
|
9
9
|
|
10
10
|
Copyright 2009, All Rights Reserved.
|
11
|
-
|
11
|
+
|
12
12
|
At the discretion of the user of this library,
|
13
13
|
this software may be licensed under the terms of the
|
14
14
|
GNU Public License v3, a BSD-Style license, or the
|
@@ -36,7 +36,7 @@ typedef LONG NTSTATUS;
|
|
36
36
|
#define _wcsdup wcsdup
|
37
37
|
#endif
|
38
38
|
|
39
|
-
|
39
|
+
/*#define HIDAPI_USE_DDK*/
|
40
40
|
|
41
41
|
#ifdef __cplusplus
|
42
42
|
extern "C" {
|
@@ -47,13 +47,13 @@ extern "C" {
|
|
47
47
|
#include <hidsdi.h>
|
48
48
|
#endif
|
49
49
|
|
50
|
-
|
50
|
+
/* Copied from inc/ddk/hidclass.h, part of the Windows DDK. */
|
51
51
|
#define HID_OUT_CTL_CODE(id) \
|
52
52
|
CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
|
53
53
|
#define IOCTL_HID_GET_FEATURE HID_OUT_CTL_CODE(100)
|
54
54
|
|
55
55
|
#ifdef __cplusplus
|
56
|
-
}
|
56
|
+
} /* extern "C" */
|
57
57
|
#endif
|
58
58
|
|
59
59
|
#include <stdio.h>
|
@@ -63,7 +63,7 @@ extern "C" {
|
|
63
63
|
#include "hidapi.h"
|
64
64
|
|
65
65
|
#ifdef _MSC_VER
|
66
|
-
|
66
|
+
/* Thanks Microsoft, but I know how to use strncpy(). */
|
67
67
|
#pragma warning(disable:4996)
|
68
68
|
#endif
|
69
69
|
|
@@ -72,10 +72,10 @@ extern "C" {
|
|
72
72
|
#endif
|
73
73
|
|
74
74
|
#ifndef HIDAPI_USE_DDK
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
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
79
|
typedef struct _HIDD_ATTRIBUTES{
|
80
80
|
ULONG Size;
|
81
81
|
USHORT VendorID;
|
@@ -120,7 +120,7 @@ extern "C" {
|
|
120
120
|
|
121
121
|
static HMODULE lib_handle = NULL;
|
122
122
|
static BOOLEAN initialized = FALSE;
|
123
|
-
#endif
|
123
|
+
#endif /* HIDAPI_USE_DDK */
|
124
124
|
|
125
125
|
struct hid_device_ {
|
126
126
|
HANDLE device_handle;
|
@@ -151,6 +151,14 @@ static hid_device *new_hid_device()
|
|
151
151
|
return dev;
|
152
152
|
}
|
153
153
|
|
154
|
+
static void free_hid_device(hid_device *dev)
|
155
|
+
{
|
156
|
+
CloseHandle(dev->ol.hEvent);
|
157
|
+
CloseHandle(dev->device_handle);
|
158
|
+
LocalFree(dev->last_error_str);
|
159
|
+
free(dev->read_buf);
|
160
|
+
free(dev);
|
161
|
+
}
|
154
162
|
|
155
163
|
static void register_error(hid_device *device, const char *op)
|
156
164
|
{
|
@@ -162,11 +170,11 @@ static void register_error(hid_device *device, const char *op)
|
|
162
170
|
NULL,
|
163
171
|
GetLastError(),
|
164
172
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
165
|
-
(
|
173
|
+
(LPVOID)&msg, 0/*sz*/,
|
166
174
|
NULL);
|
167
|
-
|
168
|
-
|
169
|
-
|
175
|
+
|
176
|
+
/* Get rid of the CR and LF that FormatMessage() sticks at the
|
177
|
+
end of the message. Thanks Microsoft! */
|
170
178
|
ptr = msg;
|
171
179
|
while (*ptr) {
|
172
180
|
if (*ptr == '\r') {
|
@@ -176,8 +184,8 @@ static void register_error(hid_device *device, const char *op)
|
|
176
184
|
ptr++;
|
177
185
|
}
|
178
186
|
|
179
|
-
|
180
|
-
|
187
|
+
/* Store the message off in the Device entry so that
|
188
|
+
the hid_error() function can pick it up. */
|
181
189
|
LocalFree(device->last_error_str);
|
182
190
|
device->last_error_str = msg;
|
183
191
|
}
|
@@ -220,7 +228,7 @@ static HANDLE open_device(const char *path, BOOL enumerate)
|
|
220
228
|
share_mode,
|
221
229
|
NULL,
|
222
230
|
OPEN_EXISTING,
|
223
|
-
FILE_FLAG_OVERLAPPED
|
231
|
+
FILE_FLAG_OVERLAPPED,/*FILE_ATTRIBUTE_NORMAL,*/
|
224
232
|
0);
|
225
233
|
|
226
234
|
return handle;
|
@@ -254,10 +262,10 @@ int HID_API_EXPORT hid_exit(void)
|
|
254
262
|
struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id)
|
255
263
|
{
|
256
264
|
BOOL res;
|
257
|
-
struct hid_device_info *root = NULL;
|
265
|
+
struct hid_device_info *root = NULL; /* return object */
|
258
266
|
struct hid_device_info *cur_dev = NULL;
|
259
267
|
|
260
|
-
|
268
|
+
/* Windows objects for interacting with the driver. */
|
261
269
|
GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, {0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30} };
|
262
270
|
SP_DEVINFO_DATA devinfo_data;
|
263
271
|
SP_DEVICE_INTERFACE_DATA device_interface_data;
|
@@ -269,16 +277,16 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor
|
|
269
277
|
if (hid_init() < 0)
|
270
278
|
return NULL;
|
271
279
|
|
272
|
-
|
280
|
+
/* Initialize the Windows objects. */
|
273
281
|
memset(&devinfo_data, 0x0, sizeof(devinfo_data));
|
274
282
|
devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA);
|
275
283
|
device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
276
284
|
|
277
|
-
|
285
|
+
/* Get information for all the devices belonging to the HID class. */
|
278
286
|
device_info_set = SetupDiGetClassDevsA(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
279
|
-
|
280
|
-
|
281
|
-
|
287
|
+
|
288
|
+
/* Iterate over each device in the HID class, looking for the right one. */
|
289
|
+
|
282
290
|
for (;;) {
|
283
291
|
HANDLE write_handle = INVALID_HANDLE_VALUE;
|
284
292
|
DWORD required_size = 0;
|
@@ -289,16 +297,16 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor
|
|
289
297
|
&InterfaceClassGuid,
|
290
298
|
device_index,
|
291
299
|
&device_interface_data);
|
292
|
-
|
300
|
+
|
293
301
|
if (!res) {
|
294
|
-
|
295
|
-
|
302
|
+
/* A return of FALSE from this function means that
|
303
|
+
there are no more devices. */
|
296
304
|
break;
|
297
305
|
}
|
298
306
|
|
299
|
-
|
300
|
-
|
301
|
-
|
307
|
+
/* Call with 0-sized detail size, and let the function
|
308
|
+
tell us how long the detail struct needs to be. The
|
309
|
+
size is put in &required_size. */
|
302
310
|
res = SetupDiGetDeviceInterfaceDetailA(device_info_set,
|
303
311
|
&device_interface_data,
|
304
312
|
NULL,
|
@@ -306,13 +314,13 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor
|
|
306
314
|
&required_size,
|
307
315
|
NULL);
|
308
316
|
|
309
|
-
|
317
|
+
/* Allocate a long enough structure for device_interface_detail_data. */
|
310
318
|
device_interface_detail_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_A*) malloc(required_size);
|
311
319
|
device_interface_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
|
312
320
|
|
313
|
-
|
314
|
-
|
315
|
-
|
321
|
+
/* Get the detailed data for this device. The detail data gives us
|
322
|
+
the device path for this device, which is then passed into
|
323
|
+
CreateFile() to get a handle to the device. */
|
316
324
|
res = SetupDiGetDeviceInterfaceDetailA(device_info_set,
|
317
325
|
&device_interface_data,
|
318
326
|
device_interface_detail_data,
|
@@ -321,18 +329,18 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor
|
|
321
329
|
NULL);
|
322
330
|
|
323
331
|
if (!res) {
|
324
|
-
|
325
|
-
|
332
|
+
/* register_error(dev, "Unable to call SetupDiGetDeviceInterfaceDetail");
|
333
|
+
Continue to the next device. */
|
326
334
|
goto cont;
|
327
335
|
}
|
328
336
|
|
329
|
-
|
330
|
-
|
337
|
+
/* Make sure this device is of Setup Class "HIDClass" and has a
|
338
|
+
driver bound to it. */
|
331
339
|
for (i = 0; ; i++) {
|
332
340
|
char driver_name[256];
|
333
341
|
|
334
|
-
|
335
|
-
|
342
|
+
/* Populate devinfo_data. This function will return failure
|
343
|
+
when there are no more interfaces left. */
|
336
344
|
res = SetupDiEnumDeviceInfo(device_info_set, i, &devinfo_data);
|
337
345
|
if (!res)
|
338
346
|
goto cont;
|
@@ -343,7 +351,7 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor
|
|
343
351
|
goto cont;
|
344
352
|
|
345
353
|
if (strcmp(driver_name, "HIDClass") == 0) {
|
346
|
-
|
354
|
+
/* See if there's a driver bound. */
|
347
355
|
res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data,
|
348
356
|
SPDRP_DRIVER, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL);
|
349
357
|
if (res)
|
@@ -353,26 +361,26 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor
|
|
353
361
|
|
354
362
|
//wprintf(L"HandleName: %s\n", device_interface_detail_data->DevicePath);
|
355
363
|
|
356
|
-
|
364
|
+
/* Open a handle to the device */
|
357
365
|
write_handle = open_device(device_interface_detail_data->DevicePath, TRUE);
|
358
366
|
|
359
|
-
|
367
|
+
/* Check validity of write_handle. */
|
360
368
|
if (write_handle == INVALID_HANDLE_VALUE) {
|
361
|
-
|
369
|
+
/* Unable to open the device. */
|
362
370
|
//register_error(dev, "CreateFile");
|
363
371
|
goto cont_close;
|
364
|
-
}
|
372
|
+
}
|
365
373
|
|
366
374
|
|
367
|
-
|
375
|
+
/* Get the Vendor ID and Product ID for this device. */
|
368
376
|
attrib.Size = sizeof(HIDD_ATTRIBUTES);
|
369
377
|
HidD_GetAttributes(write_handle, &attrib);
|
370
378
|
//wprintf(L"Product/Vendor: %x %x\n", attrib.ProductID, attrib.VendorID);
|
371
379
|
|
372
|
-
|
373
|
-
|
374
|
-
if ((vendor_id == 0x0
|
375
|
-
|
380
|
+
/* Check the VID/PID to see if we should add this
|
381
|
+
device to the enumeration list. */
|
382
|
+
if ((vendor_id == 0x0 || attrib.VendorID == vendor_id) &&
|
383
|
+
(product_id == 0x0 || attrib.ProductID == product_id)) {
|
376
384
|
|
377
385
|
#define WSTR_LEN 512
|
378
386
|
const char *str;
|
@@ -381,7 +389,7 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor
|
|
381
389
|
HIDP_CAPS caps;
|
382
390
|
BOOLEAN res;
|
383
391
|
NTSTATUS nt_res;
|
384
|
-
wchar_t wstr[WSTR_LEN];
|
392
|
+
wchar_t wstr[WSTR_LEN]; /* TODO: Determine Size */
|
385
393
|
size_t len;
|
386
394
|
|
387
395
|
/* VID/PID match. Create the record. */
|
@@ -394,7 +402,7 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor
|
|
394
402
|
}
|
395
403
|
cur_dev = tmp;
|
396
404
|
|
397
|
-
|
405
|
+
/* Get the Usage Page and Usage for this device. */
|
398
406
|
res = HidD_GetPreparsedData(write_handle, &pp_data);
|
399
407
|
if (res) {
|
400
408
|
nt_res = HidP_GetCaps(pp_data, &caps);
|
@@ -405,7 +413,7 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor
|
|
405
413
|
|
406
414
|
HidD_FreePreparsedData(pp_data);
|
407
415
|
}
|
408
|
-
|
416
|
+
|
409
417
|
/* Fill out the record */
|
410
418
|
cur_dev->next = NULL;
|
411
419
|
str = device_interface_detail_data->DevicePath;
|
@@ -469,14 +477,14 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor
|
|
469
477
|
cont_close:
|
470
478
|
CloseHandle(write_handle);
|
471
479
|
cont:
|
472
|
-
|
480
|
+
/* We no longer need the detail data. It can be freed */
|
473
481
|
free(device_interface_detail_data);
|
474
482
|
|
475
483
|
device_index++;
|
476
484
|
|
477
485
|
}
|
478
486
|
|
479
|
-
|
487
|
+
/* Close the device information handle. */
|
480
488
|
SetupDiDestroyDeviceInfoList(device_info_set);
|
481
489
|
|
482
490
|
return root;
|
@@ -485,7 +493,7 @@ cont:
|
|
485
493
|
|
486
494
|
void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs)
|
487
495
|
{
|
488
|
-
|
496
|
+
/* TODO: Merge this with the Linux version. This function is platform-independent. */
|
489
497
|
struct hid_device_info *d = devs;
|
490
498
|
while (d) {
|
491
499
|
struct hid_device_info *next = d->next;
|
@@ -501,11 +509,11 @@ void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *d
|
|
501
509
|
|
502
510
|
HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
|
503
511
|
{
|
504
|
-
|
512
|
+
/* TODO: Merge this functions with the Linux version. This function should be platform independent. */
|
505
513
|
struct hid_device_info *devs, *cur_dev;
|
506
514
|
const char *path_to_open = NULL;
|
507
515
|
hid_device *handle = NULL;
|
508
|
-
|
516
|
+
|
509
517
|
devs = hid_enumerate(vendor_id, product_id);
|
510
518
|
cur_dev = devs;
|
511
519
|
while (cur_dev) {
|
@@ -531,7 +539,7 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsi
|
|
531
539
|
}
|
532
540
|
|
533
541
|
hid_free_enumeration(devs);
|
534
|
-
|
542
|
+
|
535
543
|
return handle;
|
536
544
|
}
|
537
545
|
|
@@ -549,17 +557,17 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path)
|
|
549
557
|
|
550
558
|
dev = new_hid_device();
|
551
559
|
|
552
|
-
|
560
|
+
/* Open a handle to the device */
|
553
561
|
dev->device_handle = open_device(path, FALSE);
|
554
562
|
|
555
|
-
|
563
|
+
/* Check validity of write_handle. */
|
556
564
|
if (dev->device_handle == INVALID_HANDLE_VALUE) {
|
557
|
-
|
565
|
+
/* Unable to open the device. */
|
558
566
|
register_error(dev, "CreateFile");
|
559
567
|
goto err;
|
560
568
|
}
|
561
569
|
|
562
|
-
|
570
|
+
/* Get the Input Report length for the device. */
|
563
571
|
res = HidD_GetPreparsedData(dev->device_handle, &pp_data);
|
564
572
|
if (!res) {
|
565
573
|
register_error(dev, "HidD_GetPreparsedData");
|
@@ -567,7 +575,7 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path)
|
|
567
575
|
}
|
568
576
|
nt_res = HidP_GetCaps(pp_data, &caps);
|
569
577
|
if (nt_res != HIDP_STATUS_SUCCESS) {
|
570
|
-
register_error(dev, "HidP_GetCaps");
|
578
|
+
register_error(dev, "HidP_GetCaps");
|
571
579
|
goto err_pp_data;
|
572
580
|
}
|
573
581
|
dev->output_report_length = caps.OutputReportByteLength;
|
@@ -580,9 +588,8 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path)
|
|
580
588
|
|
581
589
|
err_pp_data:
|
582
590
|
HidD_FreePreparsedData(pp_data);
|
583
|
-
err:
|
584
|
-
|
585
|
-
free(dev);
|
591
|
+
err:
|
592
|
+
free_hid_device(dev);
|
586
593
|
return NULL;
|
587
594
|
}
|
588
595
|
|
@@ -614,21 +621,21 @@ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *
|
|
614
621
|
}
|
615
622
|
|
616
623
|
res = WriteFile(dev->device_handle, buf, length, NULL, &ol);
|
617
|
-
|
624
|
+
|
618
625
|
if (!res) {
|
619
626
|
if (GetLastError() != ERROR_IO_PENDING) {
|
620
|
-
|
627
|
+
/* WriteFile() failed. Return error. */
|
621
628
|
register_error(dev, "WriteFile");
|
622
629
|
bytes_written = -1;
|
623
630
|
goto end_of_function;
|
624
631
|
}
|
625
632
|
}
|
626
633
|
|
627
|
-
|
628
|
-
|
634
|
+
/* Wait here until the write is done. This makes
|
635
|
+
hid_write() synchronous. */
|
629
636
|
res = GetOverlappedResult(dev->device_handle, &ol, &bytes_written, TRUE/*wait*/);
|
630
637
|
if (!res) {
|
631
|
-
|
638
|
+
/* The Write operation failed. */
|
632
639
|
register_error(dev, "WriteFile");
|
633
640
|
bytes_written = -1;
|
634
641
|
goto end_of_function;
|
@@ -647,20 +654,20 @@ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char
|
|
647
654
|
DWORD bytes_read = 0;
|
648
655
|
BOOL res;
|
649
656
|
|
650
|
-
|
657
|
+
/* Copy the handle for convenience. */
|
651
658
|
HANDLE ev = dev->ol.hEvent;
|
652
659
|
|
653
660
|
if (!dev->read_pending) {
|
654
|
-
|
661
|
+
/* Start an Overlapped I/O read. */
|
655
662
|
dev->read_pending = TRUE;
|
656
663
|
memset(dev->read_buf, 0, dev->input_report_length);
|
657
664
|
ResetEvent(ev);
|
658
665
|
res = ReadFile(dev->device_handle, dev->read_buf, dev->input_report_length, &bytes_read, &dev->ol);
|
659
|
-
|
666
|
+
|
660
667
|
if (!res) {
|
661
668
|
if (GetLastError() != ERROR_IO_PENDING) {
|
662
|
-
|
663
|
-
|
669
|
+
/* ReadFile() has failed.
|
670
|
+
Clean up and return error. */
|
664
671
|
CancelIo(dev->device_handle);
|
665
672
|
dev->read_pending = FALSE;
|
666
673
|
goto end_of_function;
|
@@ -669,21 +676,21 @@ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char
|
|
669
676
|
}
|
670
677
|
|
671
678
|
if (milliseconds >= 0) {
|
672
|
-
|
679
|
+
/* See if there is any data yet. */
|
673
680
|
res = WaitForSingleObject(ev, milliseconds);
|
674
681
|
if (res != WAIT_OBJECT_0) {
|
675
|
-
|
676
|
-
|
682
|
+
/* There was no data this time. Return zero bytes available,
|
683
|
+
but leave the Overlapped I/O running. */
|
677
684
|
return 0;
|
678
685
|
}
|
679
686
|
}
|
680
687
|
|
681
|
-
|
682
|
-
|
683
|
-
|
688
|
+
/* Either WaitForSingleObject() told us that ReadFile has completed, or
|
689
|
+
we are in non-blocking mode. Get the number of bytes read. The actual
|
690
|
+
data has been copied to the data[] array which was passed to ReadFile(). */
|
684
691
|
res = GetOverlappedResult(dev->device_handle, &dev->ol, &bytes_read, TRUE/*wait*/);
|
685
|
-
|
686
|
-
|
692
|
+
|
693
|
+
/* Set pending back to false, even if GetOverlappedResult() returned error. */
|
687
694
|
dev->read_pending = FALSE;
|
688
695
|
|
689
696
|
if (res && bytes_read > 0) {
|
@@ -703,13 +710,13 @@ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char
|
|
703
710
|
memcpy(data, dev->read_buf, copy_len);
|
704
711
|
}
|
705
712
|
}
|
706
|
-
|
713
|
+
|
707
714
|
end_of_function:
|
708
715
|
if (!res) {
|
709
716
|
register_error(dev, "GetOverlappedResult");
|
710
717
|
return -1;
|
711
718
|
}
|
712
|
-
|
719
|
+
|
713
720
|
return bytes_read;
|
714
721
|
}
|
715
722
|
|
@@ -760,17 +767,17 @@ int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned
|
|
760
767
|
|
761
768
|
if (!res) {
|
762
769
|
if (GetLastError() != ERROR_IO_PENDING) {
|
763
|
-
|
770
|
+
/* DeviceIoControl() failed. Return error. */
|
764
771
|
register_error(dev, "Send Feature Report DeviceIoControl");
|
765
772
|
return -1;
|
766
773
|
}
|
767
774
|
}
|
768
775
|
|
769
|
-
|
770
|
-
|
776
|
+
/* Wait here until the write is done. This makes
|
777
|
+
hid_get_feature_report() synchronous. */
|
771
778
|
res = GetOverlappedResult(dev->device_handle, &ol, &bytes_returned, TRUE/*wait*/);
|
772
779
|
if (!res) {
|
773
|
-
|
780
|
+
/* The operation failed. */
|
774
781
|
register_error(dev, "Send Feature Report GetOverLappedResult");
|
775
782
|
return -1;
|
776
783
|
}
|
@@ -783,18 +790,14 @@ void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev)
|
|
783
790
|
if (!dev)
|
784
791
|
return;
|
785
792
|
CancelIo(dev->device_handle);
|
786
|
-
|
787
|
-
CloseHandle(dev->device_handle);
|
788
|
-
LocalFree(dev->last_error_str);
|
789
|
-
free(dev->read_buf);
|
790
|
-
free(dev);
|
793
|
+
free_hid_device(dev);
|
791
794
|
}
|
792
795
|
|
793
796
|
int HID_API_EXPORT_CALL HID_API_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen)
|
794
797
|
{
|
795
798
|
BOOL res;
|
796
799
|
|
797
|
-
res = HidD_GetManufacturerString(dev->device_handle, string,
|
800
|
+
res = HidD_GetManufacturerString(dev->device_handle, string, sizeof(wchar_t) * maxlen);
|
798
801
|
if (!res) {
|
799
802
|
register_error(dev, "HidD_GetManufacturerString");
|
800
803
|
return -1;
|
@@ -807,7 +810,7 @@ int HID_API_EXPORT_CALL HID_API_CALL hid_get_product_string(hid_device *dev, wch
|
|
807
810
|
{
|
808
811
|
BOOL res;
|
809
812
|
|
810
|
-
res = HidD_GetProductString(dev->device_handle, string,
|
813
|
+
res = HidD_GetProductString(dev->device_handle, string, sizeof(wchar_t) * maxlen);
|
811
814
|
if (!res) {
|
812
815
|
register_error(dev, "HidD_GetProductString");
|
813
816
|
return -1;
|
@@ -820,7 +823,7 @@ int HID_API_EXPORT_CALL HID_API_CALL hid_get_serial_number_string(hid_device *de
|
|
820
823
|
{
|
821
824
|
BOOL res;
|
822
825
|
|
823
|
-
res = HidD_GetSerialNumberString(dev->device_handle, string,
|
826
|
+
res = HidD_GetSerialNumberString(dev->device_handle, string, sizeof(wchar_t) * maxlen);
|
824
827
|
if (!res) {
|
825
828
|
register_error(dev, "HidD_GetSerialNumberString");
|
826
829
|
return -1;
|
@@ -833,7 +836,7 @@ int HID_API_EXPORT_CALL HID_API_CALL hid_get_indexed_string(hid_device *dev, int
|
|
833
836
|
{
|
834
837
|
BOOL res;
|
835
838
|
|
836
|
-
res = HidD_GetIndexedString(dev->device_handle, string_index, string,
|
839
|
+
res = HidD_GetIndexedString(dev->device_handle, string_index, string, sizeof(wchar_t) * maxlen);
|
837
840
|
if (!res) {
|
838
841
|
register_error(dev, "HidD_GetIndexedString");
|
839
842
|
return -1;
|
@@ -849,10 +852,10 @@ HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev)
|
|
849
852
|
}
|
850
853
|
|
851
854
|
|
852
|
-
|
853
|
-
|
855
|
+
/*#define PICPGM*/
|
856
|
+
/*#define S11*/
|
854
857
|
#define P32
|
855
|
-
#ifdef S11
|
858
|
+
#ifdef S11
|
856
859
|
unsigned short VendorID = 0xa0a0;
|
857
860
|
unsigned short ProductID = 0x0001;
|
858
861
|
#endif
|
@@ -878,36 +881,36 @@ int __cdecl main(int argc, char* argv[])
|
|
878
881
|
UNREFERENCED_PARAMETER(argc);
|
879
882
|
UNREFERENCED_PARAMETER(argv);
|
880
883
|
|
881
|
-
|
884
|
+
/* Set up the command buffer. */
|
882
885
|
memset(buf,0x00,sizeof(buf));
|
883
886
|
buf[0] = 0;
|
884
887
|
buf[1] = 0x81;
|
885
|
-
|
886
888
|
|
887
|
-
|
889
|
+
|
890
|
+
/* Open the device. */
|
888
891
|
int handle = open(VendorID, ProductID, L"12345");
|
889
892
|
if (handle < 0)
|
890
893
|
printf("unable to open device\n");
|
891
894
|
|
892
895
|
|
893
|
-
|
896
|
+
/* Toggle LED (cmd 0x80) */
|
894
897
|
buf[1] = 0x80;
|
895
898
|
res = write(handle, buf, 65);
|
896
899
|
if (res < 0)
|
897
900
|
printf("Unable to write()\n");
|
898
901
|
|
899
|
-
|
902
|
+
/* Request state (cmd 0x81) */
|
900
903
|
buf[1] = 0x81;
|
901
904
|
write(handle, buf, 65);
|
902
905
|
if (res < 0)
|
903
906
|
printf("Unable to write() (2)\n");
|
904
907
|
|
905
|
-
|
908
|
+
/* Read requested state */
|
906
909
|
read(handle, buf, 65);
|
907
910
|
if (res < 0)
|
908
911
|
printf("Unable to read()\n");
|
909
912
|
|
910
|
-
|
913
|
+
/* Print out the returned buffer. */
|
911
914
|
for (int i = 0; i < 4; i++)
|
912
915
|
printf("buf[%d]: %d\n", i, buf[i]);
|
913
916
|
|
@@ -916,5 +919,5 @@ int __cdecl main(int argc, char* argv[])
|
|
916
919
|
#endif
|
917
920
|
|
918
921
|
#ifdef __cplusplus
|
919
|
-
}
|
920
|
-
#endif
|
922
|
+
} /* extern "C" */
|
923
|
+
#endif
|