|
| 1 | +local ffi = require("ffi") |
| 2 | + |
| 3 | +local Event = require("evdev.event") |
| 4 | +local evdev = require("evdev.libevdev") |
| 5 | +local util = require("evdev.util") |
| 6 | + |
| 7 | +local libevdev_grab_mode = evdev.enum.libevdev_grab_mode |
| 8 | +local libevdev_read_flag = evdev.enum.libevdev_read_flag |
| 9 | +local open_flag = util.enum.open_flag |
| 10 | + |
| 11 | +---@class Device |
| 12 | +---@field fd number |
| 13 | +---@field pathname string |
| 14 | +---@field dev ffi.cdata* |
| 15 | +local Device = {} |
| 16 | + |
| 17 | +---@param pathname string |
| 18 | +---@param flags number[] `open_flag[]` |
| 19 | +---@return Device |
| 20 | +local function init(class, pathname, flags) |
| 21 | + ---@type Device |
| 22 | + local self = setmetatable({}, { __index = class }) |
| 23 | + |
| 24 | + self.pathname = pathname |
| 25 | + |
| 26 | + local fd = util.open_file(pathname, flags or { open_flag.RDONLY, open_flag.NONBLOCK }) |
| 27 | + if fd < 0 then |
| 28 | + return nil, string.format("Error: %s", util.err_string(ffi.errno())) |
| 29 | + end |
| 30 | + |
| 31 | + self.fd = fd |
| 32 | + |
| 33 | + local dev_ptr = ffi.new("struct libevdev *[1]") |
| 34 | + |
| 35 | + local rc = evdev.libevdev_new_from_fd(fd, dev_ptr) |
| 36 | + if rc < 0 then |
| 37 | + return nil, string.format("Error: %s", util.err_string(-rc)) |
| 38 | + end |
| 39 | + |
| 40 | + self.dev = dev_ptr[0] |
| 41 | + |
| 42 | + ffi.gc(dev_ptr, evdev.libevdev_free) |
| 43 | + |
| 44 | + return self |
| 45 | +end |
| 46 | + |
| 47 | +---@param pathname string |
| 48 | +---@param flags number[] `open_flag[]` |
| 49 | +---@return Device |
| 50 | +function Device:new(pathname, flags) |
| 51 | + return init(self, pathname, flags) |
| 52 | +end |
| 53 | + |
| 54 | +---@param mode boolean|number `libevdev_grab_mode` |
| 55 | +---@return number |
| 56 | +function Device:grab(mode) |
| 57 | + if mode == true then |
| 58 | + mode = libevdev_grab_mode.GRAB |
| 59 | + elseif mode == false then |
| 60 | + mode = libevdev_grab_mode.UNGRAB |
| 61 | + end |
| 62 | + |
| 63 | + return evdev.libevdev_grab(self.dev, mode) |
| 64 | +end |
| 65 | + |
| 66 | +---@param flags? number|number[] `libevdev_read_flag` or `libevdev_read_flag[]` (default: `NORMAL`) |
| 67 | +---@param event? Event |
| 68 | +---@return number rc, Event event |
| 69 | +function Device:next_event(flags, event) |
| 70 | + local flag = util.bit_or(flags or libevdev_read_flag.NORMAL) |
| 71 | + event = event or Event:new() |
| 72 | + local rc = evdev.libevdev_next_event(self.dev, flag, event.ev) |
| 73 | + return rc, event |
| 74 | +end |
| 75 | + |
| 76 | +---@return boolean |
| 77 | +function Device:has_event_pending() |
| 78 | + return evdev.libevdev_has_event_pending(self.dev) == 1 |
| 79 | +end |
| 80 | + |
| 81 | +---@return string |
| 82 | +function Device:name() |
| 83 | + return util.to_string(evdev.libevdev_get_name(self.dev)) |
| 84 | +end |
| 85 | + |
| 86 | +---@return string |
| 87 | +function Device:phys() |
| 88 | + return util.to_string(evdev.libevdev_get_phys(self.dev)) |
| 89 | +end |
| 90 | + |
| 91 | +---@return string |
| 92 | +function Device:uniq() |
| 93 | + return util.to_string(evdev.libevdev_get_uniq(self.dev)) |
| 94 | +end |
| 95 | + |
| 96 | +---@return number |
| 97 | +function Device:id_product() |
| 98 | + return evdev.libevdev_get_id_product(self.dev) |
| 99 | +end |
| 100 | + |
| 101 | +---@return number |
| 102 | +function Device:id_vendor() |
| 103 | + return evdev.libevdev_get_id_vendor(self.dev) |
| 104 | +end |
| 105 | + |
| 106 | +---@return number |
| 107 | +function Device:id_bustype() |
| 108 | + return evdev.libevdev_get_id_bustype(self.dev) |
| 109 | +end |
| 110 | + |
| 111 | +---@return number |
| 112 | +function Device:id_version() |
| 113 | + return evdev.libevdev_get_id_version(self.dev) |
| 114 | +end |
| 115 | + |
| 116 | +---@return number |
| 117 | +function Device:driver_version() |
| 118 | + return evdev.libevdev_get_driver_version(self.dev) |
| 119 | +end |
| 120 | + |
| 121 | +---@param prop number |
| 122 | +---@return boolean |
| 123 | +function Device:has_property(prop) |
| 124 | + return evdev.libevdev_has_property(self.dev, prop) == 1 |
| 125 | +end |
| 126 | + |
| 127 | +---@param prop number |
| 128 | +---@return number |
| 129 | +function Device:enable_property(prop) |
| 130 | + return evdev.libevdev_enable_property(self.dev, prop) |
| 131 | +end |
| 132 | + |
| 133 | +---@param prop number |
| 134 | +---@return number |
| 135 | +function Device:disable_property(prop) |
| 136 | + return evdev.libevdev_disable_property(self.dev, prop) |
| 137 | +end |
| 138 | + |
| 139 | +---@param ev_type number |
| 140 | +---@return boolean |
| 141 | +function Device:has_event_type(ev_type) |
| 142 | + return evdev.libevdev_has_event_type(self.dev, ev_type) == 1 |
| 143 | +end |
| 144 | + |
| 145 | +---@param ev_type number |
| 146 | +---@param ev_code number |
| 147 | +---@return boolean |
| 148 | +function Device:has_event_code(ev_type, ev_code) |
| 149 | + return evdev.libevdev_has_event_code(self.dev, ev_type, ev_code) == 1 |
| 150 | +end |
| 151 | + |
| 152 | +---@param code number |
| 153 | +---@return number |
| 154 | +function Device:abs_minimum(code) |
| 155 | + return evdev.libevdev_get_abs_minimum(self.dev, code) |
| 156 | +end |
| 157 | + |
| 158 | +---@param code number |
| 159 | +---@return number |
| 160 | +function Device:abs_maximum(code) |
| 161 | + return evdev.libevdev_get_abs_maximum(self.dev, code) |
| 162 | +end |
| 163 | + |
| 164 | +---@param code number |
| 165 | +---@return number |
| 166 | +function Device:abs_fuzz(code) |
| 167 | + return evdev.libevdev_get_abs_fuzz(self.dev, code) |
| 168 | +end |
| 169 | + |
| 170 | +---@param code number |
| 171 | +---@return number |
| 172 | +function Device:abs_flat(code) |
| 173 | + return evdev.libevdev_get_abs_flat(self.dev, code) |
| 174 | +end |
| 175 | + |
| 176 | +---@param code number |
| 177 | +---@return number |
| 178 | +function Device:abs_resolution(code) |
| 179 | + return evdev.libevdev_get_abs_resolution(self.dev, code) |
| 180 | +end |
| 181 | + |
| 182 | +---@param code number |
| 183 | +---@return ffi.cdata*|evdev_input_absinfo |
| 184 | +function Device:abs_info(code) |
| 185 | + return evdev.libevdev_get_abs_info(self.dev, code) |
| 186 | +end |
| 187 | + |
| 188 | +---@param ev_type number |
| 189 | +---@param code number |
| 190 | +---@return number |
| 191 | +function Device:event_value(ev_type, code) |
| 192 | + return evdev.libevdev_get_event_value(self.dev, ev_type, code) |
| 193 | +end |
| 194 | + |
| 195 | +---@param ev_type number |
| 196 | +---@param code number |
| 197 | +---@param value_ptr? ffi.cdata* |
| 198 | +---@return number|nil |
| 199 | +function Device:fetch_event_value(ev_type, code, value_ptr) |
| 200 | + value_ptr = value_ptr or ffi.new("int[1]") |
| 201 | + local rc = evdev.libevdev_fetch_event_value(self.dev, ev_type, code, value_ptr) |
| 202 | + if rc ~= 0 then |
| 203 | + return value_ptr[0] |
| 204 | + end |
| 205 | +end |
| 206 | + |
| 207 | +---@param slot number |
| 208 | +---@param code number |
| 209 | +---@return number |
| 210 | +function Device:slot_value(slot, code) |
| 211 | + return evdev.libevdev_get_slot_value(self.dev, slot, code) |
| 212 | +end |
| 213 | + |
| 214 | +---@param slot number |
| 215 | +---@param code number |
| 216 | +---@param value_ptr? ffi.cdata* |
| 217 | +---@return number|nil |
| 218 | +function Device:fetch_slot_value(slot, code, value_ptr) |
| 219 | + value_ptr = value_ptr or ffi.new("int[1]") |
| 220 | + local rc = evdev.libevdev_fetch_slot_value(self.dev, slot, code, value_ptr) |
| 221 | + if rc ~= 0 then |
| 222 | + return value_ptr[0] |
| 223 | + end |
| 224 | +end |
| 225 | + |
| 226 | +---@return number |
| 227 | +function Device:num_slots() |
| 228 | + return evdev.libevdev_get_num_slots(self.dev) |
| 229 | +end |
| 230 | + |
| 231 | +---@return number |
| 232 | +function Device:current_slot() |
| 233 | + return evdev.libevdev_get_current_slot(self.dev) |
| 234 | +end |
| 235 | + |
| 236 | +---@param ev_type number |
| 237 | +---@return number |
| 238 | +function Device:enable_event_type(ev_type) |
| 239 | + return evdev.libevdev_enable_event_type(self.dev, ev_type) |
| 240 | +end |
| 241 | + |
| 242 | +---@param ev_type number |
| 243 | +---@return number |
| 244 | +function Device:disable_event_type(ev_type) |
| 245 | + return evdev.libevdev_disable_event_type(self.dev, ev_type) |
| 246 | +end |
| 247 | + |
| 248 | +---@param ev_type number |
| 249 | +---@param code number |
| 250 | +---@param data? nil|ffi.cdata*|evdev_input_absinfo|number |
| 251 | +---@return number |
| 252 | +function Device:enable_event_code(ev_type, code, data) |
| 253 | + local data_type = type(data) |
| 254 | + if data_type == "number" then |
| 255 | + data = ffi.new("int", data) |
| 256 | + elseif data_type == "table" then |
| 257 | + data = ffi.new("struct input_absinfo", data) |
| 258 | + end |
| 259 | + |
| 260 | + return evdev.libevdev_enable_event_code(self.dev, ev_type, code, data) |
| 261 | +end |
| 262 | + |
| 263 | +---@param ev_type number |
| 264 | +---@param code number |
| 265 | +---@return number |
| 266 | +function Device:disable_event_code(ev_type, code) |
| 267 | + return evdev.libevdev_disable_event_code(self.dev, ev_type, code) |
| 268 | +end |
| 269 | + |
| 270 | +return Device |
0 commit comments