2017-11-18 17:09:20 +01:00
|
|
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <linux/input.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
2018-08-22 07:53:51 +02:00
|
|
|
#include "sd-device.h"
|
2015-11-17 06:52:45 +01:00
|
|
|
|
2015-10-27 03:01:06 +01:00
|
|
|
#include "alloc-util.h"
|
2013-11-05 01:10:21 +01:00
|
|
|
#include "bus-util.h"
|
2015-10-25 13:14:12 +01:00
|
|
|
#include "fd-util.h"
|
2013-11-05 01:10:21 +01:00
|
|
|
#include "logind-session-device.h"
|
2015-10-25 13:14:12 +01:00
|
|
|
#include "missing.h"
|
2017-03-16 11:17:09 +01:00
|
|
|
#include "parse-util.h"
|
|
|
|
#include "sd-daemon.h"
|
2015-10-25 13:14:12 +01:00
|
|
|
#include "util.h"
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
|
|
|
|
enum SessionDeviceNotifications {
|
|
|
|
SESSION_DEVICE_RESUME,
|
|
|
|
SESSION_DEVICE_TRY_PAUSE,
|
|
|
|
SESSION_DEVICE_PAUSE,
|
|
|
|
SESSION_DEVICE_RELEASE,
|
|
|
|
};
|
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
static int session_device_notify(SessionDevice *sd, enum SessionDeviceNotifications type) {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
_cleanup_free_ char *path = NULL;
|
|
|
|
const char *t = NULL;
|
2013-10-01 17:48:15 +02:00
|
|
|
uint32_t major, minor;
|
2013-11-05 01:10:21 +01:00
|
|
|
int r;
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
|
|
|
|
assert(sd);
|
|
|
|
|
2013-10-01 17:48:15 +02:00
|
|
|
major = major(sd->dev);
|
|
|
|
minor = minor(sd->dev);
|
|
|
|
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
if (!sd->session->controller)
|
2013-11-05 01:10:21 +01:00
|
|
|
return 0;
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
|
|
|
|
path = session_bus_path(sd->session);
|
|
|
|
if (!path)
|
2013-11-05 01:10:21 +01:00
|
|
|
return -ENOMEM;
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
r = sd_bus_message_new_signal(
|
2014-02-19 23:54:58 +01:00
|
|
|
sd->session->manager->bus,
|
|
|
|
&m, path,
|
2013-11-05 01:10:21 +01:00
|
|
|
"org.freedesktop.login1.Session",
|
2014-02-19 23:54:58 +01:00
|
|
|
(type == SESSION_DEVICE_RESUME) ? "ResumeDevice" : "PauseDevice");
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
if (!m)
|
2013-11-05 01:10:21 +01:00
|
|
|
return r;
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
r = sd_bus_message_set_destination(m, sd->session->controller);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
|
|
|
|
switch (type) {
|
2018-02-26 18:31:06 +01:00
|
|
|
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
case SESSION_DEVICE_RESUME:
|
2013-11-05 01:10:21 +01:00
|
|
|
r = sd_bus_message_append(m, "uuh", major, minor, sd->fd);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
break;
|
2018-02-26 18:31:06 +01:00
|
|
|
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
case SESSION_DEVICE_TRY_PAUSE:
|
|
|
|
t = "pause";
|
|
|
|
break;
|
2018-02-26 18:31:06 +01:00
|
|
|
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
case SESSION_DEVICE_PAUSE:
|
|
|
|
t = "force";
|
|
|
|
break;
|
2018-02-26 18:31:06 +01:00
|
|
|
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
case SESSION_DEVICE_RELEASE:
|
|
|
|
t = "gone";
|
|
|
|
break;
|
2018-02-26 18:31:06 +01:00
|
|
|
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
default:
|
2013-11-05 01:10:21 +01:00
|
|
|
return -EINVAL;
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
}
|
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
if (t) {
|
|
|
|
r = sd_bus_message_append(m, "uus", major, minor, t);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
}
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
return sd_bus_send(sd->session->manager->bus, m, NULL);
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
}
|
|
|
|
|
2018-03-02 11:55:16 +01:00
|
|
|
static void sd_eviocrevoke(int fd) {
|
2018-02-26 18:32:07 +01:00
|
|
|
static bool warned = false;
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
|
|
|
|
assert(fd >= 0);
|
|
|
|
|
2018-02-26 18:32:07 +01:00
|
|
|
if (ioctl(fd, EVIOCREVOKE, NULL) < 0) {
|
|
|
|
|
|
|
|
if (errno == EINVAL && !warned) {
|
|
|
|
log_warning_errno(errno, "Kernel does not support evdev-revocation: %m");
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
warned = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int sd_drmsetmaster(int fd) {
|
|
|
|
assert(fd >= 0);
|
|
|
|
|
2018-02-26 18:31:06 +01:00
|
|
|
if (ioctl(fd, DRM_IOCTL_SET_MASTER, 0) < 0)
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
return -errno;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int sd_drmdropmaster(int fd) {
|
|
|
|
assert(fd >= 0);
|
|
|
|
|
2018-02-26 18:31:06 +01:00
|
|
|
if (ioctl(fd, DRM_IOCTL_DROP_MASTER, 0) < 0)
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
return -errno;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int session_device_open(SessionDevice *sd, bool active) {
|
2013-10-01 17:53:43 +02:00
|
|
|
int fd, r;
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
|
2018-02-26 18:31:06 +01:00
|
|
|
assert(sd);
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
assert(sd->type != DEVICE_TYPE_UNKNOWN);
|
2018-02-26 18:31:06 +01:00
|
|
|
assert(sd->node);
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
|
|
|
|
/* open device and try to get an udev_device from it */
|
|
|
|
fd = open(sd->node, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
|
|
|
|
if (fd < 0)
|
|
|
|
return -errno;
|
|
|
|
|
|
|
|
switch (sd->type) {
|
2018-02-26 18:31:06 +01:00
|
|
|
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
case DEVICE_TYPE_DRM:
|
2013-10-01 17:53:43 +02:00
|
|
|
if (active) {
|
2018-02-26 18:31:06 +01:00
|
|
|
/* Weird legacy DRM semantics might return an error even though we're master. No way to detect
|
|
|
|
* that so fail at all times and let caller retry in inactive state. */
|
2013-10-01 17:53:43 +02:00
|
|
|
r = sd_drmsetmaster(fd);
|
|
|
|
if (r < 0) {
|
2013-11-28 14:51:40 +01:00
|
|
|
close_nointr(fd);
|
2013-10-01 17:53:43 +02:00
|
|
|
return r;
|
|
|
|
}
|
2018-02-26 18:31:06 +01:00
|
|
|
} else
|
|
|
|
/* DRM-Master is granted to the first user who opens a device automatically (ughh,
|
|
|
|
* racy!). Hence, we just drop DRM-Master in case we were the first. */
|
2018-03-02 11:55:33 +01:00
|
|
|
(void) sd_drmdropmaster(fd);
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
break;
|
2018-02-26 18:31:06 +01:00
|
|
|
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
case DEVICE_TYPE_EVDEV:
|
|
|
|
if (!active)
|
|
|
|
sd_eviocrevoke(fd);
|
|
|
|
break;
|
2018-02-26 18:31:06 +01:00
|
|
|
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
case DEVICE_TYPE_UNKNOWN:
|
|
|
|
default:
|
|
|
|
/* fallback for devices wihout synchronizations */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int session_device_start(SessionDevice *sd) {
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(sd);
|
|
|
|
assert(session_is_active(sd->session));
|
|
|
|
|
|
|
|
if (sd->active)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
switch (sd->type) {
|
2018-02-26 18:31:06 +01:00
|
|
|
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
case DEVICE_TYPE_DRM:
|
2018-03-02 11:55:51 +01:00
|
|
|
if (sd->fd < 0) {
|
2018-03-06 13:28:54 +01:00
|
|
|
log_error("Failed to re-activate DRM fd, as the fd was lost (maybe logind restart went wrong?)");
|
|
|
|
return -EBADF;
|
2018-03-02 11:55:51 +01:00
|
|
|
}
|
2018-03-06 13:28:54 +01:00
|
|
|
|
|
|
|
/* Device is kept open. Simply call drmSetMaster() and hope there is no-one else. In case it fails, we
|
|
|
|
* keep the device paused. Maybe at some point we have a drmStealMaster(). */
|
|
|
|
r = sd_drmsetmaster(sd->fd);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
break;
|
2018-02-26 18:31:06 +01:00
|
|
|
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
case DEVICE_TYPE_EVDEV:
|
2018-02-26 18:31:06 +01:00
|
|
|
/* Evdev devices are revoked while inactive. Reopen it and we are fine. */
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
r = session_device_open(sd, true);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2018-02-26 18:31:06 +01:00
|
|
|
|
|
|
|
/* For evdev devices, the file descriptor might be left uninitialized. This might happen while resuming
|
|
|
|
* into a session and logind has been restarted right before. */
|
2017-03-16 11:17:09 +01:00
|
|
|
safe_close(sd->fd);
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
sd->fd = r;
|
|
|
|
break;
|
2018-02-26 18:31:06 +01:00
|
|
|
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
case DEVICE_TYPE_UNKNOWN:
|
|
|
|
default:
|
2018-03-02 11:56:15 +01:00
|
|
|
/* fallback for devices without synchronizations */
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
sd->active = true;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void session_device_stop(SessionDevice *sd) {
|
|
|
|
assert(sd);
|
|
|
|
|
|
|
|
if (!sd->active)
|
|
|
|
return;
|
|
|
|
|
|
|
|
switch (sd->type) {
|
2018-03-02 11:56:15 +01:00
|
|
|
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
case DEVICE_TYPE_DRM:
|
2018-03-06 13:28:54 +01:00
|
|
|
if (sd->fd < 0) {
|
|
|
|
log_error("Failed to de-activate DRM fd, as the fd was lost (maybe logind restart went wrong?)");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
/* On DRM devices we simply drop DRM-Master but keep it open.
|
|
|
|
* This allows the user to keep resources allocated. The
|
|
|
|
* CAP_SYS_ADMIN restriction to DRM-Master prevents users from
|
|
|
|
* circumventing this. */
|
|
|
|
sd_drmdropmaster(sd->fd);
|
|
|
|
break;
|
2018-03-02 11:56:15 +01:00
|
|
|
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
case DEVICE_TYPE_EVDEV:
|
|
|
|
/* Revoke access on evdev file-descriptors during deactivation.
|
|
|
|
* This will basically prevent any operations on the fd and
|
|
|
|
* cannot be undone. Good side is: it needs no CAP_SYS_ADMIN
|
|
|
|
* protection this way. */
|
|
|
|
sd_eviocrevoke(sd->fd);
|
|
|
|
break;
|
2018-03-02 11:56:15 +01:00
|
|
|
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
case DEVICE_TYPE_UNKNOWN:
|
|
|
|
default:
|
|
|
|
/* fallback for devices without synchronization */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
sd->active = false;
|
|
|
|
}
|
|
|
|
|
2018-08-22 07:53:51 +02:00
|
|
|
static DeviceType detect_device_type(sd_device *dev) {
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
const char *sysname, *subsystem;
|
2018-08-22 07:53:51 +02:00
|
|
|
DeviceType type = DEVICE_TYPE_UNKNOWN;
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
|
2018-08-22 07:53:51 +02:00
|
|
|
if (sd_device_get_sysname(dev, &sysname) < 0 ||
|
|
|
|
sd_device_get_subsystem(dev, &subsystem) < 0)
|
|
|
|
return type;
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
|
2013-10-01 18:08:54 +02:00
|
|
|
if (streq_ptr(subsystem, "drm")) {
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
if (startswith(sysname, "card"))
|
|
|
|
type = DEVICE_TYPE_DRM;
|
|
|
|
} else if (streq_ptr(subsystem, "input")) {
|
|
|
|
if (startswith(sysname, "event"))
|
|
|
|
type = DEVICE_TYPE_EVDEV;
|
|
|
|
}
|
|
|
|
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int session_device_verify(SessionDevice *sd) {
|
2018-08-22 07:53:51 +02:00
|
|
|
_cleanup_(sd_device_unrefp) sd_device *p = NULL;
|
|
|
|
sd_device *dev;
|
|
|
|
const char *sp = NULL, *node;
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
int r;
|
|
|
|
|
2018-08-22 07:53:51 +02:00
|
|
|
if (sd_device_new_from_devnum(&p, 'c', sd->dev) < 0)
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
return -ENODEV;
|
|
|
|
|
2018-08-22 07:53:51 +02:00
|
|
|
dev = p;
|
|
|
|
|
|
|
|
(void) sd_device_get_syspath(dev, &sp);
|
|
|
|
if (sd_device_get_devname(dev, &node) < 0)
|
|
|
|
return -EINVAL;
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
|
|
|
|
/* detect device type so we can find the correct sysfs parent */
|
|
|
|
sd->type = detect_device_type(dev);
|
2018-08-22 07:53:51 +02:00
|
|
|
if (sd->type == DEVICE_TYPE_UNKNOWN)
|
|
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
else if (sd->type == DEVICE_TYPE_EVDEV) {
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
/* for evdev devices we need the parent node as device */
|
2018-08-22 07:53:51 +02:00
|
|
|
if (sd_device_get_parent_with_subsystem_devtype(p, "input", NULL, &dev) < 0)
|
|
|
|
return -ENODEV;
|
|
|
|
if (sd_device_get_syspath(dev, &sp) < 0)
|
|
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
} else if (sd->type != DEVICE_TYPE_DRM)
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
/* Prevent opening unsupported devices. Especially devices of
|
|
|
|
* subsystem "input" must be opened via the evdev node as
|
|
|
|
* we require EVIOCREVOKE. */
|
2018-08-22 07:53:51 +02:00
|
|
|
return -ENODEV;
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
|
|
|
|
/* search for an existing seat device and return it if available */
|
|
|
|
sd->device = hashmap_get(sd->session->manager->devices, sp);
|
|
|
|
if (!sd->device) {
|
|
|
|
/* The caller might have gotten the udev event before we were
|
|
|
|
* able to process it. Hence, fake the "add" event and let the
|
|
|
|
* logind-manager handle the new device. */
|
|
|
|
r = manager_process_seat_device(sd->session->manager, dev);
|
|
|
|
if (r < 0)
|
2018-08-22 07:53:51 +02:00
|
|
|
return r;
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
|
|
|
|
/* if it's still not available, then the device is invalid */
|
|
|
|
sd->device = hashmap_get(sd->session->manager->devices, sp);
|
2018-08-22 07:53:51 +02:00
|
|
|
if (!sd->device)
|
|
|
|
return -ENODEV;
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
}
|
|
|
|
|
2018-08-22 07:53:51 +02:00
|
|
|
if (sd->device->seat != sd->session->seat)
|
|
|
|
return -EPERM;
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
|
|
|
|
sd->node = strdup(node);
|
2018-08-22 07:53:51 +02:00
|
|
|
if (!sd->node)
|
|
|
|
return -ENOMEM;
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
|
2018-08-22 07:53:51 +02:00
|
|
|
return 0;
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
}
|
|
|
|
|
2017-03-16 11:17:09 +01:00
|
|
|
int session_device_new(Session *s, dev_t dev, bool open_device, SessionDevice **out) {
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
SessionDevice *sd;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(s);
|
|
|
|
assert(out);
|
|
|
|
|
|
|
|
if (!s->seat)
|
|
|
|
return -EPERM;
|
|
|
|
|
|
|
|
sd = new0(SessionDevice, 1);
|
|
|
|
if (!sd)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
sd->session = s;
|
|
|
|
sd->dev = dev;
|
|
|
|
sd->fd = -1;
|
|
|
|
sd->type = DEVICE_TYPE_UNKNOWN;
|
|
|
|
|
|
|
|
r = session_device_verify(sd);
|
|
|
|
if (r < 0)
|
|
|
|
goto error;
|
|
|
|
|
2013-09-18 01:00:02 +02:00
|
|
|
r = hashmap_put(s->devices, &sd->dev, sd);
|
2018-02-26 18:33:05 +01:00
|
|
|
if (r < 0)
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
goto error;
|
|
|
|
|
2017-03-16 11:17:09 +01:00
|
|
|
if (open_device) {
|
|
|
|
/* Open the device for the first time. We need a valid fd to pass back
|
|
|
|
* to the caller. If the session is not active, this _might_ immediately
|
|
|
|
* revoke access and thus invalidate the fd. But this is still needed
|
|
|
|
* to pass a valid fd back. */
|
|
|
|
sd->active = session_is_active(s);
|
|
|
|
r = session_device_open(sd, sd->active);
|
|
|
|
if (r < 0) {
|
|
|
|
/* EINVAL _may_ mean a master is active; retry inactive */
|
|
|
|
if (sd->active && r == -EINVAL) {
|
|
|
|
sd->active = false;
|
|
|
|
r = session_device_open(sd, false);
|
|
|
|
}
|
|
|
|
if (r < 0)
|
|
|
|
goto error;
|
2013-10-01 17:53:43 +02:00
|
|
|
}
|
2017-03-16 11:17:09 +01:00
|
|
|
sd->fd = r;
|
2013-10-01 17:53:43 +02:00
|
|
|
}
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
|
2013-10-14 06:10:14 +02:00
|
|
|
LIST_PREPEND(sd_by_device, sd->device->session_devices, sd);
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
|
|
|
|
*out = sd;
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
2013-09-18 01:00:02 +02:00
|
|
|
hashmap_remove(s->devices, &sd->dev);
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
free(sd->node);
|
|
|
|
free(sd);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
void session_device_free(SessionDevice *sd) {
|
|
|
|
assert(sd);
|
|
|
|
|
2018-03-06 16:59:38 +01:00
|
|
|
/* Make sure to remove the pushed fd. */
|
2017-11-13 19:06:11 +01:00
|
|
|
if (sd->pushed_fd) {
|
2018-03-06 16:59:38 +01:00
|
|
|
_cleanup_free_ char *m = NULL;
|
|
|
|
const char *id;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
/* Session ID does not contain separators. */
|
|
|
|
id = sd->session->id;
|
|
|
|
assert(*(id + strcspn(id, "-\n")) == '\0');
|
|
|
|
|
|
|
|
r = asprintf(&m, "FDSTOREREMOVE=1\n"
|
|
|
|
"FDNAME=session-%s-device-%u-%u\n",
|
|
|
|
id, major(sd->dev), minor(sd->dev));
|
|
|
|
if (r >= 0)
|
|
|
|
(void) sd_notify(false, m);
|
2017-11-13 19:06:11 +01:00
|
|
|
}
|
|
|
|
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
session_device_stop(sd);
|
|
|
|
session_device_notify(sd, SESSION_DEVICE_RELEASE);
|
2018-02-26 18:34:49 +01:00
|
|
|
safe_close(sd->fd);
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
|
2013-10-14 06:10:14 +02:00
|
|
|
LIST_REMOVE(sd_by_device, sd->device->session_devices, sd);
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
|
2013-09-18 01:00:02 +02:00
|
|
|
hashmap_remove(sd->session->devices, &sd->dev);
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
|
|
|
|
free(sd->node);
|
|
|
|
free(sd);
|
|
|
|
}
|
|
|
|
|
|
|
|
void session_device_complete_pause(SessionDevice *sd) {
|
2013-09-17 23:40:19 +02:00
|
|
|
SessionDevice *iter;
|
|
|
|
Iterator i;
|
|
|
|
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
if (!sd->active)
|
|
|
|
return;
|
|
|
|
|
|
|
|
session_device_stop(sd);
|
2013-09-17 23:40:19 +02:00
|
|
|
|
|
|
|
/* if not all devices are paused, wait for further completion events */
|
|
|
|
HASHMAP_FOREACH(iter, sd->session->devices, i)
|
|
|
|
if (iter->active)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* complete any pending session switch */
|
|
|
|
seat_complete_switch(sd->session->seat);
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void session_device_resume_all(Session *s) {
|
|
|
|
SessionDevice *sd;
|
|
|
|
Iterator i;
|
|
|
|
|
|
|
|
assert(s);
|
|
|
|
|
|
|
|
HASHMAP_FOREACH(sd, s->devices, i) {
|
2018-02-26 18:33:20 +01:00
|
|
|
if (sd->active)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (session_device_start(sd) < 0)
|
|
|
|
continue;
|
|
|
|
if (session_device_save(sd) < 0)
|
|
|
|
continue;
|
2018-03-02 11:56:15 +01:00
|
|
|
|
2018-02-26 18:33:20 +01:00
|
|
|
session_device_notify(sd, SESSION_DEVICE_RESUME);
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void session_device_pause_all(Session *s) {
|
|
|
|
SessionDevice *sd;
|
|
|
|
Iterator i;
|
|
|
|
|
|
|
|
assert(s);
|
|
|
|
|
|
|
|
HASHMAP_FOREACH(sd, s->devices, i) {
|
2018-02-26 18:33:20 +01:00
|
|
|
if (!sd->active)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
session_device_stop(sd);
|
|
|
|
session_device_notify(sd, SESSION_DEVICE_PAUSE);
|
logind: introduce session-devices
A session-device is a device that is bound to a seat and used by a
session-controller to run the session. This currently includes DRM, fbdev
and evdev devices. A session-device can be created via RequestDevice() on
the dbus API of the session. You can drop it via ReleaseDevice() again.
Once the session is destroyed or you drop control of the session, all
session-devices are automatically destroyed.
Session devices follow the session "active" state. A device can be
active/running or inactive/paused. Whenever a session is not the active
session, no session-device of it can be active. That is, if a session is
not in foreground, all session-devices are paused.
Whenever a session becomes active, all devices are resumed/activated by
logind. If it fails, a device may stay paused.
With every session-device you request, you also get a file-descriptor
back. logind keeps a copy of this fd and uses kernel specific calls to
pause/resume the file-descriptors. For example, a DRM fd is muted
by logind as long as a given session is not active. Hence, the fd of the
application is also muted. Once the session gets active, logind unmutes
the fd and the application will get DRM access again.
This, however, requires kernel support. DRM devices provide DRM-Master for
synchronization, evdev devices have EVIOCREVOKE (pending on
linux-input-ML). fbdev devices do not provide such synchronization methods
(and never will).
Note that for evdev devices, we call EVIOCREVOKE once a session gets
inactive. However, this cannot be undone (the fd is still valid but mostly
unusable). So we reopen a new fd once the session is activated and send it
together with the ResumeDevice() signal.
With this infrastructure in place, compositors can now run without
CAP_SYS_ADMIN (that is, without being root). They use RequestControl() to
acquire a session and listen for devices via udev_monitor. For every
device they want to open, they call RequestDevice() on logind. This
returns a fd which they can use now. They no longer have to open the
devices themselves or call any privileged ioctls. This is all done by
logind.
Session-switches are still bound to VTs. Hence, compositors will get
notified via the usual VT mechanisms and can cleanup their state. Once the
VT switch is acknowledged as usual, logind will get notified via sysfs and
pause the old-session's devices and resume the devices of the new session.
To allow using this infrastructure with systems without VTs, we provide
notification signals. logind sends PauseDevice("force") dbus signals to
the current session controller for every device that it pauses. And it
sends ResumeDevice signals for every device that it resumes. For
seats with VTs this is sent _after_ the VT switch is acknowledged. Because
the compositor already acknowledged that it cleaned-up all devices.
However, for seats without VTs, this is used to notify the active
compositor that the session is about to be deactivated. That is, logind
sends PauseDevice("force") for each active device and then performs the
session-switch. The session-switch changes the "Active" property of the
session which can be monitored by the compositor. The new session is
activated and the ResumeDevice events are sent.
For seats without VTs, this is a forced session-switch. As this is not
backwards-compatible (xserver actually crashes, weston drops the related
devices, ..) we also provide an acknowledged session-switch. Note that
this is never used for sessions with VTs. You use the acknowledged
VT-switch on these seats.
An acknowledged session switch sends PauseDevice("pause") instead of
PauseDevice("force") to the active session. It schedules a short timeout
and waits for the session to acknowledge each of them with
PauseDeviceComplete(). Once all are acknowledged, or the session ran out
of time, a PauseDevice("force") is sent for all remaining active devices
and the session switch is performed.
Note that this is only partially implemented, yet, as we don't allow
multi-session without VTs, yet. A follow up commit will hook it up and
implemented the acknowledgements+timeout.
The implementation is quite simple. We use major/minor exclusively to
identify devices on the bus. On RequestDevice() we retrieve the
udev_device from the major/minor and search for an existing "Device"
object. If no exists, we create it. This guarantees us that we are
notified whenever the device changes seats or is removed.
We create a new SessionDevice object and link it to the related Session
and Device. Session->devices is a hashtable to lookup SessionDevice
objects via major/minor. Device->session_devices is a linked list so we
can release all linked session-devices once a device vanishes.
Now we only have to hook this up in seat_set_active() so we correctly
change device states during session-switches. As mentioned earlier, these
are forced state-changes as VTs are currently used exclusively for
multi-session implementations.
Everything else are hooks to release all session-devices once the
controller changes or a session is closed or removed.
2013-09-17 23:39:04 +02:00
|
|
|
}
|
|
|
|
}
|
2013-09-17 23:40:19 +02:00
|
|
|
|
|
|
|
unsigned int session_device_try_pause_all(Session *s) {
|
2018-02-26 18:33:20 +01:00
|
|
|
unsigned num_pending = 0;
|
2013-09-17 23:40:19 +02:00
|
|
|
SessionDevice *sd;
|
|
|
|
Iterator i;
|
|
|
|
|
|
|
|
assert(s);
|
|
|
|
|
|
|
|
HASHMAP_FOREACH(sd, s->devices, i) {
|
2018-02-26 18:33:20 +01:00
|
|
|
if (!sd->active)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
session_device_notify(sd, SESSION_DEVICE_TRY_PAUSE);
|
|
|
|
num_pending++;
|
2013-09-17 23:40:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return num_pending;
|
|
|
|
}
|
2017-03-16 11:17:09 +01:00
|
|
|
|
|
|
|
int session_device_save(SessionDevice *sd) {
|
2018-03-06 16:59:38 +01:00
|
|
|
_cleanup_free_ char *m = NULL;
|
|
|
|
const char *id;
|
2017-03-16 11:17:09 +01:00
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(sd);
|
|
|
|
|
2017-11-13 19:06:11 +01:00
|
|
|
/* Store device fd in PID1. It will send it back to us on restart so revocation will continue to work. To make
|
|
|
|
* things simple, send fds for all type of devices even if they don't support the revocation mechanism so we
|
|
|
|
* don't have to handle them differently later.
|
2017-03-16 11:17:09 +01:00
|
|
|
*
|
2017-11-13 19:06:11 +01:00
|
|
|
* Note: for device supporting revocation, PID1 will drop a stored fd automatically if the corresponding device
|
|
|
|
* is revoked. */
|
|
|
|
|
|
|
|
if (sd->pushed_fd)
|
|
|
|
return 0;
|
2018-06-12 12:03:28 +02:00
|
|
|
|
2018-03-06 16:59:38 +01:00
|
|
|
/* Session ID does not contain separators. */
|
|
|
|
id = sd->session->id;
|
|
|
|
assert(*(id + strcspn(id, "-\n")) == '\0');
|
|
|
|
|
|
|
|
r = asprintf(&m, "FDSTORE=1\n"
|
|
|
|
"FDNAME=session-%s-device-%u-%u\n",
|
|
|
|
id, major(sd->dev), minor(sd->dev));
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2017-11-13 19:06:11 +01:00
|
|
|
|
|
|
|
r = sd_pid_notify_with_fds(0, false, m, &sd->fd, 1);
|
2017-03-16 11:17:09 +01:00
|
|
|
if (r < 0)
|
2017-11-13 19:06:11 +01:00
|
|
|
return r;
|
2017-03-16 11:17:09 +01:00
|
|
|
|
2017-11-13 19:06:11 +01:00
|
|
|
sd->pushed_fd = true;
|
|
|
|
return 1;
|
2017-03-16 11:17:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void session_device_attach_fd(SessionDevice *sd, int fd, bool active) {
|
2018-02-26 18:33:51 +01:00
|
|
|
assert(fd >= 0);
|
2017-03-16 11:17:09 +01:00
|
|
|
assert(sd);
|
|
|
|
assert(sd->fd < 0);
|
|
|
|
assert(!sd->active);
|
|
|
|
|
|
|
|
sd->fd = fd;
|
2018-03-03 19:44:39 +01:00
|
|
|
sd->pushed_fd = true;
|
2017-03-16 11:17:09 +01:00
|
|
|
sd->active = active;
|
|
|
|
}
|