Atlas - hid.c
Home / ext / SDL / src / hidapi / linux Lines: 6 | Size: 39371 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 libusb/hidapi Team 9 10 Copyright 2022, 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 https://github.com/libusb/hidapi . 21********************************************************/ 22 23/* C */ 24#include <stdio.h> 25#include <string.h> 26#include <stdlib.h> 27#include <locale.h> 28#include <errno.h> 29 30/* Unix */ 31#include <unistd.h> 32#include <sys/types.h> 33#include <sys/stat.h> 34#include <sys/ioctl.h> 35#include <sys/utsname.h> 36#include <fcntl.h> 37#include <poll.h> 38 39/* Linux */ 40#include <linux/hidraw.h> 41#include <linux/version.h> 42#include <linux/input.h> 43#include <libudev.h> 44 45#include "../hidapi/hidapi.h" 46 47#ifndef BUS_SPI 48#define BUS_SPI 0x1C 49#endif 50 51#ifdef HIDAPI_ALLOW_BUILD_WORKAROUND_KERNEL_2_6_39 52/* This definitions first appeared in Linux Kernel 2.6.39 in linux/hidraw.h. 53 hidapi doesn't support kernels older than that, 54 so we don't define macros below explicitly, to fail builds on old kernels. 55 For those who really need this as a workaround (e.g. to be able to build on old build machines), 56 can workaround by defining the macro above. 57*/ 58#ifndef HIDIOCSFEATURE 59#define HIDIOCSFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len) 60#endif 61#ifndef HIDIOCGFEATURE 62#define HIDIOCGFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x07, len) 63#endif 64 65#endif 66 67 68// HIDIOCGINPUT is not defined in Linux kernel headers < 5.11. 69// This definition is from hidraw.h in Linux >= 5.11. 70// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f43d3870cafa2a0f3854c1819c8385733db8f9ae 71#ifndef HIDIOCGINPUT 72#define HIDIOCGINPUT(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x0A, len) 73#endif 74 75struct hid_device_ { 76 int device_handle; 77 int blocking; 78 int needs_ble_hack; 79 wchar_t *last_error_str; 80 struct hid_device_info* device_info; 81}; 82 83static struct hid_api_version api_version = { 84 .major = HID_API_VERSION_MAJOR, 85 .minor = HID_API_VERSION_MINOR, 86 .patch = HID_API_VERSION_PATCH 87}; 88 89static wchar_t *last_global_error_str = NULL; 90 91 92static hid_device *new_hid_device(void) 93{ 94 hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device)); 95 if (dev == NULL) { 96 return NULL; 97 } 98 99 dev->device_handle = -1; 100 dev->blocking = 1; 101 dev->last_error_str = NULL; 102 dev->device_info = NULL; 103 104 return dev; 105} 106 107 108/* The caller must free the returned string with free(). */ 109static wchar_t *utf8_to_wchar_t(const char *utf8) 110{ 111 wchar_t *ret = NULL; 112 113 if (utf8) { 114 size_t wlen = mbstowcs(NULL, utf8, 0); 115 if ((size_t) -1 == wlen) { 116 return wcsdup(L""); 117 } 118 ret = (wchar_t*) calloc(wlen+1, sizeof(wchar_t)); 119 if (ret == NULL) { 120 /* as much as we can do at this point */ 121 return NULL; 122 } 123 mbstowcs(ret, utf8, wlen+1); 124 ret[wlen] = 0x0000; 125 } 126 127 return ret; 128} 129 130 131/* Makes a copy of the given error message (and decoded according to the 132 * currently locale) into the wide string pointer pointed by error_str. 133 * The last stored error string is freed. 134 * Use register_error_str(NULL) to free the error message completely. */ 135static void register_error_str(wchar_t **error_str, const char *msg) 136{ 137#ifdef HIDAPI_USING_SDL_RUNTIME 138 /* Thread-safe error handling */ 139 if (msg) { 140 SDL_SetError("%s", msg); 141 } else { 142 SDL_ClearError(); 143 } 144#else 145 free(*error_str); 146 *error_str = utf8_to_wchar_t(msg); 147#endif 148} 149 150/* Similar to register_error_str, but allows passing a format string with va_list args into this function. */ 151static void register_error_str_vformat(wchar_t **error_str, const char *format, va_list args) 152{ 153 char msg[256]; 154 vsnprintf(msg, sizeof(msg), format, args); 155 156 register_error_str(error_str, msg); 157} 158 159/* Set the last global error to be reported by hid_error(NULL). 160 * The given error message will be copied (and decoded according to the 161 * currently locale, so do not pass in string constants). 162 * The last stored global error message is freed. 163 * Use register_global_error(NULL) to indicate "no error". */ 164static void register_global_error(const char *msg) 165{ 166 register_error_str(&last_global_error_str, msg); 167} 168 169/* Similar to register_global_error, but allows passing a format string into this function. */ 170static void register_global_error_format(const char *format, ...) 171{ 172 va_list args; 173 va_start(args, format); 174 register_error_str_vformat(&last_global_error_str, format, args); 175 va_end(args); 176} 177 178/* Set the last error for a device to be reported by hid_error(dev). 179 * The given error message will be copied (and decoded according to the 180 * currently locale, so do not pass in string constants). 181 * The last stored device error message is freed. 182 * Use register_device_error(dev, NULL) to indicate "no error". */ 183static void register_device_error(hid_device *dev, const char *msg) 184{ 185 register_error_str(&dev->last_error_str, msg); 186} 187 188/* Similar to register_device_error, but you can pass a format string into this function. */ 189static void register_device_error_format(hid_device *dev, const char *format, ...) 190{ 191 va_list args; 192 va_start(args, format); 193 register_error_str_vformat(&dev->last_error_str, format, args); 194 va_end(args); 195} 196 197/* Get an attribute value from a udev_device and return it as a whar_t 198 string. The returned string must be freed with free() when done.*/ 199static wchar_t *copy_udev_string(struct udev_device *dev, const char *udev_name) 200{ 201 return utf8_to_wchar_t(udev_device_get_sysattr_value(dev, udev_name)); 202} 203 204/* 205 * Gets the size of the HID item at the given position 206 * Returns 1 if successful, 0 if an invalid key 207 * Sets data_len and key_size when successful 208 */ 209static int get_hid_item_size(const __u8 *report_descriptor, __u32 size, unsigned int pos, int *data_len, int *key_size) 210{ 211 int key = report_descriptor[pos]; 212 int size_code; 213 214 /* 215 * This is a Long Item. The next byte contains the 216 * length of the data section (value) for this key. 217 * See the HID specification, version 1.11, section 218 * 6.2.2.3, titled "Long Items." 219 */ 220 if ((key & 0xf0) == 0xf0) { 221 if (pos + 1 < size) 222 { 223 *data_len = report_descriptor[pos + 1]; 224 *key_size = 3; 225 return 1; 226 } 227 *data_len = 0; /* malformed report */ 228 *key_size = 0; 229 } 230 231 /* 232 * This is a Short Item. The bottom two bits of the 233 * key contain the size code for the data section 234 * (value) for this key. Refer to the HID 235 * specification, version 1.11, section 6.2.2.2, 236 * titled "Short Items." 237 */ 238 size_code = key & 0x3; 239 switch (size_code) { 240 case 0: 241 case 1: 242 case 2: 243 *data_len = size_code; 244 *key_size = 1; 245 return 1; 246 case 3: 247 *data_len = 4; 248 *key_size = 1; 249 return 1; 250 default: 251 /* Can't ever happen since size_code is & 0x3 */ 252 *data_len = 0; 253 *key_size = 0; 254 break; 255 } 256 257 /* malformed report */ 258 return 0; 259} 260 261/* 262 * Get bytes from a HID Report Descriptor. 263 * Only call with a num_bytes of 0, 1, 2, or 4. 264 */ 265static __u32 get_hid_report_bytes(const __u8 *rpt, size_t len, size_t num_bytes, size_t cur) 266{ 267 /* Return if there aren't enough bytes. */ 268 if (cur + num_bytes >= len) 269 return 0; 270 271 if (num_bytes == 0) 272 return 0; 273 else if (num_bytes == 1) 274 return rpt[cur + 1]; 275 else if (num_bytes == 2) 276 return (rpt[cur + 2] * 256 + rpt[cur + 1]); 277 else if (num_bytes == 4) 278 return ( 279 rpt[cur + 4] * 0x01000000 + 280 rpt[cur + 3] * 0x00010000 + 281 rpt[cur + 2] * 0x00000100 + 282 rpt[cur + 1] * 0x00000001 283 ); 284 else 285 return 0; 286} 287 288/* 289 * Iterates until the end of a Collection. 290 * Assumes that *pos is exactly at the beginning of a Collection. 291 * Skips all nested Collection, i.e. iterates until the end of current level Collection. 292 * 293 * The return value is non-0 when an end of current Collection is found, 294 * 0 when error is occurred (broken Descriptor, end of a Collection is found before its begin, 295 * or no Collection is found at all). 296 */ 297static int hid_iterate_over_collection(const __u8 *report_descriptor, __u32 size, unsigned int *pos, int *data_len, int *key_size) 298{ 299 int collection_level = 0; 300 301 while (*pos < size) { 302 int key = report_descriptor[*pos]; 303 int key_cmd = key & 0xfc; 304 305 /* Determine data_len and key_size */ 306 if (!get_hid_item_size(report_descriptor, size, *pos, data_len, key_size)) 307 return 0; /* malformed report */ 308 309 switch (key_cmd) { 310 case 0xa0: /* Collection 6.2.2.4 (Main) */ 311 collection_level++; 312 break; 313 case 0xc0: /* End Collection 6.2.2.4 (Main) */ 314 collection_level--; 315 break; 316 } 317 318 if (collection_level < 0) { 319 /* Broken descriptor or someone is using this function wrong, 320 * i.e. should be called exactly at the collection start */ 321 return 0; 322 } 323 324 if (collection_level == 0) { 325 /* Found it! 326 * Also possible when called not at the collection start, but should not happen if used correctly */ 327 return 1; 328 } 329 330 *pos += *data_len + *key_size; 331 } 332 333 return 0; /* Did not find the end of a Collection */ 334} 335 336struct hid_usage_iterator { 337 unsigned int pos; 338 int usage_page_found; 339 unsigned short usage_page; 340}; 341 342/* 343 * Retrieves the device's Usage Page and Usage from the report descriptor. 344 * The algorithm returns the current Usage Page/Usage pair whenever a new 345 * Collection is found and a Usage Local Item is currently in scope. 346 * Usage Local Items are consumed by each Main Item (See. 6.2.2.8). 347 * The algorithm should give similar results as Apple's: 348 * https://developer.apple.com/documentation/iokit/kiohiddeviceusagepairskey?language=objc 349 * Physical Collections are also matched (macOS does the same). 350 * 351 * This function can be called repeatedly until it returns non-0 352 * Usage is found. pos is the starting point (initially 0) and will be updated 353 * to the next search position. 354 * 355 * The return value is 0 when a pair is found. 356 * 1 when finished processing descriptor. 357 * -1 on a malformed report. 358 */ 359static int get_next_hid_usage(const __u8 *report_descriptor, __u32 size, struct hid_usage_iterator *ctx, unsigned short *usage_page, unsigned short *usage) 360{ 361 int data_len, key_size; 362 int initial = ctx->pos == 0; /* Used to handle case where no top-level application collection is defined */ 363 364 int usage_found = 0; 365 366 while (ctx->pos < size) { 367 int key = report_descriptor[ctx->pos]; 368 int key_cmd = key & 0xfc; 369 370 /* Determine data_len and key_size */ 371 if (!get_hid_item_size(report_descriptor, size, ctx->pos, &data_len, &key_size)) 372 return -1; /* malformed report */ 373 374 switch (key_cmd) { 375 case 0x4: /* Usage Page 6.2.2.7 (Global) */ 376 ctx->usage_page = get_hid_report_bytes(report_descriptor, size, data_len, ctx->pos); 377 ctx->usage_page_found = 1; 378 break; 379 380 case 0x8: /* Usage 6.2.2.8 (Local) */ 381 if (data_len == 4) { /* Usages 5.5 / Usage Page 6.2.2.7 */ 382 ctx->usage_page = get_hid_report_bytes(report_descriptor, size, 2, ctx->pos + 2); 383 ctx->usage_page_found = 1; 384 *usage = get_hid_report_bytes(report_descriptor, size, 2, ctx->pos); 385 usage_found = 1; 386 } 387 else { 388 *usage = get_hid_report_bytes(report_descriptor, size, data_len, ctx->pos); 389 usage_found = 1; 390 } 391 break; 392 393 case 0xa0: /* Collection 6.2.2.4 (Main) */ 394 if (!hid_iterate_over_collection(report_descriptor, size, &ctx->pos, &data_len, &key_size)) { 395 return -1; 396 } 397 398 /* A pair is valid - to be reported when Collection is found */ 399 if (usage_found && ctx->usage_page_found) { 400 *usage_page = ctx->usage_page; 401 return 0; 402 } 403 404 break; 405 } 406 407 /* Skip over this key and its associated data */ 408 ctx->pos += data_len + key_size; 409 } 410 411 /* If no top-level application collection is found and usage page/usage pair is found, pair is valid 412 https://docs.microsoft.com/en-us/windows-hardware/drivers/hid/top-level-collections */ 413 if (initial && usage_found && ctx->usage_page_found) { 414 *usage_page = ctx->usage_page; 415 return 0; /* success */ 416 } 417 418 return 1; /* finished processing */ 419} 420 421/* 422 * Retrieves the hidraw report descriptor from a file. 423 * When using this form, <sysfs_path>/device/report_descriptor, elevated privileges are not required. 424 */ 425static int get_hid_report_descriptor(const char *rpt_path, struct hidraw_report_descriptor *rpt_desc) 426{ 427 int rpt_handle; 428 ssize_t res; 429 430 rpt_handle = open(rpt_path, O_RDONLY | O_CLOEXEC); 431 if (rpt_handle < 0) { 432 register_global_error_format("open failed (%s): %s", rpt_path, strerror(errno)); 433 return -1; 434 } 435 436 /* 437 * Read in the Report Descriptor 438 * The sysfs file has a maximum size of 4096 (which is the same as HID_MAX_DESCRIPTOR_SIZE) so we should always 439 * be ok when reading the descriptor. 440 * In practice if the HID descriptor is any larger I suspect many other things will break. 441 */ 442 memset(rpt_desc, 0x0, sizeof(*rpt_desc)); 443 res = read(rpt_handle, rpt_desc->value, HID_MAX_DESCRIPTOR_SIZE); 444 if (res < 0) { 445 register_global_error_format("read failed (%s): %s", rpt_path, strerror(errno)); 446 } 447 rpt_desc->size = (__u32) res; 448 449 close(rpt_handle); 450 return (int) res; 451} 452 453/* return size of the descriptor, or -1 on failure */ 454static int get_hid_report_descriptor_from_sysfs(const char *sysfs_path, struct hidraw_report_descriptor *rpt_desc) 455{ 456 int res = -1; 457 /* Construct <sysfs_path>/device/report_descriptor */ 458 size_t rpt_path_len = strlen(sysfs_path) + 25 + 1; 459 char* rpt_path = (char*) calloc(1, rpt_path_len); 460 snprintf(rpt_path, rpt_path_len, "%s/device/report_descriptor", sysfs_path); 461 462 res = get_hid_report_descriptor(rpt_path, rpt_desc); 463 free(rpt_path); 464 465 return res; 466} 467 468/* return non-zero if successfully parsed */ 469static int parse_hid_vid_pid_from_uevent(const char *uevent, unsigned *bus_type, unsigned short *vendor_id, unsigned short *product_id) 470{ 471 char tmp[1024]; 472 size_t uevent_len = strlen(uevent); 473 if (uevent_len > sizeof(tmp) - 1) 474 uevent_len = sizeof(tmp) - 1; 475 memcpy(tmp, uevent, uevent_len); 476 tmp[uevent_len] = '\0'; 477 478 char *saveptr = NULL; 479 char *line; 480 char *key; 481 char *value; 482 483 line = strtok_r(tmp, "\n", &saveptr); 484 while (line != NULL) { 485 /* line: "KEY=value" */ 486 key = line; 487 value = strchr(line, '='); 488 if (!value) { 489 goto next_line; 490 } 491 *value = '\0'; 492 value++; 493 494 if (strcmp(key, "HID_ID") == 0) { 495 /** 496 * type vendor product 497 * HID_ID=0003:000005AC:00008242 498 **/ 499 int ret = sscanf(value, "%x:%hx:%hx", bus_type, vendor_id, product_id); 500 if (ret == 3) { 501 return 1; 502 } 503 } 504 505next_line: 506 line = strtok_r(NULL, "\n", &saveptr); 507 } 508 509 register_global_error("Couldn't find/parse HID_ID"); 510 return 0; 511} 512 513/* return non-zero if successfully parsed */ 514static int parse_hid_vid_pid_from_uevent_path(const char *uevent_path, unsigned *bus_type, unsigned short *vendor_id, unsigned short *product_id) 515{ 516 int handle; 517 ssize_t res; 518 519 handle = open(uevent_path, O_RDONLY | O_CLOEXEC); 520 if (handle < 0) { 521 register_global_error_format("open failed (%s): %s", uevent_path, strerror(errno)); 522 return 0; 523 } 524 525 char buf[1024]; 526 res = read(handle, buf, sizeof(buf) - 1); /* -1 for '\0' at the end */ 527 close(handle); 528 529 if (res < 0) { 530 register_global_error_format("read failed (%s): %s", uevent_path, strerror(errno)); 531 return 0; 532 } 533 534 buf[res] = '\0'; 535 return parse_hid_vid_pid_from_uevent(buf, bus_type, vendor_id, product_id); 536} 537 538/* return non-zero if successfully read/parsed */ 539static int parse_hid_vid_pid_from_sysfs(const char *sysfs_path, unsigned *bus_type, unsigned short *vendor_id, unsigned short *product_id) 540{ 541 int res = 0; 542 /* Construct <sysfs_path>/device/uevent */ 543 size_t uevent_path_len = strlen(sysfs_path) + 14 + 1; 544 char* uevent_path = (char*) calloc(1, uevent_path_len); 545 snprintf(uevent_path, uevent_path_len, "%s/device/uevent", sysfs_path); 546 547 res = parse_hid_vid_pid_from_uevent_path(uevent_path, bus_type, vendor_id, product_id); 548 free(uevent_path); 549 550 return res; 551} 552 553static int get_hid_report_descriptor_from_hidraw(hid_device *dev, struct hidraw_report_descriptor *rpt_desc) 554{ 555 int desc_size = 0; 556 557 /* Get Report Descriptor Size */ 558 int res = ioctl(dev->device_handle, HIDIOCGRDESCSIZE, &desc_size); 559 if (res < 0) { 560 register_device_error_format(dev, "ioctl(GRDESCSIZE): %s", strerror(errno)); 561 return res; 562 } 563 564 /* Get Report Descriptor */ 565 memset(rpt_desc, 0x0, sizeof(*rpt_desc)); 566 rpt_desc->size = desc_size; 567 res = ioctl(dev->device_handle, HIDIOCGRDESC, rpt_desc); 568 if (res < 0) { 569 register_device_error_format(dev, "ioctl(GRDESC): %s", strerror(errno)); 570 } 571 572 return res; 573} 574 575/* 576 * The caller is responsible for free()ing the (newly-allocated) character 577 * strings pointed to by serial_number_utf8 and product_name_utf8 after use. 578 */ 579static int parse_uevent_info(const char *uevent, unsigned *bus_type, 580 unsigned short *vendor_id, unsigned short *product_id, 581 char **serial_number_utf8, char **product_name_utf8) 582{ 583 char tmp[1024]; 584 585 if (!uevent) { 586 return 0; 587 } 588 589 size_t uevent_len = strlen(uevent); 590 if (uevent_len > sizeof(tmp) - 1) 591 uevent_len = sizeof(tmp) - 1; 592 memcpy(tmp, uevent, uevent_len); 593 tmp[uevent_len] = '\0'; 594 595 char *saveptr = NULL; 596 char *line; 597 char *key; 598 char *value; 599 600 int found_id = 0; 601 int found_serial = 0; 602 int found_name = 0; 603 604 line = strtok_r(tmp, "\n", &saveptr); 605 while (line != NULL) { 606 /* line: "KEY=value" */ 607 key = line; 608 value = strchr(line, '='); 609 if (!value) { 610 goto next_line; 611 } 612 *value = '\0'; 613 value++; 614 615 if (strcmp(key, "HID_ID") == 0) { 616 /** 617 * type vendor product 618 * HID_ID=0003:000005AC:00008242 619 **/ 620 int ret = sscanf(value, "%x:%hx:%hx", bus_type, vendor_id, product_id); 621 if (ret == 3) { 622 found_id = 1; 623 } 624 } else if (strcmp(key, "HID_NAME") == 0) { 625 /* The caller has to free the product name */ 626 *product_name_utf8 = strdup(value); 627 found_name = 1; 628 } else if (strcmp(key, "HID_UNIQ") == 0) { 629 /* The caller has to free the serial number */ 630 *serial_number_utf8 = strdup(value); 631 found_serial = 1; 632 } 633 634next_line: 635 line = strtok_r(NULL, "\n", &saveptr); 636 } 637 638 return (found_id && found_name && found_serial); 639} 640 641static int is_BLE(hid_device *dev) 642{ 643 struct udev *udev; 644 struct udev_device *udev_dev, *hid_dev; 645 struct stat s; 646 int ret; 647 648 /* Create the udev object */ 649 udev = udev_new(); 650 if (!udev) { 651 printf("Can't create udev\n"); 652 return -1; 653 } 654 655 /* Get the dev_t (major/minor numbers) from the file handle. */ 656 if (fstat(dev->device_handle, &s) < 0) { 657 udev_unref(udev); 658 return -1; 659 } 660 661 /* Open a udev device from the dev_t. 'c' means character device. */ 662 ret = 0; 663 udev_dev = udev_device_new_from_devnum(udev, 'c', s.st_rdev); 664 if (udev_dev) { 665 hid_dev = udev_device_get_parent_with_subsystem_devtype( 666 udev_dev, 667 "hid", 668 NULL); 669 if (hid_dev) { 670 unsigned short dev_vid = 0; 671 unsigned short dev_pid = 0; 672 unsigned bus_type = 0; 673 char *serial_number_utf8 = NULL; 674 char *product_name_utf8 = NULL; 675 676 parse_uevent_info( 677 udev_device_get_sysattr_value(hid_dev, "uevent"), 678 &bus_type, 679 &dev_vid, 680 &dev_pid, 681 &serial_number_utf8, 682 &product_name_utf8); 683 free(serial_number_utf8); 684 free(product_name_utf8); 685 686 if (bus_type == BUS_BLUETOOTH) { 687 /* Right now the Steam Controller is the only BLE device that we send feature reports to */ 688 if (dev_vid == 0x28de /* Valve */) { 689 ret = 1; 690 } 691 } 692 693 /* hid_dev doesn't need to be (and can't be) unref'd. 694 I'm not sure why, but it'll throw double-free() errors. */ 695 } 696 udev_device_unref(udev_dev); 697 } 698 699 udev_unref(udev); 700 701 return ret; 702} 703 704 705static struct hid_device_info * create_device_info_for_device(struct udev_device *raw_dev) 706{ 707 struct hid_device_info *root = NULL; 708 struct hid_device_info *cur_dev = NULL; 709 710 const char *sysfs_path; 711 const char *dev_path; 712 const char *str; 713 struct udev_device *hid_dev; /* The device's HID udev node. */ 714 struct udev_device *usb_dev; /* The device's USB udev node. */ 715 struct udev_device *intf_dev; /* The device's interface (in the USB sense). */ 716 unsigned short dev_vid; 717 unsigned short dev_pid; 718 char *serial_number_utf8 = NULL; 719 char *product_name_utf8 = NULL; 720 unsigned bus_type; 721 int result; 722 struct hidraw_report_descriptor report_desc; 723 724 sysfs_path = udev_device_get_syspath(raw_dev); 725 dev_path = udev_device_get_devnode(raw_dev); 726 727 hid_dev = udev_device_get_parent_with_subsystem_devtype( 728 raw_dev, 729 "hid", 730 NULL); 731 732 if (!hid_dev) { 733 /* Unable to find parent hid device. */ 734 goto end; 735 } 736 737 result = parse_uevent_info( 738 udev_device_get_sysattr_value(hid_dev, "uevent"), 739 &bus_type, 740 &dev_vid, 741 &dev_pid, 742 &serial_number_utf8, 743 &product_name_utf8); 744 745 if (!result) { 746 /* parse_uevent_info() failed for at least one field. */ 747 goto end; 748 } 749 750 /* Filter out unhandled devices right away */ 751 switch (bus_type) { 752 case BUS_BLUETOOTH: 753 case BUS_I2C: 754 case BUS_USB: 755 case BUS_SPI: 756 break; 757 758 default: 759 goto end; 760 } 761 762 /* Create the record. */ 763 root = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info)); 764 if (!root) 765 goto end; 766 767 cur_dev = root; 768 769 /* Fill out the record */ 770 cur_dev->next = NULL; 771 cur_dev->path = dev_path? strdup(dev_path): NULL; 772 773 /* VID/PID */ 774 cur_dev->vendor_id = dev_vid; 775 cur_dev->product_id = dev_pid; 776 777 /* Serial Number */ 778 cur_dev->serial_number = utf8_to_wchar_t(serial_number_utf8); 779 780 /* Release Number */ 781 cur_dev->release_number = 0x0; 782 783 /* Interface Number */ 784 cur_dev->interface_number = -1; 785 786 switch (bus_type) { 787 case BUS_USB: 788 /* The device pointed to by raw_dev contains information about 789 the hidraw device. In order to get information about the 790 USB device, get the parent device with the 791 subsystem/devtype pair of "usb"/"usb_device". This will 792 be several levels up the tree, but the function will find 793 it. */ 794 usb_dev = udev_device_get_parent_with_subsystem_devtype( 795 raw_dev, 796 "usb", 797 "usb_device"); 798 799 /* uhid USB devices 800 * Since this is a virtual hid interface, no USB information will 801 * be available. */ 802 if (!usb_dev) { 803 /* Manufacturer and Product strings */ 804 cur_dev->manufacturer_string = wcsdup(L""); 805 cur_dev->product_string = utf8_to_wchar_t(product_name_utf8); 806 break; 807 } 808 809 cur_dev->manufacturer_string = copy_udev_string(usb_dev, "manufacturer"); 810 cur_dev->product_string = copy_udev_string(usb_dev, "product"); 811 812 cur_dev->bus_type = HID_API_BUS_USB; 813 814 str = udev_device_get_sysattr_value(usb_dev, "bcdDevice"); 815 cur_dev->release_number = (str)? strtol(str, NULL, 16): 0x0; 816 817 /* Get a handle to the interface's udev node. */ 818 intf_dev = udev_device_get_parent_with_subsystem_devtype( 819 raw_dev, 820 "usb", 821 "usb_interface"); 822 if (intf_dev) { 823 str = udev_device_get_sysattr_value(intf_dev, "bInterfaceNumber"); 824 cur_dev->interface_number = (str)? strtol(str, NULL, 16): -1; 825 } 826 827 break; 828 829 case BUS_BLUETOOTH: 830 cur_dev->manufacturer_string = wcsdup(L""); 831 cur_dev->product_string = utf8_to_wchar_t(product_name_utf8); 832 833 cur_dev->bus_type = HID_API_BUS_BLUETOOTH; 834 835 break; 836 case BUS_I2C: 837 cur_dev->manufacturer_string = wcsdup(L""); 838 cur_dev->product_string = utf8_to_wchar_t(product_name_utf8); 839 840 cur_dev->bus_type = HID_API_BUS_I2C; 841 842 break; 843 844 case BUS_SPI: 845 cur_dev->manufacturer_string = wcsdup(L""); 846 cur_dev->product_string = utf8_to_wchar_t(product_name_utf8); 847 848 cur_dev->bus_type = HID_API_BUS_SPI; 849 850 break; 851 852 default: 853 /* Unknown device type - this should never happen, as we 854 * check for USB and Bluetooth devices above */ 855 break; 856 } 857 858 /* Usage Page and Usage */ 859 result = get_hid_report_descriptor_from_sysfs(sysfs_path, &report_desc); 860 if (result >= 0) { 861 unsigned short page = 0, usage = 0; 862 struct hid_usage_iterator usage_iterator; 863 memset(&usage_iterator, 0, sizeof(usage_iterator)); 864 865 /* 866 * Parse the first usage and usage page 867 * out of the report descriptor. 868 */ 869 if (!get_next_hid_usage(report_desc.value, report_desc.size, &usage_iterator, &page, &usage)) { 870 cur_dev->usage_page = page; 871 cur_dev->usage = usage; 872 } 873 874 /* 875 * Parse any additional usage and usage pages 876 * out of the report descriptor. 877 */ 878 while (!get_next_hid_usage(report_desc.value, report_desc.size, &usage_iterator, &page, &usage)) { 879 /* Create new record for additional usage pairs */ 880 struct hid_device_info *tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info)); 881 struct hid_device_info *prev_dev = cur_dev; 882 883 if (!tmp) 884 continue; 885 cur_dev->next = tmp; 886 cur_dev = tmp; 887 888 /* Update fields */ 889 cur_dev->path = dev_path? strdup(dev_path): NULL; 890 cur_dev->vendor_id = dev_vid; 891 cur_dev->product_id = dev_pid; 892 cur_dev->serial_number = prev_dev->serial_number? wcsdup(prev_dev->serial_number): NULL; 893 cur_dev->release_number = prev_dev->release_number; 894 cur_dev->interface_number = prev_dev->interface_number; 895 cur_dev->manufacturer_string = prev_dev->manufacturer_string? wcsdup(prev_dev->manufacturer_string): NULL; 896 cur_dev->product_string = prev_dev->product_string? wcsdup(prev_dev->product_string): NULL; 897 cur_dev->usage_page = page; 898 cur_dev->usage = usage; 899 cur_dev->bus_type = prev_dev->bus_type; 900 } 901 } 902 903#ifdef HIDAPI_IGNORE_DEVICE 904 { 905 struct hid_device_info *prev_dev = NULL; 906 907 cur_dev = root; 908 while (cur_dev) { 909 if (HIDAPI_IGNORE_DEVICE(cur_dev->bus_type, cur_dev->vendor_id, cur_dev->product_id, cur_dev->usage_page, cur_dev->usage)) { 910 struct hid_device_info *tmp = cur_dev; 911 912 cur_dev = tmp->next; 913 if (prev_dev) { 914 prev_dev->next = cur_dev; 915 } else { 916 root = cur_dev; 917 } 918 tmp->next = NULL; 919 920 hid_free_enumeration(tmp); 921 } else { 922 prev_dev = cur_dev; 923 cur_dev = cur_dev->next; 924 } 925 } 926 } 927#endif 928 929end: 930 free(serial_number_utf8); 931 free(product_name_utf8); 932 933 return root; 934} 935 936static struct hid_device_info * create_device_info_for_hid_device(hid_device *dev) { 937 struct udev *udev; 938 struct udev_device *udev_dev; 939 struct stat s; 940 int ret = -1; 941 struct hid_device_info *root = NULL; 942 943 register_device_error(dev, NULL); 944 945 /* Get the dev_t (major/minor numbers) from the file handle. */ 946 ret = fstat(dev->device_handle, &s); 947 if (-1 == ret) { 948 register_device_error(dev, "Failed to stat device handle"); 949 return NULL; 950 } 951 952 /* Create the udev object */ 953 udev = udev_new(); 954 if (!udev) { 955 register_device_error(dev, "Couldn't create udev context"); 956 return NULL; 957 } 958 959 /* Open a udev device from the dev_t. 'c' means character device. */ 960 udev_dev = udev_device_new_from_devnum(udev, 'c', s.st_rdev); 961 if (udev_dev) { 962 root = create_device_info_for_device(udev_dev); 963 } 964 965 if (!root) { 966 /* TODO: have a better error reporting via create_device_info_for_device */ 967 register_device_error(dev, "Couldn't create hid_device_info"); 968 } 969 970 udev_device_unref(udev_dev); 971 udev_unref(udev); 972 973 return root; 974} 975 976HID_API_EXPORT const struct hid_api_version* HID_API_CALL hid_version(void) 977{ 978 return &api_version; 979} 980 981HID_API_EXPORT const char* HID_API_CALL hid_version_str(void) 982{ 983 return HID_API_VERSION_STR; 984} 985 986int HID_API_EXPORT hid_init(void) 987{ 988 const char *locale; 989 990 /* indicate no error */ 991 register_global_error(NULL); 992 993 /* Set the locale if it's not set. */ 994 locale = setlocale(LC_CTYPE, NULL); 995 if (!locale) 996 setlocale(LC_CTYPE, ""); 997 998 return 0; 999} 1000 1001int HID_API_EXPORT hid_exit(void) 1002{ 1003 /* Free global error message */ 1004 register_global_error(NULL); 1005 1006 return 0; 1007} 1008 1009struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id) 1010{ 1011 struct udev *udev; 1012 struct udev_enumerate *enumerate; 1013 struct udev_list_entry *devices, *dev_list_entry; 1014 1015 struct hid_device_info *root = NULL; /* return object */ 1016 struct hid_device_info *cur_dev = NULL; 1017 1018 hid_init(); 1019 /* register_global_error: global error is reset by hid_init */ 1020 1021 /* Create the udev object */ 1022 udev = udev_new(); 1023 if (!udev) { 1024 register_global_error("Couldn't create udev context"); 1025 return NULL; 1026 } 1027 1028 /* Create a list of the devices in the 'hidraw' subsystem. */ 1029 enumerate = udev_enumerate_new(udev); 1030 udev_enumerate_add_match_subsystem(enumerate, "hidraw"); 1031 udev_enumerate_scan_devices(enumerate); 1032 devices = udev_enumerate_get_list_entry(enumerate); 1033 /* For each item, see if it matches the vid/pid, and if so 1034 create a udev_device record for it */ 1035 udev_list_entry_foreach(dev_list_entry, devices) { 1036 const char *sysfs_path; 1037 unsigned short dev_vid = 0; 1038 unsigned short dev_pid = 0; 1039 unsigned bus_type = 0; 1040 struct udev_device *raw_dev; /* The device's hidraw udev node. */ 1041 struct hid_device_info * tmp; 1042 1043 /* Get the filename of the /sys entry for the device 1044 and create a udev_device object (dev) representing it */ 1045 sysfs_path = udev_list_entry_get_name(dev_list_entry); 1046 if (!sysfs_path) 1047 continue; 1048 1049 if (vendor_id != 0 || product_id != 0) { 1050 if (!parse_hid_vid_pid_from_sysfs(sysfs_path, &bus_type, &dev_vid, &dev_pid)) 1051 continue; 1052 1053 if (vendor_id != 0 && vendor_id != dev_vid) 1054 continue; 1055 if (product_id != 0 && product_id != dev_pid) 1056 continue; 1057 } 1058 1059 raw_dev = udev_device_new_from_syspath(udev, sysfs_path); 1060 if (!raw_dev) 1061 continue; 1062 1063 tmp = create_device_info_for_device(raw_dev); 1064 if (tmp) { 1065 if (cur_dev) { 1066 cur_dev->next = tmp; 1067 } 1068 else { 1069 root = tmp; 1070 } 1071 cur_dev = tmp; 1072 1073 /* move the pointer to the tail of returned list */ 1074 while (cur_dev->next != NULL) { 1075 cur_dev = cur_dev->next; 1076 } 1077 } 1078 1079 udev_device_unref(raw_dev); 1080 } 1081 /* Free the enumerator and udev objects. */ 1082 udev_enumerate_unref(enumerate); 1083 udev_unref(udev); 1084 1085 if (root == NULL) { 1086 if (vendor_id == 0 && product_id == 0) { 1087 register_global_error("No HID devices found in the system."); 1088 } else { 1089 register_global_error("No HID devices with requested VID/PID found in the system."); 1090 } 1091 } 1092 1093 return root; 1094} 1095 1096void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs) 1097{ 1098 struct hid_device_info *d = devs; 1099 while (d) { 1100 struct hid_device_info *next = d->next; 1101 free(d->path); 1102 free(d->serial_number); 1103 free(d->manufacturer_string); 1104 free(d->product_string); 1105 free(d); 1106 d = next; 1107 } 1108} 1109 1110hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) 1111{ 1112 struct hid_device_info *devs, *cur_dev; 1113 const char *path_to_open = NULL; 1114 hid_device *handle = NULL; 1115 1116 /* register_global_error: global error is reset by hid_enumerate/hid_init */ 1117 devs = hid_enumerate(vendor_id, product_id); 1118 if (devs == NULL) { 1119 /* register_global_error: global error is already set by hid_enumerate */ 1120 return NULL; 1121 } 1122 1123 cur_dev = devs; 1124 while (cur_dev) { 1125 if (cur_dev->vendor_id == vendor_id && 1126 cur_dev->product_id == product_id) { 1127 if (serial_number) { 1128 if (wcscmp(serial_number, cur_dev->serial_number) == 0) { 1129 path_to_open = cur_dev->path; 1130 break; 1131 } 1132 } 1133 else { 1134 path_to_open = cur_dev->path; 1135 break; 1136 } 1137 } 1138 cur_dev = cur_dev->next; 1139 } 1140 1141 if (path_to_open) { 1142 /* Open the device */ 1143 handle = hid_open_path(path_to_open); 1144 } else { 1145 register_global_error("Device with requested VID/PID/(SerialNumber) not found"); 1146 } 1147 1148 hid_free_enumeration(devs); 1149 1150 return handle; 1151} 1152 1153hid_device * HID_API_EXPORT hid_open_path(const char *path) 1154{ 1155 hid_device *dev = NULL; 1156 1157 hid_init(); 1158 /* register_global_error: global error is reset by hid_init */ 1159 1160 dev = new_hid_device(); 1161 if (!dev) { 1162 register_global_error("Couldn't allocate memory"); 1163 return NULL; 1164 } 1165 1166 const int MAX_ATTEMPTS = 50; 1167 int attempt; 1168 for (attempt = 1; attempt <= MAX_ATTEMPTS; ++attempt) { 1169 dev->device_handle = open(path, O_RDWR | O_CLOEXEC); 1170 if (dev->device_handle < 0 && errno == EACCES) { 1171 /* udev might be setting up permissions, wait a bit and try again */ 1172 usleep(1 * 1000); 1173 continue; 1174 } 1175 break; 1176 } 1177 1178 if (dev->device_handle >= 0) { 1179 int res, desc_size = 0; 1180 1181 /* Make sure this is a HIDRAW device - responds to HIDIOCGRDESCSIZE */ 1182 res = ioctl(dev->device_handle, HIDIOCGRDESCSIZE, &desc_size); 1183 if (res < 0) { 1184 hid_close(dev); 1185 register_global_error_format("ioctl(GRDESCSIZE) error for '%s', not a HIDRAW device?: %s", path, strerror(errno)); 1186 return NULL; 1187 } 1188 1189 dev->needs_ble_hack = (is_BLE(dev) == 1); 1190 1191 return dev; 1192 } 1193 else { 1194 /* Unable to open a device. */ 1195 free(dev); 1196 register_global_error_format("Failed to open a device with path '%s': %s", path, strerror(errno)); 1197 return NULL; 1198 } 1199} 1200 1201 1202int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length) 1203{ 1204 int bytes_written; 1205 1206 if (!data || (length == 0)) { 1207 errno = EINVAL; 1208 register_device_error(dev, strerror(errno)); 1209 return -1; 1210 } 1211 1212 bytes_written = write(dev->device_handle, data, length); 1213 1214 register_device_error(dev, (bytes_written == -1)? strerror(errno): NULL); 1215 1216 return bytes_written; 1217} 1218 1219 1220int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) 1221{ 1222 /* Set device error to none */ 1223 register_device_error(dev, NULL); 1224 1225 int bytes_read; 1226 1227 if (milliseconds >= 0) { 1228 /* Milliseconds is either 0 (non-blocking) or > 0 (contains 1229 a valid timeout). In both cases we want to call poll() 1230 and wait for data to arrive. Don't rely on non-blocking 1231 operation (O_NONBLOCK) since some kernels don't seem to 1232 properly report device disconnection through read() when 1233 in non-blocking mode. */ 1234 int ret; 1235 struct pollfd fds; 1236 1237 fds.fd = dev->device_handle; 1238 fds.events = POLLIN; 1239 fds.revents = 0; 1240 ret = poll(&fds, 1, milliseconds); 1241 if (ret == 0) { 1242 /* Timeout */ 1243 return ret; 1244 } 1245 if (ret == -1) { 1246 /* Error */ 1247 register_device_error(dev, strerror(errno)); 1248 return ret; 1249 } 1250 else { 1251 /* Check for errors on the file descriptor. This will 1252 indicate a device disconnection. */ 1253 if (fds.revents & (POLLERR | POLLHUP | POLLNVAL)) { 1254 // We cannot use strerror() here as no -1 was returned from poll(). 1255 register_device_error(dev, "hid_read_timeout: unexpected poll error (device disconnected)"); 1256 return -1; 1257 } 1258 } 1259 } 1260 1261 bytes_read = read(dev->device_handle, data, length); 1262 if (bytes_read < 0) { 1263 if (errno == EAGAIN || errno == EINPROGRESS) 1264 bytes_read = 0; 1265 else 1266 register_device_error(dev, strerror(errno)); 1267 } 1268 1269 return bytes_read; 1270} 1271 1272int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length) 1273{ 1274 return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0); 1275} 1276 1277int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock) 1278{ 1279 /* Do all non-blocking in userspace using poll(), since it looks 1280 like there's a bug in the kernel in some versions where 1281 read() will not return -1 on disconnection of the USB device */ 1282 1283 dev->blocking = !nonblock; 1284 return 0; /* Success */ 1285} 1286 1287 1288int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) 1289{ 1290 static const int MAX_RETRIES = 50; 1291 int retry; 1292 int res; 1293 1294 register_device_error(dev, NULL); 1295 1296 for (retry = 0; retry < MAX_RETRIES; ++retry) { 1297 res = ioctl(dev->device_handle, HIDIOCSFEATURE(length), data); 1298 if (res < 0 && errno == EPIPE) { 1299 /* Try again... */ 1300 continue; 1301 } 1302 1303 if (res < 0) 1304 register_device_error_format(dev, "ioctl (SFEATURE): %s", strerror(errno)); 1305 break; 1306 } 1307 return res; 1308} 1309 1310int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) 1311{ 1312 int res; 1313 unsigned char report = data[0]; 1314 1315 register_device_error(dev, NULL); 1316 1317 res = ioctl(dev->device_handle, HIDIOCGFEATURE(length), data); 1318 if (res < 0) 1319 register_device_error_format(dev, "ioctl (GFEATURE): %s", strerror(errno)); 1320 else if (dev->needs_ble_hack) { 1321 /* Versions of BlueZ before 5.56 don't include the report in the data, 1322 * and versions of BlueZ >= 5.56 include 2 copies of the report. 1323 * We'll fix it so that there is a single copy of the report in both cases 1324 */ 1325 if (data[0] == report && data[1] == report) { 1326 memmove(&data[0], &data[1], res); 1327 } else if (data[0] != report) { 1328 memmove(&data[1], &data[0], res); 1329 data[0] = report; 1330 ++res; 1331 } 1332 } 1333 1334 return res; 1335} 1336 1337int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length) 1338{ 1339 int res; 1340 1341 register_device_error(dev, NULL); 1342 1343 res = ioctl(dev->device_handle, HIDIOCGINPUT(length), data); 1344 if (res < 0) 1345 register_device_error_format(dev, "ioctl (GINPUT): %s", strerror(errno)); 1346 1347 return res; 1348} 1349 1350void HID_API_EXPORT hid_close(hid_device *dev) 1351{ 1352 if (!dev) 1353 return; 1354 1355 close(dev->device_handle); 1356 1357 /* Free the device error message */ 1358 register_device_error(dev, NULL); 1359 1360 hid_free_enumeration(dev->device_info); 1361 1362 free(dev); 1363} 1364 1365 1366int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) 1367{ 1368 if (!string || !maxlen) { 1369 register_device_error(dev, "Zero buffer/length"); 1370 return -1; 1371 } 1372 1373 struct hid_device_info *info = hid_get_device_info(dev); 1374 if (!info) { 1375 // hid_get_device_info will have set an error already 1376 return -1; 1377 } 1378 1379 if (info->manufacturer_string) { 1380 wcsncpy(string, info->manufacturer_string, maxlen); 1381 string[maxlen - 1] = L'\0'; 1382 } 1383 else { 1384 string[0] = L'\0'; 1385 } 1386 1387 return 0; 1388} 1389 1390int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) 1391{ 1392 if (!string || !maxlen) { 1393 register_device_error(dev, "Zero buffer/length"); 1394 return -1; 1395 } 1396 1397 struct hid_device_info *info = hid_get_device_info(dev); 1398 if (!info) { 1399 // hid_get_device_info will have set an error already 1400 return -1; 1401 } 1402 1403 if (info->product_string) { 1404 wcsncpy(string, info->product_string, maxlen); 1405 string[maxlen - 1] = L'\0'; 1406 } 1407 else { 1408 string[0] = L'\0'; 1409 } 1410 1411 return 0; 1412} 1413 1414int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) 1415{ 1416 if (!string || !maxlen) { 1417 register_device_error(dev, "Zero buffer/length"); 1418 return -1; 1419 } 1420 1421 struct hid_device_info *info = hid_get_device_info(dev); 1422 if (!info) { 1423 // hid_get_device_info will have set an error already 1424 return -1; 1425 } 1426 1427 if (info->serial_number) { 1428 wcsncpy(string, info->serial_number, maxlen); 1429 string[maxlen - 1] = L'\0'; 1430 } 1431 else { 1432 string[0] = L'\0'; 1433 } 1434 1435 return 0; 1436} 1437 1438 1439HID_API_EXPORT struct hid_device_info *HID_API_CALL hid_get_device_info(hid_device *dev) { 1440 if (!dev->device_info) { 1441 // Lazy initialize device_info 1442 dev->device_info = create_device_info_for_hid_device(dev); 1443 } 1444 1445 // create_device_info_for_hid_device will set an error if needed 1446 return dev->device_info; 1447} 1448 1449int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) 1450{ 1451 (void)string_index; 1452 (void)string; 1453 (void)maxlen; 1454 1455 register_device_error(dev, "hid_get_indexed_string: not supported by hidraw"); 1456 1457 return -1; 1458} 1459 1460 1461int HID_API_EXPORT_CALL hid_get_report_descriptor(hid_device *dev, unsigned char *buf, size_t buf_size) 1462{ 1463 struct hidraw_report_descriptor rpt_desc; 1464 int res = get_hid_report_descriptor_from_hidraw(dev, &rpt_desc); 1465 if (res < 0) { 1466 /* error already registered */ 1467 return res; 1468 } 1469 1470 if (rpt_desc.size < buf_size) { 1471 buf_size = (size_t) rpt_desc.size; 1472 } 1473 1474 memcpy(buf, rpt_desc.value, buf_size); 1475 1476 return (int) buf_size; 1477} 1478 1479 1480/* Passing in NULL means asking for the last global error message. */ 1481HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) 1482{ 1483 if (dev) { 1484 if (dev->last_error_str == NULL) 1485 return L"Success"; 1486 return dev->last_error_str; 1487 } 1488 1489 if (last_global_error_str == NULL) 1490 return L"Success"; 1491 return last_global_error_str; 1492} 1493[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.