linux specific: Explicit linking of libudev because there are
two versions out there in the wild. libusb0 is still used on some LTS distros, for example on Centos6.
This commit is contained in:
parent
67b8506800
commit
67827546cf
2 changed files with 156 additions and 29 deletions
|
@ -13,5 +13,7 @@ include_directories(include)
|
||||||
add_library(hidapi STATIC ${HIDAPI_IMPL})
|
add_library(hidapi STATIC ${HIDAPI_IMPL})
|
||||||
|
|
||||||
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
target_link_libraries(hidapi udev)
|
# Don't link the udev library, as there are two versions out there (libudev.so.0, libudev.so.1), so they are linked explicitely.
|
||||||
|
# target_link_libraries(hidapi udev)
|
||||||
|
target_link_libraries(hidapi)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
/* Unix */
|
/* Unix */
|
||||||
|
#include <dlfcn.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
@ -45,6 +46,130 @@
|
||||||
|
|
||||||
#include "hidapi.h"
|
#include "hidapi.h"
|
||||||
|
|
||||||
|
typedef const char* (*hid_wrapper_udev_device_get_devnode_type)(struct udev_device *udev_device);
|
||||||
|
typedef struct udev_device* (*hid_wrapper_udev_device_get_parent_with_subsystem_devtype_type)(struct udev_device *udev_device, const char *subsystem, const char *devtype);
|
||||||
|
typedef const char* (*hid_wrapper_udev_device_get_sysattr_value_type)(struct udev_device *udev_device, const char *sysattr);
|
||||||
|
typedef struct udev_device* (*hid_wrapper_udev_device_new_from_devnum_type)(struct udev *udev, char type, dev_t devnum);
|
||||||
|
typedef struct udev_device* (*hid_wrapper_udev_device_new_from_syspath_type)(struct udev *udev, const char *syspath);
|
||||||
|
typedef struct udev_device* (*hid_wrapper_udev_device_unref_type)(struct udev_device *udev_device);
|
||||||
|
typedef int (*hid_wrapper_udev_enumerate_add_match_subsystem_type)(struct udev_enumerate *udev_enumerate, const char *subsystem);
|
||||||
|
typedef struct udev_list_entry* (*hid_wrapper_udev_enumerate_get_list_entry_type)(struct udev_enumerate *udev_enumerate);
|
||||||
|
typedef struct udev_enumerate* (*hid_wrapper_udev_enumerate_new_type)(struct udev *udev);
|
||||||
|
typedef int (*hid_wrapper_udev_enumerate_scan_devices_type)(struct udev_enumerate *udev_enumerate);
|
||||||
|
typedef struct udev_enumerate* (*hid_wrapper_udev_enumerate_unref_type)(struct udev_enumerate *udev_enumerate);
|
||||||
|
typedef const char* (*hid_wrapper_udev_list_entry_get_name_type)(struct udev_list_entry *list_entry);
|
||||||
|
typedef struct udev* (*hid_wrapper_udev_new_type)(void);
|
||||||
|
typedef struct udev* (*hid_wrapper_udev_unref_type)(struct udev *udev);
|
||||||
|
|
||||||
|
void *hid_wrapper_handle = NULL;
|
||||||
|
static hid_wrapper_udev_device_get_devnode_type hid_wrapper_udev_device_get_devnode = NULL;
|
||||||
|
static hid_wrapper_udev_device_get_parent_with_subsystem_devtype_type hid_wrapper_udev_device_get_parent_with_subsystem_devtype = NULL;
|
||||||
|
static hid_wrapper_udev_device_get_sysattr_value_type hid_wrapper_udev_device_get_sysattr_value = NULL;
|
||||||
|
static hid_wrapper_udev_device_new_from_devnum_type hid_wrapper_udev_device_new_from_devnum = NULL;
|
||||||
|
static hid_wrapper_udev_device_new_from_syspath_type hid_wrapper_udev_device_new_from_syspath = NULL;
|
||||||
|
static hid_wrapper_udev_device_unref_type hid_wrapper_udev_device_unref = NULL;
|
||||||
|
static hid_wrapper_udev_enumerate_add_match_subsystem_type hid_wrapper_udev_enumerate_add_match_subsystem = NULL;
|
||||||
|
static hid_wrapper_udev_enumerate_get_list_entry_type hid_wrapper_udev_enumerate_get_list_entry = NULL;
|
||||||
|
static hid_wrapper_udev_enumerate_new_type hid_wrapper_udev_enumerate_new = NULL;
|
||||||
|
static hid_wrapper_udev_enumerate_scan_devices_type hid_wrapper_udev_enumerate_scan_devices = NULL;
|
||||||
|
static hid_wrapper_udev_enumerate_unref_type hid_wrapper_udev_enumerate_unref = NULL;
|
||||||
|
static hid_wrapper_udev_list_entry_get_name_type hid_wrapper_udev_list_entry_get_name = NULL;
|
||||||
|
static hid_wrapper_udev_new_type hid_wrapper_udev_new = NULL;
|
||||||
|
static hid_wrapper_udev_unref_type hid_wrapper_udev_unref = NULL;
|
||||||
|
|
||||||
|
static void hid_wrapper_udev_close()
|
||||||
|
{
|
||||||
|
if (hid_wrapper_handle)
|
||||||
|
dlclose(hid_wrapper_handle);
|
||||||
|
hid_wrapper_handle = NULL;
|
||||||
|
hid_wrapper_udev_device_get_devnode = NULL;
|
||||||
|
hid_wrapper_udev_device_get_parent_with_subsystem_devtype = NULL;
|
||||||
|
hid_wrapper_udev_device_get_sysattr_value = NULL;
|
||||||
|
hid_wrapper_udev_device_new_from_devnum = NULL;
|
||||||
|
hid_wrapper_udev_device_new_from_syspath = NULL;
|
||||||
|
hid_wrapper_udev_device_unref = NULL;
|
||||||
|
hid_wrapper_udev_enumerate_add_match_subsystem = NULL;
|
||||||
|
hid_wrapper_udev_enumerate_get_list_entry = NULL;
|
||||||
|
hid_wrapper_udev_enumerate_new = NULL;
|
||||||
|
hid_wrapper_udev_enumerate_scan_devices = NULL;
|
||||||
|
hid_wrapper_udev_enumerate_unref = NULL;
|
||||||
|
hid_wrapper_udev_list_entry_get_name = NULL;
|
||||||
|
hid_wrapper_udev_new = NULL;
|
||||||
|
hid_wrapper_udev_unref = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *hid_wrapper_libudev_paths[] = {
|
||||||
|
// First try to find the libudev1.
|
||||||
|
"/lib/x86_64-linux-gnu/libudev.so.1", // Ubuntu, Xubuntu, Mint
|
||||||
|
"/usr/lib64/libudev.so.1", // SUSE, Fedora
|
||||||
|
"/usr/lib/libudev.so.1", // Arch, Fedora 32bit
|
||||||
|
"/lib/i386-linux-gnu/libudev.so.1", // Ubuntu 32bit
|
||||||
|
// If the search fails, try to find libudev0 (supporting CentOS6 and possibly other LTS distros).
|
||||||
|
"/lib/x86_64-linux-gnu/libudev.so.0", // Ubuntu, Xubuntu, Mint
|
||||||
|
"/usr/lib64/libudev.so.0", // SUSE, Fedora
|
||||||
|
"/usr/lib/libudev.so.0", // Arch, Fedora 32bit
|
||||||
|
"/lib/i386-linux-gnu/libudev.so.0" // Ubuntu 32bit
|
||||||
|
};
|
||||||
|
|
||||||
|
static int hid_wrapper_udev_init()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
hid_wrapper_udev_close();
|
||||||
|
|
||||||
|
// Search for the libudev0 or libudev1 library.
|
||||||
|
for (i = 0; i < sizeof(hid_wrapper_libudev_paths) / sizeof(hid_wrapper_libudev_paths[0]); ++ i)
|
||||||
|
if ((hid_wrapper_handle = dlopen(hid_wrapper_libudev_paths[i], RTLD_NOW | RTLD_GLOBAL)) != NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (hid_wrapper_handle == NULL) {
|
||||||
|
// Error, close the shared library handle and finish.
|
||||||
|
hid_wrapper_udev_close();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve the functions.
|
||||||
|
hid_wrapper_udev_device_get_devnode = (hid_wrapper_udev_device_get_devnode_type) dlsym(handle, "udev_device_get_devnode");
|
||||||
|
hid_wrapper_udev_device_get_parent_with_subsystem_devtype = (hid_wrapper_udev_device_get_parent_with_subsystem_devtype_type) dlsym(handle, "udev_device_get_parent_with_subsystem_devtype");
|
||||||
|
hid_wrapper_udev_device_get_sysattr_value = (hid_wrapper_udev_device_get_sysattr_value_type) dlsym(handle, "udev_device_get_sysattr_value");
|
||||||
|
hid_wrapper_udev_device_new_from_devnum = (hid_wrapper_udev_device_new_from_devnum_type) dlsym(handle, "udev_device_new_from_devnum");
|
||||||
|
hid_wrapper_udev_device_new_from_syspath = (hid_wrapper_udev_device_new_from_syspath_type) dlsym(handle, "udev_device_new_from_syspath");
|
||||||
|
hid_wrapper_udev_device_unref = (hid_wrapper_udev_device_unref_type) dlsym(handle, "udev_device_unref");
|
||||||
|
hid_wrapper_udev_enumerate_add_match_subsystem = (hid_wrapper_udev_enumerate_add_match_subsystem_type) dlsym(handle, "udev_enumerate_add_match_subsystem");
|
||||||
|
hid_wrapper_udev_enumerate_get_list_entry = (hid_wrapper_udev_enumerate_get_list_entry_type) dlsym(handle, "udev_enumerate_get_list_entry");
|
||||||
|
hid_wrapper_udev_enumerate_new = (hid_wrapper_udev_enumerate_new_type) dlsym(handle, "udev_enumerate_new");
|
||||||
|
hid_wrapper_udev_enumerate_scan_devices = (hid_wrapper_udev_enumerate_scan_devices_type) dlsym(handle, "udev_enumerate_scan_devices");
|
||||||
|
hid_wrapper_udev_enumerate_unref = (hid_wrapper_udev_enumerate_unref_type) dlsym(handle, "udev_enumerate_unref");
|
||||||
|
hid_wrapper_udev_list_entry_get_name = (hid_wrapper_udev_list_entry_get_name_type) dlsym(handle, "udev_list_entry_get_name");
|
||||||
|
hid_wrapper_udev_new = (hid_wrapper_udev_new_type) dlsym(handle, "udev_new");
|
||||||
|
hid_wrapper_udev_unref = (hid_wrapper_udev_unref_type) dlsym(handle, "udev_unref");
|
||||||
|
|
||||||
|
// Were all the funcions resolved?
|
||||||
|
if (hid_wrapper_handle == NULL ||
|
||||||
|
hid_wrapper_udev_device_get_devnode == NULL ||
|
||||||
|
hid_wrapper_udev_device_get_parent_with_subsystem_devtype == NULL ||
|
||||||
|
hid_wrapper_udev_device_get_sysattr_value == NULL ||
|
||||||
|
hid_wrapper_udev_device_new_from_devnum == NULL ||
|
||||||
|
hid_wrapper_udev_device_new_from_syspath == NULL ||
|
||||||
|
hid_wrapper_udev_device_unref == NULL ||
|
||||||
|
hid_wrapper_udev_enumerate_add_match_subsystem == NULL ||
|
||||||
|
hid_wrapper_udev_enumerate_get_list_entry == NULL ||
|
||||||
|
hid_wrapper_udev_enumerate_new == NULL ||
|
||||||
|
hid_wrapper_udev_enumerate_scan_devices == NULL ||
|
||||||
|
hid_wrapper_udev_enumerate_unref == NULL ||
|
||||||
|
hid_wrapper_udev_list_entry_get_name == NULL ||
|
||||||
|
hid_wrapper_udev_new == NULL ||
|
||||||
|
hid_wrapper_udev_unref == NULL)
|
||||||
|
{
|
||||||
|
// Error, close the shared library handle and finish.
|
||||||
|
hid_wrapper_udev_close();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Success.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Definitions from linux/hidraw.h. Since these are new, some distros
|
/* Definitions from linux/hidraw.h. Since these are new, some distros
|
||||||
may not have header files which contain them. */
|
may not have header files which contain them. */
|
||||||
#ifndef HIDIOCSFEATURE
|
#ifndef HIDIOCSFEATURE
|
||||||
|
@ -134,7 +259,7 @@ static wchar_t *utf8_to_wchar_t(const char *utf8)
|
||||||
string. The returned string must be freed with free() when done.*/
|
string. The returned string must be freed with free() when done.*/
|
||||||
static wchar_t *copy_udev_string(struct udev_device *dev, const char *udev_name)
|
static wchar_t *copy_udev_string(struct udev_device *dev, const char *udev_name)
|
||||||
{
|
{
|
||||||
return utf8_to_wchar_t(udev_device_get_sysattr_value(dev, udev_name));
|
return utf8_to_wchar_t(hid_wrapper_udev_device_get_sysattr_value(dev, udev_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* uses_numbered_reports() returns 1 if report_descriptor describes a device
|
/* uses_numbered_reports() returns 1 if report_descriptor describes a device
|
||||||
|
@ -267,7 +392,7 @@ static int get_device_string(hid_device *dev, enum device_string_id key, wchar_t
|
||||||
char *product_name_utf8 = NULL;
|
char *product_name_utf8 = NULL;
|
||||||
|
|
||||||
/* Create the udev object */
|
/* Create the udev object */
|
||||||
udev = udev_new();
|
udev = hid_wrapper_udev_new();
|
||||||
if (!udev) {
|
if (!udev) {
|
||||||
printf("Can't create udev\n");
|
printf("Can't create udev\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -278,9 +403,9 @@ static int get_device_string(hid_device *dev, enum device_string_id key, wchar_t
|
||||||
if (-1 == ret)
|
if (-1 == ret)
|
||||||
return ret;
|
return ret;
|
||||||
/* Open a udev device from the dev_t. 'c' means character device. */
|
/* Open a udev device from the dev_t. 'c' means character device. */
|
||||||
udev_dev = udev_device_new_from_devnum(udev, 'c', s.st_rdev);
|
udev_dev = hid_wrapper_udev_device_new_from_devnum(udev, 'c', s.st_rdev);
|
||||||
if (udev_dev) {
|
if (udev_dev) {
|
||||||
hid_dev = udev_device_get_parent_with_subsystem_devtype(
|
hid_dev = hid_wrapper_udev_device_get_parent_with_subsystem_devtype(
|
||||||
udev_dev,
|
udev_dev,
|
||||||
"hid",
|
"hid",
|
||||||
NULL);
|
NULL);
|
||||||
|
@ -291,7 +416,7 @@ static int get_device_string(hid_device *dev, enum device_string_id key, wchar_t
|
||||||
size_t retm;
|
size_t retm;
|
||||||
|
|
||||||
ret = parse_uevent_info(
|
ret = parse_uevent_info(
|
||||||
udev_device_get_sysattr_value(hid_dev, "uevent"),
|
hid_wrapper_udev_device_get_sysattr_value(hid_dev, "uevent"),
|
||||||
&bus_type,
|
&bus_type,
|
||||||
&dev_vid,
|
&dev_vid,
|
||||||
&dev_pid,
|
&dev_pid,
|
||||||
|
@ -320,7 +445,7 @@ static int get_device_string(hid_device *dev, enum device_string_id key, wchar_t
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* This is a USB device. Find its parent USB Device node. */
|
/* This is a USB device. Find its parent USB Device node. */
|
||||||
parent = udev_device_get_parent_with_subsystem_devtype(
|
parent = hid_wrapper_udev_device_get_parent_with_subsystem_devtype(
|
||||||
udev_dev,
|
udev_dev,
|
||||||
"usb",
|
"usb",
|
||||||
"usb_device");
|
"usb_device");
|
||||||
|
@ -335,7 +460,7 @@ static int get_device_string(hid_device *dev, enum device_string_id key, wchar_t
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
str = udev_device_get_sysattr_value(parent, key_str);
|
str = hid_wrapper_udev_device_get_sysattr_value(parent, key_str);
|
||||||
if (str) {
|
if (str) {
|
||||||
/* Convert the string from UTF-8 to wchar_t */
|
/* Convert the string from UTF-8 to wchar_t */
|
||||||
retm = mbstowcs(string, str, maxlen);
|
retm = mbstowcs(string, str, maxlen);
|
||||||
|
@ -351,10 +476,10 @@ end:
|
||||||
free(serial_number_utf8);
|
free(serial_number_utf8);
|
||||||
free(product_name_utf8);
|
free(product_name_utf8);
|
||||||
|
|
||||||
udev_device_unref(udev_dev);
|
hid_wrapper_udev_device_unref(udev_dev);
|
||||||
/* parent and hid_dev don't need to be (and can't be) unref'd.
|
/* parent and hid_dev don't need to be (and can't be) unref'd.
|
||||||
I'm not sure why, but they'll throw double-free() errors. */
|
I'm not sure why, but they'll throw double-free() errors. */
|
||||||
udev_unref(udev);
|
hid_wrapper_udev_unref(udev);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -370,16 +495,16 @@ int HID_API_EXPORT hid_init(void)
|
||||||
|
|
||||||
kernel_version = detect_kernel_version();
|
kernel_version = detect_kernel_version();
|
||||||
|
|
||||||
return 0;
|
return hid_wrapper_udev_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
int HID_API_EXPORT hid_exit(void)
|
int HID_API_EXPORT hid_exit(void)
|
||||||
{
|
{
|
||||||
/* Nothing to do for this in the Linux/hidraw implementation. */
|
/* Nothing to do for this in the Linux/hidraw implementation. */
|
||||||
|
hid_wrapper_udev_close();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id)
|
struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id)
|
||||||
{
|
{
|
||||||
struct udev *udev;
|
struct udev *udev;
|
||||||
|
@ -393,17 +518,17 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
|
||||||
hid_init();
|
hid_init();
|
||||||
|
|
||||||
/* Create the udev object */
|
/* Create the udev object */
|
||||||
udev = udev_new();
|
udev = hid_wrapper_udev_new();
|
||||||
if (!udev) {
|
if (!udev) {
|
||||||
printf("Can't create udev\n");
|
printf("Can't create udev\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a list of the devices in the 'hidraw' subsystem. */
|
/* Create a list of the devices in the 'hidraw' subsystem. */
|
||||||
enumerate = udev_enumerate_new(udev);
|
enumerate = hid_wrapper_udev_enumerate_new(udev);
|
||||||
udev_enumerate_add_match_subsystem(enumerate, "hidraw");
|
hid_wrapper_udev_enumerate_add_match_subsystem(enumerate, "hidraw");
|
||||||
udev_enumerate_scan_devices(enumerate);
|
hid_wrapper_udev_enumerate_scan_devices(enumerate);
|
||||||
devices = udev_enumerate_get_list_entry(enumerate);
|
devices = hid_wrapper_udev_enumerate_get_list_entry(enumerate);
|
||||||
/* For each item, see if it matches the vid/pid, and if so
|
/* For each item, see if it matches the vid/pid, and if so
|
||||||
create a udev_device record for it */
|
create a udev_device record for it */
|
||||||
udev_list_entry_foreach(dev_list_entry, devices) {
|
udev_list_entry_foreach(dev_list_entry, devices) {
|
||||||
|
@ -423,11 +548,11 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
|
||||||
|
|
||||||
/* Get the filename of the /sys entry for the device
|
/* Get the filename of the /sys entry for the device
|
||||||
and create a udev_device object (dev) representing it */
|
and create a udev_device object (dev) representing it */
|
||||||
sysfs_path = udev_list_entry_get_name(dev_list_entry);
|
sysfs_path = hid_wrapper_udev_list_entry_get_name(dev_list_entry);
|
||||||
raw_dev = udev_device_new_from_syspath(udev, sysfs_path);
|
raw_dev = hid_wrapper_udev_device_new_from_syspath(udev, sysfs_path);
|
||||||
dev_path = udev_device_get_devnode(raw_dev);
|
dev_path = hid_wrapper_udev_device_get_devnode(raw_dev);
|
||||||
|
|
||||||
hid_dev = udev_device_get_parent_with_subsystem_devtype(
|
hid_dev = hid_wrapper_udev_device_get_parent_with_subsystem_devtype(
|
||||||
raw_dev,
|
raw_dev,
|
||||||
"hid",
|
"hid",
|
||||||
NULL);
|
NULL);
|
||||||
|
@ -438,7 +563,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
|
||||||
}
|
}
|
||||||
|
|
||||||
result = parse_uevent_info(
|
result = parse_uevent_info(
|
||||||
udev_device_get_sysattr_value(hid_dev, "uevent"),
|
hid_wrapper_udev_device_get_sysattr_value(hid_dev, "uevent"),
|
||||||
&bus_type,
|
&bus_type,
|
||||||
&dev_vid,
|
&dev_vid,
|
||||||
&dev_pid,
|
&dev_pid,
|
||||||
|
@ -496,7 +621,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
|
||||||
subsystem/devtype pair of "usb"/"usb_device". This will
|
subsystem/devtype pair of "usb"/"usb_device". This will
|
||||||
be several levels up the tree, but the function will find
|
be several levels up the tree, but the function will find
|
||||||
it. */
|
it. */
|
||||||
usb_dev = udev_device_get_parent_with_subsystem_devtype(
|
usb_dev = hid_wrapper_udev_device_get_parent_with_subsystem_devtype(
|
||||||
raw_dev,
|
raw_dev,
|
||||||
"usb",
|
"usb",
|
||||||
"usb_device");
|
"usb_device");
|
||||||
|
@ -524,16 +649,16 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
|
||||||
cur_dev->product_string = copy_udev_string(usb_dev, device_string_names[DEVICE_STRING_PRODUCT]);
|
cur_dev->product_string = copy_udev_string(usb_dev, device_string_names[DEVICE_STRING_PRODUCT]);
|
||||||
|
|
||||||
/* Release Number */
|
/* Release Number */
|
||||||
str = udev_device_get_sysattr_value(usb_dev, "bcdDevice");
|
str = hid_wrapper_udev_device_get_sysattr_value(usb_dev, "bcdDevice");
|
||||||
cur_dev->release_number = (str)? strtol(str, NULL, 16): 0x0;
|
cur_dev->release_number = (str)? strtol(str, NULL, 16): 0x0;
|
||||||
|
|
||||||
/* Get a handle to the interface's udev node. */
|
/* Get a handle to the interface's udev node. */
|
||||||
intf_dev = udev_device_get_parent_with_subsystem_devtype(
|
intf_dev = hid_wrapper_udev_device_get_parent_with_subsystem_devtype(
|
||||||
raw_dev,
|
raw_dev,
|
||||||
"usb",
|
"usb",
|
||||||
"usb_interface");
|
"usb_interface");
|
||||||
if (intf_dev) {
|
if (intf_dev) {
|
||||||
str = udev_device_get_sysattr_value(intf_dev, "bInterfaceNumber");
|
str = hid_wrapper_udev_device_get_sysattr_value(intf_dev, "bInterfaceNumber");
|
||||||
cur_dev->interface_number = (str)? strtol(str, NULL, 16): -1;
|
cur_dev->interface_number = (str)? strtol(str, NULL, 16): -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -556,14 +681,14 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
|
||||||
next:
|
next:
|
||||||
free(serial_number_utf8);
|
free(serial_number_utf8);
|
||||||
free(product_name_utf8);
|
free(product_name_utf8);
|
||||||
udev_device_unref(raw_dev);
|
hid_wrapper_udev_device_unref(raw_dev);
|
||||||
/* hid_dev, usb_dev and intf_dev don't need to be (and can't be)
|
/* hid_dev, usb_dev and intf_dev don't need to be (and can't be)
|
||||||
unref()d. It will cause a double-free() error. I'm not
|
unref()d. It will cause a double-free() error. I'm not
|
||||||
sure why. */
|
sure why. */
|
||||||
}
|
}
|
||||||
/* Free the enumerator and udev objects. */
|
/* Free the enumerator and udev objects. */
|
||||||
udev_enumerate_unref(enumerate);
|
hid_wrapper_udev_enumerate_unref(enumerate);
|
||||||
udev_unref(udev);
|
hid_wrapper_udev_unref(udev);
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue