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