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 : }