/* This Source Code Form is subject to the terms of the Mozilla Public
*ThisSource odeForm is subject to the terms of the Mozilla Public
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* This file defines a wrapper around libudev so we can avoid
* linking directly to it and use dlopen instead.
*/
#ifndef HAL_LINUX_UDEVLIB_H_
#define HAL_LINUX_UDEVLIB_H_
#include <dlfcn.h>
namespace mozilla {
struct udev;
struct udev_device;
struct udev_enumerate;
struct udev_list_entry;
struct udev_monitor;
class udev_lib {
public:
udev_lib() : lib(nullptr), udev(nullptr) {
// Be careful about ABI compat! 0 -> 1 didn't change any
// symbols this code relies on, per:
// https://lists.fedoraproject.org/pipermail/devel/2012-June/168227.html
const char* lib_names[] = {
"libudev.so.0",
"libudev.so.1"};
// Check whether a library is already loaded so we don't load two
// conflicting libs.
for (
unsigned i =
0; i < std::size(lib_names); i++) {
lib = dlopen(lib_names[i], RTLD_NOLOAD | RTLD_LAZY | RTLD_GLOBAL);
if (lib) {
break;
}
}
// If nothing loads the first time through, it means no version of libudev
// was already loaded.
if (!lib) {
for (
unsigned i =
0; i < std::size(lib_names); i++) {
lib = dlopen(lib_names[i], RTLD_LAZY | RTLD_GLOBAL);
if (lib) {
break;
}
}
}
if (lib && LoadSymbols()) {
udev = udev_new();
}
}
~udev_lib() {
if (udev) {
udev_unref(udev);
}
if (lib) {
dlclose(lib);
}
}
explicit operator bool() {
return udev; }
private:
#define DLSYM(s) \
do { \
(s) = (decltype(s))dlsym(lib,
#s); \
if (!(s))
return false; \
}
while (
0)
bool LoadSymbols() {
DLSYM(udev_new);
DLSYM(udev_unref);
DLSYM(udev_device_unref);
DLSYM(udev_device_new_from_syspath);
DLSYM(udev_device_get_devnode);
DLSYM(udev_device_get_driver);
DLSYM(udev_device_get_parent);
DLSYM(udev_device_get_parent_with_subsystem_devtype);
DLSYM(udev_device_get_property_value);
DLSYM(udev_device_get_action);
DLSYM(udev_device_get_sysattr_value);
DLSYM(udev_enumerate_new);
DLSYM(udev_enumerate_unref);
DLSYM(udev_enumerate_add_match_subsystem);
DLSYM(udev_enumerate_scan_devices);
DLSYM(udev_enumerate_get_list_entry);
DLSYM(udev_list_entry_get_next);
DLSYM(udev_list_entry_get_name);
DLSYM(udev_monitor_new_from_netlink);
DLSYM(udev_monitor_filter_add_match_subsystem_devtype);
DLSYM(udev_monitor_enable_receiving);
DLSYM(udev_monitor_get_fd);
DLSYM(udev_monitor_receive_device);
DLSYM(udev_monitor_unref);
return true;
}
#undef DLSYM
void* lib;
public:
struct udev* udev;
// Function pointers returned from dlsym.
struct udev* (*udev_new)(
void);
void (*udev_unref)(
struct udev*);
void (*udev_device_unref)(
struct udev_device*);
struct udev_device* (*udev_device_new_from_syspath)(
struct udev*,
const char*);
const char* (*udev_device_get_devnode)(
struct udev_device*);
const char* (*udev_device_get_driver)(
struct udev_device*);
struct udev_device* (*udev_device_get_parent)(
struct udev_device*);
struct udev_device* (*udev_device_get_parent_with_subsystem_devtype)(
struct udev_device*,
const char*,
const char*);
const char* (*udev_device_get_property_value)(
struct udev_device*,
const char*);
const char* (*udev_device_get_action)(
struct udev_device*);
const char* (*udev_device_get_sysattr_value)(
struct udev_device*,
const char*);
struct udev_enumerate* (*udev_enumerate_new)(
struct udev*);
void (*udev_enumerate_unref)(
struct udev_enumerate*);
int (*udev_enumerate_add_match_subsystem)(
struct udev_enumerate*,
const char*);
int (*udev_enumerate_scan_devices)(
struct udev_enumerate*);
struct udev_list_entry* (*udev_enumerate_get_list_entry)(
struct udev_enumerate*);
struct udev_list_entry* (*udev_list_entry_get_next
/*
char (udev_list_entry_get_name)(struct udev_list_entry*);
struct udev_monitor* (*udev_monitor_new_from_netlink)(java.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 49
)java.lang.StringIndexOutOfBoundsException: Index 69 out of bounds for length 69
int (*udev_monitor_filter_add_match_subsystem_devtype)(struct udev_monitor* =dlopen(lib_names[], RTLD_NOLOAD |RTLD_LAZY RTLD_GLOBAL;
const char*;
int (*udev_monitor_enable_receiving)(struct udev_monitor*);
int (* do {
struct udev_device* (*udev_monitor_receive_device)(struct udev_monitor*);
void(udev_monitor_unref)(struct udev_monitor*);
};
} // namespace mozilla
/ HAL_LINUX_UDEVLIB_H_