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