diff --git a/src/lib/ecore_drm/ecore_drm.c b/src/lib/ecore_drm/ecore_drm.c index 6bbbde05d7..02dd76edbb 100644 --- a/src/lib/ecore_drm/ecore_drm.c +++ b/src/lib/ecore_drm/ecore_drm.c @@ -1,146 +1,150 @@ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include "ecore_drm_private.h" /* local variables */ static int _ecore_drm_init_count = 0; /* external variables */ int _ecore_drm_log_dom = -1; EAPI int ECORE_DRM_EVENT_ACTIVATE = 0; static void _ecore_drm_event_activate_free(void *data EINA_UNUSED, void *event) { free(event); } void _ecore_drm_event_activate_send(Eina_Bool active) { Ecore_Drm_Event_Activate *e; if (!(e = calloc(1, sizeof(Ecore_Drm_Event_Activate)))) return; e->active = active; ecore_event_add(ECORE_DRM_EVENT_ACTIVATE, e, _ecore_drm_event_activate_free, NULL); } /** * @defgroup Ecore_Drm_Init_Group Drm Library Init and Shutdown Functions * * Functions that start and shutdown the Ecore_Drm Library. */ /** * Initialize the Ecore_Drm library * * @return The number of times the library has been initialized without * being shut down. 0 is returned if an error occurs. * * @ingroup Ecore_Drm_Init_Group */ EAPI int ecore_drm_init(void) { /* if we have already initialized, return the count */ if (++_ecore_drm_init_count != 1) return _ecore_drm_init_count; /* try to init eina */ if (!eina_init()) return --_ecore_drm_init_count; /* try to init ecore */ if (!ecore_init()) { eina_shutdown(); return --_ecore_drm_init_count; } /* try to init ecore_event */ if (!ecore_event_init()) { ecore_shutdown(); eina_shutdown(); return --_ecore_drm_init_count; } /* set logging level */ eina_log_level_set(EINA_LOG_LEVEL_DBG); /* try to create logging domain */ _ecore_drm_log_dom = eina_log_domain_register("ecore_drm", ECORE_DRM_DEFAULT_LOG_COLOR); if (!_ecore_drm_log_dom) { EINA_LOG_ERR("Could not create log domain for Ecore_Drm"); goto log_err; } /* set default logging level for this domain */ if (!eina_log_domain_level_check(_ecore_drm_log_dom, EINA_LOG_LEVEL_DBG)) eina_log_domain_level_set("ecore_drm", EINA_LOG_LEVEL_DBG); /* try to init eeze */ if (!eeze_init()) goto eeze_err; + _ecore_drm_inputs_init(); + ECORE_DRM_EVENT_ACTIVATE = ecore_event_type_new(); ECORE_DRM_EVENT_OUTPUT = ecore_event_type_new(); ECORE_DRM_EVENT_SEAT_ADD = ecore_event_type_new(); /* return init count */ return _ecore_drm_init_count; eeze_err: eina_log_domain_unregister(_ecore_drm_log_dom); _ecore_drm_log_dom = -1; log_err: ecore_event_shutdown(); ecore_shutdown(); eina_shutdown(); return --_ecore_drm_init_count; } /** * Shutdown the Ecore_Drm library. * * @return The number of times the library has been initialized without * being shutdown. 0 is returned if an error occurs. * * @ingroup Ecore_Drm_Init_Group */ EAPI int ecore_drm_shutdown(void) { /* _ecore_drm_init_count should not go below zero. */ if (_ecore_drm_init_count < 1) { ERR("Ecore_Drm Shutdown called without Ecore_Drm Init"); return 0; } /* if we are still in use, decrement init count and get out */ if (--_ecore_drm_init_count != 0) return _ecore_drm_init_count; /* close eeze */ eeze_shutdown(); /* shutdown ecore_event */ ecore_event_shutdown(); /* shutdown ecore */ ecore_shutdown(); /* unregsiter log domain */ eina_log_domain_unregister(_ecore_drm_log_dom); _ecore_drm_log_dom = -1; /* shutdown eina */ eina_shutdown(); + _ecore_drm_inputs_shutdown(); + /* return init count */ return _ecore_drm_init_count; } diff --git a/src/lib/ecore_drm/ecore_drm_inputs.c b/src/lib/ecore_drm/ecore_drm_inputs.c index 75655ec1db..df46b19a7a 100644 --- a/src/lib/ecore_drm/ecore_drm_inputs.c +++ b/src/lib/ecore_drm/ecore_drm_inputs.c @@ -1,347 +1,356 @@ #ifdef HAVE_CONFIG_H # include #endif #include "ecore_drm_private.h" EAPI int ECORE_DRM_EVENT_SEAT_ADD = -1; +static Eina_Hash *_fd_hash = NULL; /* local functions */ static int _cb_open_restricted(const char *path, int flags, void *data) { Ecore_Drm_Input *input; - Ecore_Drm_Seat *seat; - Ecore_Drm_Evdev *edev; - Eina_List *l, *ll; int fd = -1; if (!(input = data)) return -1; /* try to open the device */ fd = _ecore_drm_launcher_device_open_no_pending(path, flags); if (fd < 0) ERR("Could not open device"); - - EINA_LIST_FOREACH(input->dev->seats, l, seat) - { - EINA_LIST_FOREACH(seat->devices, ll, edev) - { - if (strstr(path, edev->path)) - { - edev->fd = fd; - return fd; - } - } - } + if (_fd_hash) + eina_hash_add(_fd_hash, path, (void *)(intptr_t)fd); return fd; } static void _cb_close_restricted(int fd, void *data) { Ecore_Drm_Input *input; Ecore_Drm_Seat *seat; Ecore_Drm_Evdev *edev; Eina_List *l, *ll; if (!(input = data)) return; EINA_LIST_FOREACH(input->dev->seats, l, seat) { EINA_LIST_FOREACH(seat->devices, ll, edev) { if (edev->fd == fd) { _ecore_drm_launcher_device_close(edev->path, fd); + + /* re-initialize fd after closing */ + edev->fd = -1; return; } } } } static Ecore_Drm_Seat * _seat_create(Ecore_Drm_Input *input, const char *seat) { Ecore_Drm_Seat *s; /* try to allocate space for new seat */ if (!(s = calloc(1, sizeof(Ecore_Drm_Seat)))) return NULL; s->input = input; s->name = eina_stringshare_add(seat); /* add this new seat to list */ input->dev->seats = eina_list_append(input->dev->seats, s); ecore_event_add(ECORE_DRM_EVENT_SEAT_ADD, NULL, NULL, NULL); return s; } static Ecore_Drm_Seat * _seat_get(Ecore_Drm_Input *input, const char *seat) { Ecore_Drm_Seat *s; Eina_List *l; /* search for this name in existing seats */ EINA_LIST_FOREACH(input->dev->seats, l, s) if (!strcmp(s->name, seat)) return s; return _seat_create(input, seat); } static void _device_added(Ecore_Drm_Input *input, struct libinput_device *device) { struct libinput_seat *libinput_seat; const char *seat_name; Ecore_Drm_Seat *seat; Ecore_Drm_Evdev *edev; libinput_seat = libinput_device_get_seat(device); seat_name = libinput_seat_get_logical_name(libinput_seat); /* try to get a seat */ if (!(seat = _seat_get(input, seat_name))) { ERR("Could not get matching seat: %s", seat_name); return; } /* try to create a new evdev device */ if (!(edev = _ecore_drm_evdev_device_create(seat, device))) { ERR("Failed to create new evdev device"); return; } + edev->fd = (int)(intptr_t)eina_hash_find(_fd_hash, edev->path); + /* append this device to the seat */ seat->devices = eina_list_append(seat->devices, edev); } static void _device_removed(Ecore_Drm_Input *input EINA_UNUSED, struct libinput_device *device) { Ecore_Drm_Evdev *edev; /* try to get the evdev structure */ if (!(edev = libinput_device_get_user_data(device))) return; /* remove this evdev from the seat's list of devices */ edev->seat->devices = eina_list_remove(edev->seat->devices, edev); + if (_fd_hash) + eina_hash_del_by_key(_fd_hash, edev->path); + /* tell launcher to release device */ _ecore_drm_launcher_device_close(edev->path, edev->fd); /* destroy this evdev */ _ecore_drm_evdev_device_destroy(edev); } static int _udev_event_process(struct libinput_event *event) { struct libinput *libinput; struct libinput_device *device; Ecore_Drm_Input *input; Eina_Bool ret = EINA_TRUE; libinput = libinput_event_get_context(event); input = libinput_get_user_data(libinput); device = libinput_event_get_device(event); switch (libinput_event_get_type(event)) { case LIBINPUT_EVENT_DEVICE_ADDED: _device_added(input, device); break; case LIBINPUT_EVENT_DEVICE_REMOVED: _device_removed(input, device); break; default: ret = EINA_FALSE; } return ret; } static void _input_event_process(struct libinput_event *event) { if (_udev_event_process(event)) return; if (_ecore_drm_evdev_event_process(event)) return; } static void _input_events_process(Ecore_Drm_Input *input) { struct libinput_event *event; while ((event = libinput_get_event(input->libinput))) { _input_event_process(event); libinput_event_destroy(event); } } static Eina_Bool _cb_input_dispatch(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED) { Ecore_Drm_Input *input; if (!(input = data)) return EINA_TRUE; if (libinput_dispatch(input->libinput) != 0) ERR("Failed to dispatch libinput events: %m"); /* process pending events */ _input_events_process(input); return EINA_TRUE; } const struct libinput_interface _input_interface = { _cb_open_restricted, _cb_close_restricted, }; /* public functions */ EAPI Eina_Bool ecore_drm_inputs_create(Ecore_Drm_Device *dev) { Ecore_Drm_Input *input; /* check for valid device */ EINA_SAFETY_ON_NULL_RETURN_VAL(dev, EINA_FALSE); /* try to allocate space for new input structure */ if (!(input = calloc(1, sizeof(Ecore_Drm_Input)))) return EINA_FALSE; /* set reference for parent device */ input->dev = dev; /* try to create libinput context */ input->libinput = libinput_udev_create_context(&_input_interface, input, eeze_udev_get()); if (!input->libinput) { ERR("Could not create libinput context: %m"); goto err; } /* set libinput log priority */ libinput_log_set_priority(input->libinput, LIBINPUT_LOG_PRIORITY_INFO); /* assign udev seat */ if (libinput_udev_assign_seat(input->libinput, dev->seat) != 0) { ERR("Failed to assign seat: %m"); goto err; } /* process pending events */ _input_events_process(input); /* enable this input */ if (!ecore_drm_inputs_enable(input)) { ERR("Failed to enable input"); goto err; } /* append this input */ dev->inputs = eina_list_append(dev->inputs, input); return EINA_TRUE; err: if (input->libinput) libinput_unref(input->libinput); free(input); return EINA_FALSE; } EAPI void ecore_drm_inputs_destroy(Ecore_Drm_Device *dev) { Ecore_Drm_Input *input; Ecore_Drm_Seat *seat; Ecore_Drm_Evdev *edev; EINA_SAFETY_ON_NULL_RETURN(dev); EINA_LIST_FREE(dev->seats, seat) { EINA_LIST_FREE(seat->devices, edev) { _ecore_drm_launcher_device_close(edev->path, edev->fd); _ecore_drm_evdev_device_destroy(edev); } if (seat->name) eina_stringshare_del(seat->name); free(seat); } EINA_LIST_FREE(dev->inputs, input) { if (input->hdlr) ecore_main_fd_handler_del(input->hdlr); if (input->libinput) libinput_unref(input->libinput); free(input); } } EAPI Eina_Bool ecore_drm_inputs_enable(Ecore_Drm_Input *input) { EINA_SAFETY_ON_NULL_RETURN_VAL(input, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(input->libinput, EINA_FALSE); input->fd = libinput_get_fd(input->libinput); if (!input->hdlr) { input->hdlr = ecore_main_fd_handler_add(input->fd, ECORE_FD_READ, _cb_input_dispatch, input, NULL, NULL); } if (input->suspended) { if (libinput_resume(input->libinput) != 0) goto err; input->suspended = EINA_FALSE; /* process pending events */ _input_events_process(input); } input->enabled = EINA_TRUE; input->suspended = EINA_FALSE; return EINA_TRUE; err: input->enabled = EINA_FALSE; if (input->hdlr) ecore_main_fd_handler_del(input->hdlr); input->hdlr = NULL; return EINA_FALSE; } EAPI void ecore_drm_inputs_disable(Ecore_Drm_Input *input) { EINA_SAFETY_ON_NULL_RETURN(input); EINA_SAFETY_ON_TRUE_RETURN(input->suspended); /* suspend this input */ libinput_suspend(input->libinput); /* process pending events */ _input_events_process(input); input->suspended = EINA_TRUE; } + +void +_ecore_drm_inputs_init(void) +{ + _fd_hash = eina_hash_string_superfast_new(NULL); +} + +void +_ecore_drm_inputs_shutdown(void) +{ + eina_hash_free(_fd_hash); + _fd_hash = NULL; +} diff --git a/src/lib/ecore_drm/ecore_drm_launcher.c b/src/lib/ecore_drm/ecore_drm_launcher.c index 2baa550bbf..6ba92ecd2e 100644 --- a/src/lib/ecore_drm/ecore_drm_launcher.c +++ b/src/lib/ecore_drm/ecore_drm_launcher.c @@ -1,171 +1,172 @@ #include "ecore_drm_private.h" static Eina_Bool logind = EINA_FALSE; static Eina_Bool _ecore_drm_launcher_cb_vt_switch(void *data, int type EINA_UNUSED, void *event) { Ecore_Drm_Device *dev; Ecore_Event_Key *ev; int keycode; int vt; dev = data; ev = event; keycode = ev->keycode - 8; if ((ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) && (ev->modifiers & ECORE_EVENT_MODIFIER_ALT) && (keycode >= KEY_F1) && (keycode <= KEY_F8)) { vt = (keycode - KEY_F1 + 1); if (!_ecore_drm_tty_switch(dev, vt)) ERR("Failed to activate vt: %m"); } return ECORE_CALLBACK_PASS_ON; } int _ecore_drm_launcher_device_flags_set(int fd, int flags) { int fl; fl = fcntl(fd, F_GETFL); if (fl < 0) return -1; if (flags & O_NONBLOCK) fl |= O_NONBLOCK; if (fcntl(fd, F_SETFL, fl) < 0) return -1; fl = fcntl(fd, F_GETFD); if (fl < 0) return -1; if (!(flags & O_CLOEXEC)) fl &= ~FD_CLOEXEC; if (fcntl(fd, F_SETFD, fl) < 0) return -1; return fd; } EAPI Eina_Bool ecore_drm_launcher_connect(Ecore_Drm_Device *dev) { EINA_SAFETY_ON_NULL_RETURN_VAL(dev, EINA_FALSE); /* try to connect to logind */ if (!(logind = _ecore_drm_logind_connect(dev))) { DBG("Launcher: Logind not supported"); if (geteuid() == 0) { DBG("Launcher: Trying to continue with root privileges"); if (!ecore_drm_tty_open(dev, NULL)) { ERR("Launcher: Could not setup tty"); return EINA_FALSE; } } else { ERR("Launcher: Root privileges needed"); return EINA_FALSE; } } dev->tty.switch_hdlr = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, _ecore_drm_launcher_cb_vt_switch, dev); return EINA_TRUE; } EAPI void ecore_drm_launcher_disconnect(Ecore_Drm_Device *dev) { EINA_SAFETY_ON_NULL_RETURN(dev); if (dev->tty.switch_hdlr) ecore_event_handler_del(dev->tty.switch_hdlr); dev->tty.switch_hdlr = NULL; if (!logind) { if (!ecore_drm_tty_close(dev)) ERR("Launcher: Could not close tty"); } else { _ecore_drm_logind_disconnect(dev); logind = EINA_FALSE; } } Eina_Bool _ecore_drm_launcher_device_open(const char *device, Ecore_Drm_Open_Cb callback, void *data, int flags) { int fd = -1; struct stat s; if (logind) { if (!_ecore_drm_logind_device_open(device, callback, data)) return EINA_FALSE; } else { fd = open(device, flags | O_CLOEXEC); if (fd < 0) return EINA_FALSE; if (fstat(fd, &s) == -1) { close(fd); fd = -1; return EINA_FALSE; } callback(data, fd, EINA_FALSE); } return EINA_TRUE; } int _ecore_drm_launcher_device_open_no_pending(const char *device, int flags) { int fd = -1; struct stat s; if (logind) { fd = _ecore_drm_logind_device_open_no_pending(device); if (fd < 0) return -1; if (_ecore_drm_launcher_device_flags_set(fd, flags | O_CLOEXEC) < 0) { close(fd); _ecore_drm_logind_device_close(device); return -1; } } else { fd = open(device, flags | O_CLOEXEC); if (fd < 0) return fd; if (fstat(fd, &s) == -1) { close(fd); return -1; } } return fd; } void _ecore_drm_launcher_device_close(const char *device, int fd) { if ((logind) && (device)) _ecore_drm_logind_device_close(device); + if (fd < 0) return; close(fd); } diff --git a/src/lib/ecore_drm/ecore_drm_private.h b/src/lib/ecore_drm/ecore_drm_private.h index aa97a2025f..fbc6bda00e 100644 --- a/src/lib/ecore_drm/ecore_drm_private.h +++ b/src/lib/ecore_drm/ecore_drm_private.h @@ -1,292 +1,294 @@ #ifndef _ECORE_DRM_PRIVATE_H # define _ECORE_DRM_PRIVATE_H # ifdef HAVE_CONFIG_H # include "config.h" # endif # include "Ecore.h" # include "ecore_private.h" # include "Ecore_Input.h" # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # ifdef HAVE_SYSTEMD # include # endif # include # include # define NUM_FRAME_BUFFERS 2 # ifndef DRM_MAJOR # define DRM_MAJOR 226 # endif # ifndef DRM_CAP_TIMESTAMP_MONOTONIC # define DRM_CAP_TIMESTAMP_MONOTONIC 0x6 # endif # ifdef ECORE_DRM_DEFAULT_LOG_COLOR # undef ECORE_DRM_DEFAULT_LOG_COLOR # endif # define ECORE_DRM_DEFAULT_LOG_COLOR EINA_COLOR_BLUE # define EVDEV_SEAT_POINTER (1 << 0) # define EVDEV_SEAT_KEYBOARD (1 << 1) # define EVDEV_SEAT_TOUCH (1 << 2) # ifdef ERR # undef ERR # endif # ifdef DBG # undef DBG # endif # ifdef INF # undef INF # endif # ifdef WRN # undef WRN # endif # ifdef CRIT # undef CRIT # endif extern int _ecore_drm_log_dom; # define EVDEV_MAX_SLOTS 32 # define ERR(...) EINA_LOG_DOM_ERR(_ecore_drm_log_dom, __VA_ARGS__) # define DBG(...) EINA_LOG_DOM_DBG(_ecore_drm_log_dom, __VA_ARGS__) # define INF(...) EINA_LOG_DOM_INFO(_ecore_drm_log_dom, __VA_ARGS__) # define WRN(...) EINA_LOG_DOM_WARN(_ecore_drm_log_dom, __VA_ARGS__) # define CRIT(...) EINA_LOG_DOM_CRIT(_ecore_drm_log_dom, __VA_ARGS__) # define ALEN(array) (sizeof(array) / sizeof(array)[0]) typedef struct _Ecore_Drm_Pageflip_Callback { Ecore_Drm_Device *dev; Ecore_Drm_Pageflip_Cb func; void *data; int count; } Ecore_Drm_Pageflip_Callback; typedef enum _Ecore_Drm_Backlight_Type { ECORE_DRM_BACKLIGHT_RAW, ECORE_DRM_BACKLIGHT_PLATFORM, ECORE_DRM_BACKLIGHT_FIRMWARE } Ecore_Drm_Backlight_Type; typedef struct _Ecore_Drm_Backlight { const char *device; double brightness_max; double brightness_actual; double brightness; Ecore_Drm_Backlight_Type type; } Ecore_Drm_Backlight; struct _Ecore_Drm_Output { Ecore_Drm_Device *dev; unsigned int crtc_id; unsigned int conn_id; unsigned int conn_type; drmModeCrtcPtr crtc; drmModePropertyPtr dpms; int x, y, phys_width, phys_height; int pipe; const char *make, *model, *name; unsigned int subpixel; uint16_t gamma; Ecore_Drm_Output_Mode *current_mode; Eina_List *modes; unsigned char *edid_blob; struct { char eisa[13]; char monitor[13]; char pnp[5]; char serial[13]; } edid; Ecore_Drm_Backlight *backlight; Eina_Bool primary : 1; Eina_Bool connected : 1; Eina_Bool enabled : 1; Eina_Bool cloned : 1; Eina_Bool need_repaint : 1; Eina_Bool repaint_scheduled : 1; Eina_Bool pending_destroy : 1; Eina_Bool pending_flip : 1; Eina_Bool pending_vblank : 1; }; struct _Ecore_Drm_Seat { // struct libinput_seat *seat; const char *name; Ecore_Drm_Input *input; Eina_List *devices; struct { int ix, iy; double dx, dy; } ptr; }; struct _Ecore_Drm_Input { int fd; Ecore_Drm_Device *dev; struct libinput *libinput; Ecore_Fd_Handler *hdlr; Eina_Bool enabled : 1; Eina_Bool suspended : 1; }; struct _Ecore_Drm_Evdev { Ecore_Drm_Seat *seat; struct libinput_device *device; const char *path; int fd; int mt_slot; Ecore_Drm_Output *output; /* struct */ /* { */ /* int min_x, min_y; */ /* int max_x, max_y; */ /* double rel_w, rel_h; */ /* struct */ /* { */ /* int x[2]; */ /* int y[2]; */ /* Eina_Bool down : 1; */ /* } pt[EVDEV_MAX_SLOTS]; */ /* } abs; */ struct { int ix, iy; int minx, miny, maxw, maxh; double dx, dy; unsigned int last, prev; uint32_t threshold; Eina_Bool did_double : 1; Eina_Bool did_triple : 1; uint32_t prev_button, last_button; } mouse; struct { struct xkb_keymap *keymap; struct xkb_state *state; xkb_mod_mask_t ctrl_mask; xkb_mod_mask_t alt_mask; xkb_mod_mask_t shift_mask; xkb_mod_mask_t win_mask; xkb_mod_mask_t scroll_mask; xkb_mod_mask_t num_mask; xkb_mod_mask_t caps_mask; xkb_mod_mask_t altgr_mask; unsigned int modifiers; unsigned int depressed, latched, locked, group; } xkb; /* Ecore_Drm_Evdev_Capabilities caps; */ Ecore_Drm_Seat_Capabilities seat_caps; }; struct _Ecore_Drm_Sprite { Ecore_Drm_Fb *current_fb, *next_fb; Ecore_Drm_Output *output; int drm_fd; unsigned int crtcs; unsigned int plane_id; struct { int x, y; unsigned int w, h; } src, dest; unsigned int num_formats; unsigned int formats[]; }; typedef void (*Ecore_Drm_Open_Cb)(void *data, int fd, Eina_Bool b); void _ecore_drm_event_activate_send(Eina_Bool active); Eina_Bool _ecore_drm_launcher_device_open(const char *device, Ecore_Drm_Open_Cb callback, void *data, int flags); int _ecore_drm_launcher_device_open_no_pending(const char *device, int flags); void _ecore_drm_launcher_device_close(const char *device, int fd); int _ecore_drm_launcher_device_flags_set(int fd, int flags); Eina_Bool _ecore_drm_tty_switch(Ecore_Drm_Device *dev, int activate_vt); Ecore_Drm_Evdev *_ecore_drm_evdev_device_create(Ecore_Drm_Seat *seat, struct libinput_device *device); void _ecore_drm_evdev_device_destroy(Ecore_Drm_Evdev *evdev); Eina_Bool _ecore_drm_evdev_event_process(struct libinput_event *event); Ecore_Drm_Fb *_ecore_drm_fb_create(Ecore_Drm_Device *dev, int width, int height); void _ecore_drm_fb_destroy(Ecore_Drm_Fb *fb); void _ecore_drm_output_fb_release(Ecore_Drm_Output *output, Ecore_Drm_Fb *fb); void _ecore_drm_output_repaint_start(Ecore_Drm_Output *output); void _ecore_drm_output_frame_finish(Ecore_Drm_Output *output); void _ecore_drm_outputs_update(Ecore_Drm_Device *dev); void _ecore_drm_output_render_enable(Ecore_Drm_Output *output); void _ecore_drm_output_render_disable(Ecore_Drm_Output *output); Eina_Bool _ecore_drm_logind_connect(Ecore_Drm_Device *dev); void _ecore_drm_logind_disconnect(Ecore_Drm_Device *dev); void _ecore_drm_logind_restore(Ecore_Drm_Device *dev); Eina_Bool _ecore_drm_logind_device_open(const char *device, Ecore_Drm_Open_Cb callback, void *data); int _ecore_drm_logind_device_open_no_pending(const char *device); void _ecore_drm_logind_device_close(const char *device); int _ecore_drm_dbus_init(Ecore_Drm_Device *dev); int _ecore_drm_dbus_shutdown(void); int _ecore_drm_dbus_device_take(uint32_t major, uint32_t minor, Ecore_Drm_Open_Cb callback, void *data); int _ecore_drm_dbus_device_take_no_pending(uint32_t major, uint32_t minor, Eina_Bool *paused_out, double timeout); void _ecore_drm_dbus_device_release(uint32_t major, uint32_t minor); Eina_Bool _ecore_drm_dbus_session_take(void); Eina_Bool _ecore_drm_dbus_session_release(void); +void _ecore_drm_inputs_init(void); +void _ecore_drm_inputs_shutdown(void); #endif