Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : :
3 : : #include <string.h>
4 : :
5 : : #include "alloc-util.h"
6 : : #include "logind-device.h"
7 : : #include "logind-seat-dbus.h"
8 : : #include "util.h"
9 : :
10 : 0 : Device* device_new(Manager *m, const char *sysfs, bool master) {
11 : : Device *d;
12 : :
13 [ # # ]: 0 : assert(m);
14 [ # # ]: 0 : assert(sysfs);
15 : :
16 : 0 : d = new0(Device, 1);
17 [ # # ]: 0 : if (!d)
18 : 0 : return NULL;
19 : :
20 : 0 : d->sysfs = strdup(sysfs);
21 [ # # ]: 0 : if (!d->sysfs)
22 : 0 : return mfree(d);
23 : :
24 [ # # ]: 0 : if (hashmap_put(m->devices, d->sysfs, d) < 0) {
25 : 0 : free(d->sysfs);
26 : 0 : return mfree(d);
27 : : }
28 : :
29 : 0 : d->manager = m;
30 : 0 : d->master = master;
31 : 0 : dual_timestamp_get(&d->timestamp);
32 : :
33 : 0 : return d;
34 : : }
35 : :
36 : 0 : static void device_detach(Device *d) {
37 : : Seat *s;
38 : : SessionDevice *sd;
39 : :
40 [ # # ]: 0 : assert(d);
41 : :
42 [ # # ]: 0 : if (!d->seat)
43 : 0 : return;
44 : :
45 [ # # ]: 0 : while ((sd = d->session_devices))
46 : 0 : session_device_free(sd);
47 : :
48 : 0 : s = d->seat;
49 [ # # # # : 0 : LIST_REMOVE(devices, d->seat->devices, d);
# # # # ]
50 : 0 : d->seat = NULL;
51 : :
52 [ # # ]: 0 : if (!seat_has_master_device(s)) {
53 : 0 : seat_add_to_gc_queue(s);
54 : 0 : seat_send_changed(s, "CanGraphical", NULL);
55 : : }
56 : : }
57 : :
58 : 0 : void device_free(Device *d) {
59 [ # # ]: 0 : assert(d);
60 : :
61 : 0 : device_detach(d);
62 : :
63 : 0 : hashmap_remove(d->manager->devices, d->sysfs);
64 : :
65 : 0 : free(d->sysfs);
66 : 0 : free(d);
67 : 0 : }
68 : :
69 : 0 : void device_attach(Device *d, Seat *s) {
70 : : Device *i;
71 : : bool had_master;
72 : :
73 [ # # ]: 0 : assert(d);
74 [ # # ]: 0 : assert(s);
75 : :
76 [ # # ]: 0 : if (d->seat == s)
77 : 0 : return;
78 : :
79 [ # # ]: 0 : if (d->seat)
80 : 0 : device_detach(d);
81 : :
82 : 0 : d->seat = s;
83 : 0 : had_master = seat_has_master_device(s);
84 : :
85 : : /* We keep the device list sorted by the "master" flag. That is, master
86 : : * devices are at the front, other devices at the tail. As there is no
87 : : * way to easily add devices at the list-tail, we need to iterate the
88 : : * list to find the first non-master device when adding non-master
89 : : * devices. We assume there is only a few (normally 1) master devices
90 : : * per seat, so we iterate only a few times. */
91 : :
92 [ # # # # ]: 0 : if (d->master || !s->devices)
93 [ # # # # ]: 0 : LIST_PREPEND(devices, s->devices, d);
94 : : else {
95 [ # # ]: 0 : LIST_FOREACH(devices, i, s->devices) {
96 [ # # # # ]: 0 : if (!i->devices_next || !i->master) {
97 [ # # # # : 0 : LIST_INSERT_AFTER(devices, s->devices, i, d);
# # # # ]
98 : 0 : break;
99 : : }
100 : : }
101 : : }
102 : :
103 [ # # # # : 0 : if (!had_master && d->master && s->started) {
# # ]
104 : 0 : seat_save(s);
105 : 0 : seat_send_changed(s, "CanGraphical", NULL);
106 : : }
107 : : }
|