Atlas - hid.c
Home / ext / SDL / src / hidapi / linux Lines: 6 | Size: 40136 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, false)) { 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_hwdb *hwdb = NULL; 1012 struct udev_list_entry *entry; 1013 1014 char modalias[64]; 1015 const char *key; 1016 const char *manufacturer_string; 1017 1018 struct udev *udev; 1019 struct udev_enumerate *enumerate; 1020 struct udev_list_entry *devices, *dev_list_entry; 1021 1022 struct hid_device_info *root = NULL; /* return object */ 1023 struct hid_device_info *cur_dev = NULL; 1024 1025 hid_init(); 1026 /* register_global_error: global error is reset by hid_init */ 1027 1028 /* Create the udev object */ 1029 udev = udev_new(); 1030 if (!udev) { 1031 register_global_error("Couldn't create udev context"); 1032 return NULL; 1033 } 1034 1035 /* Create a list of the devices in the 'hidraw' subsystem. */ 1036 enumerate = udev_enumerate_new(udev); 1037 udev_enumerate_add_match_subsystem(enumerate, "hidraw"); 1038 udev_enumerate_scan_devices(enumerate); 1039 devices = udev_enumerate_get_list_entry(enumerate); 1040 /* For each item, see if it matches the vid/pid, and if so 1041 create a udev_device record for it */ 1042 udev_list_entry_foreach(dev_list_entry, devices) { 1043 const char *sysfs_path; 1044 unsigned short dev_vid = 0; 1045 unsigned short dev_pid = 0; 1046 unsigned bus_type = 0; 1047 struct udev_device *raw_dev; /* The device's hidraw udev node. */ 1048 struct hid_device_info * tmp; 1049 1050 /* Get the filename of the /sys entry for the device 1051 and create a udev_device object (dev) representing it */ 1052 sysfs_path = udev_list_entry_get_name(dev_list_entry); 1053 if (!sysfs_path) 1054 continue; 1055 1056 if (vendor_id != 0 || product_id != 0) { 1057 if (!parse_hid_vid_pid_from_sysfs(sysfs_path, &bus_type, &dev_vid, &dev_pid)) 1058 continue; 1059 1060 if (vendor_id != 0 && vendor_id != dev_vid) 1061 continue; 1062 if (product_id != 0 && product_id != dev_pid) 1063 continue; 1064 } 1065 1066 raw_dev = udev_device_new_from_syspath(udev, sysfs_path); 1067 if (!raw_dev) 1068 continue; 1069 1070 1071 tmp = create_device_info_for_device(raw_dev); 1072 1073 if (tmp) { 1074 if (!tmp->manufacturer_string && udev_hwdb_new) { 1075 key = "ID_VENDOR_FROM_DATABASE"; 1076 1077 if ((hwdb = udev_hwdb_new(udev)) != NULL) { 1078 snprintf(modalias, sizeof(modalias), "usb:v%04X*", vendor_id); 1079 1080 udev_list_entry_foreach(entry, udev_hwdb_get_properties_list_entry(hwdb, modalias, 0)) { 1081 if (strcmp(udev_list_entry_get_name(entry), key) == 0) { 1082 manufacturer_string = udev_list_entry_get_value(entry); 1083 if (manufacturer_string) { 1084 tmp->manufacturer_string = utf8_to_wchar_t(manufacturer_string); 1085 } 1086 break; 1087 } 1088 } 1089 1090 hwdb = udev_hwdb_unref(hwdb); 1091 } 1092 } 1093 1094 if (cur_dev) { 1095 cur_dev->next = tmp; 1096 } 1097 else { 1098 root = tmp; 1099 } 1100 cur_dev = tmp; 1101 1102 /* move the pointer to the tail of returned list */ 1103 while (cur_dev->next != NULL) { 1104 cur_dev = cur_dev->next; 1105 } 1106 } 1107 1108 udev_device_unref(raw_dev); 1109 } 1110 /* Free the enumerator and udev objects. */ 1111 udev_enumerate_unref(enumerate); 1112 udev_unref(udev); 1113 1114 if (root == NULL) { 1115 if (vendor_id == 0 && product_id == 0) { 1116 register_global_error("No HID devices found in the system."); 1117 } else { 1118 register_global_error("No HID devices with requested VID/PID found in the system."); 1119 } 1120 } 1121 1122 return root; 1123} 1124 1125void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs) 1126{ 1127 struct hid_device_info *d = devs; 1128 while (d) { 1129 struct hid_device_info *next = d->next; 1130 free(d->path); 1131 free(d->serial_number); 1132 free(d->manufacturer_string); 1133 free(d->product_string); 1134 free(d); 1135 d = next; 1136 } 1137} 1138 1139hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) 1140{ 1141 struct hid_device_info *devs, *cur_dev; 1142 const char *path_to_open = NULL; 1143 hid_device *handle = NULL; 1144 1145 /* register_global_error: global error is reset by hid_enumerate/hid_init */ 1146 devs = hid_enumerate(vendor_id, product_id); 1147 if (devs == NULL) { 1148 /* register_global_error: global error is already set by hid_enumerate */ 1149 return NULL; 1150 } 1151 1152 cur_dev = devs; 1153 while (cur_dev) { 1154 if (cur_dev->vendor_id == vendor_id && 1155 cur_dev->product_id == product_id) { 1156 if (serial_number) { 1157 if (wcscmp(serial_number, cur_dev->serial_number) == 0) { 1158 path_to_open = cur_dev->path; 1159 break; 1160 } 1161 } 1162 else { 1163 path_to_open = cur_dev->path; 1164 break; 1165 } 1166 } 1167 cur_dev = cur_dev->next; 1168 } 1169 1170 if (path_to_open) { 1171 /* Open the device */ 1172 handle = hid_open_path(path_to_open); 1173 } else { 1174 register_global_error("Device with requested VID/PID/(SerialNumber) not found"); 1175 } 1176 1177 hid_free_enumeration(devs); 1178 1179 return handle; 1180} 1181 1182hid_device * HID_API_EXPORT hid_open_path(const char *path) 1183{ 1184 hid_device *dev = NULL; 1185 1186 hid_init(); 1187 /* register_global_error: global error is reset by hid_init */ 1188 1189 dev = new_hid_device(); 1190 if (!dev) { 1191 register_global_error("Couldn't allocate memory"); 1192 return NULL; 1193 } 1194 1195 const int MAX_ATTEMPTS = 50; 1196 int attempt; 1197 for (attempt = 1; attempt <= MAX_ATTEMPTS; ++attempt) { 1198 dev->device_handle = open(path, O_RDWR | O_CLOEXEC); 1199 if (dev->device_handle < 0 && errno == EACCES) { 1200 /* udev might be setting up permissions, wait a bit and try again */ 1201 usleep(1 * 1000); 1202 continue; 1203 } 1204 break; 1205 } 1206 1207 if (dev->device_handle >= 0) { 1208 int res, desc_size = 0; 1209 1210 /* Make sure this is a HIDRAW device - responds to HIDIOCGRDESCSIZE */ 1211 res = ioctl(dev->device_handle, HIDIOCGRDESCSIZE, &desc_size); 1212 if (res < 0) { 1213 hid_close(dev); 1214 register_global_error_format("ioctl(GRDESCSIZE) error for '%s', not a HIDRAW device?: %s", path, strerror(errno)); 1215 return NULL; 1216 } 1217 1218 dev->needs_ble_hack = (is_BLE(dev) == 1); 1219 1220 return dev; 1221 } 1222 else { 1223 /* Unable to open a device. */ 1224 free(dev); 1225 register_global_error_format("Failed to open a device with path '%s': %s", path, strerror(errno)); 1226 return NULL; 1227 } 1228} 1229 1230 1231int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length) 1232{ 1233 int bytes_written; 1234 1235 if (!data || (length == 0)) { 1236 errno = EINVAL; 1237 register_device_error(dev, strerror(errno)); 1238 return -1; 1239 } 1240 1241 bytes_written = write(dev->device_handle, data, length); 1242 1243 register_device_error(dev, (bytes_written == -1)? strerror(errno): NULL); 1244 1245 return bytes_written; 1246} 1247 1248 1249int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) 1250{ 1251 /* Set device error to none */ 1252 register_device_error(dev, NULL); 1253 1254 int bytes_read; 1255 1256 if (milliseconds >= 0) { 1257 /* Milliseconds is either 0 (non-blocking) or > 0 (contains 1258 a valid timeout). In both cases we want to call poll() 1259 and wait for data to arrive. Don't rely on non-blocking 1260 operation (O_NONBLOCK) since some kernels don't seem to 1261 properly report device disconnection through read() when 1262 in non-blocking mode. */ 1263 int ret; 1264 struct pollfd fds; 1265 1266 fds.fd = dev->device_handle; 1267 fds.events = POLLIN; 1268 fds.revents = 0; 1269 ret = poll(&fds, 1, milliseconds); 1270 if (ret == 0) { 1271 /* Timeout */ 1272 return ret; 1273 } 1274 if (ret == -1) { 1275 /* Error */ 1276 register_device_error(dev, strerror(errno)); 1277 return ret; 1278 } 1279 else { 1280 /* Check for errors on the file descriptor. This will 1281 indicate a device disconnection. */ 1282 if (fds.revents & (POLLERR | POLLHUP | POLLNVAL)) { 1283 // We cannot use strerror() here as no -1 was returned from poll(). 1284 register_device_error(dev, "hid_read_timeout: unexpected poll error (device disconnected)"); 1285 return -1; 1286 } 1287 } 1288 } 1289 1290 bytes_read = read(dev->device_handle, data, length); 1291 if (bytes_read < 0) { 1292 if (errno == EAGAIN || errno == EINPROGRESS) 1293 bytes_read = 0; 1294 else 1295 register_device_error(dev, strerror(errno)); 1296 } 1297 1298 return bytes_read; 1299} 1300 1301int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length) 1302{ 1303 return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0); 1304} 1305 1306int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock) 1307{ 1308 /* Do all non-blocking in userspace using poll(), since it looks 1309 like there's a bug in the kernel in some versions where 1310 read() will not return -1 on disconnection of the USB device */ 1311 1312 dev->blocking = !nonblock; 1313 return 0; /* Success */ 1314} 1315 1316 1317int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) 1318{ 1319 static const int MAX_RETRIES = 50; 1320 int retry; 1321 int res; 1322 1323 register_device_error(dev, NULL); 1324 1325 for (retry = 0; retry < MAX_RETRIES; ++retry) { 1326 res = ioctl(dev->device_handle, HIDIOCSFEATURE(length), data); 1327 if (res < 0 && errno == EPIPE) { 1328 /* Try again... */ 1329 continue; 1330 } 1331 1332 if (res < 0) 1333 register_device_error_format(dev, "ioctl (SFEATURE): %s", strerror(errno)); 1334 break; 1335 } 1336 return res; 1337} 1338 1339int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) 1340{ 1341 int res; 1342 unsigned char report = data[0]; 1343 1344 register_device_error(dev, NULL); 1345 1346 res = ioctl(dev->device_handle, HIDIOCGFEATURE(length), data); 1347 if (res < 0) 1348 register_device_error_format(dev, "ioctl (GFEATURE): %s", strerror(errno)); 1349 else if (dev->needs_ble_hack) { 1350 /* Versions of BlueZ before 5.56 don't include the report in the data, 1351 * and versions of BlueZ >= 5.56 include 2 copies of the report. 1352 * We'll fix it so that there is a single copy of the report in both cases 1353 */ 1354 if (data[0] == report && data[1] == report) { 1355 memmove(&data[0], &data[1], res); 1356 } else if (data[0] != report) { 1357 memmove(&data[1], &data[0], res); 1358 data[0] = report; 1359 ++res; 1360 } 1361 } 1362 1363 return res; 1364} 1365 1366int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length) 1367{ 1368 int res; 1369 1370 register_device_error(dev, NULL); 1371 1372 res = ioctl(dev->device_handle, HIDIOCGINPUT(length), data); 1373 if (res < 0) 1374 register_device_error_format(dev, "ioctl (GINPUT): %s", strerror(errno)); 1375 1376 return res; 1377} 1378 1379void HID_API_EXPORT hid_close(hid_device *dev) 1380{ 1381 if (!dev) 1382 return; 1383 1384 close(dev->device_handle); 1385 1386 /* Free the device error message */ 1387 register_device_error(dev, NULL); 1388 1389 hid_free_enumeration(dev->device_info); 1390 1391 free(dev); 1392} 1393 1394 1395int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) 1396{ 1397 if (!string || !maxlen) { 1398 register_device_error(dev, "Zero buffer/length"); 1399 return -1; 1400 } 1401 1402 struct hid_device_info *info = hid_get_device_info(dev); 1403 if (!info) { 1404 // hid_get_device_info will have set an error already 1405 return -1; 1406 } 1407 1408 if (info->manufacturer_string) { 1409 wcsncpy(string, info->manufacturer_string, maxlen); 1410 string[maxlen - 1] = L'\0'; 1411 } 1412 else { 1413 string[0] = L'\0'; 1414 } 1415 1416 return 0; 1417} 1418 1419int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) 1420{ 1421 if (!string || !maxlen) { 1422 register_device_error(dev, "Zero buffer/length"); 1423 return -1; 1424 } 1425 1426 struct hid_device_info *info = hid_get_device_info(dev); 1427 if (!info) { 1428 // hid_get_device_info will have set an error already 1429 return -1; 1430 } 1431 1432 if (info->product_string) { 1433 wcsncpy(string, info->product_string, maxlen); 1434 string[maxlen - 1] = L'\0'; 1435 } 1436 else { 1437 string[0] = L'\0'; 1438 } 1439 1440 return 0; 1441} 1442 1443int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) 1444{ 1445 if (!string || !maxlen) { 1446 register_device_error(dev, "Zero buffer/length"); 1447 return -1; 1448 } 1449 1450 struct hid_device_info *info = hid_get_device_info(dev); 1451 if (!info) { 1452 // hid_get_device_info will have set an error already 1453 return -1; 1454 } 1455 1456 if (info->serial_number) { 1457 wcsncpy(string, info->serial_number, maxlen); 1458 string[maxlen - 1] = L'\0'; 1459 } 1460 else { 1461 string[0] = L'\0'; 1462 } 1463 1464 return 0; 1465} 1466 1467 1468HID_API_EXPORT struct hid_device_info *HID_API_CALL hid_get_device_info(hid_device *dev) { 1469 if (!dev->device_info) { 1470 // Lazy initialize device_info 1471 dev->device_info = create_device_info_for_hid_device(dev); 1472 } 1473 1474 // create_device_info_for_hid_device will set an error if needed 1475 return dev->device_info; 1476} 1477 1478int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) 1479{ 1480 (void)string_index; 1481 (void)string; 1482 (void)maxlen; 1483 1484 register_device_error(dev, "hid_get_indexed_string: not supported by hidraw"); 1485 1486 return -1; 1487} 1488 1489 1490int HID_API_EXPORT_CALL hid_get_report_descriptor(hid_device *dev, unsigned char *buf, size_t buf_size) 1491{ 1492 struct hidraw_report_descriptor rpt_desc; 1493 int res = get_hid_report_descriptor_from_hidraw(dev, &rpt_desc); 1494 if (res < 0) { 1495 /* error already registered */ 1496 return res; 1497 } 1498 1499 if (rpt_desc.size < buf_size) { 1500 buf_size = (size_t) rpt_desc.size; 1501 } 1502 1503 memcpy(buf, rpt_desc.value, buf_size); 1504 1505 return (int) buf_size; 1506} 1507 1508 1509/* Passing in NULL means asking for the last global error message. */ 1510HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) 1511{ 1512 if (dev) { 1513 if (dev->last_error_str == NULL) 1514 return L"Success"; 1515 return dev->last_error_str; 1516 } 1517 1518 if (last_global_error_str == NULL) 1519 return L"Success"; 1520 return last_global_error_str; 1521} 1522[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.