/* * Copyright © 2020 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include "config.h" #include #include "util-bits.h" #include "util-macros.h" #include "util-mem.h" #include "util-io.h" #include "util-strings.h" #include "libei-private.h" static void ei_seat_destroy(struct ei_seat *seat) { free(seat->name); } _public_ OBJECT_IMPLEMENT_REF(ei_seat); _public_ OBJECT_IMPLEMENT_UNREF(ei_seat); static OBJECT_IMPLEMENT_CREATE(ei_seat); static OBJECT_IMPLEMENT_PARENT(ei_seat, ei); _public_ OBJECT_IMPLEMENT_GETTER(ei_seat, name, const char *); _public_ OBJECT_IMPLEMENT_SETTER(ei_seat, user_data, void *); _public_ struct ei* ei_seat_get_context(struct ei_seat *seat) { assert(seat); return ei_seat_parent(seat); } struct ei_seat * ei_seat_new(struct ei *ei, uint32_t id, const char *name, uint32_t capabilities) { struct ei_seat *seat = ei_seat_create(&ei->object); seat->state = EI_SEAT_STATE_NEW; seat->name = xstrdup(name); seat->id = id; seat->capabilities = capabilities; seat->capabilities_mask = ~0; /* Masked out by client */ list_init(&seat->devices); list_init(&seat->devices_removed); list_init(&seat->link); return seat; /* ref owned by caller */ } void ei_seat_remove(struct ei_seat *seat) { /* Sigh, this is terrible and needs to be fixed: * if our fd is broken, trying to send any event causes an ei_disconnect(), * which eventually calls in here. So we need to guard this function * against nested callers. */ if (seat->state == EI_SEAT_STATE_REMOVED) return; struct ei_device *d; /* If the server disconnects us before processing a new device, we * need to clean this up in the library */ list_for_each_safe(d, &seat->devices, link) { /* remove the device */ ei_device_close(d); /* And pretend to process the removed message from * the server */ ei_device_removed_by_server(d); } /* Check the seat state again, because the above device removal may * have triggered ei_disconnect() */ if (seat->state != EI_SEAT_STATE_REMOVED) { seat->state = EI_SEAT_STATE_REMOVED; list_remove(&seat->link); list_init(&seat->link); ei_queue_seat_removed_event(seat); ei_seat_unref(seat); } } struct ei_device * ei_seat_find_device(struct ei_seat *seat, uint32_t deviceid) { struct ei_device *device; list_for_each(device, &seat->devices, link) { if (device->id == deviceid) return device; } return NULL; } _public_ void ei_seat_drop_capability(struct ei_seat *seat, enum ei_device_capability cap) { if (seat->state != EI_SEAT_STATE_NEW) { log_bug_client(ei_seat_get_context(seat), "Seat is already bound\n"); return; } flag_clear(seat->capabilities_mask, cap); } _public_ void ei_seat_bind(struct ei_seat *seat) { if (seat->state != EI_SEAT_STATE_NEW) { log_bug_client(ei_seat_get_context(seat), "Seat is already bound\n"); return; } ei_send_seat_bind(seat, seat->capabilities & seat->capabilities_mask); seat->state = EI_SEAT_STATE_BOUND; } _public_ void ei_seat_unbind(struct ei_seat *seat) { switch (seat->state) { case EI_SEAT_STATE_NEW: case EI_SEAT_STATE_BOUND: break; case EI_SEAT_STATE_UNBOUND: case EI_SEAT_STATE_REMOVED: return; } struct ei_device *device; list_for_each(device, &seat->devices, link) { ei_device_close(device); } ei_send_seat_unbind(seat); seat->state = EI_SEAT_STATE_UNBOUND; }