efl/src/lib/ecore_drm/ecore_drm_dbus.c

368 lines
9.1 KiB
C

#include "ecore_drm_private.h"
static int _dbus_init_count = 0;
static const char *dsession;
static Eldbus_Connection *dconn;
static Eldbus_Object *dobj;
static void
_ecore_drm_dbus_device_pause_done(uint32_t major, uint32_t minor)
{
Eldbus_Proxy *proxy;
Eldbus_Message *msg;
/* try to get the Session proxy */
if (!(proxy = eldbus_proxy_get(dobj, "org.freedesktop.login1.Session")))
{
ERR("Could not get eldbus session proxy");
return;
}
if (!(msg = eldbus_proxy_method_call_new(proxy, "PauseDeviceComplete")))
{
ERR("Could not create method call for proxy");
return;
}
eldbus_message_arguments_append(msg, "uu", major, minor);
eldbus_proxy_send(proxy, msg, NULL, NULL, -1);
}
static void
_cb_session_removed(void *ctxt EINA_UNUSED, const Eldbus_Message *msg)
{
const char *errname, *errmsg;
const char *sid;
if (eldbus_message_error_get(msg, &errname, &errmsg))
{
ERR("Eldbus Message Error: %s %s", errname, errmsg);
return;
}
if (eldbus_message_arguments_get(msg, "s", &sid))
{
if (!strcmp(sid, dsession))
ERR("\tCurrent Session Removed!!");
}
}
static void
_cb_device_paused(void *ctxt EINA_UNUSED, const Eldbus_Message *msg)
{
const char *errname, *errmsg;
const char *type;
uint32_t maj, min;
if (eldbus_message_error_get(msg, &errname, &errmsg))
{
ERR("Eldbus Message Error: %s %s", errname, errmsg);
return;
}
if (eldbus_message_arguments_get(msg, "uus", &maj, &min, &type))
{
if (!strcmp(type, "pause"))
{
_ecore_drm_dbus_device_pause_done(maj, min);
}
/* if (maj == DRM_MAJOR) */
/* { */
/* // emit paused to compositor */
/* } */
}
}
static void
_cb_device_resumed(void *ctxt EINA_UNUSED, const Eldbus_Message *msg)
{
const char *errname, *errmsg;
uint32_t maj, min;
int fd;
if (eldbus_message_error_get(msg, &errname, &errmsg))
{
ERR("Eldbus Message Error: %s %s", errname, errmsg);
return;
}
if (eldbus_message_arguments_get(msg, "uuh", &maj, &min, &fd))
{
/* if (maj == DRM_MAJOR) */
/* { */
/* // emit active to compositor */
/* } */
}
}
static void
_property_response_set(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
{
const char *errname, *errmsg;
if (eldbus_message_error_get(msg, &errname, &errmsg))
ERR("Eldbus Message error %s - %s\n\n", errname, errmsg);
}
static void
_cb_properties_changed(void *data EINA_UNUSED, Eldbus_Proxy *proxy EINA_UNUSED, void *event)
{
Eldbus_Proxy_Event_Property_Changed *ev;
ev = event;
if (!strcmp(ev->name, "Active"))
{
eldbus_proxy_property_set(proxy, "Active", "b", (void *)EINA_TRUE,
_property_response_set, NULL);
eldbus_proxy_property_set(proxy, "State", "s", &"active",
_property_response_set, NULL);
}
}
static Eina_Bool
_ecore_drm_dbus_session_take(const char *session)
{
Eldbus_Proxy *proxy;
if ((session) && (strcmp(session, dsession)))
{
ERR("Invalid session: %s", session);
return EINA_FALSE;
}
/* try to get the Session proxy */
if (!(proxy = eldbus_proxy_get(dobj, "org.freedesktop.login1.Session")))
{
ERR("Could not get eldbus session proxy");
return EINA_FALSE;
}
/* send call to take control */
if (eldbus_proxy_call(proxy, "TakeControl", NULL, NULL, -1, "b", EINA_FALSE))
{
ERR("Could not send message to proxy");
return EINA_FALSE;
}
return EINA_TRUE;
}
static Eina_Bool
_ecore_drm_dbus_session_release(const char *session)
{
Eldbus_Proxy *proxy;
if ((session) && (strcmp(session, dsession)))
{
ERR("Invalid session: %s", session);
return EINA_FALSE;
}
/* try to get the Session proxy */
if (!(proxy = eldbus_proxy_get(dobj, "org.freedesktop.login1.Session")))
{
ERR("Could not get eldbus session proxy");
return EINA_FALSE;
}
/* send call to release control */
if (!eldbus_proxy_call(proxy, "ReleaseControl", NULL, NULL, -1, ""))
ERR("Could not send ReleaseControl message to proxy");
return EINA_TRUE;
}
static void
_ecore_drm_dbus_device_release(uint32_t major, uint32_t minor)
{
Eldbus_Proxy *proxy;
Eldbus_Message *msg;
/* try to get the Session proxy */
if (!(proxy = eldbus_proxy_get(dobj, "org.freedesktop.login1.Session")))
{
ERR("Could not get eldbus session proxy");
return;
}
if (!(msg = eldbus_proxy_method_call_new(proxy, "ReleaseDevice")))
{
ERR("Could not create method call for proxy");
return;
}
eldbus_message_arguments_append(msg, "uu", major, minor);
eldbus_proxy_send(proxy, msg, NULL, NULL, -1);
}
static int
_ecore_drm_dbus_device_take(uint32_t major, uint32_t minor, Eldbus_Message_Cb callback, const void *data)
{
Eldbus_Proxy *proxy;
Eldbus_Message *msg;
/* try to get the Session proxy */
if (!(proxy = eldbus_proxy_get(dobj, "org.freedesktop.login1.Session")))
{
ERR("Could not get eldbus session proxy");
return -1;
}
if (!(msg = eldbus_proxy_method_call_new(proxy, "TakeDevice")))
{
ERR("Could not create method call for proxy");
return -1;
}
eldbus_message_arguments_append(msg, "uu", major, minor);
eldbus_proxy_send(proxy, msg, callback, data, -1);
return 1;
}
int
_ecore_drm_dbus_init(const char *session)
{
Eldbus_Proxy *proxy;
int ret = 0;
char *dpath;
if (++_dbus_init_count != 1) return _dbus_init_count;
if (!session) return --_dbus_init_count;
/* try to init eldbus */
if (!eldbus_init())
{
ERR("Could not init eldbus library");
return --_dbus_init_count;
}
dsession = eina_stringshare_add(session);
/* try to get the dbus connection */
if (!(dconn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM)))
{
ERR("Failed to get eldbus system connection");
goto conn_err;
}
/* assemble dbus path */
ret = asprintf(&dpath, "/org/freedesktop/login1/session/%s", session);
if (ret < 0)
{
ERR("Could not assemble dbus path");
goto path_err;
}
/* try to get the eldbus object */
if (!(dobj = eldbus_object_get(dconn, "org.freedesktop.login1", dpath)))
{
ERR("Could not get eldbus object: %s", dpath);
goto obj_err;
}
/* try to get the Manager proxy */
if (!(proxy = eldbus_proxy_get(dobj, "org.freedesktop.login1.Manager")))
{
ERR("Could not get eldbus proxy");
goto proxy_err;
}
eldbus_proxy_signal_handler_add(proxy, "SessionRemoved",
_cb_session_removed, NULL);
/* try to get the Session proxy */
if (!(proxy = eldbus_proxy_get(dobj, "org.freedesktop.login1.Session")))
{
ERR("Could not get eldbus proxy");
goto proxy_err;
}
eldbus_proxy_signal_handler_add(proxy, "PauseDevice",
_cb_device_paused, NULL);
eldbus_proxy_signal_handler_add(proxy, "ResumeDevice",
_cb_device_resumed, NULL);
/* try to get the Properties proxy */
if (!(proxy = eldbus_proxy_get(dobj, "org.freedesktop.DBus.Properties")))
{
ERR("Could not get eldbus proxy");
goto proxy_err;
}
eldbus_proxy_properties_monitor(proxy, EINA_TRUE);
eldbus_proxy_event_callback_add(proxy, ELDBUS_PROXY_EVENT_PROPERTY_CHANGED,
_cb_properties_changed, NULL);
if (!_ecore_drm_dbus_session_take(dsession))
{
ERR("Failed to take control of session");
goto session_err;
}
return _dbus_init_count;
session_err:
eldbus_proxy_event_callback_del(proxy, ELDBUS_PROXY_EVENT_PROPERTY_CHANGED,
_cb_properties_changed, NULL);
proxy_err:
eldbus_object_unref(dobj);
obj_err:
free(dpath);
path_err:
eldbus_connection_unref(dconn);
conn_err:
eina_stringshare_del(dsession);
eldbus_shutdown();
return --_dbus_init_count;
}
int
_ecore_drm_dbus_shutdown(void)
{
if (--_dbus_init_count != 0) return _dbus_init_count;
/* release control of the session */
_ecore_drm_dbus_session_release(dsession);
/* release dbus object */
if (dobj) eldbus_object_unref(dobj);
/* release the dbus connection */
if (dconn) eldbus_connection_unref(dconn);
eina_stringshare_del(dsession);
/* shutdown eldbus library */
eldbus_shutdown();
return _dbus_init_count;
}
void
_ecore_drm_dbus_device_open(const char *device, Eldbus_Message_Cb callback, const void *data)
{
struct stat st;
if (stat(device, &st) < 0) return;
if (!S_ISCHR(st.st_mode)) return;
_ecore_drm_dbus_device_take(major(st.st_rdev), minor(st.st_rdev), callback, data);
}
void
_ecore_drm_dbus_device_close(const char *device)
{
struct stat st;
if (stat(device, &st) < 0) return;
if (!S_ISCHR(st.st_mode)) return;
_ecore_drm_dbus_device_release(major(st.st_rdev), minor(st.st_rdev));
}