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