1a46c0ec8Sopenharmony_ci/* 2a46c0ec8Sopenharmony_ci * Copyright © 2013 Intel Corporation 3a46c0ec8Sopenharmony_ci * Copyright © 2013-2015 Red Hat, Inc. 4a46c0ec8Sopenharmony_ci * 5a46c0ec8Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 6a46c0ec8Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 7a46c0ec8Sopenharmony_ci * to deal in the Software without restriction, including without limitation 8a46c0ec8Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9a46c0ec8Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 10a46c0ec8Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 11a46c0ec8Sopenharmony_ci * 12a46c0ec8Sopenharmony_ci * The above copyright notice and this permission notice (including the next 13a46c0ec8Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 14a46c0ec8Sopenharmony_ci * Software. 15a46c0ec8Sopenharmony_ci * 16a46c0ec8Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17a46c0ec8Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18a46c0ec8Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19a46c0ec8Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20a46c0ec8Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21a46c0ec8Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22a46c0ec8Sopenharmony_ci * DEALINGS IN THE SOFTWARE. 23a46c0ec8Sopenharmony_ci */ 24a46c0ec8Sopenharmony_ci 25a46c0ec8Sopenharmony_ci#include "config.h" 26a46c0ec8Sopenharmony_ci 27a46c0ec8Sopenharmony_ci#include <stdlib.h> 28a46c0ec8Sopenharmony_ci#include <stdio.h> 29a46c0ec8Sopenharmony_ci#include <string.h> 30a46c0ec8Sopenharmony_ci 31a46c0ec8Sopenharmony_ci#include "evdev.h" 32a46c0ec8Sopenharmony_ci#include "udev-seat.h" 33a46c0ec8Sopenharmony_ci 34a46c0ec8Sopenharmony_cistatic const char default_seat[] = "seat0"; 35a46c0ec8Sopenharmony_cistatic const char default_seat_name[] = "default"; 36a46c0ec8Sopenharmony_ci 37a46c0ec8Sopenharmony_cistatic struct udev_seat * 38a46c0ec8Sopenharmony_ciudev_seat_create(struct udev_input *input, 39a46c0ec8Sopenharmony_ci const char *device_seat, 40a46c0ec8Sopenharmony_ci const char *seat_name); 41a46c0ec8Sopenharmony_cistatic struct udev_seat * 42a46c0ec8Sopenharmony_ciudev_seat_get_named(struct udev_input *input, const char *seat_name); 43a46c0ec8Sopenharmony_ci 44a46c0ec8Sopenharmony_cistatic inline bool 45a46c0ec8Sopenharmony_cifilter_duplicates(struct udev_seat *udev_seat, 46a46c0ec8Sopenharmony_ci struct udev_device *udev_device) 47a46c0ec8Sopenharmony_ci{ 48a46c0ec8Sopenharmony_ci struct libinput_device *device; 49a46c0ec8Sopenharmony_ci const char *new_syspath = udev_device_get_syspath(udev_device); 50a46c0ec8Sopenharmony_ci bool ignore_device = false; 51a46c0ec8Sopenharmony_ci 52a46c0ec8Sopenharmony_ci if (!udev_seat) 53a46c0ec8Sopenharmony_ci return false; 54a46c0ec8Sopenharmony_ci 55a46c0ec8Sopenharmony_ci list_for_each(device, &udev_seat->base.devices_list, link) { 56a46c0ec8Sopenharmony_ci const char *syspath; 57a46c0ec8Sopenharmony_ci struct udev_device *ud; 58a46c0ec8Sopenharmony_ci 59a46c0ec8Sopenharmony_ci ud = libinput_device_get_udev_device(device); 60a46c0ec8Sopenharmony_ci if (!ud) 61a46c0ec8Sopenharmony_ci continue; 62a46c0ec8Sopenharmony_ci 63a46c0ec8Sopenharmony_ci syspath = udev_device_get_syspath(ud); 64a46c0ec8Sopenharmony_ci if (syspath && new_syspath && streq(syspath, new_syspath)) 65a46c0ec8Sopenharmony_ci ignore_device = true; 66a46c0ec8Sopenharmony_ci udev_device_unref(ud); 67a46c0ec8Sopenharmony_ci 68a46c0ec8Sopenharmony_ci if (ignore_device) 69a46c0ec8Sopenharmony_ci break; 70a46c0ec8Sopenharmony_ci } 71a46c0ec8Sopenharmony_ci 72a46c0ec8Sopenharmony_ci return ignore_device; 73a46c0ec8Sopenharmony_ci} 74a46c0ec8Sopenharmony_ci 75a46c0ec8Sopenharmony_cistatic int 76a46c0ec8Sopenharmony_cidevice_added(struct udev_device *udev_device, 77a46c0ec8Sopenharmony_ci struct udev_input *input, 78a46c0ec8Sopenharmony_ci const char *seat_name) 79a46c0ec8Sopenharmony_ci{ 80a46c0ec8Sopenharmony_ci struct evdev_device *device; 81a46c0ec8Sopenharmony_ci const char *devnode, *sysname; 82a46c0ec8Sopenharmony_ci const char *device_seat, *output_name; 83a46c0ec8Sopenharmony_ci struct udev_seat *seat; 84a46c0ec8Sopenharmony_ci 85a46c0ec8Sopenharmony_ci device_seat = udev_device_get_property_value(udev_device, "ID_SEAT"); 86a46c0ec8Sopenharmony_ci if (!device_seat) 87a46c0ec8Sopenharmony_ci device_seat = default_seat; 88a46c0ec8Sopenharmony_ci 89a46c0ec8Sopenharmony_ci if (!streq(device_seat, input->seat_id)) 90a46c0ec8Sopenharmony_ci return 0; 91a46c0ec8Sopenharmony_ci 92a46c0ec8Sopenharmony_ci if (ignore_litest_test_suite_device(udev_device)) 93a46c0ec8Sopenharmony_ci return 0; 94a46c0ec8Sopenharmony_ci 95a46c0ec8Sopenharmony_ci devnode = udev_device_get_devnode(udev_device); 96a46c0ec8Sopenharmony_ci sysname = udev_device_get_sysname(udev_device); 97a46c0ec8Sopenharmony_ci 98a46c0ec8Sopenharmony_ci /* Search for matching logical seat */ 99a46c0ec8Sopenharmony_ci if (!seat_name) 100a46c0ec8Sopenharmony_ci seat_name = udev_device_get_property_value(udev_device, "WL_SEAT"); 101a46c0ec8Sopenharmony_ci if (!seat_name) 102a46c0ec8Sopenharmony_ci seat_name = default_seat_name; 103a46c0ec8Sopenharmony_ci 104a46c0ec8Sopenharmony_ci seat = udev_seat_get_named(input, seat_name); 105a46c0ec8Sopenharmony_ci 106a46c0ec8Sopenharmony_ci /* There is a race at startup: a device added between setting 107a46c0ec8Sopenharmony_ci * up the udev monitor and enumerating all current devices may show 108a46c0ec8Sopenharmony_ci * up in both lists. Filter those out. 109a46c0ec8Sopenharmony_ci */ 110a46c0ec8Sopenharmony_ci if (filter_duplicates(seat, udev_device)) 111a46c0ec8Sopenharmony_ci return 0; 112a46c0ec8Sopenharmony_ci 113a46c0ec8Sopenharmony_ci if (seat) 114a46c0ec8Sopenharmony_ci libinput_seat_ref(&seat->base); 115a46c0ec8Sopenharmony_ci else { 116a46c0ec8Sopenharmony_ci seat = udev_seat_create(input, device_seat, seat_name); 117a46c0ec8Sopenharmony_ci if (!seat) 118a46c0ec8Sopenharmony_ci return -1; 119a46c0ec8Sopenharmony_ci } 120a46c0ec8Sopenharmony_ci 121a46c0ec8Sopenharmony_ci device = evdev_device_create(&seat->base, udev_device); 122a46c0ec8Sopenharmony_ci libinput_seat_unref(&seat->base); 123a46c0ec8Sopenharmony_ci 124a46c0ec8Sopenharmony_ci if (device == EVDEV_UNHANDLED_DEVICE) { 125a46c0ec8Sopenharmony_ci log_info(&input->base, 126a46c0ec8Sopenharmony_ci "%-7s - not using input device '%s'\n", 127a46c0ec8Sopenharmony_ci sysname, 128a46c0ec8Sopenharmony_ci devnode); 129a46c0ec8Sopenharmony_ci return 0; 130a46c0ec8Sopenharmony_ci } 131a46c0ec8Sopenharmony_ci 132a46c0ec8Sopenharmony_ci if (device == NULL) { 133a46c0ec8Sopenharmony_ci log_info(&input->base, 134a46c0ec8Sopenharmony_ci "%-7s - failed to create input device '%s'\n", 135a46c0ec8Sopenharmony_ci sysname, 136a46c0ec8Sopenharmony_ci devnode); 137a46c0ec8Sopenharmony_ci return 0; 138a46c0ec8Sopenharmony_ci } 139a46c0ec8Sopenharmony_ci 140a46c0ec8Sopenharmony_ci evdev_read_calibration_prop(device); 141a46c0ec8Sopenharmony_ci 142a46c0ec8Sopenharmony_ci output_name = udev_device_get_property_value(udev_device, "WL_OUTPUT"); 143a46c0ec8Sopenharmony_ci device->output_name = safe_strdup(output_name); 144a46c0ec8Sopenharmony_ci 145a46c0ec8Sopenharmony_ci return 0; 146a46c0ec8Sopenharmony_ci} 147a46c0ec8Sopenharmony_ci 148a46c0ec8Sopenharmony_cistatic void 149a46c0ec8Sopenharmony_cidevice_removed(struct udev_device *udev_device, struct udev_input *input) 150a46c0ec8Sopenharmony_ci{ 151a46c0ec8Sopenharmony_ci struct evdev_device *device; 152a46c0ec8Sopenharmony_ci struct udev_seat *seat; 153a46c0ec8Sopenharmony_ci const char *syspath; 154a46c0ec8Sopenharmony_ci 155a46c0ec8Sopenharmony_ci syspath = udev_device_get_syspath(udev_device); 156a46c0ec8Sopenharmony_ci list_for_each(seat, &input->base.seat_list, base.link) { 157a46c0ec8Sopenharmony_ci list_for_each_safe(device, 158a46c0ec8Sopenharmony_ci &seat->base.devices_list, base.link) { 159a46c0ec8Sopenharmony_ci if (streq(syspath, 160a46c0ec8Sopenharmony_ci udev_device_get_syspath(device->udev_device))) { 161a46c0ec8Sopenharmony_ci evdev_device_remove(device); 162a46c0ec8Sopenharmony_ci break; 163a46c0ec8Sopenharmony_ci } 164a46c0ec8Sopenharmony_ci } 165a46c0ec8Sopenharmony_ci } 166a46c0ec8Sopenharmony_ci} 167a46c0ec8Sopenharmony_ci 168a46c0ec8Sopenharmony_cistatic int 169a46c0ec8Sopenharmony_ciudev_input_add_devices(struct udev_input *input, struct udev *udev) 170a46c0ec8Sopenharmony_ci{ 171a46c0ec8Sopenharmony_ci struct udev_enumerate *e; 172a46c0ec8Sopenharmony_ci struct udev_list_entry *entry; 173a46c0ec8Sopenharmony_ci struct udev_device *device; 174a46c0ec8Sopenharmony_ci const char *path, *sysname; 175a46c0ec8Sopenharmony_ci 176a46c0ec8Sopenharmony_ci e = udev_enumerate_new(udev); 177a46c0ec8Sopenharmony_ci udev_enumerate_add_match_subsystem(e, "input"); 178a46c0ec8Sopenharmony_ci udev_enumerate_scan_devices(e); 179a46c0ec8Sopenharmony_ci udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) { 180a46c0ec8Sopenharmony_ci path = udev_list_entry_get_name(entry); 181a46c0ec8Sopenharmony_ci device = udev_device_new_from_syspath(udev, path); 182a46c0ec8Sopenharmony_ci if (!device) 183a46c0ec8Sopenharmony_ci continue; 184a46c0ec8Sopenharmony_ci 185a46c0ec8Sopenharmony_ci sysname = udev_device_get_sysname(device); 186a46c0ec8Sopenharmony_ci if (!strneq("event", sysname, 5)) { 187a46c0ec8Sopenharmony_ci udev_device_unref(device); 188a46c0ec8Sopenharmony_ci continue; 189a46c0ec8Sopenharmony_ci } 190a46c0ec8Sopenharmony_ci 191a46c0ec8Sopenharmony_ci /* Skip unconfigured device. udev will send an event 192a46c0ec8Sopenharmony_ci * when device is fully configured */ 193a46c0ec8Sopenharmony_ci if (!udev_device_get_is_initialized(device)) { 194a46c0ec8Sopenharmony_ci log_debug(&input->base, 195a46c0ec8Sopenharmony_ci "%-7s - skip unconfigured input device '%s'\n", 196a46c0ec8Sopenharmony_ci sysname, 197a46c0ec8Sopenharmony_ci udev_device_get_devnode(device)); 198a46c0ec8Sopenharmony_ci udev_device_unref(device); 199a46c0ec8Sopenharmony_ci continue; 200a46c0ec8Sopenharmony_ci } 201a46c0ec8Sopenharmony_ci 202a46c0ec8Sopenharmony_ci if (device_added(device, input, NULL) < 0) { 203a46c0ec8Sopenharmony_ci udev_device_unref(device); 204a46c0ec8Sopenharmony_ci udev_enumerate_unref(e); 205a46c0ec8Sopenharmony_ci return -1; 206a46c0ec8Sopenharmony_ci } 207a46c0ec8Sopenharmony_ci 208a46c0ec8Sopenharmony_ci udev_device_unref(device); 209a46c0ec8Sopenharmony_ci } 210a46c0ec8Sopenharmony_ci udev_enumerate_unref(e); 211a46c0ec8Sopenharmony_ci 212a46c0ec8Sopenharmony_ci return 0; 213a46c0ec8Sopenharmony_ci} 214a46c0ec8Sopenharmony_ci 215a46c0ec8Sopenharmony_cistatic void 216a46c0ec8Sopenharmony_cievdev_udev_handler(void *data) 217a46c0ec8Sopenharmony_ci{ 218a46c0ec8Sopenharmony_ci struct udev_input *input = data; 219a46c0ec8Sopenharmony_ci struct udev_device *udev_device; 220a46c0ec8Sopenharmony_ci const char *action; 221a46c0ec8Sopenharmony_ci 222a46c0ec8Sopenharmony_ci udev_device = udev_monitor_receive_device(input->udev_monitor); 223a46c0ec8Sopenharmony_ci if (!udev_device) 224a46c0ec8Sopenharmony_ci return; 225a46c0ec8Sopenharmony_ci 226a46c0ec8Sopenharmony_ci action = udev_device_get_action(udev_device); 227a46c0ec8Sopenharmony_ci if (!action) 228a46c0ec8Sopenharmony_ci goto out; 229a46c0ec8Sopenharmony_ci 230a46c0ec8Sopenharmony_ci if (!strneq("event", udev_device_get_sysname(udev_device), 5)) 231a46c0ec8Sopenharmony_ci goto out; 232a46c0ec8Sopenharmony_ci 233a46c0ec8Sopenharmony_ci if (streq(action, "add")) 234a46c0ec8Sopenharmony_ci device_added(udev_device, input, NULL); 235a46c0ec8Sopenharmony_ci else if (streq(action, "remove")) 236a46c0ec8Sopenharmony_ci device_removed(udev_device, input); 237a46c0ec8Sopenharmony_ci 238a46c0ec8Sopenharmony_ciout: 239a46c0ec8Sopenharmony_ci udev_device_unref(udev_device); 240a46c0ec8Sopenharmony_ci} 241a46c0ec8Sopenharmony_ci 242a46c0ec8Sopenharmony_cistatic void 243a46c0ec8Sopenharmony_ciudev_input_remove_devices(struct udev_input *input) 244a46c0ec8Sopenharmony_ci{ 245a46c0ec8Sopenharmony_ci struct evdev_device *device; 246a46c0ec8Sopenharmony_ci struct udev_seat *seat; 247a46c0ec8Sopenharmony_ci 248a46c0ec8Sopenharmony_ci list_for_each_safe(seat, &input->base.seat_list, base.link) { 249a46c0ec8Sopenharmony_ci libinput_seat_ref(&seat->base); 250a46c0ec8Sopenharmony_ci list_for_each_safe(device, 251a46c0ec8Sopenharmony_ci &seat->base.devices_list, base.link) { 252a46c0ec8Sopenharmony_ci evdev_device_remove(device); 253a46c0ec8Sopenharmony_ci } 254a46c0ec8Sopenharmony_ci libinput_seat_unref(&seat->base); 255a46c0ec8Sopenharmony_ci } 256a46c0ec8Sopenharmony_ci} 257a46c0ec8Sopenharmony_ci 258a46c0ec8Sopenharmony_cistatic void 259a46c0ec8Sopenharmony_ciudev_input_disable(struct libinput *libinput) 260a46c0ec8Sopenharmony_ci{ 261a46c0ec8Sopenharmony_ci struct udev_input *input = (struct udev_input*)libinput; 262a46c0ec8Sopenharmony_ci 263a46c0ec8Sopenharmony_ci if (!input->udev_monitor) 264a46c0ec8Sopenharmony_ci return; 265a46c0ec8Sopenharmony_ci 266a46c0ec8Sopenharmony_ci udev_monitor_unref(input->udev_monitor); 267a46c0ec8Sopenharmony_ci input->udev_monitor = NULL; 268a46c0ec8Sopenharmony_ci libinput_remove_source(&input->base, input->udev_monitor_source); 269a46c0ec8Sopenharmony_ci input->udev_monitor_source = NULL; 270a46c0ec8Sopenharmony_ci 271a46c0ec8Sopenharmony_ci udev_input_remove_devices(input); 272a46c0ec8Sopenharmony_ci} 273a46c0ec8Sopenharmony_ci 274a46c0ec8Sopenharmony_cistatic int 275a46c0ec8Sopenharmony_ciudev_input_enable(struct libinput *libinput) 276a46c0ec8Sopenharmony_ci{ 277a46c0ec8Sopenharmony_ci struct udev_input *input = (struct udev_input*)libinput; 278a46c0ec8Sopenharmony_ci struct udev *udev = input->udev; 279a46c0ec8Sopenharmony_ci int fd; 280a46c0ec8Sopenharmony_ci 281a46c0ec8Sopenharmony_ci if (input->udev_monitor || !input->seat_id) 282a46c0ec8Sopenharmony_ci return 0; 283a46c0ec8Sopenharmony_ci 284a46c0ec8Sopenharmony_ci input->udev_monitor = udev_monitor_new_from_netlink(udev, "udev"); 285a46c0ec8Sopenharmony_ci if (!input->udev_monitor) { 286a46c0ec8Sopenharmony_ci log_info(libinput, 287a46c0ec8Sopenharmony_ci "udev: failed to create the udev monitor\n"); 288a46c0ec8Sopenharmony_ci return -1; 289a46c0ec8Sopenharmony_ci } 290a46c0ec8Sopenharmony_ci 291a46c0ec8Sopenharmony_ci if (udev_monitor_filter_add_match_subsystem_devtype( 292a46c0ec8Sopenharmony_ci input->udev_monitor, "input", NULL)) { 293a46c0ec8Sopenharmony_ci log_info(libinput, "udev: failed to set up filter\n"); 294a46c0ec8Sopenharmony_ci return -1; 295a46c0ec8Sopenharmony_ci } 296a46c0ec8Sopenharmony_ci 297a46c0ec8Sopenharmony_ci if (udev_monitor_enable_receiving(input->udev_monitor)) { 298a46c0ec8Sopenharmony_ci log_info(libinput, "udev: failed to bind the udev monitor\n"); 299a46c0ec8Sopenharmony_ci udev_monitor_unref(input->udev_monitor); 300a46c0ec8Sopenharmony_ci input->udev_monitor = NULL; 301a46c0ec8Sopenharmony_ci return -1; 302a46c0ec8Sopenharmony_ci } 303a46c0ec8Sopenharmony_ci 304a46c0ec8Sopenharmony_ci fd = udev_monitor_get_fd(input->udev_monitor); 305a46c0ec8Sopenharmony_ci input->udev_monitor_source = libinput_add_fd(&input->base, 306a46c0ec8Sopenharmony_ci fd, 307a46c0ec8Sopenharmony_ci evdev_udev_handler, 308a46c0ec8Sopenharmony_ci input); 309a46c0ec8Sopenharmony_ci if (!input->udev_monitor_source) { 310a46c0ec8Sopenharmony_ci udev_monitor_unref(input->udev_monitor); 311a46c0ec8Sopenharmony_ci input->udev_monitor = NULL; 312a46c0ec8Sopenharmony_ci return -1; 313a46c0ec8Sopenharmony_ci } 314a46c0ec8Sopenharmony_ci 315a46c0ec8Sopenharmony_ci if (udev_input_add_devices(input, udev) < 0) { 316a46c0ec8Sopenharmony_ci udev_input_disable(libinput); 317a46c0ec8Sopenharmony_ci return -1; 318a46c0ec8Sopenharmony_ci } 319a46c0ec8Sopenharmony_ci 320a46c0ec8Sopenharmony_ci return 0; 321a46c0ec8Sopenharmony_ci} 322a46c0ec8Sopenharmony_ci 323a46c0ec8Sopenharmony_cistatic void 324a46c0ec8Sopenharmony_ciudev_input_destroy(struct libinput *input) 325a46c0ec8Sopenharmony_ci{ 326a46c0ec8Sopenharmony_ci struct udev_input *udev_input = (struct udev_input*)input; 327a46c0ec8Sopenharmony_ci 328a46c0ec8Sopenharmony_ci if (input == NULL) 329a46c0ec8Sopenharmony_ci return; 330a46c0ec8Sopenharmony_ci 331a46c0ec8Sopenharmony_ci udev_unref(udev_input->udev); 332a46c0ec8Sopenharmony_ci free(udev_input->seat_id); 333a46c0ec8Sopenharmony_ci} 334a46c0ec8Sopenharmony_ci 335a46c0ec8Sopenharmony_cistatic void 336a46c0ec8Sopenharmony_ciudev_seat_destroy(struct libinput_seat *seat) 337a46c0ec8Sopenharmony_ci{ 338a46c0ec8Sopenharmony_ci struct udev_seat *useat = (struct udev_seat*)seat; 339a46c0ec8Sopenharmony_ci free(useat); 340a46c0ec8Sopenharmony_ci} 341a46c0ec8Sopenharmony_ci 342a46c0ec8Sopenharmony_cistatic struct udev_seat * 343a46c0ec8Sopenharmony_ciudev_seat_create(struct udev_input *input, 344a46c0ec8Sopenharmony_ci const char *device_seat, 345a46c0ec8Sopenharmony_ci const char *seat_name) 346a46c0ec8Sopenharmony_ci{ 347a46c0ec8Sopenharmony_ci struct udev_seat *seat; 348a46c0ec8Sopenharmony_ci 349a46c0ec8Sopenharmony_ci seat = zalloc(sizeof *seat); 350a46c0ec8Sopenharmony_ci 351a46c0ec8Sopenharmony_ci libinput_seat_init(&seat->base, &input->base, 352a46c0ec8Sopenharmony_ci device_seat, seat_name, 353a46c0ec8Sopenharmony_ci udev_seat_destroy); 354a46c0ec8Sopenharmony_ci 355a46c0ec8Sopenharmony_ci return seat; 356a46c0ec8Sopenharmony_ci} 357a46c0ec8Sopenharmony_ci 358a46c0ec8Sopenharmony_cistatic struct udev_seat * 359a46c0ec8Sopenharmony_ciudev_seat_get_named(struct udev_input *input, const char *seat_name) 360a46c0ec8Sopenharmony_ci{ 361a46c0ec8Sopenharmony_ci struct udev_seat *seat; 362a46c0ec8Sopenharmony_ci 363a46c0ec8Sopenharmony_ci list_for_each(seat, &input->base.seat_list, base.link) { 364a46c0ec8Sopenharmony_ci if (streq(seat->base.logical_name, seat_name)) 365a46c0ec8Sopenharmony_ci return seat; 366a46c0ec8Sopenharmony_ci } 367a46c0ec8Sopenharmony_ci 368a46c0ec8Sopenharmony_ci return NULL; 369a46c0ec8Sopenharmony_ci} 370a46c0ec8Sopenharmony_ci 371a46c0ec8Sopenharmony_cistatic int 372a46c0ec8Sopenharmony_ciudev_device_change_seat(struct libinput_device *device, 373a46c0ec8Sopenharmony_ci const char *seat_name) 374a46c0ec8Sopenharmony_ci{ 375a46c0ec8Sopenharmony_ci struct libinput *libinput = device->seat->libinput; 376a46c0ec8Sopenharmony_ci struct udev_input *input = (struct udev_input *)libinput; 377a46c0ec8Sopenharmony_ci struct evdev_device *evdev = evdev_device(device); 378a46c0ec8Sopenharmony_ci struct udev_device *udev_device = evdev->udev_device; 379a46c0ec8Sopenharmony_ci int rc; 380a46c0ec8Sopenharmony_ci 381a46c0ec8Sopenharmony_ci udev_device_ref(udev_device); 382a46c0ec8Sopenharmony_ci device_removed(udev_device, input); 383a46c0ec8Sopenharmony_ci rc = device_added(udev_device, input, seat_name); 384a46c0ec8Sopenharmony_ci udev_device_unref(udev_device); 385a46c0ec8Sopenharmony_ci 386a46c0ec8Sopenharmony_ci return rc; 387a46c0ec8Sopenharmony_ci} 388a46c0ec8Sopenharmony_ci 389a46c0ec8Sopenharmony_cistatic const struct libinput_interface_backend interface_backend = { 390a46c0ec8Sopenharmony_ci .resume = udev_input_enable, 391a46c0ec8Sopenharmony_ci .suspend = udev_input_disable, 392a46c0ec8Sopenharmony_ci .destroy = udev_input_destroy, 393a46c0ec8Sopenharmony_ci .device_change_seat = udev_device_change_seat, 394a46c0ec8Sopenharmony_ci}; 395a46c0ec8Sopenharmony_ci 396a46c0ec8Sopenharmony_ciLIBINPUT_EXPORT struct libinput * 397a46c0ec8Sopenharmony_cilibinput_udev_create_context(const struct libinput_interface *interface, 398a46c0ec8Sopenharmony_ci void *user_data, 399a46c0ec8Sopenharmony_ci struct udev *udev) 400a46c0ec8Sopenharmony_ci{ 401a46c0ec8Sopenharmony_ci struct udev_input *input; 402a46c0ec8Sopenharmony_ci 403a46c0ec8Sopenharmony_ci if (!interface || !udev) 404a46c0ec8Sopenharmony_ci return NULL; 405a46c0ec8Sopenharmony_ci 406a46c0ec8Sopenharmony_ci input = zalloc(sizeof *input); 407a46c0ec8Sopenharmony_ci 408a46c0ec8Sopenharmony_ci if (libinput_init(&input->base, interface, 409a46c0ec8Sopenharmony_ci &interface_backend, user_data) != 0) { 410a46c0ec8Sopenharmony_ci libinput_unref(&input->base); 411a46c0ec8Sopenharmony_ci free(input); 412a46c0ec8Sopenharmony_ci return NULL; 413a46c0ec8Sopenharmony_ci } 414a46c0ec8Sopenharmony_ci 415a46c0ec8Sopenharmony_ci input->udev = udev_ref(udev); 416a46c0ec8Sopenharmony_ci 417a46c0ec8Sopenharmony_ci return &input->base; 418a46c0ec8Sopenharmony_ci} 419a46c0ec8Sopenharmony_ci 420a46c0ec8Sopenharmony_ciLIBINPUT_EXPORT int 421a46c0ec8Sopenharmony_cilibinput_udev_assign_seat(struct libinput *libinput, 422a46c0ec8Sopenharmony_ci const char *seat_id) 423a46c0ec8Sopenharmony_ci{ 424a46c0ec8Sopenharmony_ci struct udev_input *input = (struct udev_input*)libinput; 425a46c0ec8Sopenharmony_ci 426a46c0ec8Sopenharmony_ci if (!seat_id) 427a46c0ec8Sopenharmony_ci return -1; 428a46c0ec8Sopenharmony_ci 429a46c0ec8Sopenharmony_ci if (strlen(seat_id) > 256) { 430a46c0ec8Sopenharmony_ci log_bug_client(libinput, 431a46c0ec8Sopenharmony_ci "Unexpected seat id, limited to 256 characters.\n"); 432a46c0ec8Sopenharmony_ci return -1; 433a46c0ec8Sopenharmony_ci } 434a46c0ec8Sopenharmony_ci 435a46c0ec8Sopenharmony_ci if (libinput->interface_backend != &interface_backend) { 436a46c0ec8Sopenharmony_ci log_bug_client(libinput, "Mismatching backends.\n"); 437a46c0ec8Sopenharmony_ci return -1; 438a46c0ec8Sopenharmony_ci } 439a46c0ec8Sopenharmony_ci 440a46c0ec8Sopenharmony_ci if (input->seat_id != NULL) 441a46c0ec8Sopenharmony_ci return -1; 442a46c0ec8Sopenharmony_ci 443a46c0ec8Sopenharmony_ci /* We cannot do this during udev_create_context because the log 444a46c0ec8Sopenharmony_ci * handler isn't set up there but we really want to log to the right 445a46c0ec8Sopenharmony_ci * place if the quirks run into parser errors. So we have to do it 446a46c0ec8Sopenharmony_ci * here since we can expect the log handler to be set up by now. 447a46c0ec8Sopenharmony_ci */ 448a46c0ec8Sopenharmony_ci libinput_init_quirks(libinput); 449a46c0ec8Sopenharmony_ci 450a46c0ec8Sopenharmony_ci input->seat_id = safe_strdup(seat_id); 451a46c0ec8Sopenharmony_ci 452a46c0ec8Sopenharmony_ci if (udev_input_enable(&input->base) < 0) 453a46c0ec8Sopenharmony_ci return -1; 454a46c0ec8Sopenharmony_ci 455a46c0ec8Sopenharmony_ci return 0; 456a46c0ec8Sopenharmony_ci} 457