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