25 #include "../../SDL_internal.h" 27 #ifdef SDL_JOYSTICK_HIDAPI 43 #include <sys/types.h> 45 #include <sys/ioctl.h> 46 #include <sys/utsname.h> 69 typedef int pthread_barrierattr_t;
70 typedef struct pthread_barrier {
71 pthread_mutex_t
mutex;
77 static int pthread_barrier_init(pthread_barrier_t *barrier,
const pthread_barrierattr_t *attr,
unsigned int count)
84 if(pthread_mutex_init(&barrier->mutex, 0) < 0) {
87 if(pthread_cond_init(&barrier->cond, 0) < 0) {
88 pthread_mutex_destroy(&barrier->mutex);
91 barrier->trip_count =
count;
97 static int pthread_barrier_destroy(pthread_barrier_t *barrier)
99 pthread_cond_destroy(&barrier->cond);
100 pthread_mutex_destroy(&barrier->mutex);
104 static int pthread_barrier_wait(pthread_barrier_t *barrier)
106 pthread_mutex_lock(&barrier->mutex);
108 if(barrier->count >= barrier->trip_count)
111 pthread_cond_broadcast(&barrier->cond);
112 pthread_mutex_unlock(&barrier->mutex);
117 pthread_cond_wait(&barrier->cond, &(barrier->mutex));
118 pthread_mutex_unlock(&barrier->mutex);
125 #if defined(__cplusplus) && !defined(NAMESPACE) 130 #define LOG(...) fprintf(stderr, __VA_ARGS__) 132 #define LOG(...) do {} while (0) 136 #define DETACH_KERNEL_DRIVER 148 struct input_report {
151 struct input_report *next;
157 libusb_device_handle *device_handle;
162 int input_ep_max_packet_size;
168 int manufacturer_index;
177 pthread_mutex_t
mutex;
179 pthread_barrier_t barrier;
182 struct libusb_transfer *transfer;
185 struct input_report *input_reports;
188 static libusb_context *usb_context =
NULL;
190 uint16_t get_usb_code_for_current_locale(
void);
191 static int return_data(hid_device *dev,
unsigned char *
data,
size_t length);
193 static hid_device *new_hid_device(
void)
195 hid_device *dev = (hid_device *)calloc(1,
sizeof(hid_device));
198 pthread_mutex_init(&dev->mutex,
NULL);
199 pthread_cond_init(&dev->condition,
NULL);
200 pthread_barrier_init(&dev->barrier,
NULL, 2);
205 static void free_hid_device(hid_device *dev)
208 pthread_barrier_destroy(&dev->barrier);
209 pthread_cond_destroy(&dev->condition);
210 pthread_mutex_destroy(&dev->mutex);
218 static void register_error(hid_device *
device,
const char *op)
224 #ifdef INVASIVE_GET_USAGE 230 if (cur + num_bytes >= len)
235 else if (num_bytes == 1) {
238 else if (num_bytes == 2) {
239 return (rpt[cur+2] * 256 + rpt[cur+1]);
241 else if (num_bytes == 4) {
242 return (rpt[cur+4] * 0x01000000 +
243 rpt[cur+3] * 0x00010000 +
244 rpt[cur+2] * 0x00000100 +
245 rpt[cur+1] * 0x00000001);
255 static int get_usage(
uint8_t *report_descriptor,
size_t size,
256 unsigned short *usage_page,
unsigned short *
usage)
260 int data_len, key_size;
261 int usage_found = 0, usage_page_found = 0;
264 int key = report_descriptor[
i];
265 int key_cmd = key & 0xfc;
269 if ((key & 0xf0) == 0xf0) {
275 data_len = report_descriptor[i+1];
286 size_code = key & 0x3;
291 data_len = size_code;
304 if (key_cmd == 0x4) {
305 *usage_page = get_bytes(report_descriptor, size, data_len, i);
306 usage_page_found = 1;
309 if (key_cmd == 0x8) {
310 *usage = get_bytes(report_descriptor, size, data_len, i);
315 if (usage_page_found && usage_found)
319 i += data_len + key_size;
326 #if defined(__FreeBSD__) && __FreeBSD__ < 10 334 static inline int libusb_get_string_descriptor(libusb_device_handle *dev,
338 return libusb_control_transfer(dev,
339 LIBUSB_ENDPOINT_IN | 0
x0,
340 LIBUSB_REQUEST_GET_DESCRIPTOR,
341 (LIBUSB_DT_STRING << 8) | descriptor_index,
342 lang_id, data, (
uint16_t) length, 1000);
350 static uint16_t get_first_language(libusb_device_handle *dev)
356 len = libusb_get_string_descriptor(dev,
367 static int is_language_supported(libusb_device_handle *dev,
uint16_t lang)
374 len = libusb_get_string_descriptor(dev,
385 for (i = 1; i <
len; i++) {
397 static wchar_t *get_usb_string(libusb_device_handle *dev,
uint8_t idx)
420 lang = get_usb_code_for_current_locale();
421 if (!is_language_supported(dev, lang))
422 lang = get_first_language(dev);
425 len = libusb_get_string_descriptor(dev,
443 str =
malloc((len / 2 + 1) *
sizeof(
wchar_t));
445 for (i = 0; i < len / 2; i++) {
446 str[
i] = buf[i * 2 + 2] | (buf[i * 2 + 3] << 8);
448 str[len / 2] = 0x00000000;
456 ic = iconv_open(
"WCHAR_T",
"UTF-16LE");
457 if (ic == (iconv_t)-1) {
458 LOG(
"iconv_open() failed\n");
466 outptr = (
char*) wbuf;
467 outbytes =
sizeof(wbuf);
468 res = iconv(ic, &inptr, &inbytes, &outptr, &outbytes);
469 if (res == (
size_t)-1) {
470 LOG(
"iconv() failed\n");
475 wbuf[
sizeof(wbuf)/
sizeof(wbuf[0])-1] = 0x00000000;
476 if (outbytes >=
sizeof(wbuf[0]))
477 *((
wchar_t*)outptr) = 0x00000000;
490 static char *make_path(libusb_device *dev,
int interface_number)
493 snprintf(str,
sizeof(str),
"%04x:%04x:%02x",
494 libusb_get_bus_number(dev),
495 libusb_get_device_address(dev),
497 str[
sizeof(str)-1] =
'\0';
509 if (libusb_init(&usb_context))
513 locale = setlocale(LC_CTYPE,
NULL);
515 setlocale(LC_CTYPE,
"");
524 libusb_exit(usb_context);
531 static int is_xbox360(
unsigned short vendor_id,
const struct libusb_interface_descriptor *intf_desc)
533 static const int XB360_IFACE_SUBCLASS = 93;
534 static const int XB360_IFACE_PROTOCOL = 1;
535 static const int SUPPORTED_VENDORS[] = {
558 if (intf_desc->bInterfaceNumber == 0 &&
559 intf_desc->bInterfaceClass == LIBUSB_CLASS_VENDOR_SPEC &&
560 intf_desc->bInterfaceSubClass == XB360_IFACE_SUBCLASS &&
561 intf_desc->bInterfaceProtocol == XB360_IFACE_PROTOCOL) {
563 for (i = 0; i <
sizeof(SUPPORTED_VENDORS)/
sizeof(SUPPORTED_VENDORS[0]); ++
i) {
564 if (vendor_id == SUPPORTED_VENDORS[i]) {
572 static int is_xboxone(
unsigned short vendor_id,
const struct libusb_interface_descriptor *intf_desc)
574 static const int XB1_IFACE_SUBCLASS = 71;
575 static const int XB1_IFACE_PROTOCOL = 208;
576 static const int SUPPORTED_VENDORS[] = {
585 if (intf_desc->bInterfaceNumber == 0 &&
586 intf_desc->bInterfaceClass == LIBUSB_CLASS_VENDOR_SPEC &&
587 intf_desc->bInterfaceSubClass == XB1_IFACE_SUBCLASS &&
588 intf_desc->bInterfaceProtocol == XB1_IFACE_PROTOCOL) {
590 for (i = 0; i <
sizeof(SUPPORTED_VENDORS)/
sizeof(SUPPORTED_VENDORS[0]); ++
i) {
591 if (vendor_id == SUPPORTED_VENDORS[i]) {
599 static int should_enumerate_interface(
unsigned short vendor_id,
const struct libusb_interface_descriptor *intf_desc)
601 if (intf_desc->bInterfaceClass == LIBUSB_CLASS_HID)
605 if (is_xbox360(vendor_id, intf_desc))
615 if (is_xboxone(vendor_id, intf_desc))
623 libusb_device **devs;
625 libusb_device_handle *
handle;
635 num_devs = libusb_get_device_list(usb_context, &devs);
638 while ((dev = devs[i++]) !=
NULL) {
639 struct libusb_device_descriptor desc;
640 struct libusb_config_descriptor *conf_desc =
NULL;
642 int interface_num = 0;
644 int res = libusb_get_device_descriptor(dev, &desc);
645 unsigned short dev_vid = desc.idVendor;
646 unsigned short dev_pid = desc.idProduct;
648 res = libusb_get_active_config_descriptor(dev, &conf_desc);
650 libusb_get_config_descriptor(dev, 0, &conf_desc);
652 for (j = 0; j < conf_desc->bNumInterfaces; j++) {
653 const struct libusb_interface *intf = &conf_desc->interface[
j];
654 for (k = 0; k < intf->num_altsetting; k++) {
655 const struct libusb_interface_descriptor *intf_desc;
656 intf_desc = &intf->altsetting[
k];
657 if (should_enumerate_interface(dev_vid, intf_desc)) {
658 interface_num = intf_desc->bInterfaceNumber;
661 if ((vendor_id == 0
x0 || vendor_id == dev_vid) &&
662 (product_id == 0
x0 || product_id == dev_pid)) {
677 cur_dev->
path = make_path(dev, interface_num);
679 res = libusb_open(dev, &handle);
683 if (desc.iSerialNumber > 0)
685 get_usb_string(handle, desc.iSerialNumber);
688 if (desc.iManufacturer > 0)
690 get_usb_string(handle, desc.iManufacturer);
691 if (desc.iProduct > 0)
693 get_usb_string(handle, desc.iProduct);
695 #ifdef INVASIVE_GET_USAGE 712 unsigned char data[256];
713 #ifdef DETACH_KERNEL_DRIVER 716 res = libusb_kernel_driver_active(handle, interface_num);
718 res = libusb_detach_kernel_driver(handle, interface_num);
720 LOG(
"Couldn't detach kernel driver, even though a kernel driver was attached.");
725 res = libusb_claim_interface(handle, interface_num);
728 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);
730 unsigned short page=0, usage=0;
733 get_usage(data, res, &page, &usage);
738 LOG(
"libusb_control_transfer() for getting the HID report failed with %d\n", res);
741 res = libusb_release_interface(handle, interface_num);
743 LOG(
"Can't release the interface.\n");
746 LOG(
"Can't claim interface %d\n", res);
747 #ifdef DETACH_KERNEL_DRIVER 750 res = libusb_attach_kernel_driver(handle, interface_num);
752 LOG(
"Couldn't re-attach kernel driver.\n");
758 libusb_close(handle);
773 libusb_free_config_descriptor(conf_desc);
777 libusb_free_device_list(devs, 1);
796 hid_device *
hid_open(
unsigned short vendor_id,
unsigned short product_id,
const wchar_t *
serial_number)
799 const char *path_to_open =
NULL;
800 hid_device *handle =
NULL;
810 path_to_open = cur_dev->
path;
815 path_to_open = cur_dev->
path;
819 cur_dev = cur_dev->
next;
832 static void read_callback(
struct libusb_transfer *transfer)
834 hid_device *dev = (hid_device *)transfer->user_data;
837 if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {
839 struct input_report *rpt = (
struct input_report *)
malloc(
sizeof(*rpt));
841 memcpy(rpt->data, transfer->buffer, transfer->actual_length);
842 rpt->len = transfer->actual_length;
845 pthread_mutex_lock(&dev->mutex);
848 if (dev->input_reports ==
NULL) {
850 dev->input_reports = rpt;
851 pthread_cond_signal(&dev->condition);
855 struct input_report *cur = dev->input_reports;
857 while (cur->next !=
NULL) {
866 if (num_queued > 30) {
867 return_data(dev,
NULL, 0);
870 pthread_mutex_unlock(&dev->mutex);
872 else if (transfer->status == LIBUSB_TRANSFER_CANCELLED) {
873 dev->shutdown_thread = 1;
877 else if (transfer->status == LIBUSB_TRANSFER_NO_DEVICE) {
878 dev->shutdown_thread = 1;
882 else if (transfer->status == LIBUSB_TRANSFER_TIMED_OUT) {
886 LOG(
"Unknown transfer code: %d\n", transfer->status);
890 res = libusb_submit_transfer(transfer);
892 LOG(
"Unable to submit URB. libusb error code: %d\n", res);
893 dev->shutdown_thread = 1;
899 static void *read_thread(
void *
param)
901 hid_device *dev = (hid_device *)param;
903 const size_t length = dev->input_ep_max_packet_size;
906 buf = (
unsigned char *)
malloc(length);
907 dev->transfer = libusb_alloc_transfer(0);
908 libusb_fill_interrupt_transfer(dev->transfer,
919 libusb_submit_transfer(dev->transfer);
922 pthread_barrier_wait(&dev->barrier);
925 while (!dev->shutdown_thread) {
927 res = libusb_handle_events(usb_context);
930 LOG(
"read_thread(): libusb reports error # %d\n", res);
933 if (res != LIBUSB_ERROR_BUSY &&
934 res != LIBUSB_ERROR_TIMEOUT &&
935 res != LIBUSB_ERROR_OVERFLOW &&
936 res != LIBUSB_ERROR_INTERRUPTED) {
944 libusb_cancel_transfer(dev->transfer);
946 while (!dev->cancelled)
947 libusb_handle_events_completed(usb_context, &dev->cancelled);
954 pthread_mutex_lock(&dev->mutex);
955 pthread_cond_broadcast(&dev->condition);
956 pthread_mutex_unlock(&dev->mutex);
972 hid_device *dev =
NULL;
974 libusb_device **devs;
975 libusb_device *usb_dev;
983 dev = new_hid_device();
985 libusb_get_device_list(usb_context, &devs);
986 while ((usb_dev = devs[d++]) !=
NULL) {
987 struct libusb_device_descriptor desc;
988 struct libusb_config_descriptor *conf_desc =
NULL;
990 libusb_get_device_descriptor(usb_dev, &desc);
992 if (libusb_get_active_config_descriptor(usb_dev, &conf_desc) < 0)
994 for (j = 0; j < conf_desc->bNumInterfaces; j++) {
995 const struct libusb_interface *intf = &conf_desc->interface[
j];
996 for (k = 0; k < intf->num_altsetting; k++) {
997 const struct libusb_interface_descriptor *intf_desc;
998 intf_desc = &intf->altsetting[
k];
999 if (should_enumerate_interface(desc.idVendor, intf_desc)) {
1000 char *dev_path = make_path(usb_dev, intf_desc->bInterfaceNumber);
1001 if (!strcmp(dev_path, path)) {
1005 res = libusb_open(usb_dev, &dev->device_handle);
1007 LOG(
"can't open device\n");
1012 #ifdef DETACH_KERNEL_DRIVER 1015 if (libusb_kernel_driver_active(dev->device_handle, intf_desc->bInterfaceNumber) == 1) {
1016 res = libusb_detach_kernel_driver(dev->device_handle, intf_desc->bInterfaceNumber);
1018 libusb_close(dev->device_handle);
1019 LOG(
"Unable to detach Kernel Driver\n");
1026 res = libusb_claim_interface(dev->device_handle, intf_desc->bInterfaceNumber);
1028 LOG(
"can't claim interface %d: %d\n", intf_desc->bInterfaceNumber, res);
1030 libusb_close(dev->device_handle);
1036 dev->manufacturer_index = desc.iManufacturer;
1037 dev->product_index = desc.iProduct;
1038 dev->serial_index = desc.iSerialNumber;
1041 dev->interface = intf_desc->bInterfaceNumber;
1045 for (i = 0; i < intf_desc->bNumEndpoints; i++) {
1046 const struct libusb_endpoint_descriptor *ep
1047 = &intf_desc->endpoint[
i];
1052 (ep->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK)
1053 == LIBUSB_TRANSFER_TYPE_INTERRUPT;
1055 (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK)
1056 == LIBUSB_ENDPOINT_OUT;
1058 (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK)
1059 == LIBUSB_ENDPOINT_IN;
1062 if (dev->input_endpoint == 0 &&
1063 is_interrupt && is_input) {
1065 dev->input_endpoint = ep->bEndpointAddress;
1066 dev->input_ep_max_packet_size = ep->wMaxPacketSize;
1068 if (dev->output_endpoint == 0 &&
1069 is_interrupt && is_output) {
1071 dev->output_endpoint = ep->bEndpointAddress;
1075 pthread_create(&dev->thread,
NULL, read_thread, dev);
1078 pthread_barrier_wait(&dev->barrier);
1085 libusb_free_config_descriptor(conf_desc);
1089 libusb_free_device_list(devs, 1);
1097 free_hid_device(dev);
1106 int report_number = data[0];
1107 int skipped_report_id = 0;
1109 if (report_number == 0
x0) {
1112 skipped_report_id = 1;
1116 if (dev->output_endpoint <= 0) {
1118 res = libusb_control_transfer(dev->device_handle,
1119 LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT,
1121 (2 << 8) | report_number,
1123 (
unsigned char *)data, length,
1129 if (skipped_report_id)
1137 res = libusb_interrupt_transfer(dev->device_handle,
1138 dev->output_endpoint,
1139 (
unsigned char*)data,
1141 &actual_length, 1000);
1146 if (skipped_report_id)
1149 return actual_length;
1155 static int return_data(hid_device *dev,
unsigned char *data,
size_t length)
1159 struct input_report *rpt = dev->input_reports;
1160 size_t len = (length < rpt->len)? length: rpt->len;
1161 if (data && len > 0)
1162 memcpy(data, rpt->data, len);
1163 dev->input_reports = rpt->next;
1169 static void cleanup_mutex(
void *param)
1171 hid_device *dev = (hid_device *)param;
1172 pthread_mutex_unlock(&dev->mutex);
1178 int bytes_read = -1;
1182 int res = libusb_interrupt_transfer(dev->device_handle, dev->input_endpoint, data, length, &transferred, 5000);
1183 LOG(
"transferred: %d\n", transferred);
1187 pthread_mutex_lock(&dev->mutex);
1188 pthread_cleanup_push(&cleanup_mutex, dev);
1191 if (dev->input_reports) {
1193 bytes_read = return_data(dev, data, length);
1197 if (dev->shutdown_thread) {
1204 if (milliseconds == -1) {
1206 while (!dev->input_reports && !dev->shutdown_thread) {
1207 pthread_cond_wait(&dev->condition, &dev->mutex);
1209 if (dev->input_reports) {
1210 bytes_read = return_data(dev, data, length);
1213 else if (milliseconds > 0) {
1217 clock_gettime(CLOCK_REALTIME, &ts);
1218 ts.tv_sec += milliseconds / 1000;
1219 ts.tv_nsec += (milliseconds % 1000) * 1000000;
1220 if (ts.tv_nsec >= 1000000000L) {
1222 ts.tv_nsec -= 1000000000L;
1225 while (!dev->input_reports && !dev->shutdown_thread) {
1226 res = pthread_cond_timedwait(&dev->condition, &dev->mutex, &ts);
1228 if (dev->input_reports) {
1229 bytes_read = return_data(dev, data, length);
1237 else if (res == ETIMEDOUT) {
1255 pthread_mutex_unlock(&dev->mutex);
1256 pthread_cleanup_pop(0);
1268 dev->blocking = !nonblock;
1277 int skipped_report_id = 0;
1278 int report_number = data[0];
1280 if (report_number == 0
x0) {
1283 skipped_report_id = 1;
1286 res = libusb_control_transfer(dev->device_handle,
1287 LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT,
1289 (3 << 8) | report_number,
1291 (
unsigned char *)data, length,
1298 if (skipped_report_id)
1307 int skipped_report_id = 0;
1308 int report_number = data[0];
1310 if (report_number == 0
x0) {
1315 skipped_report_id = 1;
1317 res = libusb_control_transfer(dev->device_handle,
1318 LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_IN,
1320 (3 << 8) | report_number,
1322 (
unsigned char *)data, length,
1328 if (skipped_report_id)
1341 dev->shutdown_thread = 1;
1342 libusb_cancel_transfer(dev->transfer);
1345 pthread_join(dev->thread,
NULL);
1348 free(dev->transfer->buffer);
1349 libusb_free_transfer(dev->transfer);
1352 libusb_release_interface(dev->device_handle, dev->interface);
1355 libusb_close(dev->device_handle);
1358 pthread_mutex_lock(&dev->mutex);
1359 while (dev->input_reports) {
1360 return_data(dev,
NULL, 0);
1362 pthread_mutex_unlock(&dev->mutex);
1364 free_hid_device(dev);
1387 str = get_usb_string(dev->device_handle, string_index);
1389 wcsncpy(
string, str, maxlen);
1390 string[maxlen-1] = L
'\0';
1405 struct lang_map_entry {
1407 const char *string_code;
1411 #define LANG(name,code,usb_code) { name, code, usb_code } 1412 static struct lang_map_entry lang_map[] = {
1413 LANG(
"Afrikaans",
"af", 0x0436),
1414 LANG(
"Albanian",
"sq", 0x041C),
1415 LANG(
"Arabic - United Arab Emirates",
"ar_ae", 0x3801),
1416 LANG(
"Arabic - Bahrain",
"ar_bh", 0x3C01),
1417 LANG(
"Arabic - Algeria",
"ar_dz", 0x1401),
1418 LANG(
"Arabic - Egypt",
"ar_eg", 0x0C01),
1419 LANG(
"Arabic - Iraq",
"ar_iq", 0x0801),
1420 LANG(
"Arabic - Jordan",
"ar_jo", 0x2C01),
1421 LANG(
"Arabic - Kuwait",
"ar_kw", 0x3401),
1422 LANG(
"Arabic - Lebanon",
"ar_lb", 0x3001),
1423 LANG(
"Arabic - Libya",
"ar_ly", 0x1001),
1424 LANG(
"Arabic - Morocco",
"ar_ma", 0x1801),
1425 LANG(
"Arabic - Oman",
"ar_om", 0x2001),
1426 LANG(
"Arabic - Qatar",
"ar_qa", 0x4001),
1427 LANG(
"Arabic - Saudi Arabia",
"ar_sa", 0x0401),
1428 LANG(
"Arabic - Syria",
"ar_sy", 0x2801),
1429 LANG(
"Arabic - Tunisia",
"ar_tn", 0x1C01),
1430 LANG(
"Arabic - Yemen",
"ar_ye", 0x2401),
1431 LANG(
"Armenian",
"hy", 0x042B),
1432 LANG(
"Azeri - Latin",
"az_az", 0x042C),
1433 LANG(
"Azeri - Cyrillic",
"az_az", 0x082C),
1434 LANG(
"Basque",
"eu", 0x042D),
1435 LANG(
"Belarusian",
"be", 0x0423),
1436 LANG(
"Bulgarian",
"bg", 0x0402),
1437 LANG(
"Catalan",
"ca", 0x0403),
1438 LANG(
"Chinese - China",
"zh_cn", 0x0804),
1439 LANG(
"Chinese - Hong Kong SAR",
"zh_hk", 0x0C04),
1440 LANG(
"Chinese - Macau SAR",
"zh_mo", 0x1404),
1441 LANG(
"Chinese - Singapore",
"zh_sg", 0x1004),
1442 LANG(
"Chinese - Taiwan",
"zh_tw", 0x0404),
1443 LANG(
"Croatian",
"hr", 0x041A),
1444 LANG(
"Czech",
"cs", 0x0405),
1445 LANG(
"Danish",
"da", 0x0406),
1446 LANG(
"Dutch - Netherlands",
"nl_nl", 0x0413),
1447 LANG(
"Dutch - Belgium",
"nl_be", 0x0813),
1448 LANG(
"English - Australia",
"en_au", 0x0C09),
1449 LANG(
"English - Belize",
"en_bz", 0x2809),
1450 LANG(
"English - Canada",
"en_ca", 0x1009),
1451 LANG(
"English - Caribbean",
"en_cb", 0x2409),
1452 LANG(
"English - Ireland",
"en_ie", 0x1809),
1453 LANG(
"English - Jamaica",
"en_jm", 0x2009),
1454 LANG(
"English - New Zealand",
"en_nz", 0x1409),
1455 LANG(
"English - Phillippines",
"en_ph", 0x3409),
1456 LANG(
"English - Southern Africa",
"en_za", 0x1C09),
1457 LANG(
"English - Trinidad",
"en_tt", 0x2C09),
1458 LANG(
"English - Great Britain",
"en_gb", 0x0809),
1459 LANG(
"English - United States",
"en_us", 0x0409),
1460 LANG(
"Estonian",
"et", 0x0425),
1461 LANG(
"Farsi",
"fa", 0x0429),
1462 LANG(
"Finnish",
"fi", 0x040B),
1463 LANG(
"Faroese",
"fo", 0x0438),
1464 LANG(
"French - France",
"fr_fr", 0x040C),
1465 LANG(
"French - Belgium",
"fr_be", 0x080C),
1466 LANG(
"French - Canada",
"fr_ca", 0x0C0C),
1467 LANG(
"French - Luxembourg",
"fr_lu", 0x140C),
1468 LANG(
"French - Switzerland",
"fr_ch", 0x100C),
1469 LANG(
"Gaelic - Ireland",
"gd_ie", 0x083C),
1470 LANG(
"Gaelic - Scotland",
"gd", 0x043C),
1471 LANG(
"German - Germany",
"de_de", 0x0407),
1472 LANG(
"German - Austria",
"de_at", 0x0C07),
1473 LANG(
"German - Liechtenstein",
"de_li", 0x1407),
1474 LANG(
"German - Luxembourg",
"de_lu", 0x1007),
1475 LANG(
"German - Switzerland",
"de_ch", 0x0807),
1476 LANG(
"Greek",
"el", 0x0408),
1477 LANG(
"Hebrew",
"he", 0x040D),
1478 LANG(
"Hindi",
"hi", 0x0439),
1479 LANG(
"Hungarian",
"hu", 0x040E),
1480 LANG(
"Icelandic",
"is", 0x040F),
1481 LANG(
"Indonesian",
"id", 0x0421),
1482 LANG(
"Italian - Italy",
"it_it", 0x0410),
1483 LANG(
"Italian - Switzerland",
"it_ch", 0x0810),
1484 LANG(
"Japanese",
"ja", 0x0411),
1485 LANG(
"Korean",
"ko", 0x0412),
1486 LANG(
"Latvian",
"lv", 0x0426),
1487 LANG(
"Lithuanian",
"lt", 0x0427),
1488 LANG(
"F.Y.R.O. Macedonia",
"mk", 0x042F),
1489 LANG(
"Malay - Malaysia",
"ms_my", 0x043E),
1490 LANG(
"Malay – Brunei",
"ms_bn", 0x083E),
1491 LANG(
"Maltese",
"mt", 0x043A),
1492 LANG(
"Marathi",
"mr", 0x044E),
1493 LANG(
"Norwegian - Bokml",
"no_no", 0x0414),
1494 LANG(
"Norwegian - Nynorsk",
"no_no", 0x0814),
1495 LANG(
"Polish",
"pl", 0x0415),
1496 LANG(
"Portuguese - Portugal",
"pt_pt", 0x0816),
1497 LANG(
"Portuguese - Brazil",
"pt_br", 0x0416),
1498 LANG(
"Raeto-Romance",
"rm", 0x0417),
1499 LANG(
"Romanian - Romania",
"ro", 0x0418),
1500 LANG(
"Romanian - Republic of Moldova",
"ro_mo", 0x0818),
1501 LANG(
"Russian",
"ru", 0x0419),
1502 LANG(
"Russian - Republic of Moldova",
"ru_mo", 0x0819),
1503 LANG(
"Sanskrit",
"sa", 0x044F),
1504 LANG(
"Serbian - Cyrillic",
"sr_sp", 0x0C1A),
1505 LANG(
"Serbian - Latin",
"sr_sp", 0x081A),
1506 LANG(
"Setsuana",
"tn", 0x0432),
1507 LANG(
"Slovenian",
"sl", 0x0424),
1508 LANG(
"Slovak",
"sk", 0x041B),
1509 LANG(
"Sorbian",
"sb", 0x042E),
1510 LANG(
"Spanish - Spain (Traditional)",
"es_es", 0x040A),
1511 LANG(
"Spanish - Argentina",
"es_ar", 0x2C0A),
1512 LANG(
"Spanish - Bolivia",
"es_bo", 0x400A),
1513 LANG(
"Spanish - Chile",
"es_cl", 0x340A),
1514 LANG(
"Spanish - Colombia",
"es_co", 0x240A),
1515 LANG(
"Spanish - Costa Rica",
"es_cr", 0x140A),
1516 LANG(
"Spanish - Dominican Republic",
"es_do", 0x1C0A),
1517 LANG(
"Spanish - Ecuador",
"es_ec", 0x300A),
1518 LANG(
"Spanish - Guatemala",
"es_gt", 0x100A),
1519 LANG(
"Spanish - Honduras",
"es_hn", 0x480A),
1520 LANG(
"Spanish - Mexico",
"es_mx", 0x080A),
1521 LANG(
"Spanish - Nicaragua",
"es_ni", 0x4C0A),
1522 LANG(
"Spanish - Panama",
"es_pa", 0x180A),
1523 LANG(
"Spanish - Peru",
"es_pe", 0x280A),
1524 LANG(
"Spanish - Puerto Rico",
"es_pr", 0x500A),
1525 LANG(
"Spanish - Paraguay",
"es_py", 0x3C0A),
1526 LANG(
"Spanish - El Salvador",
"es_sv", 0x440A),
1527 LANG(
"Spanish - Uruguay",
"es_uy", 0x380A),
1528 LANG(
"Spanish - Venezuela",
"es_ve", 0x200A),
1529 LANG(
"Southern Sotho",
"st", 0x0430),
1530 LANG(
"Swahili",
"sw", 0x0441),
1531 LANG(
"Swedish - Sweden",
"sv_se", 0x041D),
1532 LANG(
"Swedish - Finland",
"sv_fi", 0x081D),
1533 LANG(
"Tamil",
"ta", 0x0449),
1534 LANG(
"Tatar",
"tt", 0X0444),
1535 LANG(
"Thai",
"th", 0x041E),
1536 LANG(
"Turkish",
"tr", 0x041F),
1537 LANG(
"Tsonga",
"ts", 0x0431),
1538 LANG(
"Ukrainian",
"uk", 0x0422),
1539 LANG(
"Urdu",
"ur", 0x0420),
1540 LANG(
"Uzbek - Cyrillic",
"uz_uz", 0x0843),
1541 LANG(
"Uzbek – Latin",
"uz_uz", 0x0443),
1542 LANG(
"Vietnamese",
"vi", 0x042A),
1543 LANG(
"Xhosa",
"xh", 0x0434),
1544 LANG(
"Yiddish",
"yi", 0x043D),
1545 LANG(
"Zulu",
"zu", 0x0435),
1549 uint16_t get_usb_code_for_current_locale(
void)
1552 char search_string[64];
1554 struct lang_map_entry *lang;
1557 locale = setlocale(0,
NULL);
1562 strncpy(search_string, locale,
sizeof(search_string));
1563 search_string[
sizeof(search_string)-1] =
'\0';
1566 ptr = search_string;
1568 *ptr = tolower(*ptr);
1578 while (lang->string_code) {
1579 if (!strcmp(lang->string_code, search_string)) {
1580 return lang->usb_code;
1587 ptr = search_string;
1589 *ptr = tolower(*ptr);
1600 while (lang->string_code) {
1601 if (!strcmp(lang->string_code, search_string)) {
1602 return lang->usb_code;
1612 #if defined(__cplusplus) && !defined(NAMESPACE)
HID_API_EXPORT const wchar_t *HID_API_CALL hid_error(hid_device *device)
Get a string describing the last error which occurred.
GLuint GLuint GLsizei count
void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs)
Free an enumeration Linked List.
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
wchar_t * manufacturer_string
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length)
Write an Output report to a HID device.
int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen)
Get a string from a HID device, based on its string index.
GLuint const GLchar * name
static SDL_AudioDeviceID device
int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *device, unsigned char *data, size_t length, int milliseconds)
Read an Input report from a HID device with timeout.
struct hid_device_info * next
int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock)
Set the device handle to be non-blocking.
GLsizeiptr const void GLenum usage
void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device)
Close a HID device.
int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen)
Get The Product String from a HID device.
unsigned short product_id
EGLImageKHR EGLint EGLint * handle
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 SDL_AssertionHandler void SDL_SpinLock SDL_atomic_t int int return SDL_atomic_t return void void void return void return int return SDL_AudioSpec SDL_AudioSpec return int int return return int SDL_RWops int SDL_AudioSpec Uint8 ** d
int hid_exit(void)
Finalize the HIDAPI library.
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int int in j)
HID_API_EXPORT hid_device *HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
Open a HID device using a Vendor ID (VID), Product ID (PID) and optionally a serial number...
int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length)
Get a feature report from a HID device.
GLenum GLuint GLenum GLsizei const GLchar * buf
int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen)
Get The Serial Number String from a HID device.
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
#define HID_API_EXPORT_CALL
int hid_init(void)
Initialize the HIDAPI library.
unsigned short usage_page
HID_API_EXPORT hid_device *HID_API_CALL hid_open_path(const char *path, int bExclusive)
Open a HID device by its path name.
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int int int return Display Window Cursor return Display Window return Display Drawable GC int int unsigned int unsigned int return Display Drawable GC int int _Xconst char int return Display Drawable GC int int unsigned int unsigned int return Display return Display Cursor return Display GC return XModifierKeymap return char Display Window int return Display return Display Atom return Display Window XWindowAttributes return Display Window return Display XEvent Bool(*) XPointer return Display Window Bool unsigned int int int Window Cursor Time return Display Window int return KeySym return Display _Xconst char Bool return Display _Xconst char return XKeyEvent char int KeySym XComposeStatus return Display int int int XVisualInfo return Display Window int int return _Xconst char return Display XEvent return Display Drawable GC XImage int int int int unsigned int unsigned int return Display Window Window Window int int int int unsigned int return Display Window Window int int return Display Window unsigned int unsigned int return Display Window Bool long XEvent return Display GC unsigned long return Display Window int Time return Display Window Window return Display Window unsigned long return Display Window XSizeHints Display Colormap XColor int return char int XTextProperty return XFontStruct _Xconst char int int int int XCharStruct return Display Window return Display Time return Display Colormap return Display Window Window int int unsigned int unsigned int int int return Display Window int return XExtensionInfo Display char XExtensionHooks int XPointer return XExtensionInfo XExtensionInfo Display return Display return Display unsigned long Display GC Display char long Display xReply int Bool return Display Bool return Display int SDL_X11_XESetEventToWireRetType return Display Window Window Window Window unsigned int return Display XShmSegmentInfo return Display Drawable GC XImage int int int int unsigned int unsigned int Boo k)
GLsizei const GLchar *const * path
int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length)
Send a Feature report to the device.
int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen)
Get The Manufacturer String from a HID device.
GLuint GLsizei GLsizei * length
struct hid_device_info HID_API_EXPORT *HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id)
Enumerate the HID Devices.
unsigned short release_number
int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length)
Read an Input report from a HID device.