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