Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : /*
8 : * This file defines a wrapper around libudev so we can avoid
9 : * linking directly to it and use dlopen instead.
10 : */
11 :
12 : #ifndef HAL_LINUX_UDEV_H_
13 : #define HAL_LINUX_UDEV_H_
14 :
15 : #include <dlfcn.h>
16 :
17 : #include "mozilla/ArrayUtils.h"
18 :
19 : namespace mozilla {
20 :
21 : struct udev;
22 : struct udev_device;
23 : struct udev_enumerate;
24 : struct udev_list_entry;
25 : struct udev_monitor;
26 :
27 : class udev_lib {
28 : public:
29 0 : udev_lib() : lib(nullptr),
30 0 : udev(nullptr) {
31 : // Be careful about ABI compat! 0 -> 1 didn't change any
32 : // symbols this code relies on, per:
33 : // https://lists.fedoraproject.org/pipermail/devel/2012-June/168227.html
34 0 : const char* lib_names[] = {"libudev.so.0", "libudev.so.1"};
35 : // Check whether a library is already loaded so we don't load two
36 : // conflicting libs.
37 0 : for (unsigned i = 0; i < ArrayLength(lib_names); i++) {
38 0 : lib = dlopen(lib_names[i], RTLD_NOLOAD | RTLD_LAZY | RTLD_GLOBAL);
39 0 : if (lib) {
40 0 : break;
41 : }
42 : }
43 : // If nothing loads the first time through, it means no version of libudev
44 : // was already loaded.
45 0 : if (!lib) {
46 0 : for (unsigned i = 0; i < ArrayLength(lib_names); i++) {
47 0 : lib = dlopen(lib_names[i], RTLD_LAZY | RTLD_GLOBAL);
48 0 : if (lib) {
49 0 : break;
50 : }
51 : }
52 : }
53 0 : if (lib && LoadSymbols()) {
54 0 : udev = udev_new();
55 : }
56 0 : }
57 :
58 0 : ~udev_lib() {
59 0 : if (udev) {
60 0 : udev_unref(udev);
61 : }
62 :
63 0 : if (lib) {
64 0 : dlclose(lib);
65 : }
66 0 : }
67 :
68 0 : explicit operator bool() {
69 0 : return udev;
70 : }
71 :
72 : private:
73 0 : bool LoadSymbols() {
74 : #define DLSYM(s) \
75 : do { \
76 : s = (typeof(s))dlsym(lib, #s); \
77 : if (!s) return false; \
78 : } while (0)
79 :
80 0 : DLSYM(udev_new);
81 0 : DLSYM(udev_unref);
82 0 : DLSYM(udev_device_unref);
83 0 : DLSYM(udev_device_new_from_syspath);
84 0 : DLSYM(udev_device_get_devnode);
85 0 : DLSYM(udev_device_get_parent_with_subsystem_devtype);
86 0 : DLSYM(udev_device_get_property_value);
87 0 : DLSYM(udev_device_get_action);
88 0 : DLSYM(udev_device_get_sysattr_value);
89 0 : DLSYM(udev_enumerate_new);
90 0 : DLSYM(udev_enumerate_unref);
91 0 : DLSYM(udev_enumerate_add_match_subsystem);
92 0 : DLSYM(udev_enumerate_scan_devices);
93 0 : DLSYM(udev_enumerate_get_list_entry);
94 0 : DLSYM(udev_list_entry_get_next);
95 0 : DLSYM(udev_list_entry_get_name);
96 0 : DLSYM(udev_monitor_new_from_netlink);
97 0 : DLSYM(udev_monitor_filter_add_match_subsystem_devtype);
98 0 : DLSYM(udev_monitor_enable_receiving);
99 0 : DLSYM(udev_monitor_get_fd);
100 0 : DLSYM(udev_monitor_receive_device);
101 0 : DLSYM(udev_monitor_unref);
102 : #undef DLSYM
103 0 : return true;
104 : }
105 :
106 : void* lib;
107 :
108 : public:
109 : struct udev* udev;
110 :
111 : // Function pointers returned from dlsym.
112 : struct udev* (*udev_new)(void);
113 : void (*udev_unref)(struct udev*);
114 :
115 : void (*udev_device_unref)(struct udev_device*);
116 : struct udev_device* (*udev_device_new_from_syspath)(struct udev*,
117 : const char*);
118 : const char* (*udev_device_get_devnode)(struct udev_device*);
119 : struct udev_device* (*udev_device_get_parent_with_subsystem_devtype)
120 : (struct udev_device*, const char*, const char*);
121 : const char* (*udev_device_get_property_value)(struct udev_device*,
122 : const char*);
123 : const char* (*udev_device_get_action)(struct udev_device*);
124 : const char* (*udev_device_get_sysattr_value)(struct udev_device*,
125 : const char*);
126 :
127 : struct udev_enumerate* (*udev_enumerate_new)(struct udev*);
128 : void (*udev_enumerate_unref)(struct udev_enumerate*);
129 : int (*udev_enumerate_add_match_subsystem)(struct udev_enumerate*,
130 : const char*);
131 : int (*udev_enumerate_scan_devices)(struct udev_enumerate*);
132 : struct udev_list_entry* (*udev_enumerate_get_list_entry)
133 : (struct udev_enumerate*);
134 :
135 : struct udev_list_entry* (*udev_list_entry_get_next)(struct udev_list_entry *);
136 : const char* (*udev_list_entry_get_name)(struct udev_list_entry*);
137 :
138 : struct udev_monitor* (*udev_monitor_new_from_netlink)(struct udev*,
139 : const char*);
140 : int (*udev_monitor_filter_add_match_subsystem_devtype)
141 : (struct udev_monitor*, const char*, const char*);
142 : int (*udev_monitor_enable_receiving)(struct udev_monitor*);
143 : int (*udev_monitor_get_fd)(struct udev_monitor*);
144 : struct udev_device* (*udev_monitor_receive_device)(struct udev_monitor*);
145 : void (*udev_monitor_unref)(struct udev_monitor*);
146 : };
147 :
148 : } // namespace mozilla
149 :
150 : #endif // HAL_LINUX_UDEV_H_
|