Atlas - hid.c

Home / ext / SDL2 / src / hidapi / linux Lines: 8 | Size: 22185 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 Linux Version - 6/2/2009 10 11 Copyright 2009, All Rights Reserved. 12 13 At the discretion of the user of this library, 14 this software may be licensed under the terms of the 15 GNU General Public License v3, a BSD-Style license, or the 16 original HIDAPI license as outlined in the LICENSE.txt, 17 LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt 18 files located at the root of the source distribution. 19 These files may also be found in the public source 20 code repository located at: 21 http://github.com/signal11/hidapi . 22********************************************************/ 23 24#ifndef _GNU_SOURCE 25#define _GNU_SOURCE /* needed for wcsdup() before glibc 2.10 */ 26#endif 27 28/* C */ 29#include <stdio.h> 30#include <string.h> 31#include <stdlib.h> 32#include <locale.h> 33#include <errno.h> 34 35/* Unix */ 36#include <unistd.h> 37#include <sys/types.h> 38#include <sys/stat.h> 39#include <sys/ioctl.h> 40#include <sys/utsname.h> 41#include <fcntl.h> 42#include <poll.h> 43 44/* Linux */ 45#include <linux/hidraw.h> 46#include <linux/version.h> 47#include <linux/input.h> 48#include <libudev.h> 49 50#include "hidapi.h" 51 52#ifdef NAMESPACE 53namespace NAMESPACE 54{ 55#endif 56 57/* Definitions from linux/hidraw.h. Since these are new, some distros 58 may not have header files which contain them. */ 59#ifndef HIDIOCSFEATURE 60#define HIDIOCSFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len) 61#endif 62#ifndef HIDIOCGFEATURE 63#define HIDIOCGFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x07, len) 64#endif 65 66/* USB HID device property names */ 67const char *device_string_names[] = { 68 "manufacturer", 69 "product", 70 "serial", 71}; 72 73/* Symbolic names for the properties above */ 74enum device_string_id { 75 DEVICE_STRING_MANUFACTURER, 76 DEVICE_STRING_PRODUCT, 77 DEVICE_STRING_SERIAL, 78 79 DEVICE_STRING_COUNT, 80}; 81 82struct hid_device_ { 83 int device_handle; 84 int blocking; 85 int uses_numbered_reports; 86 int is_bluetooth; 87}; 88 89 90static __u32 kernel_version = 0; 91 92static __u32 detect_kernel_version(void) 93{ 94 struct utsname name; 95 int major, minor, release; 96 int ret; 97 98 uname(&name); 99 ret = sscanf(name.release, "%d.%d.%d", &major, &minor, &release); 100 if (ret == 3) { 101 return KERNEL_VERSION(major, minor, release); 102 } 103 104 ret = sscanf(name.release, "%d.%d", &major, &minor); 105 if (ret == 2) { 106 return KERNEL_VERSION(major, minor, 0); 107 } 108 109 printf("Couldn't determine kernel version from version string \"%s\"\n", name.release); 110 return 0; 111} 112 113static hid_device *new_hid_device(void) 114{ 115 hid_device *dev = (hid_device *)calloc(1, sizeof(hid_device)); 116 dev->device_handle = -1; 117 dev->blocking = 1; 118 dev->uses_numbered_reports = 0; 119 dev->is_bluetooth = 0; 120 121 return dev; 122} 123 124 125/* The caller must free the returned string with free(). */ 126static wchar_t *utf8_to_wchar_t(const char *utf8) 127{ 128 wchar_t *ret = NULL; 129 130 if (utf8) { 131 size_t wlen = mbstowcs(NULL, utf8, 0); 132 if ((size_t) -1 == wlen) { 133 return wcsdup(L""); 134 } 135 ret = (wchar_t *)calloc(wlen+1, sizeof(wchar_t)); 136 mbstowcs(ret, utf8, wlen+1); 137 ret[wlen] = 0x0000; 138 } 139 140 return ret; 141} 142 143/* Get an attribute value from a udev_device and return it as a whar_t 144 string. The returned string must be freed with free() when done.*/ 145static wchar_t *copy_udev_string(struct udev_device *dev, const char *udev_name) 146{ 147 return utf8_to_wchar_t(udev_device_get_sysattr_value(dev, udev_name)); 148} 149 150/* uses_numbered_reports() returns 1 if report_descriptor describes a device 151 which contains numbered reports. */ 152static int uses_numbered_reports(__u8 *report_descriptor, __u32 size) { 153 unsigned int i = 0; 154 int size_code; 155 int data_len, key_size; 156 157 while (i < size) { 158 int key = report_descriptor[i]; 159 160 /* Check for the Report ID key */ 161 if (key == 0x85/*Report ID*/) { 162 /* This device has a Report ID, which means it uses 163 numbered reports. */ 164 return 1; 165 } 166 167 //printf("key: %02hhx\n", key); 168 169 if ((key & 0xf0) == 0xf0) { 170 /* This is a Long Item. The next byte contains the 171 length of the data section (value) for this key. 172 See the HID specification, version 1.11, section 173 6.2.2.3, titled "Long Items." */ 174 if (i+1 < size) 175 data_len = report_descriptor[i+1]; 176 else 177 data_len = 0; /* malformed report */ 178 key_size = 3; 179 } 180 else { 181 /* This is a Short Item. The bottom two bits of the 182 key contain the size code for the data section 183 (value) for this key. Refer to the HID 184 specification, version 1.11, section 6.2.2.2, 185 titled "Short Items." */ 186 size_code = key & 0x3; 187 switch (size_code) { 188 case 0: 189 case 1: 190 case 2: 191 data_len = size_code; 192 break; 193 case 3: 194 data_len = 4; 195 break; 196 default: 197 /* Can't ever happen since size_code is & 0x3 */ 198 data_len = 0; 199 break; 200 }; 201 key_size = 1; 202 } 203 204 /* Skip over this key and it's associated data */ 205 i += data_len + key_size; 206 } 207 208 /* Didn't find a Report ID key. Device doesn't use numbered reports. */ 209 return 0; 210} 211 212/* 213 * The caller is responsible for free()ing the (newly-allocated) character 214 * strings pointed to by serial_number_utf8 and product_name_utf8 after use. 215 */ 216static int 217parse_uevent_info(const char *uevent, int *bus_type, 218 unsigned short *vendor_id, unsigned short *product_id, 219 char **serial_number_utf8, char **product_name_utf8) 220{ 221 char *tmp = strdup(uevent); 222 char *saveptr = NULL; 223 char *line; 224 char *key; 225 char *value; 226 227 int found_id = 0; 228 int found_serial = 0; 229 int found_name = 0; 230 231 line = strtok_r(tmp, "\n", &saveptr); 232 while (line != NULL) { 233 /* line: "KEY=value" */ 234 key = line; 235 value = strchr(line, '='); 236 if (!value) { 237 goto next_line; 238 } 239 *value = '\0'; 240 value++; 241 242 if (strcmp(key, "HID_ID") == 0) { 243 /** 244 * type vendor product 245 * HID_ID=0003:000005AC:00008242 246 **/ 247 int ret = sscanf(value, "%x:%hx:%hx", bus_type, vendor_id, product_id); 248 if (ret == 3) { 249 found_id = 1; 250 } 251 } else if (strcmp(key, "HID_NAME") == 0) { 252 /* The caller has to free the product name */ 253 *product_name_utf8 = strdup(value); 254 found_name = 1; 255 } else if (strcmp(key, "HID_UNIQ") == 0) { 256 /* The caller has to free the serial number */ 257 *serial_number_utf8 = strdup(value); 258 found_serial = 1; 259 } 260 261next_line: 262 line = strtok_r(NULL, "\n", &saveptr); 263 } 264 265 free(tmp); 266 return (found_id && found_name && found_serial); 267} 268 269static int is_bluetooth(hid_device *dev) 270{ 271 struct udev *udev; 272 struct udev_device *udev_dev, *hid_dev; 273 struct stat s; 274 int ret = -1; 275 276 /* Create the udev object */ 277 udev = udev_new(); 278 if (!udev) { 279 printf("Can't create udev\n"); 280 return -1; 281 } 282 283 /* Get the dev_t (major/minor numbers) from the file handle. */ 284 ret = fstat(dev->device_handle, &s); 285 if (-1 == ret) { 286 udev_unref(udev); 287 return ret; 288 } 289 290 /* Open a udev device from the dev_t. 'c' means character device. */ 291 udev_dev = udev_device_new_from_devnum(udev, 'c', s.st_rdev); 292 if (udev_dev) { 293 hid_dev = udev_device_get_parent_with_subsystem_devtype( 294 udev_dev, 295 "hid", 296 NULL); 297 if (hid_dev) { 298 unsigned short dev_vid; 299 unsigned short dev_pid; 300 int bus_type; 301 char *serial_number_utf8 = NULL; 302 char *product_name_utf8 = NULL; 303 304 ret = parse_uevent_info( 305 udev_device_get_sysattr_value(hid_dev, "uevent"), 306 &bus_type, 307 &dev_vid, 308 &dev_pid, 309 &serial_number_utf8, 310 &product_name_utf8); 311 free(serial_number_utf8); 312 free(product_name_utf8); 313 314 ret = (bus_type == BUS_BLUETOOTH); 315 316 /* hid_dev doesn't need to be (and can't be) unref'd. 317 I'm not sure why, but it'll throw double-free() errors. */ 318 } 319 udev_device_unref(udev_dev); 320 } 321 322 udev_unref(udev); 323 324 return ret; 325} 326 327 328static int get_device_string(hid_device *dev, enum device_string_id key, wchar_t *string, size_t maxlen) 329{ 330 struct udev *udev; 331 struct udev_device *udev_dev, *parent, *hid_dev; 332 struct stat s; 333 int ret = -1; 334 char *serial_number_utf8 = NULL; 335 char *product_name_utf8 = NULL; 336 char *tmp; 337 338 /* Create the udev object */ 339 udev = udev_new(); 340 if (!udev) { 341 printf("Can't create udev\n"); 342 return -1; 343 } 344 345 /* Get the dev_t (major/minor numbers) from the file handle. */ 346 ret = fstat(dev->device_handle, &s); 347 if (-1 == ret) { 348 udev_unref(udev); 349 return ret; 350 } 351 /* Open a udev device from the dev_t. 'c' means character device. */ 352 udev_dev = udev_device_new_from_devnum(udev, 'c', s.st_rdev); 353 if (udev_dev) { 354 hid_dev = udev_device_get_parent_with_subsystem_devtype( 355 udev_dev, 356 "hid", 357 NULL); 358 if (hid_dev) { 359 unsigned short dev_vid; 360 unsigned short dev_pid; 361 int bus_type; 362 size_t retm; 363 364 ret = parse_uevent_info( 365 udev_device_get_sysattr_value(hid_dev, "uevent"), 366 &bus_type, 367 &dev_vid, 368 &dev_pid, 369 &serial_number_utf8, 370 &product_name_utf8); 371 372 if (bus_type == BUS_BLUETOOTH) { 373 switch (key) { 374 case DEVICE_STRING_MANUFACTURER: 375 wcsncpy(string, L"", maxlen); 376 ret = 0; 377 break; 378 case DEVICE_STRING_PRODUCT: 379 retm = mbstowcs(string, product_name_utf8, maxlen); 380 ret = (retm == (size_t)-1)? -1: 0; 381 break; 382 case DEVICE_STRING_SERIAL: 383 /* Bluetooth serial numbers are often the bluetooth device address 384 and we want that with the colons stripped out, which is the correct 385 serial number for PS4 controllers 386 */ 387 while ((tmp = strchr(serial_number_utf8, ':')) != NULL) { 388 memmove(tmp, tmp+1, strlen(tmp)); 389 } 390 retm = mbstowcs(string, serial_number_utf8, maxlen); 391 ret = (retm == (size_t)-1)? -1: 0; 392 break; 393 case DEVICE_STRING_COUNT: 394 default: 395 ret = -1; 396 break; 397 } 398 } 399 else { 400 /* This is a USB device. Find its parent USB Device node. */ 401 parent = udev_device_get_parent_with_subsystem_devtype( 402 udev_dev, 403 "usb", 404 "usb_device"); 405 if (parent) { 406 const char *str; 407 const char *key_str = NULL; 408 409 if (key >= 0 && key < DEVICE_STRING_COUNT) { 410 key_str = device_string_names[key]; 411 } else { 412 ret = -1; 413 goto end; 414 } 415 416 str = udev_device_get_sysattr_value(parent, key_str); 417 if (str) { 418 /* Convert the string from UTF-8 to wchar_t */ 419 retm = mbstowcs(string, str, maxlen); 420 ret = (retm == (size_t)-1)? -1: 0; 421 goto end; 422 } 423 } 424 } 425 } 426 } 427 428end: 429 free(serial_number_utf8); 430 free(product_name_utf8); 431 432 udev_device_unref(udev_dev); 433 /* parent and hid_dev don't need to be (and can't be) unref'd. 434 I'm not sure why, but they'll throw double-free() errors. */ 435 udev_unref(udev); 436 437 return ret; 438} 439 440int HID_API_EXPORT hid_init(void) 441{ 442 const char *locale; 443 444 /* Set the locale if it's not set. */ 445 locale = setlocale(LC_CTYPE, NULL); 446 if (!locale) 447 setlocale(LC_CTYPE, ""); 448 449 kernel_version = detect_kernel_version(); 450 451 return 0; 452} 453 454int HID_API_EXPORT hid_exit(void) 455{ 456 /* Nothing to do for this in the Linux/hidraw implementation. */ 457 return 0; 458} 459 460 461struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id) 462{ 463 struct udev *udev; 464 struct udev_enumerate *enumerate; 465 struct udev_list_entry *devices, *dev_list_entry; 466 467 struct hid_device_info *root = NULL; /* return object */ 468 struct hid_device_info *cur_dev = NULL; 469 struct hid_device_info *prev_dev = NULL; /* previous device */ 470 471 hid_init(); 472 473 /* Create the udev object */ 474 udev = udev_new(); 475 if (!udev) { 476 printf("Can't create udev\n"); 477 return NULL; 478 } 479 480 /* Create a list of the devices in the 'hidraw' subsystem. */ 481 enumerate = udev_enumerate_new(udev); 482 udev_enumerate_add_match_subsystem(enumerate, "hidraw"); 483 udev_enumerate_scan_devices(enumerate); 484 devices = udev_enumerate_get_list_entry(enumerate); 485 /* For each item, see if it matches the vid/pid, and if so 486 create a udev_device record for it */ 487 udev_list_entry_foreach(dev_list_entry, devices) { 488 const char *sysfs_path; 489 const char *dev_path; 490 const char *str; 491 struct udev_device *raw_dev; /* The device's hidraw udev node. */ 492 struct udev_device *hid_dev; /* The device's HID udev node. */ 493 struct udev_device *usb_dev; /* The device's USB udev node. */ 494 struct udev_device *intf_dev; /* The device's interface (in the USB sense). */ 495 unsigned short dev_vid; 496 unsigned short dev_pid; 497 char *serial_number_utf8 = NULL; 498 char *product_name_utf8 = NULL; 499 int bus_type; 500 int result; 501 502 /* Get the filename of the /sys entry for the device 503 and create a udev_device object (dev) representing it */ 504 sysfs_path = udev_list_entry_get_name(dev_list_entry); 505 raw_dev = udev_device_new_from_syspath(udev, sysfs_path); 506 dev_path = udev_device_get_devnode(raw_dev); 507 508 hid_dev = udev_device_get_parent_with_subsystem_devtype( 509 raw_dev, 510 "hid", 511 NULL); 512 513 if (!hid_dev) { 514 /* Unable to find parent hid device. */ 515 goto next; 516 } 517 518 result = parse_uevent_info( 519 udev_device_get_sysattr_value(hid_dev, "uevent"), 520 &bus_type, 521 &dev_vid, 522 &dev_pid, 523 &serial_number_utf8, 524 &product_name_utf8); 525 526 if (!result) { 527 /* parse_uevent_info() failed for at least one field. */ 528 goto next; 529 } 530 531 if (bus_type != BUS_USB && bus_type != BUS_BLUETOOTH) { 532 /* We only know how to handle USB and BT devices. */ 533 goto next; 534 } 535 536 if (access(dev_path, R_OK|W_OK) != 0) { 537 /* We can't open this device, ignore it */ 538 goto next; 539 } 540 541 /* Check the VID/PID against the arguments */ 542 if ((vendor_id == 0x0 || vendor_id == dev_vid) && 543 (product_id == 0x0 || product_id == dev_pid)) { 544 struct hid_device_info *tmp; 545 546 /* VID/PID match. Create the record. */ 547 tmp = (struct hid_device_info *)malloc(sizeof(struct hid_device_info)); 548 if (cur_dev) { 549 cur_dev->next = tmp; 550 } 551 else { 552 root = tmp; 553 } 554 prev_dev = cur_dev; 555 cur_dev = tmp; 556 557 /* Fill out the record */ 558 cur_dev->next = NULL; 559 cur_dev->path = dev_path? strdup(dev_path): NULL; 560 561 /* VID/PID */ 562 cur_dev->vendor_id = dev_vid; 563 cur_dev->product_id = dev_pid; 564 565 /* Serial Number */ 566 cur_dev->serial_number = utf8_to_wchar_t(serial_number_utf8); 567 568 /* Release Number */ 569 cur_dev->release_number = 0x0; 570 571 /* Interface Number */ 572 cur_dev->interface_number = -1; 573 574 switch (bus_type) { 575 case BUS_USB: 576 /* The device pointed to by raw_dev contains information about 577 the hidraw device. In order to get information about the 578 USB device, get the parent device with the 579 subsystem/devtype pair of "usb"/"usb_device". This will 580 be several levels up the tree, but the function will find 581 it. */ 582 usb_dev = udev_device_get_parent_with_subsystem_devtype( 583 raw_dev, 584 "usb", 585 "usb_device"); 586 587 if (!usb_dev) { 588 /* Free this device */ 589 free(cur_dev->serial_number); 590 free(cur_dev->path); 591 free(cur_dev); 592 593 /* Take it off the device list. */ 594 if (prev_dev) { 595 prev_dev->next = NULL; 596 cur_dev = prev_dev; 597 } 598 else { 599 cur_dev = root = NULL; 600 } 601 602 goto next; 603 } 604 605 /* Manufacturer and Product strings */ 606 cur_dev->manufacturer_string = copy_udev_string(usb_dev, device_string_names[DEVICE_STRING_MANUFACTURER]); 607 cur_dev->product_string = copy_udev_string(usb_dev, device_string_names[DEVICE_STRING_PRODUCT]); 608 609 /* Release Number */ 610 str = udev_device_get_sysattr_value(usb_dev, "bcdDevice"); 611 cur_dev->release_number = (str)? strtol(str, NULL, 16): 0x0; 612 613 /* Get a handle to the interface's udev node. */ 614 intf_dev = udev_device_get_parent_with_subsystem_devtype( 615 raw_dev, 616 "usb", 617 "usb_interface"); 618 if (intf_dev) { 619 str = udev_device_get_sysattr_value(intf_dev, "bInterfaceNumber"); 620 cur_dev->interface_number = (str)? strtol(str, NULL, 16): -1; 621 } 622 623 break; 624 625 case BUS_BLUETOOTH: 626 /* Manufacturer and Product strings */ 627 cur_dev->manufacturer_string = wcsdup(L""); 628 cur_dev->product_string = utf8_to_wchar_t(product_name_utf8); 629 630 break; 631 632 default: 633 /* Unknown device type - this should never happen, as we 634 * check for USB and Bluetooth devices above */ 635 break; 636 } 637 } 638 639 next: 640 free(serial_number_utf8); 641 free(product_name_utf8); 642 udev_device_unref(raw_dev); 643 /* hid_dev, usb_dev and intf_dev don't need to be (and can't be) 644 unref()d. It will cause a double-free() error. I'm not 645 sure why. */ 646 } 647 /* Free the enumerator and udev objects. */ 648 udev_enumerate_unref(enumerate); 649 udev_unref(udev); 650 651 return root; 652} 653 654void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs) 655{ 656 struct hid_device_info *d = devs; 657 while (d) { 658 struct hid_device_info *next = d->next; 659 free(d->path); 660 free(d->serial_number); 661 free(d->manufacturer_string); 662 free(d->product_string); 663 free(d); 664 d = next; 665 } 666} 667 668hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) 669{ 670 struct hid_device_info *devs, *cur_dev; 671 const char *path_to_open = NULL; 672 hid_device *handle = NULL; 673 674 devs = hid_enumerate(vendor_id, product_id); 675 cur_dev = devs; 676 while (cur_dev) { 677 if (cur_dev->vendor_id == vendor_id && 678 cur_dev->product_id == product_id) { 679 if (serial_number) { 680 if (wcscmp(serial_number, cur_dev->serial_number) == 0) { 681 path_to_open = cur_dev->path; 682 break; 683 } 684 } 685 else { 686 path_to_open = cur_dev->path; 687 break; 688 } 689 } 690 cur_dev = cur_dev->next; 691 } 692 693 if (path_to_open) { 694 /* Open the device */ 695 handle = hid_open_path(path_to_open, 0); 696 } 697 698 hid_free_enumeration(devs); 699 700 return handle; 701} 702 703hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive) 704{ 705 hid_device *dev = NULL; 706 707 hid_init(); 708 709 dev = new_hid_device(); 710 711 /* OPEN HERE */ 712 dev->device_handle = open(path, O_RDWR); 713 714 /* If we have a good handle, return it. */ 715 if (dev->device_handle > 0) { 716 717 /* Get the report descriptor */ 718 int res, desc_size = 0; 719 struct hidraw_report_descriptor rpt_desc; 720 721 memset(&rpt_desc, 0x0, sizeof(rpt_desc)); 722 723 /* Get Report Descriptor Size */ 724 res = ioctl(dev->device_handle, HIDIOCGRDESCSIZE, &desc_size); 725 if (res < 0) 726 perror("HIDIOCGRDESCSIZE"); 727 728 729 /* Get Report Descriptor */ 730 rpt_desc.size = desc_size; 731 res = ioctl(dev->device_handle, HIDIOCGRDESC, &rpt_desc); 732 if (res < 0) { 733 perror("HIDIOCGRDESC"); 734 } else { 735 /* Determine if this device uses numbered reports. */ 736 dev->uses_numbered_reports = 737 uses_numbered_reports(rpt_desc.value, 738 rpt_desc.size); 739 } 740 741 dev->is_bluetooth = (is_bluetooth(dev) == 1); 742 743 return dev; 744 } 745 else { 746 /* Unable to open any devices. */ 747 free(dev); 748 return NULL; 749 } 750} 751 752 753int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length) 754{ 755 int bytes_written; 756 757 bytes_written = write(dev->device_handle, data, length); 758 759 return bytes_written; 760} 761 762 763int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) 764{ 765 int bytes_read; 766 767 if (milliseconds >= 0) { 768 /* Milliseconds is either 0 (non-blocking) or > 0 (contains 769 a valid timeout). In both cases we want to call poll() 770 and wait for data to arrive. Don't rely on non-blocking 771 operation (O_NONBLOCK) since some kernels don't seem to 772 properly report device disconnection through read() when 773 in non-blocking mode. */ 774 int ret; 775 struct pollfd fds; 776 777 fds.fd = dev->device_handle; 778 fds.events = POLLIN; 779 fds.revents = 0; 780 ret = poll(&fds, 1, milliseconds); 781 if (ret == -1 || ret == 0) { 782 /* Error or timeout */ 783 return ret; 784 } 785 else { 786 /* Check for errors on the file descriptor. This will 787 indicate a device disconnection. */ 788 if (fds.revents & (POLLERR | POLLHUP | POLLNVAL)) 789 return -1; 790 } 791 } 792 793 bytes_read = read(dev->device_handle, data, length); 794 if (bytes_read < 0 && (errno == EAGAIN || errno == EINPROGRESS)) 795 bytes_read = 0; 796 797 if (bytes_read >= 0 && 798 kernel_version != 0 && 799 kernel_version < KERNEL_VERSION(2,6,34) && 800 dev->uses_numbered_reports) { 801 /* Work around a kernel bug. Chop off the first byte. */ 802 memmove(data, data+1, bytes_read); 803 bytes_read--; 804 } 805 806 return bytes_read; 807} 808 809int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length) 810{ 811 return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0); 812} 813 814int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock) 815{ 816 /* Do all non-blocking in userspace using poll(), since it looks 817 like there's a bug in the kernel in some versions where 818 read() will not return -1 on disconnection of the USB device */ 819 820 dev->blocking = !nonblock; 821 return 0; /* Success */ 822} 823 824 825int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) 826{ 827 int res; 828 829 res = ioctl(dev->device_handle, HIDIOCSFEATURE(length), data); 830 if (res < 0) 831 perror("ioctl (SFEATURE)"); 832 833 return res; 834} 835 836int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) 837{ 838 int res; 839 840 /* It looks like HIDIOCGFEATURE() on Bluetooth devices doesn't return the report number */ 841 if (dev->is_bluetooth) { 842 data[1] = data[0]; 843 ++data; 844 --length; 845 } 846 res = ioctl(dev->device_handle, HIDIOCGFEATURE(length), data); 847 if (res < 0) 848 perror("ioctl (GFEATURE)"); 849 else if (dev->is_bluetooth) 850 ++res; 851 852 return res; 853} 854 855 856void HID_API_EXPORT hid_close(hid_device *dev) 857{ 858 if (!dev) 859 return; 860 close(dev->device_handle); 861 free(dev); 862} 863 864 865int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) 866{ 867 return get_device_string(dev, DEVICE_STRING_MANUFACTURER, string, maxlen); 868} 869 870int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) 871{ 872 return get_device_string(dev, DEVICE_STRING_PRODUCT, string, maxlen); 873} 874 875int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) 876{ 877 return get_device_string(dev, DEVICE_STRING_SERIAL, string, maxlen); 878} 879 880int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) 881{ 882 return -1; 883} 884 885 886HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) 887{ 888 return NULL; 889} 890 891#ifdef NAMESPACE 892} 893#endif 894
[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.