Atlas - hid.c

Home / ext / SDL2 / src / hidapi / libusb Lines: 18 | Size: 43672 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/2010 10 Libusb Version - 8/13/2010 11 FreeBSD Version - 11/1/2011 12 13 Copyright 2009, All Rights Reserved. 14 15 At the discretion of the user of this library, 16 this software may be licensed under the terms of the 17 GNU General Public License v3, a BSD-Style license, or the 18 original HIDAPI license as outlined in the LICENSE.txt, 19 LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt 20 files located at the root of the source distribution. 21 These files may also be found in the public source 22 code repository located at: 23 http://github.com/signal11/hidapi . 24********************************************************/ 25 26#ifndef _GNU_SOURCE 27#define _GNU_SOURCE /* needed for wcsdup() before glibc 2.10 */ 28#endif 29 30/* C */ 31#include <stdio.h> 32#include <string.h> 33#include <stdlib.h> 34#include <ctype.h> 35#include <locale.h> 36#include <errno.h> 37 38/* Unix */ 39#include <unistd.h> 40#include <sys/types.h> 41#include <sys/stat.h> 42#include <sys/ioctl.h> 43#include <sys/utsname.h> 44#include <fcntl.h> 45#include <pthread.h> 46#include <wchar.h> 47 48/* GNU / LibUSB */ 49#include <libusb.h> 50#ifndef __ANDROID__ 51#include <iconv.h> 52#endif 53 54#include "hidapi.h" 55 56#ifdef NAMESPACE 57namespace NAMESPACE 58{ 59#endif 60 61#ifdef __ANDROID__ 62 63/* Barrier implementation because Android/Bionic don't have pthread_barrier. 64 This implementation came from Brent Priddy and was posted on 65 StackOverflow. It is used with his permission. */ 66typedef int pthread_barrierattr_t; 67typedef struct pthread_barrier { 68 pthread_mutex_t mutex; 69 pthread_cond_t cond; 70 int count; 71 int trip_count; 72} pthread_barrier_t; 73 74static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count) 75{ 76 if(count == 0) { 77 errno = EINVAL; 78 return -1; 79 } 80 81 if(pthread_mutex_init(&barrier->mutex, 0) < 0) { 82 return -1; 83 } 84 if(pthread_cond_init(&barrier->cond, 0) < 0) { 85 pthread_mutex_destroy(&barrier->mutex); 86 return -1; 87 } 88 barrier->trip_count = count; 89 barrier->count = 0; 90 91 return 0; 92} 93 94static int pthread_barrier_destroy(pthread_barrier_t *barrier) 95{ 96 pthread_cond_destroy(&barrier->cond); 97 pthread_mutex_destroy(&barrier->mutex); 98 return 0; 99} 100 101static int pthread_barrier_wait(pthread_barrier_t *barrier) 102{ 103 pthread_mutex_lock(&barrier->mutex); 104 ++(barrier->count); 105 if(barrier->count >= barrier->trip_count) 106 { 107 barrier->count = 0; 108 pthread_cond_broadcast(&barrier->cond); 109 pthread_mutex_unlock(&barrier->mutex); 110 return 1; 111 } 112 else 113 { 114 pthread_cond_wait(&barrier->cond, &(barrier->mutex)); 115 pthread_mutex_unlock(&barrier->mutex); 116 return 0; 117 } 118} 119 120#endif 121 122#if defined(__cplusplus) && !defined(NAMESPACE) 123extern "C" { 124#endif 125 126#ifdef DEBUG_PRINTF 127#define LOG(...) fprintf(stderr, __VA_ARGS__) 128#else 129#define LOG(...) do {} while (0) 130#endif 131 132#ifndef __FreeBSD__ 133#define DETACH_KERNEL_DRIVER 134#endif 135 136/* Uncomment to enable the retrieval of Usage and Usage Page in 137hid_enumerate(). Warning, on platforms different from FreeBSD 138this is very invasive as it requires the detach 139and re-attach of the kernel driver. See comments inside hid_enumerate(). 140libusb HIDAPI programs are encouraged to use the interface number 141instead to differentiate between interfaces on a composite HID device. */ 142/*#define INVASIVE_GET_USAGE*/ 143 144/* Linked List of input reports received from the device. */ 145struct input_report { 146 uint8_t *data; 147 size_t len; 148 struct input_report *next; 149}; 150 151 152struct hid_device_ { 153 /* Handle to the actual device. */ 154 libusb_device_handle *device_handle; 155 156 /* Endpoint information */ 157 int input_endpoint; 158 int output_endpoint; 159 int input_ep_max_packet_size; 160 161 /* The interface number of the HID */ 162 int interface; 163 164 /* Indexes of Strings */ 165 int manufacturer_index; 166 int product_index; 167 int serial_index; 168 169 /* Whether blocking reads are used */ 170 int blocking; /* boolean */ 171 172 /* Read thread objects */ 173 pthread_t thread; 174 pthread_mutex_t mutex; /* Protects input_reports */ 175 pthread_cond_t condition; 176 pthread_barrier_t barrier; /* Ensures correct startup sequence */ 177 int shutdown_thread; 178 int cancelled; 179 struct libusb_transfer *transfer; 180 181 /* List of received input reports. */ 182 struct input_report *input_reports; 183}; 184 185static libusb_context *usb_context = NULL; 186 187uint16_t get_usb_code_for_current_locale(void); 188static int return_data(hid_device *dev, unsigned char *data, size_t length); 189 190static hid_device *new_hid_device(void) 191{ 192 hid_device *dev = (hid_device *)calloc(1, sizeof(hid_device)); 193 dev->blocking = 1; 194 195 pthread_mutex_init(&dev->mutex, NULL); 196 pthread_cond_init(&dev->condition, NULL); 197 pthread_barrier_init(&dev->barrier, NULL, 2); 198 199 return dev; 200} 201 202static void free_hid_device(hid_device *dev) 203{ 204 /* Clean up the thread objects */ 205 pthread_barrier_destroy(&dev->barrier); 206 pthread_cond_destroy(&dev->condition); 207 pthread_mutex_destroy(&dev->mutex); 208 209 /* Free the device itself */ 210 free(dev); 211} 212 213#if 0 214/*TODO: Implement this funciton on hidapi/libusb.. */ 215static void register_error(hid_device *device, const char *op) 216{ 217 218} 219#endif 220 221#ifdef INVASIVE_GET_USAGE 222/* Get bytes from a HID Report Descriptor. 223 Only call with a num_bytes of 0, 1, 2, or 4. */ 224static uint32_t get_bytes(uint8_t *rpt, size_t len, size_t num_bytes, size_t cur) 225{ 226 /* Return if there aren't enough bytes. */ 227 if (cur + num_bytes >= len) 228 return 0; 229 230 if (num_bytes == 0) 231 return 0; 232 else if (num_bytes == 1) { 233 return rpt[cur+1]; 234 } 235 else if (num_bytes == 2) { 236 return (rpt[cur+2] * 256 + rpt[cur+1]); 237 } 238 else if (num_bytes == 4) { 239 return (rpt[cur+4] * 0x01000000 + 240 rpt[cur+3] * 0x00010000 + 241 rpt[cur+2] * 0x00000100 + 242 rpt[cur+1] * 0x00000001); 243 } 244 else 245 return 0; 246} 247 248/* Retrieves the device's Usage Page and Usage from the report 249 descriptor. The algorithm is simple, as it just returns the first 250 Usage and Usage Page that it finds in the descriptor. 251 The return value is 0 on success and -1 on failure. */ 252static int get_usage(uint8_t *report_descriptor, size_t size, 253 unsigned short *usage_page, unsigned short *usage) 254{ 255 unsigned int i = 0; 256 int size_code; 257 int data_len, key_size; 258 int usage_found = 0, usage_page_found = 0; 259 260 while (i < size) { 261 int key = report_descriptor[i]; 262 int key_cmd = key & 0xfc; 263 264 //printf("key: %02hhx\n", key); 265 266 if ((key & 0xf0) == 0xf0) { 267 /* This is a Long Item. The next byte contains the 268 length of the data section (value) for this key. 269 See the HID specification, version 1.11, section 270 6.2.2.3, titled "Long Items." */ 271 if (i+1 < size) 272 data_len = report_descriptor[i+1]; 273 else 274 data_len = 0; /* malformed report */ 275 key_size = 3; 276 } 277 else { 278 /* This is a Short Item. The bottom two bits of the 279 key contain the size code for the data section 280 (value) for this key. Refer to the HID 281 specification, version 1.11, section 6.2.2.2, 282 titled "Short Items." */ 283 size_code = key & 0x3; 284 switch (size_code) { 285 case 0: 286 case 1: 287 case 2: 288 data_len = size_code; 289 break; 290 case 3: 291 data_len = 4; 292 break; 293 default: 294 /* Can't ever happen since size_code is & 0x3 */ 295 data_len = 0; 296 break; 297 }; 298 key_size = 1; 299 } 300 301 if (key_cmd == 0x4) { 302 *usage_page = get_bytes(report_descriptor, size, data_len, i); 303 usage_page_found = 1; 304 //printf("Usage Page: %x\n", (uint32_t)*usage_page); 305 } 306 if (key_cmd == 0x8) { 307 *usage = get_bytes(report_descriptor, size, data_len, i); 308 usage_found = 1; 309 //printf("Usage: %x\n", (uint32_t)*usage); 310 } 311 312 if (usage_page_found && usage_found) 313 return 0; /* success */ 314 315 /* Skip over this key and it's associated data */ 316 i += data_len + key_size; 317 } 318 319 return -1; /* failure */ 320} 321#endif /* INVASIVE_GET_USAGE */ 322 323#if defined(__FreeBSD__) && __FreeBSD__ < 10 324/* The libusb version included in FreeBSD < 10 doesn't have this function. In 325 mainline libusb, it's inlined in libusb.h. This function will bear a striking 326 resemblance to that one, because there's about one way to code it. 327 328 Note that the data parameter is Unicode in UTF-16LE encoding. 329 Return value is the number of bytes in data, or LIBUSB_ERROR_*. 330 */ 331static inline int libusb_get_string_descriptor(libusb_device_handle *dev, 332 uint8_t descriptor_index, uint16_t lang_id, 333 unsigned char *data, int length) 334{ 335 return libusb_control_transfer(dev, 336 LIBUSB_ENDPOINT_IN | 0x0, /* Endpoint 0 IN */ 337 LIBUSB_REQUEST_GET_DESCRIPTOR, 338 (LIBUSB_DT_STRING << 8) | descriptor_index, 339 lang_id, data, (uint16_t) length, 1000); 340} 341 342#endif 343 344 345/* Get the first language the device says it reports. This comes from 346 USB string #0. */ 347static uint16_t get_first_language(libusb_device_handle *dev) 348{ 349 uint16_t buf[32]; 350 int len; 351 352 /* Get the string from libusb. */ 353 len = libusb_get_string_descriptor(dev, 354 0x0, /* String ID */ 355 0x0, /* Language */ 356 (unsigned char*)buf, 357 sizeof(buf)); 358 if (len < 4) 359 return 0x0; 360 361 return buf[1]; /* First two bytes are len and descriptor type. */ 362} 363 364static int is_language_supported(libusb_device_handle *dev, uint16_t lang) 365{ 366 uint16_t buf[32]; 367 int len; 368 int i; 369 370 /* Get the string from libusb. */ 371 len = libusb_get_string_descriptor(dev, 372 0x0, /* String ID */ 373 0x0, /* Language */ 374 (unsigned char*)buf, 375 sizeof(buf)); 376 if (len < 4) 377 return 0x0; 378 379 380 len /= 2; /* language IDs are two-bytes each. */ 381 /* Start at index 1 because there are two bytes of protocol data. */ 382 for (i = 1; i < len; i++) { 383 if (buf[i] == lang) 384 return 1; 385 } 386 387 return 0; 388} 389 390 391/* This function returns a newly allocated wide string containing the USB 392 device string numbered by the index. The returned string must be freed 393 by using free(). */ 394static wchar_t *get_usb_string(libusb_device_handle *dev, uint8_t idx) 395{ 396 char buf[512]; 397 int len; 398 wchar_t *str = NULL; 399 400#ifndef __ANDROID__ /* we don't use iconv on Android */ 401 wchar_t wbuf[256]; 402 /* iconv variables */ 403 iconv_t ic; 404 size_t inbytes; 405 size_t outbytes; 406 size_t res; 407#ifdef __FreeBSD__ 408 const char *inptr; 409#else 410 char *inptr; 411#endif 412 char *outptr; 413#endif 414 415 /* Determine which language to use. */ 416 uint16_t lang; 417 lang = get_usb_code_for_current_locale(); 418 if (!is_language_supported(dev, lang)) 419 lang = get_first_language(dev); 420 421 /* Get the string from libusb. */ 422 len = libusb_get_string_descriptor(dev, 423 idx, 424 lang, 425 (unsigned char*)buf, 426 sizeof(buf)); 427 if (len < 0) 428 return NULL; 429 430#ifdef __ANDROID__ 431 432 /* Bionic does not have iconv support nor wcsdup() function, so it 433 has to be done manually. The following code will only work for 434 code points that can be represented as a single UTF-16 character, 435 and will incorrectly convert any code points which require more 436 than one UTF-16 character. 437 438 Skip over the first character (2-bytes). */ 439 len -= 2; 440 str = malloc((len / 2 + 1) * sizeof(wchar_t)); 441 int i; 442 for (i = 0; i < len / 2; i++) { 443 str[i] = buf[i * 2 + 2] | (buf[i * 2 + 3] << 8); 444 } 445 str[len / 2] = 0x00000000; 446 447#else 448 449 /* buf does not need to be explicitly NULL-terminated because 450 it is only passed into iconv() which does not need it. */ 451 452 /* Initialize iconv. */ 453 ic = iconv_open("WCHAR_T", "UTF-16LE"); 454 if (ic == (iconv_t)-1) { 455 LOG("iconv_open() failed\n"); 456 return NULL; 457 } 458 459 /* Convert to native wchar_t (UTF-32 on glibc/BSD systems). 460 Skip the first character (2-bytes). */ 461 inptr = buf+2; 462 inbytes = len-2; 463 outptr = (char*) wbuf; 464 outbytes = sizeof(wbuf); 465 res = iconv(ic, &inptr, &inbytes, &outptr, &outbytes); 466 if (res == (size_t)-1) { 467 LOG("iconv() failed\n"); 468 goto err; 469 } 470 471 /* Write the terminating NULL. */ 472 wbuf[sizeof(wbuf)/sizeof(wbuf[0])-1] = 0x00000000; 473 if (outbytes >= sizeof(wbuf[0])) 474 *((wchar_t*)outptr) = 0x00000000; 475 476 /* Allocate and copy the string. */ 477 str = wcsdup(wbuf); 478 479err: 480 iconv_close(ic); 481 482#endif 483 484 return str; 485} 486 487static char *make_path(libusb_device *dev, int interface_number) 488{ 489 char str[64]; 490 snprintf(str, sizeof(str), "%04x:%04x:%02x", 491 libusb_get_bus_number(dev), 492 libusb_get_device_address(dev), 493 interface_number); 494 str[sizeof(str)-1] = '\0'; 495 496 return strdup(str); 497} 498 499 500int HID_API_EXPORT hid_init(void) 501{ 502 if (!usb_context) { 503 const char *locale; 504 505 /* Init Libusb */ 506 if (libusb_init(&usb_context)) 507 return -1; 508 509 /* Set the locale if it's not set. */ 510 locale = setlocale(LC_CTYPE, NULL); 511 if (!locale) 512 setlocale(LC_CTYPE, ""); 513 } 514 515 return 0; 516} 517 518int HID_API_EXPORT hid_exit(void) 519{ 520 if (usb_context) { 521 libusb_exit(usb_context); 522 usb_context = NULL; 523 } 524 525 return 0; 526} 527 528static int is_xbox360(unsigned short vendor_id, const struct libusb_interface_descriptor *intf_desc) 529{ 530 static const int XB360_IFACE_SUBCLASS = 93; 531 static const int XB360_IFACE_PROTOCOL = 1; /* Wired only */ 532 static const int SUPPORTED_VENDORS[] = { 533 0x0079, /* GPD Win 2 */ 534 0x044f, /* Thrustmaster */ 535 0x045e, /* Microsoft */ 536 0x046d, /* Logitech */ 537 0x056e, /* Elecom */ 538 0x06a3, /* Saitek */ 539 0x0738, /* Mad Catz */ 540 0x07ff, /* Mad Catz */ 541 0x0e6f, /* Unknown */ 542 0x0f0d, /* Hori */ 543 0x11c9, /* Nacon */ 544 0x12ab, /* Unknown */ 545 0x1430, /* RedOctane */ 546 0x146b, /* BigBen */ 547 0x1532, /* Razer Sabertooth */ 548 0x15e4, /* Numark */ 549 0x162e, /* Joytech */ 550 0x1689, /* Razer Onza */ 551 0x1bad, /* Harmonix */ 552 0x24c6, /* PowerA */ 553 }; 554 555 if (intf_desc->bInterfaceNumber == 0 && 556 intf_desc->bInterfaceClass == LIBUSB_CLASS_VENDOR_SPEC && 557 intf_desc->bInterfaceSubClass == XB360_IFACE_SUBCLASS && 558 intf_desc->bInterfaceProtocol == XB360_IFACE_PROTOCOL) { 559 int i; 560 for (i = 0; i < sizeof(SUPPORTED_VENDORS)/sizeof(SUPPORTED_VENDORS[0]); ++i) { 561 if (vendor_id == SUPPORTED_VENDORS[i]) { 562 return 1; 563 } 564 } 565 } 566 return 0; 567} 568 569static int is_xboxone(unsigned short vendor_id, const struct libusb_interface_descriptor *intf_desc) 570{ 571 static const int XB1_IFACE_SUBCLASS = 71; 572 static const int XB1_IFACE_PROTOCOL = 208; 573 static const int SUPPORTED_VENDORS[] = { 574 0x045e, /* Microsoft */ 575 0x0738, /* Mad Catz */ 576 0x0e6f, /* Unknown */ 577 0x0f0d, /* Hori */ 578 0x1532, /* Razer Wildcat */ 579 0x24c6, /* PowerA */ 580 }; 581 582 if (intf_desc->bInterfaceNumber == 0 && 583 intf_desc->bInterfaceClass == LIBUSB_CLASS_VENDOR_SPEC && 584 intf_desc->bInterfaceSubClass == XB1_IFACE_SUBCLASS && 585 intf_desc->bInterfaceProtocol == XB1_IFACE_PROTOCOL) { 586 int i; 587 for (i = 0; i < sizeof(SUPPORTED_VENDORS)/sizeof(SUPPORTED_VENDORS[0]); ++i) { 588 if (vendor_id == SUPPORTED_VENDORS[i]) { 589 return 1; 590 } 591 } 592 } 593 return 0; 594} 595 596static int should_enumerate_interface(unsigned short vendor_id, const struct libusb_interface_descriptor *intf_desc) 597{ 598 if (intf_desc->bInterfaceClass == LIBUSB_CLASS_HID) 599 return 1; 600 601 /* Also enumerate Xbox 360 controllers */ 602 if (is_xbox360(vendor_id, intf_desc)) 603 { 604 /* hid_write() to Xbox 360 controllers doesn't seem to work on Linux: 605 - xpad 1-2:1.0: xpad_try_sending_next_out_packet - usb_submit_urb failed with result -2 606 Xbox 360 controller support is good on Linux anyway, so we'll ignore this for now. 607 return 1; 608 */ 609 } 610 611 /* Also enumerate Xbox One controllers */ 612 if (is_xboxone(vendor_id, intf_desc)) 613 return 1; 614 615 return 0; 616} 617 618struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id) 619{ 620 libusb_device **devs; 621 libusb_device *dev; 622 libusb_device_handle *handle; 623 ssize_t num_devs; 624 int i = 0; 625 626 struct hid_device_info *root = NULL; /* return object */ 627 struct hid_device_info *cur_dev = NULL; 628 629 if(hid_init() < 0) 630 return NULL; 631 632 num_devs = libusb_get_device_list(usb_context, &devs); 633 if (num_devs < 0) 634 return NULL; 635 while ((dev = devs[i++]) != NULL) { 636 struct libusb_device_descriptor desc; 637 struct libusb_config_descriptor *conf_desc = NULL; 638 int j, k; 639 int interface_num = 0; 640 641 int res = libusb_get_device_descriptor(dev, &desc); 642 unsigned short dev_vid = desc.idVendor; 643 unsigned short dev_pid = desc.idProduct; 644 645 res = libusb_get_active_config_descriptor(dev, &conf_desc); 646 if (res < 0) 647 libusb_get_config_descriptor(dev, 0, &conf_desc); 648 if (conf_desc) { 649 for (j = 0; j < conf_desc->bNumInterfaces; j++) { 650 const struct libusb_interface *intf = &conf_desc->interface[j]; 651 for (k = 0; k < intf->num_altsetting; k++) { 652 const struct libusb_interface_descriptor *intf_desc; 653 intf_desc = &intf->altsetting[k]; 654 if (should_enumerate_interface(dev_vid, intf_desc)) { 655 interface_num = intf_desc->bInterfaceNumber; 656 657 /* Check the VID/PID against the arguments */ 658 if ((vendor_id == 0x0 || vendor_id == dev_vid) && 659 (product_id == 0x0 || product_id == dev_pid)) { 660 struct hid_device_info *tmp; 661 662 /* VID/PID match. Create the record. */ 663 tmp = (struct hid_device_info *)calloc(1, sizeof(struct hid_device_info)); 664 if (cur_dev) { 665 cur_dev->next = tmp; 666 } 667 else { 668 root = tmp; 669 } 670 cur_dev = tmp; 671 672 /* Fill out the record */ 673 cur_dev->next = NULL; 674 cur_dev->path = make_path(dev, interface_num); 675 676 res = libusb_open(dev, &handle); 677 678 if (res >= 0) { 679 /* Serial Number */ 680 if (desc.iSerialNumber > 0) 681 cur_dev->serial_number = 682 get_usb_string(handle, desc.iSerialNumber); 683 684 /* Manufacturer and Product strings */ 685 if (desc.iManufacturer > 0) 686 cur_dev->manufacturer_string = 687 get_usb_string(handle, desc.iManufacturer); 688 if (desc.iProduct > 0) 689 cur_dev->product_string = 690 get_usb_string(handle, desc.iProduct); 691 692#ifdef INVASIVE_GET_USAGE 693{ 694 /* 695 This section is removed because it is too 696 invasive on the system. Getting a Usage Page 697 and Usage requires parsing the HID Report 698 descriptor. Getting a HID Report descriptor 699 involves claiming the interface. Claiming the 700 interface involves detaching the kernel driver. 701 Detaching the kernel driver is hard on the system 702 because it will unclaim interfaces (if another 703 app has them claimed) and the re-attachment of 704 the driver will sometimes change /dev entry names. 705 It is for these reasons that this section is 706 #if 0. For composite devices, use the interface 707 field in the hid_device_info struct to distinguish 708 between interfaces. */ 709 unsigned char data[256]; 710#ifdef DETACH_KERNEL_DRIVER 711 int detached = 0; 712 /* Usage Page and Usage */ 713 res = libusb_kernel_driver_active(handle, interface_num); 714 if (res == 1) { 715 res = libusb_detach_kernel_driver(handle, interface_num); 716 if (res < 0) 717 LOG("Couldn't detach kernel driver, even though a kernel driver was attached."); 718 else 719 detached = 1; 720 } 721#endif 722 res = libusb_claim_interface(handle, interface_num); 723 if (res >= 0) { 724 /* Get the HID Report Descriptor. */ 725 res = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_RECIPIENT_INTERFACE, LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_REPORT << 8)|interface_num, 0, data, sizeof(data), 5000); 726 if (res >= 0) { 727 unsigned short page=0, usage=0; 728 /* Parse the usage and usage page 729 out of the report descriptor. */ 730 get_usage(data, res, &page, &usage); 731 cur_dev->usage_page = page; 732 cur_dev->usage = usage; 733 } 734 else 735 LOG("libusb_control_transfer() for getting the HID report failed with %d\n", res); 736 737 /* Release the interface */ 738 res = libusb_release_interface(handle, interface_num); 739 if (res < 0) 740 LOG("Can't release the interface.\n"); 741 } 742 else 743 LOG("Can't claim interface %d\n", res); 744#ifdef DETACH_KERNEL_DRIVER 745 /* Re-attach kernel driver if necessary. */ 746 if (detached) { 747 res = libusb_attach_kernel_driver(handle, interface_num); 748 if (res < 0) 749 LOG("Couldn't re-attach kernel driver.\n"); 750 } 751#endif 752} 753#endif /* INVASIVE_GET_USAGE */ 754 755 libusb_close(handle); 756 } 757 /* VID/PID */ 758 cur_dev->vendor_id = dev_vid; 759 cur_dev->product_id = dev_pid; 760 761 /* Release Number */ 762 cur_dev->release_number = desc.bcdDevice; 763 764 /* Interface Number */ 765 cur_dev->interface_number = interface_num; 766 } 767 } 768 } /* altsettings */ 769 } /* interfaces */ 770 libusb_free_config_descriptor(conf_desc); 771 } 772 } 773 774 libusb_free_device_list(devs, 1); 775 776 return root; 777} 778 779void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs) 780{ 781 struct hid_device_info *d = devs; 782 while (d) { 783 struct hid_device_info *next = d->next; 784 free(d->path); 785 free(d->serial_number); 786 free(d->manufacturer_string); 787 free(d->product_string); 788 free(d); 789 d = next; 790 } 791} 792 793hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) 794{ 795 struct hid_device_info *devs, *cur_dev; 796 const char *path_to_open = NULL; 797 hid_device *handle = NULL; 798 799 devs = hid_enumerate(vendor_id, product_id); 800 cur_dev = devs; 801 while (cur_dev) { 802 if (cur_dev->vendor_id == vendor_id && 803 cur_dev->product_id == product_id) { 804 if (serial_number) { 805 if (cur_dev->serial_number && 806 wcscmp(serial_number, cur_dev->serial_number) == 0) { 807 path_to_open = cur_dev->path; 808 break; 809 } 810 } 811 else { 812 path_to_open = cur_dev->path; 813 break; 814 } 815 } 816 cur_dev = cur_dev->next; 817 } 818 819 if (path_to_open) { 820 /* Open the device */ 821 handle = hid_open_path(path_to_open, 0); 822 } 823 824 hid_free_enumeration(devs); 825 826 return handle; 827} 828 829static void read_callback(struct libusb_transfer *transfer) 830{ 831 hid_device *dev = (hid_device *)transfer->user_data; 832 int res; 833 834 if (transfer->status == LIBUSB_TRANSFER_COMPLETED) { 835 836 struct input_report *rpt = (struct input_report *)malloc(sizeof(*rpt)); 837 rpt->data = (uint8_t *)malloc(transfer->actual_length); 838 memcpy(rpt->data, transfer->buffer, transfer->actual_length); 839 rpt->len = transfer->actual_length; 840 rpt->next = NULL; 841 842 pthread_mutex_lock(&dev->mutex); 843 844 /* Attach the new report object to the end of the list. */ 845 if (dev->input_reports == NULL) { 846 /* The list is empty. Put it at the root. */ 847 dev->input_reports = rpt; 848 pthread_cond_signal(&dev->condition); 849 } 850 else { 851 /* Find the end of the list and attach. */ 852 struct input_report *cur = dev->input_reports; 853 int num_queued = 0; 854 while (cur->next != NULL) { 855 cur = cur->next; 856 num_queued++; 857 } 858 cur->next = rpt; 859 860 /* Pop one off if we've reached 30 in the queue. This 861 way we don't grow forever if the user never reads 862 anything from the device. */ 863 if (num_queued > 30) { 864 return_data(dev, NULL, 0); 865 } 866 } 867 pthread_mutex_unlock(&dev->mutex); 868 } 869 else if (transfer->status == LIBUSB_TRANSFER_CANCELLED) { 870 dev->shutdown_thread = 1; 871 dev->cancelled = 1; 872 return; 873 } 874 else if (transfer->status == LIBUSB_TRANSFER_NO_DEVICE) { 875 dev->shutdown_thread = 1; 876 dev->cancelled = 1; 877 return; 878 } 879 else if (transfer->status == LIBUSB_TRANSFER_TIMED_OUT) { 880 //LOG("Timeout (normal)\n"); 881 } 882 else { 883 LOG("Unknown transfer code: %d\n", transfer->status); 884 } 885 886 /* Re-submit the transfer object. */ 887 res = libusb_submit_transfer(transfer); 888 if (res != 0) { 889 LOG("Unable to submit URB. libusb error code: %d\n", res); 890 dev->shutdown_thread = 1; 891 dev->cancelled = 1; 892 } 893} 894 895 896static void *read_thread(void *param) 897{ 898 hid_device *dev = (hid_device *)param; 899 unsigned char *buf; 900 const size_t length = dev->input_ep_max_packet_size; 901 902 /* Set up the transfer object. */ 903 buf = (unsigned char *)malloc(length); 904 dev->transfer = libusb_alloc_transfer(0); 905 libusb_fill_interrupt_transfer(dev->transfer, 906 dev->device_handle, 907 dev->input_endpoint, 908 buf, 909 length, 910 read_callback, 911 dev, 912 5000/*timeout*/); 913 914 /* Make the first submission. Further submissions are made 915 from inside read_callback() */ 916 libusb_submit_transfer(dev->transfer); 917 918 /* Notify the main thread that the read thread is up and running. */ 919 pthread_barrier_wait(&dev->barrier); 920 921 /* Handle all the events. */ 922 while (!dev->shutdown_thread) { 923 int res; 924 res = libusb_handle_events(usb_context); 925 if (res < 0) { 926 /* There was an error. */ 927 LOG("read_thread(): libusb reports error # %d\n", res); 928 929 /* Break out of this loop only on fatal error.*/ 930 if (res != LIBUSB_ERROR_BUSY && 931 res != LIBUSB_ERROR_TIMEOUT && 932 res != LIBUSB_ERROR_OVERFLOW && 933 res != LIBUSB_ERROR_INTERRUPTED) { 934 break; 935 } 936 } 937 } 938 939 /* Cancel any transfer that may be pending. This call will fail 940 if no transfers are pending, but that's OK. */ 941 libusb_cancel_transfer(dev->transfer); 942 943 while (!dev->cancelled) 944 libusb_handle_events_completed(usb_context, &dev->cancelled); 945 946 /* Now that the read thread is stopping, Wake any threads which are 947 waiting on data (in hid_read_timeout()). Do this under a mutex to 948 make sure that a thread which is about to go to sleep waiting on 949 the condition actually will go to sleep before the condition is 950 signaled. */ 951 pthread_mutex_lock(&dev->mutex); 952 pthread_cond_broadcast(&dev->condition); 953 pthread_mutex_unlock(&dev->mutex); 954 955 /* The dev->transfer->buffer and dev->transfer objects are cleaned up 956 in hid_close(). They are not cleaned up here because this thread 957 could end either due to a disconnect or due to a user 958 call to hid_close(). In both cases the objects can be safely 959 cleaned up after the call to pthread_join() (in hid_close()), but 960 since hid_close() calls libusb_cancel_transfer(), on these objects, 961 they can not be cleaned up here. */ 962 963 return NULL; 964} 965 966 967hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive) 968{ 969 hid_device *dev = NULL; 970 971 libusb_device **devs; 972 libusb_device *usb_dev; 973 int res; 974 int d = 0; 975 int good_open = 0; 976 977 if(hid_init() < 0) 978 return NULL; 979 980 dev = new_hid_device(); 981 982 libusb_get_device_list(usb_context, &devs); 983 while ((usb_dev = devs[d++]) != NULL) { 984 struct libusb_device_descriptor desc; 985 struct libusb_config_descriptor *conf_desc = NULL; 986 int i,j,k; 987 libusb_get_device_descriptor(usb_dev, &desc); 988 989 if (libusb_get_active_config_descriptor(usb_dev, &conf_desc) < 0) 990 continue; 991 for (j = 0; j < conf_desc->bNumInterfaces; j++) { 992 const struct libusb_interface *intf = &conf_desc->interface[j]; 993 for (k = 0; k < intf->num_altsetting; k++) { 994 const struct libusb_interface_descriptor *intf_desc; 995 intf_desc = &intf->altsetting[k]; 996 if (should_enumerate_interface(desc.idVendor, intf_desc)) { 997 char *dev_path = make_path(usb_dev, intf_desc->bInterfaceNumber); 998 if (!strcmp(dev_path, path)) { 999 /* Matched Paths. Open this device */ 1000 1001 /* OPEN HERE */ 1002 res = libusb_open(usb_dev, &dev->device_handle); 1003 if (res < 0) { 1004 LOG("can't open device\n"); 1005 free(dev_path); 1006 break; 1007 } 1008 good_open = 1; 1009#ifdef DETACH_KERNEL_DRIVER 1010 /* Detach the kernel driver, but only if the 1011 device is managed by the kernel */ 1012 if (libusb_kernel_driver_active(dev->device_handle, intf_desc->bInterfaceNumber) == 1) { 1013 res = libusb_detach_kernel_driver(dev->device_handle, intf_desc->bInterfaceNumber); 1014 if (res < 0) { 1015 libusb_close(dev->device_handle); 1016 LOG("Unable to detach Kernel Driver\n"); 1017 free(dev_path); 1018 good_open = 0; 1019 break; 1020 } 1021 } 1022#endif 1023 res = libusb_claim_interface(dev->device_handle, intf_desc->bInterfaceNumber); 1024 if (res < 0) { 1025 LOG("can't claim interface %d: %d\n", intf_desc->bInterfaceNumber, res); 1026 free(dev_path); 1027 libusb_close(dev->device_handle); 1028 good_open = 0; 1029 break; 1030 } 1031 1032 /* Store off the string descriptor indexes */ 1033 dev->manufacturer_index = desc.iManufacturer; 1034 dev->product_index = desc.iProduct; 1035 dev->serial_index = desc.iSerialNumber; 1036 1037 /* Store off the interface number */ 1038 dev->interface = intf_desc->bInterfaceNumber; 1039 1040 /* Find the INPUT and OUTPUT endpoints. An 1041 OUTPUT endpoint is not required. */ 1042 for (i = 0; i < intf_desc->bNumEndpoints; i++) { 1043 const struct libusb_endpoint_descriptor *ep 1044 = &intf_desc->endpoint[i]; 1045 1046 /* Determine the type and direction of this 1047 endpoint. */ 1048 int is_interrupt = 1049 (ep->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) 1050 == LIBUSB_TRANSFER_TYPE_INTERRUPT; 1051 int is_output = 1052 (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) 1053 == LIBUSB_ENDPOINT_OUT; 1054 int is_input = 1055 (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) 1056 == LIBUSB_ENDPOINT_IN; 1057 1058 /* Decide whether to use it for input or output. */ 1059 if (dev->input_endpoint == 0 && 1060 is_interrupt && is_input) { 1061 /* Use this endpoint for INPUT */ 1062 dev->input_endpoint = ep->bEndpointAddress; 1063 dev->input_ep_max_packet_size = ep->wMaxPacketSize; 1064 } 1065 if (dev->output_endpoint == 0 && 1066 is_interrupt && is_output) { 1067 /* Use this endpoint for OUTPUT */ 1068 dev->output_endpoint = ep->bEndpointAddress; 1069 } 1070 } 1071 1072 pthread_create(&dev->thread, NULL, read_thread, dev); 1073 1074 /* Wait here for the read thread to be initialized. */ 1075 pthread_barrier_wait(&dev->barrier); 1076 1077 } 1078 free(dev_path); 1079 } 1080 } 1081 } 1082 libusb_free_config_descriptor(conf_desc); 1083 1084 } 1085 1086 libusb_free_device_list(devs, 1); 1087 1088 /* If we have a good handle, return it. */ 1089 if (good_open) { 1090 return dev; 1091 } 1092 else { 1093 /* Unable to open any devices. */ 1094 free_hid_device(dev); 1095 return NULL; 1096 } 1097} 1098 1099 1100int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length) 1101{ 1102 int res; 1103 int report_number = data[0]; 1104 int skipped_report_id = 0; 1105 1106 if (report_number == 0x0) { 1107 data++; 1108 length--; 1109 skipped_report_id = 1; 1110 } 1111 1112 1113 if (dev->output_endpoint <= 0) { 1114 /* No interrupt out endpoint. Use the Control Endpoint */ 1115 res = libusb_control_transfer(dev->device_handle, 1116 LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT, 1117 0x09/*HID Set_Report*/, 1118 (2/*HID output*/ << 8) | report_number, 1119 dev->interface, 1120 (unsigned char *)data, length, 1121 1000/*timeout millis*/); 1122 1123 if (res < 0) 1124 return -1; 1125 1126 if (skipped_report_id) 1127 length++; 1128 1129 return length; 1130 } 1131 else { 1132 /* Use the interrupt out endpoint */ 1133 int actual_length; 1134 res = libusb_interrupt_transfer(dev->device_handle, 1135 dev->output_endpoint, 1136 (unsigned char*)data, 1137 length, 1138 &actual_length, 1000); 1139 1140 if (res < 0) 1141 return -1; 1142 1143 if (skipped_report_id) 1144 actual_length++; 1145 1146 return actual_length; 1147 } 1148} 1149 1150/* Helper function, to simplify hid_read(). 1151 This should be called with dev->mutex locked. */ 1152static int return_data(hid_device *dev, unsigned char *data, size_t length) 1153{ 1154 /* Copy the data out of the linked list item (rpt) into the 1155 return buffer (data), and delete the liked list item. */ 1156 struct input_report *rpt = dev->input_reports; 1157 size_t len = (length < rpt->len)? length: rpt->len; 1158 if (data && len > 0) 1159 memcpy(data, rpt->data, len); 1160 dev->input_reports = rpt->next; 1161 free(rpt->data); 1162 free(rpt); 1163 return len; 1164} 1165 1166static void cleanup_mutex(void *param) 1167{ 1168 hid_device *dev = (hid_device *)param; 1169 pthread_mutex_unlock(&dev->mutex); 1170} 1171 1172 1173int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) 1174{ 1175 int bytes_read = -1; 1176 1177#if 0 1178 int transferred; 1179 int res = libusb_interrupt_transfer(dev->device_handle, dev->input_endpoint, data, length, &transferred, 5000); 1180 LOG("transferred: %d\n", transferred); 1181 return transferred; 1182#endif 1183 1184 pthread_mutex_lock(&dev->mutex); 1185 pthread_cleanup_push(&cleanup_mutex, dev); 1186 1187 /* There's an input report queued up. Return it. */ 1188 if (dev->input_reports) { 1189 /* Return the first one */ 1190 bytes_read = return_data(dev, data, length); 1191 goto ret; 1192 } 1193 1194 if (dev->shutdown_thread) { 1195 /* This means the device has been disconnected. 1196 An error code of -1 should be returned. */ 1197 bytes_read = -1; 1198 goto ret; 1199 } 1200 1201 if (milliseconds == -1) { 1202 /* Blocking */ 1203 while (!dev->input_reports && !dev->shutdown_thread) { 1204 pthread_cond_wait(&dev->condition, &dev->mutex); 1205 } 1206 if (dev->input_reports) { 1207 bytes_read = return_data(dev, data, length); 1208 } 1209 } 1210 else if (milliseconds > 0) { 1211 /* Non-blocking, but called with timeout. */ 1212 int res; 1213 struct timespec ts; 1214 clock_gettime(CLOCK_REALTIME, &ts); 1215 ts.tv_sec += milliseconds / 1000; 1216 ts.tv_nsec += (milliseconds % 1000) * 1000000; 1217 if (ts.tv_nsec >= 1000000000L) { 1218 ts.tv_sec++; 1219 ts.tv_nsec -= 1000000000L; 1220 } 1221 1222 while (!dev->input_reports && !dev->shutdown_thread) { 1223 res = pthread_cond_timedwait(&dev->condition, &dev->mutex, &ts); 1224 if (res == 0) { 1225 if (dev->input_reports) { 1226 bytes_read = return_data(dev, data, length); 1227 break; 1228 } 1229 1230 /* If we're here, there was a spurious wake up 1231 or the read thread was shutdown. Run the 1232 loop again (ie: don't break). */ 1233 } 1234 else if (res == ETIMEDOUT) { 1235 /* Timed out. */ 1236 bytes_read = 0; 1237 break; 1238 } 1239 else { 1240 /* Error. */ 1241 bytes_read = -1; 1242 break; 1243 } 1244 } 1245 } 1246 else { 1247 /* Purely non-blocking */ 1248 bytes_read = 0; 1249 } 1250 1251ret: 1252 pthread_mutex_unlock(&dev->mutex); 1253 pthread_cleanup_pop(0); 1254 1255 return bytes_read; 1256} 1257 1258int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length) 1259{ 1260 return hid_read_timeout(dev, data, length, dev->blocking ? -1 : 0); 1261} 1262 1263int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock) 1264{ 1265 dev->blocking = !nonblock; 1266 1267 return 0; 1268} 1269 1270 1271int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) 1272{ 1273 int res = -1; 1274 int skipped_report_id = 0; 1275 int report_number = data[0]; 1276 1277 if (report_number == 0x0) { 1278 data++; 1279 length--; 1280 skipped_report_id = 1; 1281 } 1282 1283 res = libusb_control_transfer(dev->device_handle, 1284 LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT, 1285 0x09/*HID set_report*/, 1286 (3/*HID feature*/ << 8) | report_number, 1287 dev->interface, 1288 (unsigned char *)data, length, 1289 1000/*timeout millis*/); 1290 1291 if (res < 0) 1292 return -1; 1293 1294 /* Account for the report ID */ 1295 if (skipped_report_id) 1296 length++; 1297 1298 return length; 1299} 1300 1301int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) 1302{ 1303 int res = -1; 1304 int skipped_report_id = 0; 1305 int report_number = data[0]; 1306 1307 if (report_number == 0x0) { 1308 /* Offset the return buffer by 1, so that the report ID 1309 will remain in byte 0. */ 1310 data++; 1311 length--; 1312 skipped_report_id = 1; 1313 } 1314 res = libusb_control_transfer(dev->device_handle, 1315 LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_IN, 1316 0x01/*HID get_report*/, 1317 (3/*HID feature*/ << 8) | report_number, 1318 dev->interface, 1319 (unsigned char *)data, length, 1320 1000/*timeout millis*/); 1321 1322 if (res < 0) 1323 return -1; 1324 1325 if (skipped_report_id) 1326 res++; 1327 1328 return res; 1329} 1330 1331 1332void HID_API_EXPORT hid_close(hid_device *dev) 1333{ 1334 if (!dev) 1335 return; 1336 1337 /* Cause read_thread() to stop. */ 1338 dev->shutdown_thread = 1; 1339 libusb_cancel_transfer(dev->transfer); 1340 1341 /* Wait for read_thread() to end. */ 1342 pthread_join(dev->thread, NULL); 1343 1344 /* Clean up the Transfer objects allocated in read_thread(). */ 1345 free(dev->transfer->buffer); 1346 libusb_free_transfer(dev->transfer); 1347 1348 /* release the interface */ 1349 libusb_release_interface(dev->device_handle, dev->interface); 1350 1351 /* Close the handle */ 1352 libusb_close(dev->device_handle); 1353 1354 /* Clear out the queue of received reports. */ 1355 pthread_mutex_lock(&dev->mutex); 1356 while (dev->input_reports) { 1357 return_data(dev, NULL, 0); 1358 } 1359 pthread_mutex_unlock(&dev->mutex); 1360 1361 free_hid_device(dev); 1362} 1363 1364 1365int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) 1366{ 1367 return hid_get_indexed_string(dev, dev->manufacturer_index, string, maxlen); 1368} 1369 1370int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) 1371{ 1372 return hid_get_indexed_string(dev, dev->product_index, string, maxlen); 1373} 1374 1375int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) 1376{ 1377 return hid_get_indexed_string(dev, dev->serial_index, string, maxlen); 1378} 1379 1380int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) 1381{ 1382 wchar_t *str; 1383 1384 str = get_usb_string(dev->device_handle, string_index); 1385 if (str) { 1386 wcsncpy(string, str, maxlen); 1387 string[maxlen-1] = L'\0'; 1388 free(str); 1389 return 0; 1390 } 1391 else 1392 return -1; 1393} 1394 1395 1396HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) 1397{ 1398 return NULL; 1399} 1400 1401 1402struct lang_map_entry { 1403 const char *name; 1404 const char *string_code; 1405 uint16_t usb_code; 1406}; 1407 1408#define LANG(name,code,usb_code) { name, code, usb_code } 1409static struct lang_map_entry lang_map[] = { 1410 LANG("Afrikaans", "af", 0x0436), 1411 LANG("Albanian", "sq", 0x041C), 1412 LANG("Arabic - United Arab Emirates", "ar_ae", 0x3801), 1413 LANG("Arabic - Bahrain", "ar_bh", 0x3C01), 1414 LANG("Arabic - Algeria", "ar_dz", 0x1401), 1415 LANG("Arabic - Egypt", "ar_eg", 0x0C01), 1416 LANG("Arabic - Iraq", "ar_iq", 0x0801), 1417 LANG("Arabic - Jordan", "ar_jo", 0x2C01), 1418 LANG("Arabic - Kuwait", "ar_kw", 0x3401), 1419 LANG("Arabic - Lebanon", "ar_lb", 0x3001), 1420 LANG("Arabic - Libya", "ar_ly", 0x1001), 1421 LANG("Arabic - Morocco", "ar_ma", 0x1801), 1422 LANG("Arabic - Oman", "ar_om", 0x2001), 1423 LANG("Arabic - Qatar", "ar_qa", 0x4001), 1424 LANG("Arabic - Saudi Arabia", "ar_sa", 0x0401), 1425 LANG("Arabic - Syria", "ar_sy", 0x2801), 1426 LANG("Arabic - Tunisia", "ar_tn", 0x1C01), 1427 LANG("Arabic - Yemen", "ar_ye", 0x2401), 1428 LANG("Armenian", "hy", 0x042B), 1429 LANG("Azeri - Latin", "az_az", 0x042C), 1430 LANG("Azeri - Cyrillic", "az_az", 0x082C), 1431 LANG("Basque", "eu", 0x042D), 1432 LANG("Belarusian", "be", 0x0423), 1433 LANG("Bulgarian", "bg", 0x0402), 1434 LANG("Catalan", "ca", 0x0403), 1435 LANG("Chinese - China", "zh_cn", 0x0804), 1436 LANG("Chinese - Hong Kong SAR", "zh_hk", 0x0C04), 1437 LANG("Chinese - Macau SAR", "zh_mo", 0x1404), 1438 LANG("Chinese - Singapore", "zh_sg", 0x1004), 1439 LANG("Chinese - Taiwan", "zh_tw", 0x0404), 1440 LANG("Croatian", "hr", 0x041A), 1441 LANG("Czech", "cs", 0x0405), 1442 LANG("Danish", "da", 0x0406), 1443 LANG("Dutch - Netherlands", "nl_nl", 0x0413), 1444 LANG("Dutch - Belgium", "nl_be", 0x0813), 1445 LANG("English - Australia", "en_au", 0x0C09), 1446 LANG("English - Belize", "en_bz", 0x2809), 1447 LANG("English - Canada", "en_ca", 0x1009), 1448 LANG("English - Caribbean", "en_cb", 0x2409), 1449 LANG("English - Ireland", "en_ie", 0x1809), 1450 LANG("English - Jamaica", "en_jm", 0x2009), 1451 LANG("English - New Zealand", "en_nz", 0x1409), 1452 LANG("English - Phillippines", "en_ph", 0x3409), 1453 LANG("English - Southern Africa", "en_za", 0x1C09), 1454 LANG("English - Trinidad", "en_tt", 0x2C09), 1455 LANG("English - Great Britain", "en_gb", 0x0809), 1456 LANG("English - United States", "en_us", 0x0409), 1457 LANG("Estonian", "et", 0x0425), 1458 LANG("Farsi", "fa", 0x0429), 1459 LANG("Finnish", "fi", 0x040B), 1460 LANG("Faroese", "fo", 0x0438), 1461 LANG("French - France", "fr_fr", 0x040C), 1462 LANG("French - Belgium", "fr_be", 0x080C), 1463 LANG("French - Canada", "fr_ca", 0x0C0C), 1464 LANG("French - Luxembourg", "fr_lu", 0x140C), 1465 LANG("French - Switzerland", "fr_ch", 0x100C), 1466 LANG("Gaelic - Ireland", "gd_ie", 0x083C), 1467 LANG("Gaelic - Scotland", "gd", 0x043C), 1468 LANG("German - Germany", "de_de", 0x0407), 1469 LANG("German - Austria", "de_at", 0x0C07), 1470 LANG("German - Liechtenstein", "de_li", 0x1407), 1471 LANG("German - Luxembourg", "de_lu", 0x1007), 1472 LANG("German - Switzerland", "de_ch", 0x0807), 1473 LANG("Greek", "el", 0x0408), 1474 LANG("Hebrew", "he", 0x040D), 1475 LANG("Hindi", "hi", 0x0439), 1476 LANG("Hungarian", "hu", 0x040E), 1477 LANG("Icelandic", "is", 0x040F), 1478 LANG("Indonesian", "id", 0x0421), 1479 LANG("Italian - Italy", "it_it", 0x0410), 1480 LANG("Italian - Switzerland", "it_ch", 0x0810), 1481 LANG("Japanese", "ja", 0x0411), 1482 LANG("Korean", "ko", 0x0412), 1483 LANG("Latvian", "lv", 0x0426), 1484 LANG("Lithuanian", "lt", 0x0427), 1485 LANG("F.Y.R.O. Macedonia", "mk", 0x042F), 1486 LANG("Malay - Malaysia", "ms_my", 0x043E), 1487 LANG("Malay – Brunei", "ms_bn", 0x083E), 1488 LANG("Maltese", "mt", 0x043A), 1489 LANG("Marathi", "mr", 0x044E), 1490 LANG("Norwegian - Bokml", "no_no", 0x0414), 1491 LANG("Norwegian - Nynorsk", "no_no", 0x0814), 1492 LANG("Polish", "pl", 0x0415), 1493 LANG("Portuguese - Portugal", "pt_pt", 0x0816), 1494 LANG("Portuguese - Brazil", "pt_br", 0x0416), 1495 LANG("Raeto-Romance", "rm", 0x0417), 1496 LANG("Romanian - Romania", "ro", 0x0418), 1497 LANG("Romanian - Republic of Moldova", "ro_mo", 0x0818), 1498 LANG("Russian", "ru", 0x0419), 1499 LANG("Russian - Republic of Moldova", "ru_mo", 0x0819), 1500 LANG("Sanskrit", "sa", 0x044F), 1501 LANG("Serbian - Cyrillic", "sr_sp", 0x0C1A), 1502 LANG("Serbian - Latin", "sr_sp", 0x081A), 1503 LANG("Setsuana", "tn", 0x0432), 1504 LANG("Slovenian", "sl", 0x0424), 1505 LANG("Slovak", "sk", 0x041B), 1506 LANG("Sorbian", "sb", 0x042E), 1507 LANG("Spanish - Spain (Traditional)", "es_es", 0x040A), 1508 LANG("Spanish - Argentina", "es_ar", 0x2C0A), 1509 LANG("Spanish - Bolivia", "es_bo", 0x400A), 1510 LANG("Spanish - Chile", "es_cl", 0x340A), 1511 LANG("Spanish - Colombia", "es_co", 0x240A), 1512 LANG("Spanish - Costa Rica", "es_cr", 0x140A), 1513 LANG("Spanish - Dominican Republic", "es_do", 0x1C0A), 1514 LANG("Spanish - Ecuador", "es_ec", 0x300A), 1515 LANG("Spanish - Guatemala", "es_gt", 0x100A), 1516 LANG("Spanish - Honduras", "es_hn", 0x480A), 1517 LANG("Spanish - Mexico", "es_mx", 0x080A), 1518 LANG("Spanish - Nicaragua", "es_ni", 0x4C0A), 1519 LANG("Spanish - Panama", "es_pa", 0x180A), 1520 LANG("Spanish - Peru", "es_pe", 0x280A), 1521 LANG("Spanish - Puerto Rico", "es_pr", 0x500A), 1522 LANG("Spanish - Paraguay", "es_py", 0x3C0A), 1523 LANG("Spanish - El Salvador", "es_sv", 0x440A), 1524 LANG("Spanish - Uruguay", "es_uy", 0x380A), 1525 LANG("Spanish - Venezuela", "es_ve", 0x200A), 1526 LANG("Southern Sotho", "st", 0x0430), 1527 LANG("Swahili", "sw", 0x0441), 1528 LANG("Swedish - Sweden", "sv_se", 0x041D), 1529 LANG("Swedish - Finland", "sv_fi", 0x081D), 1530 LANG("Tamil", "ta", 0x0449), 1531 LANG("Tatar", "tt", 0X0444), 1532 LANG("Thai", "th", 0x041E), 1533 LANG("Turkish", "tr", 0x041F), 1534 LANG("Tsonga", "ts", 0x0431), 1535 LANG("Ukrainian", "uk", 0x0422), 1536 LANG("Urdu", "ur", 0x0420), 1537 LANG("Uzbek - Cyrillic", "uz_uz", 0x0843), 1538 LANG("Uzbek – Latin", "uz_uz", 0x0443), 1539 LANG("Vietnamese", "vi", 0x042A), 1540 LANG("Xhosa", "xh", 0x0434), 1541 LANG("Yiddish", "yi", 0x043D), 1542 LANG("Zulu", "zu", 0x0435), 1543 LANG(NULL, NULL, 0x0), 1544}; 1545 1546uint16_t get_usb_code_for_current_locale(void) 1547{ 1548 char *locale; 1549 char search_string[64]; 1550 char *ptr; 1551 struct lang_map_entry *lang; 1552 1553 /* Get the current locale. */ 1554 locale = setlocale(0, NULL); 1555 if (!locale) 1556 return 0x0; 1557 1558 /* Make a copy of the current locale string. */ 1559 strncpy(search_string, locale, sizeof(search_string)); 1560 search_string[sizeof(search_string)-1] = '\0'; 1561 1562 /* Chop off the encoding part, and make it lower case. */ 1563 ptr = search_string; 1564 while (*ptr) { 1565 *ptr = tolower(*ptr); 1566 if (*ptr == '.') { 1567 *ptr = '\0'; 1568 break; 1569 } 1570 ptr++; 1571 } 1572 1573 /* Find the entry which matches the string code of our locale. */ 1574 lang = lang_map; 1575 while (lang->string_code) { 1576 if (!strcmp(lang->string_code, search_string)) { 1577 return lang->usb_code; 1578 } 1579 lang++; 1580 } 1581 1582 /* There was no match. Find with just the language only. */ 1583 /* Chop off the variant. Chop it off at the '_'. */ 1584 ptr = search_string; 1585 while (*ptr) { 1586 *ptr = tolower(*ptr); 1587 if (*ptr == '_') { 1588 *ptr = '\0'; 1589 break; 1590 } 1591 ptr++; 1592 } 1593 1594#if 0 /* TODO: Do we need this? */ 1595 /* Find the entry which matches the string code of our language. */ 1596 lang = lang_map; 1597 while (lang->string_code) { 1598 if (!strcmp(lang->string_code, search_string)) { 1599 return lang->usb_code; 1600 } 1601 lang++; 1602 } 1603#endif 1604 1605 /* Found nothing. */ 1606 return 0x0; 1607} 1608 1609#if defined(__cplusplus) && !defined(NAMESPACE) 1610} 1611#endif 1612 1613#ifdef NAMESPACE 1614} 1615#endif 1616
[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.