~mr-unwell2006/mixxx/features_vamp

« back to all changes in this revision

Viewing changes to mixxx/lib/hidapi-0.7.0/windows/hid.c

  • Committer: Varun Jewalikar
  • Date: 2012-05-30 15:45:54 UTC
  • mfrom: (2684.18.247 mixxx-trunk)
  • Revision ID: mr.unwell2006@gmail.com-20120530154554-sh6i8m265v43gqtd
merge with the trunk

Show diffs side-by-side

added added

removed removed

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