]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/login/logind-device.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / login / logind-device.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
20263082
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2011 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
20263082
LP
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 15 Lesser General Public License for more details.
20263082 16
5430f7f2 17 You should have received a copy of the GNU Lesser General Public License
20263082
LP
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
20263082
LP
21#include <string.h>
22
b5efdb8a 23#include "alloc-util.h"
cc377381 24#include "logind-device.h"
b5efdb8a 25#include "util.h"
20263082 26
718d006a 27Device* device_new(Manager *m, const char *sysfs, bool master) {
20263082
LP
28 Device *d;
29
30 assert(m);
31 assert(sysfs);
32
33 d = new0(Device, 1);
34 if (!d)
35 return NULL;
36
37 d->sysfs = strdup(sysfs);
6b430fdb
ZJS
38 if (!d->sysfs)
39 return mfree(d);
20263082
LP
40
41 if (hashmap_put(m->devices, d->sysfs, d) < 0) {
42 free(d->sysfs);
6b430fdb 43 return mfree(d);
20263082
LP
44 }
45
46 d->manager = m;
718d006a 47 d->master = master;
20263082
LP
48 dual_timestamp_get(&d->timestamp);
49
50 return d;
51}
52
9588bc32 53static void device_detach(Device *d) {
f1a8e221 54 Seat *s;
118ecf32 55 SessionDevice *sd;
cc377381 56
20263082
LP
57 assert(d);
58
f1a8e221
LP
59 if (!d->seat)
60 return;
20263082 61
118ecf32
DH
62 while ((sd = d->session_devices))
63 session_device_free(sd);
64
f1a8e221 65 s = d->seat;
71fda00f 66 LIST_REMOVE(devices, d->seat->devices, d);
20263082 67 d->seat = NULL;
f1a8e221 68
718d006a
DH
69 if (!seat_has_master_device(s)) {
70 seat_add_to_gc_queue(s);
cc377381 71 seat_send_changed(s, "CanGraphical", NULL);
718d006a 72 }
20263082
LP
73}
74
9588bc32
LP
75void device_free(Device *d) {
76 assert(d);
77
78 device_detach(d);
79
80 hashmap_remove(d->manager->devices, d->sysfs);
81
82 free(d->sysfs);
83 free(d);
84}
85
20263082 86void device_attach(Device *d, Seat *s) {
718d006a
DH
87 Device *i;
88 bool had_master;
89
20263082
LP
90 assert(d);
91 assert(s);
92
f1a8e221
LP
93 if (d->seat == s)
94 return;
95
20263082
LP
96 if (d->seat)
97 device_detach(d);
98
20263082 99 d->seat = s;
718d006a
DH
100 had_master = seat_has_master_device(s);
101
102 /* We keep the device list sorted by the "master" flag. That is, master
103 * devices are at the front, other devices at the tail. As there is no
104 * way to easily add devices at the list-tail, we need to iterate the
105 * list to find the first non-master device when adding non-master
106 * devices. We assume there is only a few (normally 1) master devices
107 * per seat, so we iterate only a few times. */
108
109 if (d->master || !s->devices)
71fda00f 110 LIST_PREPEND(devices, s->devices, d);
718d006a
DH
111 else {
112 LIST_FOREACH(devices, i, s->devices) {
113 if (!i->devices_next || !i->master) {
71fda00f 114 LIST_INSERT_AFTER(devices, s->devices, i, d);
718d006a
DH
115 break;
116 }
117 }
118 }
f1a8e221 119
718d006a 120 if (!had_master && d->master)
cc377381 121 seat_send_changed(s, "CanGraphical", NULL);
20263082 122}