1 /* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef TEST_DEVICE_H 17 #define TEST_DEVICE_H 18 19 #include <chrono> 20 #include <thread> 21 22 #include <libevdev/libevdev-uinput.h> 23 #include <libevdev/libevdev.h> 24 25 class TestDevice { 26 public: 27 static constexpr auto TEST_BUS = 0xBAD; 28 static constexpr auto TEST_VENDOR = 0x1234; 29 static constexpr auto TEST_PRODUCT = 0x5678; 30 static constexpr auto TEST_VERSION = 0xAA; 31 static constexpr auto TEST_NAME = "test device"; 32 TestDevice()33 TestDevice() 34 { 35 evdev_ = libevdev_new(); 36 } 37 ~TestDevice()38 ~TestDevice() 39 { 40 if (uidev_ != nullptr) { 41 Destroy(); 42 } 43 libevdev_free(evdev_); 44 } 45 DefaultSetup()46 void DefaultSetup() 47 { 48 libevdev_set_name(evdev_, TEST_NAME); 49 libevdev_set_id_bustype(evdev_, TEST_BUS); 50 libevdev_set_id_vendor(evdev_, TEST_VENDOR); 51 libevdev_set_id_product(evdev_, TEST_PRODUCT); // fake product id 52 libevdev_set_id_version(evdev_, TEST_VERSION); // fake version id 53 libevdev_enable_event_type(evdev_, EV_REL); 54 libevdev_enable_event_code(evdev_, EV_REL, REL_X, nullptr); 55 libevdev_enable_event_code(evdev_, EV_REL, REL_Y, nullptr); 56 libevdev_enable_event_type(evdev_, EV_KEY); 57 libevdev_enable_event_code(evdev_, EV_KEY, BTN_LEFT, nullptr); 58 libevdev_enable_event_code(evdev_, EV_KEY, BTN_MIDDLE, nullptr); 59 libevdev_enable_event_code(evdev_, EV_KEY, BTN_RIGHT, nullptr); 60 } 61 AbsMouseSetup()62 void AbsMouseSetup() 63 { 64 libevdev_set_name(evdev_, TEST_NAME); 65 libevdev_enable_event_type(evdev_, EV_ABS); 66 input_absinfo info{.maximum = 100}; 67 libevdev_enable_event_code(evdev_, EV_ABS, ABS_X, &info); 68 libevdev_enable_event_code(evdev_, EV_ABS, ABS_Y, &info); 69 libevdev_enable_event_type(evdev_, EV_KEY); 70 libevdev_enable_event_code(evdev_, EV_KEY, BTN_LEFT, nullptr); 71 libevdev_enable_event_code(evdev_, EV_KEY, BTN_MIDDLE, nullptr); 72 libevdev_enable_event_code(evdev_, EV_KEY, BTN_RIGHT, nullptr); 73 // Test special case with too many axis here too 74 libevdev_enable_event_code(evdev_, EV_ABS, ABS_MT_POSITION_X, &info); 75 libevdev_enable_event_code(evdev_, EV_ABS, ABS_MT_POSITION_Y, &info); 76 libevdev_enable_event_code(evdev_, EV_ABS, ABS_MT_SLOT, &info); 77 libevdev_enable_event_code(evdev_, EV_ABS, ABS_MT_SLOT - 1, &info); 78 } 79 WheelSetup()80 void WheelSetup() 81 { 82 // Also test special names 83 libevdev_set_name(evdev_, TEST_NAME); 84 libevdev_enable_event_type(evdev_, EV_REL); 85 libevdev_enable_event_code(evdev_, EV_REL, REL_WHEEL, nullptr); 86 } 87 KeyboardSetup()88 void KeyboardSetup() 89 { 90 libevdev_set_name(evdev_, TEST_NAME); 91 libevdev_enable_event_type(evdev_, EV_KEY); 92 for (int32_t i = KEY_ESC; i < KEY_D; i++) { 93 libevdev_enable_event_code(evdev_, EV_KEY, i, nullptr); 94 } 95 } 96 SwitchSetup()97 void SwitchSetup() 98 { 99 libevdev_set_name(evdev_, TEST_NAME); 100 libevdev_enable_event_type(evdev_, EV_SW); 101 libevdev_enable_event_code(evdev_, EV_SW, 0, nullptr); 102 } 103 AccelerometerSetup()104 void AccelerometerSetup() 105 { 106 libevdev_set_name(evdev_, TEST_NAME); 107 libevdev_enable_event_type(evdev_, EV_ABS); 108 input_absinfo info{.maximum = 100}; 109 libevdev_enable_event_code(evdev_, EV_ABS, ABS_X, &info); 110 libevdev_enable_event_code(evdev_, EV_ABS, ABS_Y, &info); 111 libevdev_enable_event_code(evdev_, EV_ABS, ABS_Z, &info); 112 libevdev_enable_property(evdev_, INPUT_PROP_ACCELEROMETER); 113 } 114 StickSetup()115 void StickSetup() 116 { 117 libevdev_set_name(evdev_, TEST_NAME); 118 libevdev_enable_property(evdev_, INPUT_PROP_POINTING_STICK); 119 } 120 TouchpadSetup()121 void TouchpadSetup() 122 { 123 libevdev_set_name(evdev_, TEST_NAME); 124 libevdev_enable_event_type(evdev_, EV_ABS); 125 input_absinfo info{.maximum = 100}; 126 libevdev_enable_event_code(evdev_, EV_ABS, ABS_X, &info); 127 libevdev_enable_event_code(evdev_, EV_ABS, ABS_Y, &info); 128 libevdev_enable_event_code(evdev_, EV_ABS, ABS_MT_POSITION_X, &info); 129 libevdev_enable_event_code(evdev_, EV_ABS, ABS_MT_POSITION_Y, &info); 130 libevdev_enable_event_type(evdev_, EV_KEY); 131 libevdev_enable_event_code(evdev_, EV_KEY, BTN_TOOL_FINGER, nullptr); 132 libevdev_enable_event_code(evdev_, EV_KEY, BTN_TOUCH, nullptr); 133 } 134 TouchscreenSetup()135 void TouchscreenSetup() 136 { 137 libevdev_set_name(evdev_, TEST_NAME); 138 libevdev_enable_event_type(evdev_, EV_ABS); 139 input_absinfo info{.maximum = 100}; 140 libevdev_enable_event_code(evdev_, EV_ABS, ABS_X, &info); 141 libevdev_enable_event_code(evdev_, EV_ABS, ABS_Y, &info); 142 libevdev_enable_event_code(evdev_, EV_ABS, ABS_MT_POSITION_X, &info); 143 libevdev_enable_event_code(evdev_, EV_ABS, ABS_MT_POSITION_Y, &info); 144 libevdev_enable_event_type(evdev_, EV_KEY); 145 libevdev_enable_event_code(evdev_, EV_KEY, BTN_TOUCH, nullptr); 146 libevdev_enable_property(evdev_, INPUT_PROP_DIRECT); 147 } 148 JoystickSetup()149 void JoystickSetup() 150 { 151 libevdev_set_name(evdev_, TEST_NAME); 152 libevdev_enable_event_type(evdev_, EV_KEY); 153 libevdev_enable_event_code(evdev_, EV_KEY, BTN_JOYSTICK, nullptr); 154 } 155 JoystickSetup1()156 void JoystickSetup1() 157 { 158 libevdev_set_name(evdev_, TEST_NAME); 159 libevdev_enable_event_type(evdev_, EV_ABS); 160 input_absinfo info{.maximum = 100}; 161 libevdev_enable_event_code(evdev_, EV_ABS, ABS_X, &info); 162 libevdev_enable_event_code(evdev_, EV_ABS, ABS_Y, &info); 163 libevdev_enable_event_code(evdev_, EV_ABS, ABS_RX, &info); 164 libevdev_enable_event_code(evdev_, EV_ABS, ABS_RY, &info); 165 } 166 TabletSetup()167 void TabletSetup() 168 { 169 libevdev_set_name(evdev_, TEST_NAME); 170 libevdev_enable_event_type(evdev_, EV_ABS); 171 input_absinfo info{.maximum = 100, .resolution = 10}; 172 libevdev_enable_event_code(evdev_, EV_ABS, ABS_X, &info); 173 libevdev_enable_event_code(evdev_, EV_ABS, ABS_Y, &info); 174 libevdev_enable_event_code(evdev_, EV_ABS, ABS_MT_POSITION_X, &info); 175 libevdev_enable_event_code(evdev_, EV_ABS, ABS_MT_POSITION_Y, &info); 176 libevdev_enable_event_type(evdev_, EV_KEY); 177 libevdev_enable_event_code(evdev_, EV_KEY, BTN_STYLUS, nullptr); 178 } 179 Destroy()180 void Destroy() 181 { 182 libevdev_uinput_destroy(uidev_); 183 uidev_ = nullptr; 184 } 185 GetDevNode()186 auto GetDevNode() 187 { 188 return libevdev_uinput_get_devnode(uidev_); 189 } 190 GetSysPath()191 auto GetSysPath() 192 { 193 return libevdev_uinput_get_syspath(uidev_); 194 } 195 GetDevNum()196 auto GetDevNum() const 197 { 198 return devnum_; 199 } 200 SetDevnum()201 bool SetDevnum() 202 { 203 const auto* fname = libevdev_uinput_get_devnode(uidev_); 204 if (fname == nullptr) { 205 return false; 206 } 207 struct stat st; 208 int t = stat(fname, &st); 209 if (t < 0) { 210 return false; 211 } 212 devnum_ = st.st_rdev; 213 return true; 214 } 215 216 void Init(bool def = true) 217 { 218 using namespace std::chrono_literals; 219 constexpr auto initDelay = 50ms; 220 ASSERT_NE(evdev_, nullptr); 221 if (def) { 222 DefaultSetup(); 223 } 224 auto res = libevdev_uinput_create_from_device(evdev_, LIBEVDEV_UINPUT_OPEN_MANAGED, &uidev_); 225 auto err = std::error_code{errno, std::system_category()}; 226 ASSERT_EQ(res, 0) << "Failed to create uinput device. Error: " << err.message() 227 << (err == std::errc::permission_denied ? ". Run test as ROOT!" : "") << std::endl; 228 ASSERT_NE(uidev_, nullptr); 229 230 std::this_thread::sleep_for(initDelay); 231 ASSERT_TRUE(SetDevnum()); 232 } 233 234 private: 235 struct libevdev* evdev_ {}; 236 struct libevdev_uinput* uidev_ {}; 237 dev_t devnum_ {}; 238 }; 239 #endif // TEST_DEVICE_H 240