23 #include "../../SDL_internal.h"
25 #ifdef SDL_JOYSTICK_HIDAPI
40 #include <sys/types.h>
42 #include <sys/ioctl.h>
43 #include <sys/utsname.h>
48 #include <linux/hidraw.h>
49 #include <linux/version.h>
50 #include <linux/input.h>
62 #ifndef HIDIOCSFEATURE
63 #define HIDIOCSFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len)
65 #ifndef HIDIOCGFEATURE
66 #define HIDIOCGFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x07, len)
70 const char *device_string_names[] = {
77 enum device_string_id {
78 DEVICE_STRING_MANUFACTURER,
79 DEVICE_STRING_PRODUCT,
88 int uses_numbered_reports;
93 static __u32 kernel_version = 0;
95 static __u32 detect_kernel_version(
void)
98 int major, minor, release;
102 ret = sscanf(
name.release,
"%d.%d.%d", &major, &minor, &release);
104 return KERNEL_VERSION(major, minor, release);
107 ret = sscanf(
name.release,
"%d.%d", &major, &minor);
109 return KERNEL_VERSION(major, minor, 0);
112 printf(
"Couldn't determine kernel version from version string \"%s\"\n",
name.release);
119 dev->device_handle = -1;
121 dev->uses_numbered_reports = 0;
122 dev->needs_ble_hack = 0;
129 static wchar_t *utf8_to_wchar_t(
const char *utf8)
134 size_t wlen = mbstowcs(
NULL, utf8, 0);
135 if ((
size_t) -1 == wlen) {
138 ret = (
wchar_t *)calloc(wlen+1,
sizeof(
wchar_t));
139 mbstowcs(ret, utf8, wlen+1);
148 static wchar_t *copy_udev_string(
struct udev_device *dev,
const char *udev_name)
150 return utf8_to_wchar_t(udev_device_get_sysattr_value(dev, udev_name));
155 static int uses_numbered_reports(__u8 *report_descriptor, __u32
size) {
158 int data_len, key_size;
161 int key = report_descriptor[
i];
172 if ((
key & 0xf0) == 0xf0) {
178 data_len = report_descriptor[
i+1];
189 size_code =
key & 0x3;
194 data_len = size_code;
208 i += data_len + key_size;
220 parse_uevent_info(
const char *uevent,
int *bus_type,
221 unsigned short *vendor_id,
unsigned short *product_id,
222 char **serial_number_utf8,
char **product_name_utf8)
224 char *tmp =
strdup(uevent);
225 char *saveptr =
NULL;
231 int found_serial = 0;
234 line = strtok_r(tmp,
"\n", &saveptr);
235 while (line !=
NULL) {
238 value = strchr(line,
'=');
245 if (strcmp(
key,
"HID_ID") == 0) {
250 int ret = sscanf(
value,
"%x:%hx:%hx", bus_type, vendor_id, product_id);
254 }
else if (strcmp(
key,
"HID_NAME") == 0) {
258 }
else if (strcmp(
key,
"HID_UNIQ") == 0) {
265 line = strtok_r(
NULL,
"\n", &saveptr);
269 return (found_id && found_name && found_serial);
275 struct udev_device *udev_dev, *hid_dev;
282 printf(
"Can't create udev\n");
287 if (fstat(dev->device_handle, &
s) < 0) {
294 udev_dev = udev_device_new_from_devnum(udev,
'c',
s.st_rdev);
296 hid_dev = udev_device_get_parent_with_subsystem_devtype(
301 unsigned short dev_vid = 0;
302 unsigned short dev_pid = 0;
304 char *serial_number_utf8 =
NULL;
305 char *product_name_utf8 =
NULL;
308 udev_device_get_sysattr_value(hid_dev,
"uevent"),
314 free(serial_number_utf8);
315 free(product_name_utf8);
317 if (bus_type == BUS_BLUETOOTH) {
319 if (dev_vid == 0x28de ) {
327 udev_device_unref(udev_dev);
335 static int get_device_string(
hid_device *dev,
enum device_string_id
key,
wchar_t *
string,
size_t maxlen)
338 struct udev_device *udev_dev, *parent, *hid_dev;
341 char *serial_number_utf8 =
NULL;
342 char *product_name_utf8 =
NULL;
348 printf(
"Can't create udev\n");
353 ret = fstat(dev->device_handle, &
s);
359 udev_dev = udev_device_new_from_devnum(udev,
'c',
s.st_rdev);
361 hid_dev = udev_device_get_parent_with_subsystem_devtype(
366 unsigned short dev_vid;
367 unsigned short dev_pid;
371 ret = parse_uevent_info(
372 udev_device_get_sysattr_value(hid_dev,
"uevent"),
379 if (bus_type == BUS_BLUETOOTH) {
381 case DEVICE_STRING_MANUFACTURER:
382 wcsncpy(
string, L
"", maxlen);
385 case DEVICE_STRING_PRODUCT:
386 retm = mbstowcs(
string, product_name_utf8, maxlen);
387 ret = (retm == (
size_t)-1)? -1: 0;
389 case DEVICE_STRING_SERIAL:
394 while ((tmp = strchr(serial_number_utf8,
':')) !=
NULL) {
395 memmove(tmp, tmp+1, strlen(tmp));
397 retm = mbstowcs(
string, serial_number_utf8, maxlen);
398 ret = (retm == (
size_t)-1)? -1: 0;
400 case DEVICE_STRING_COUNT:
408 parent = udev_device_get_parent_with_subsystem_devtype(
414 const char *key_str =
NULL;
416 if (
key >= 0 &&
key < DEVICE_STRING_COUNT) {
417 key_str = device_string_names[
key];
423 str = udev_device_get_sysattr_value(parent, key_str);
426 retm = mbstowcs(
string, str, maxlen);
427 ret = (retm == (
size_t)-1)? -1: 0;
436 free(serial_number_utf8);
437 free(product_name_utf8);
439 udev_device_unref(udev_dev);
452 locale = setlocale(LC_CTYPE,
NULL);
454 setlocale(LC_CTYPE,
"");
456 kernel_version = detect_kernel_version();
471 struct udev_enumerate *enumerate;
472 struct udev_list_entry *
devices, *dev_list_entry;
483 printf(
"Can't create udev\n");
488 enumerate = udev_enumerate_new(udev);
489 udev_enumerate_add_match_subsystem(enumerate,
"hidraw");
490 udev_enumerate_scan_devices(enumerate);
491 devices = udev_enumerate_get_list_entry(enumerate);
494 udev_list_entry_foreach(dev_list_entry,
devices) {
495 const char *sysfs_path;
496 const char *dev_path;
498 struct udev_device *raw_dev;
499 struct udev_device *hid_dev;
500 struct udev_device *usb_dev;
501 struct udev_device *intf_dev;
502 unsigned short dev_vid;
503 unsigned short dev_pid;
504 char *serial_number_utf8 =
NULL;
505 char *product_name_utf8 =
NULL;
511 sysfs_path = udev_list_entry_get_name(dev_list_entry);
512 raw_dev = udev_device_new_from_syspath(udev, sysfs_path);
513 dev_path = udev_device_get_devnode(raw_dev);
515 hid_dev = udev_device_get_parent_with_subsystem_devtype(
525 result = parse_uevent_info(
526 udev_device_get_sysattr_value(hid_dev,
"uevent"),
538 if (bus_type != BUS_USB && bus_type != BUS_BLUETOOTH) {
543 if (
access(dev_path, R_OK|W_OK) != 0) {
549 if ((vendor_id == 0x0 || vendor_id == dev_vid) &&
550 (product_id == 0x0 || product_id == dev_pid)) {
573 cur_dev->
serial_number = utf8_to_wchar_t(serial_number_utf8);
589 usb_dev = udev_device_get_parent_with_subsystem_devtype(
606 cur_dev = root =
NULL;
613 cur_dev->
manufacturer_string = copy_udev_string(usb_dev, device_string_names[DEVICE_STRING_MANUFACTURER]);
614 cur_dev->
product_string = copy_udev_string(usb_dev, device_string_names[DEVICE_STRING_PRODUCT]);
617 str = udev_device_get_sysattr_value(usb_dev,
"bcdDevice");
621 intf_dev = udev_device_get_parent_with_subsystem_devtype(
626 str = udev_device_get_sysattr_value(intf_dev,
"bInterfaceNumber");
647 free(serial_number_utf8);
648 free(product_name_utf8);
649 udev_device_unref(raw_dev);
655 udev_enumerate_unref(enumerate);
667 free(
d->serial_number);
668 free(
d->manufacturer_string);
669 free(
d->product_string);
678 const char *path_to_open =
NULL;
688 path_to_open = cur_dev->
path;
693 path_to_open = cur_dev->
path;
697 cur_dev = cur_dev->
next;
716 dev = new_hid_device();
719 dev->device_handle = open(
path, O_RDWR);
722 if (dev->device_handle >= 0) {
725 int res, desc_size = 0;
726 struct hidraw_report_descriptor rpt_desc;
728 memset(&rpt_desc, 0x0,
sizeof(rpt_desc));
731 res = ioctl(dev->device_handle, HIDIOCGRDESCSIZE, &desc_size);
733 perror(
"HIDIOCGRDESCSIZE");
737 rpt_desc.size = desc_size;
738 res = ioctl(dev->device_handle, HIDIOCGRDESC, &rpt_desc);
740 perror(
"HIDIOCGRDESC");
743 dev->uses_numbered_reports =
744 uses_numbered_reports(rpt_desc.value,
748 dev->needs_ble_hack = (is_BLE(dev) == 1);
764 bytes_written = write(dev->device_handle,
data,
length);
766 return bytes_written;
774 if (milliseconds >= 0) {
784 fds.fd = dev->device_handle;
787 ret = poll(&
fds, 1, milliseconds);
788 if (ret == -1 || ret == 0) {
795 if (
fds.revents & (POLLERR | POLLHUP | POLLNVAL))
800 bytes_read = read(dev->device_handle,
data,
length);
801 if (bytes_read < 0 && (errno == EAGAIN || errno == EINPROGRESS))
804 if (bytes_read >= 0 &&
805 kernel_version != 0 &&
806 kernel_version < KERNEL_VERSION(2,6,34) &&
807 dev->uses_numbered_reports) {
827 dev->blocking = !nonblock;
836 res = ioctl(dev->device_handle, HIDIOCSFEATURE(
length),
data);
838 perror(
"ioctl (SFEATURE)");
848 if (dev->needs_ble_hack) {
853 res = ioctl(dev->device_handle, HIDIOCGFEATURE(
length),
data);
855 perror(
"ioctl (GFEATURE)");
856 else if (dev->needs_ble_hack)
867 close(dev->device_handle);
874 return get_device_string(dev, DEVICE_STRING_MANUFACTURER,
string, maxlen);
879 return get_device_string(dev, DEVICE_STRING_PRODUCT,
string, maxlen);
884 return get_device_string(dev, DEVICE_STRING_SERIAL,
string, maxlen);
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
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
GLuint const GLchar * name
GLuint GLint GLboolean GLint GLenum access
GLsizei const GLchar *const * path
GLuint GLsizei GLsizei * length
GLsizei const GLfloat * value
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)
EGLImageKHR EGLint EGLint * handle
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.
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_read_timeout(hid_device *device, unsigned char *data, size_t length, int milliseconds)
Read an Input report from a HID device with timeout.
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.
struct hid_device_info HID_API_EXPORT *HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id)
Enumerate the HID Devices.
int HID_API_EXPORT HID_API_CALL hid_init(void)
Initialize the HIDAPI library.
HID_API_EXPORT const wchar_t *HID_API_CALL hid_error(hid_device *device)
Get a string describing the last error which occurred.
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.
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.
HID_API_EXPORT hid_device *HID_API_CALL hid_open_path(const char *path, int bExclusive)
Open a HID device by its path name.
#define HID_API_EXPORT_CALL
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.
void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device)
Close a HID device.
struct hid_device_ 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.
int HID_API_EXPORT HID_API_CALL hid_exit(void)
Finalize the HIDAPI library.
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 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 HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock)
Set the device handle to be non-blocking.
void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs)
Free an enumeration Linked List.
unsigned short product_id
struct hid_device_info * next
wchar_t * manufacturer_string
unsigned short release_number