1818
1919#include <errno.h>
2020#include <fcntl.h>
21- #include <glob.h>
2221#include <libevdev/libevdev.h>
2322#include <libevdev/libevdev-uinput.h>
23+ #include <libudev.h>
2424#include <stdlib.h>
25+ #include <string.h>
2526#include <sys/epoll.h>
2627#include <uiohook.h>
2728#include <unistd.h>
3031#include "input_helper.h"
3132#include "logger.h"
3233
33- #define EVENT_GLOB_PATTERN "/dev/input/event*"
34-
35-
3634struct input_hook {
3735 struct libevdev * evdev ;
3836 struct libevdev_uinput * uinput ;
3937};
4038
39+ struct epoll_event_listener {
40+ struct epoll_event epoll ;
41+ struct epoll_event_listener * next ;
42+ };
43+
4144static int rel_x = 0 , rel_y = 0 ;
4245static int wheel_h = 0 , wheel_v = 0 ;
4346
@@ -148,7 +151,7 @@ static bool hook_event_proc(struct input_event *ev) {
148151 return consumed ;
149152}
150153
151- static int create_hook (char * path , struct input_hook * * hook ) {
154+ static int create_hook (const char * path , struct input_hook * * hook ) {
152155 int fd = open (path , O_RDONLY | O_NONBLOCK );
153156 if (fd < 0 ) {
154157 logger (LOG_LEVEL_ERROR , "%s [%u]: Failed to open input device: %s! (%d)\n" ,
@@ -158,21 +161,21 @@ static int create_hook(char *path, struct input_hook **hook) {
158161 }
159162
160163 * hook = malloc (sizeof (struct input_hook ));
161- if (hook == NULL ) {
164+ if (* hook == NULL ) {
162165 logger (LOG_LEVEL_ERROR , "%s [%u]: Failed to allocate memory for evdev buffer!\n" ,
163166 __FUNCTION__ , __LINE__ );
164167 return UIOHOOK_ERROR_OUT_OF_MEMORY ;
165168 }
166169
167170 int err = libevdev_new_from_fd (fd , & (* hook )-> evdev );
168171 if (err < 0 ) {
169- logger (LOG_LEVEL_ERROR , "%s [%u]: Failed to create evdev from file descriptor! (%d)\n" ,
172+ logger (LOG_LEVEL_ERROR , "%s [%u]: Failed to create evdev from file descriptor: %s ! (%d)\n" ,
170173 __FUNCTION__ , __LINE__ ,
171- err );
174+ path , err );
172175 return UIOHOOK_FAILURE ;
173176 }
174177
175- // We need to wait until no key is being pressed becasue we are going to grab below and that will cause keys to stick.
178+ // We need to wait until no key is being pressed because we are going to grab below and that will cause keys to stick.
176179 struct input_event ev ;
177180 for (unsigned int i = 0 ; i < KEY_MAX ; i ++ ) {
178181 while (libevdev_get_event_value ((* hook )-> evdev , EV_KEY , i )) {
@@ -219,7 +222,7 @@ static int create_hook(char *path, struct input_hook **hook) {
219222 return UIOHOOK_FAILURE ;
220223 }
221224
222- logger (LOG_LEVEL_DEBUG , "%s [%u]: Found %s device: %s.\n" ,
225+ logger (LOG_LEVEL_DEBUG , "%s [%u]: Registering %s device: %s.\n" ,
223226 __FUNCTION__ , __LINE__ ,
224227 label , path );
225228
@@ -228,107 +231,127 @@ static int create_hook(char *path, struct input_hook **hook) {
228231
229232static void destroy_hook (struct input_hook * * hook ) {
230233 if (* hook != NULL ) {
231- int fd = libevdev_get_fd ((* hook )-> evdev );
232-
233- if ((* hook )-> evdev != NULL ) {
234- libevdev_grab ((* hook )-> evdev , LIBEVDEV_UNGRAB );
235- libevdev_free ((* hook )-> evdev );
236- (* hook )-> evdev = NULL ;
237- }
238-
239- if ((* hook )-> uinput != NULL ) {
240- libevdev_uinput_destroy ((* hook )-> uinput );
241- (* hook )-> uinput = NULL ;
242- }
243-
244- free (* hook );
245- * hook = NULL ;
246-
247- if (fd >= 0 ) {
248- close (fd );
249- }
234+ return ;
250235 }
251- }
252236
237+ const int fd = libevdev_get_fd ((* hook )-> evdev );
253238
254- static int create_glob_buffer (glob_t * glob_buffer ) {
255- int status = glob (EVENT_GLOB_PATTERN , GLOB_ERR | GLOB_NOSORT | GLOB_NOESCAPE , NULL , glob_buffer );
256- switch (status ) {
257- case GLOB_NOSPACE :
258- logger (LOG_LEVEL_ERROR , "%s [%u]: Failed to allocate memory for glob!\n" ,
259- __FUNCTION__ , __LINE__ );
260- return UIOHOOK_ERROR_OUT_OF_MEMORY ;
261-
262- default :
263- logger (LOG_LEVEL_ERROR , "%s [%u]: Failed to call glob()! (%d)\n" ,
264- __FUNCTION__ , __LINE__ ,
265- status );
266- return UIOHOOK_FAILURE ;
239+ if ((* hook )-> evdev != NULL ) {
240+ libevdev_grab ((* hook )-> evdev , LIBEVDEV_UNGRAB );
241+ libevdev_free ((* hook )-> evdev );
242+ (* hook )-> evdev = NULL ;
243+ }
267244
268- case 0 :
269- // Success
245+ if ((* hook )-> uinput != NULL ) {
246+ libevdev_uinput_destroy ((* hook )-> uinput );
247+ (* hook )-> uinput = NULL ;
270248 }
271249
272- return UIOHOOK_SUCCESS ;
273- }
250+ free ( * hook ) ;
251+ * hook = NULL ;
274252
275- static void destroy_glob (glob_t * glob_buffer ) {
276- globfree (glob_buffer );
253+ if (fd >= 0 ) {
254+ close (fd );
255+ }
277256}
278257
279-
280- static int create_event_listeners (int epoll_fd , struct epoll_event * * listeners ) {
281- glob_t glob_buffer ;
282- int status = create_glob_buffer (& glob_buffer );
283- if (status != UIOHOOK_SUCCESS ) {
284- destroy_glob (& glob_buffer );
285- return status ;
258+ static int create_event_listeners (int epoll_fd , struct epoll_event_listener * * listeners ) {
259+ struct udev * udev = udev_new ();
260+ if (udev == NULL ) {
261+ logger (LOG_LEVEL_ERROR , "%s [%u]: Failed to create new udev context!\n" ,
262+ __FUNCTION__ , __LINE__ );
263+ return UIOHOOK_FAILURE ;
286264 }
287265
288- struct epoll_event * event_buffer = * listeners = malloc ( sizeof ( struct epoll_event ) * glob_buffer . gl_pathc );
289- if ( event_buffer == NULL ) {
290- logger ( LOG_LEVEL_ERROR , "%s [%u]: Failed to allocate memory for epoll event devices!\n" ,
291- __FUNCTION__ , __LINE__ );
266+ struct udev_enumerate * enumerate = udev_enumerate_new ( udev );
267+ udev_enumerate_add_match_subsystem ( enumerate , "input" );
268+ udev_enumerate_add_match_sysname ( enumerate , "event*" );
269+ udev_enumerate_scan_devices ( enumerate );
292270
293- destroy_glob (& glob_buffer );
294- return UIOHOOK_ERROR_OUT_OF_MEMORY ;
295- }
271+ struct epoll_event_listener * * listener_next = listeners ;
272+
273+ struct udev_list_entry * devices = udev_enumerate_get_list_entry (enumerate );
274+ struct udev_list_entry * dev_list_entry ;
296275
297- int found = 0 ;
298- for ( int i = 0 ; i < glob_buffer . gl_pathc ; i ++ ) {
299- struct input_hook * hook = NULL ;
300- if ( create_hook ( glob_buffer . gl_pathv [ i ], & hook ) != UIOHOOK_SUCCESS ) {
301- destroy_hook ( & hook );
276+ udev_list_entry_foreach ( dev_list_entry , devices ) {
277+ const char * path = udev_list_entry_get_name ( dev_list_entry );
278+ if ( path == NULL ) {
279+ logger ( LOG_LEVEL_WARN , "%s [%u]: Failed to get udev entry name!\n" ,
280+ __FUNCTION__ , __LINE__ );
302281 continue ;
303282 }
304283
305- event_buffer [found ].events = EPOLLIN ;
306- event_buffer [found ].data .ptr = hook ;
284+ struct udev_device * dev = udev_device_new_from_syspath (udev , path );
285+ if (dev == NULL ) {
286+ logger (LOG_LEVEL_WARN , "%s [%u]: Failed to create new udev device: %s!\n" ,
287+ __FUNCTION__ , __LINE__ ,
288+ path );
289+ continue ;
290+ }
307291
308- int fd = libevdev_get_fd (hook -> evdev );
309- if (epoll_ctl (epoll_fd , EPOLL_CTL_ADD , fd , & event_buffer [found ]) < 0 ) {
310- logger (LOG_LEVEL_ERROR , "%s [%u]: Failed to add file descriptor to epoll! (%d)\n" ,
311- __FUNCTION__ , __LINE__ );
312-
313- destroy_hook (& hook );
314- event_buffer [found ].data .ptr = NULL ;
292+ const char * devnode = udev_device_get_devnode (dev );
293+ if (devnode == NULL ) {
294+ logger (LOG_LEVEL_WARN , "%s [%u]: Failed to get udev device node: %s!\n" ,
295+ __FUNCTION__ , __LINE__ ,
296+ path );
297+ udev_device_unref (dev );
315298 continue ;
316299 }
317300
318- found ++ ;
319- }
301+ const char * is_keyboard = udev_device_get_property_value (dev , "ID_INPUT_KEYBOARD" );
302+ const char * is_mouse = udev_device_get_property_value (dev , "ID_INPUT_MOUSE" );
303+ if ((is_keyboard && strcmp (is_keyboard , "1" ) == 0 ) || (is_mouse && strcmp (is_mouse , "1" ) == 0 )) {
304+ logger (LOG_LEVEL_DEBUG , "%s [%u]: Found udev input device: %s %s.\n" ,
305+ __FUNCTION__ , __LINE__ ,
306+ udev_device_get_property_value (dev , "ID_VENDOR" ),
307+ udev_device_get_property_value (dev , "ID_MODEL" ));
308+
309+ * listener_next = malloc (sizeof (struct epoll_event_listener ));
310+ if (* listener_next == NULL ) {
311+ logger (LOG_LEVEL_ERROR , "%s [%u]: Failed to allocate memory for epoll event devices!\n" ,
312+ __FUNCTION__ , __LINE__ );
313+ udev_device_unref (dev );
314+ continue ;
315+ }
320316
321- destroy_glob (& glob_buffer );
317+ struct input_hook * hook = NULL ;
318+ if (create_hook (devnode , & hook ) != UIOHOOK_SUCCESS ) {
319+ logger (LOG_LEVEL_ERROR , "%s [%u]: Staring destroy_hook 0x%p\n" ,
320+ __FUNCTION__ , __LINE__ , hook );
321+ destroy_hook (& hook );
322+ udev_device_unref (dev );
323+ free (* listener_next );
324+ * listener_next = NULL ;
325+ continue ;
326+ }
322327
323- * listeners = realloc (event_buffer , sizeof (struct epoll_event * ) * found );
324- if (* listeners == NULL ) {
325- logger (LOG_LEVEL_WARN , "%s [%u]: Failed to realloc event listeners! (%d)\n" ,
326- __FUNCTION__ , __LINE__ );
328+ struct epoll_event_listener * listener_current = * listener_next ;
329+ listener_current -> epoll .events = EPOLLIN ;
330+ listener_current -> epoll .data .ptr = hook ;
331+ listener_current -> next = NULL ;
332+
333+ const int fd = libevdev_get_fd (hook -> evdev );
334+ if (epoll_ctl (epoll_fd , EPOLL_CTL_ADD , fd , & listener_current -> epoll ) < 0 ) {
335+ logger (LOG_LEVEL_ERROR , "%s [%u]: Failed to add file descriptor to epoll! (%d)\n" ,
336+ __FUNCTION__ , __LINE__ );
337+
338+ destroy_hook (& hook );
339+ listener_current -> epoll .data .ptr = NULL ;
340+ udev_device_unref (dev );
341+ free (* listener_next );
342+ * listener_next = NULL ;
343+ continue ;
344+ }
327345
328- * listeners = event_buffer ;
329- event_buffer = NULL ;
346+ listener_next = & listener_current -> next ;
347+ }
348+
349+ udev_device_unref (dev );
330350 }
331351
352+ udev_enumerate_unref (enumerate );
353+ udev_unref (udev );
354+
332355 return UIOHOOK_SUCCESS ;
333356}
334357
@@ -346,7 +369,7 @@ UIOHOOK_API int hook_run() {
346369 return UIOHOOK_ERROR_EPOLL_CREATE ;
347370 }
348371
349- struct epoll_event * listeners = NULL ;
372+ struct epoll_event_listener * listeners = NULL ;
350373 int status = create_event_listeners (epoll_fd , & listeners );
351374 if (status != UIOHOOK_SUCCESS ) {
352375 close (epoll_fd );
0 commit comments