From d0e6c251b60fa4ee5a7ffe58fa5aae2808a19578 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 1 Feb 2023 15:36:41 +1000 Subject: [PATCH] protocol: rename the ei core interface to ei_connection In the protocol this is a simple rename but in the implementation we can now separate the protocol object out from the ei/ei-client context itself by having the ei_connection objects. --- meson.build | 2 + proto/ei-proto.c.tmpl | 18 ++-- proto/ei-proto.h.tmpl | 4 +- proto/protocol.xml | 2 +- proto/scanner.py | 8 ++ src/brei-shared.h | 3 + src/libei-connection.c | 84 ++++++++++++++++ src/libei-connection.h | 46 +++++++++ src/libei-private.h | 23 ++++- src/libei.c | 207 +++++++++++++++++++++++++++------------- src/libeis-client.c | 151 ++++++++++++++++++++--------- src/libeis-client.h | 16 +++- src/libeis-connection.c | 87 +++++++++++++++++ src/libeis-connection.h | 48 ++++++++++ src/libeis-device.c | 4 +- src/libeis-private.h | 1 + 16 files changed, 571 insertions(+), 133 deletions(-) create mode 100644 src/libei-connection.c create mode 100644 src/libei-connection.h create mode 100644 src/libeis-connection.c create mode 100644 src/libeis-connection.h diff --git a/meson.build b/meson.build index 43cce74..9f15f3e 100644 --- a/meson.build +++ b/meson.build @@ -75,6 +75,7 @@ dep_libutil = declare_dependency(link_with: lib_util) src_libei = files( 'src/brei-shared.c', 'src/libei.c', + 'src/libei-connection.c', 'src/libei-device.c', 'src/libei-event.c', 'src/libei-fd.c', @@ -118,6 +119,7 @@ src_libeis = files( 'src/brei-shared.c', 'src/libeis.c', 'src/libeis-client.c', + 'src/libeis-connection.c', 'src/libeis-device.c', 'src/libeis-event.c', 'src/libeis-fd.c', diff --git a/proto/ei-proto.c.tmpl b/proto/ei-proto.c.tmpl index c916155..a581826 100644 --- a/proto/ei-proto.c.tmpl +++ b/proto/ei-proto.c.tmpl @@ -49,14 +49,14 @@ extern int {{target.name}}_send_message( ***************************************************************************/ /* returns the protocol interface from the given struct, see the dispatcher */ -const struct {{interface.name}}_interface *{{target.name}}_get_interface({{target.as_arg}}); +const struct {{interface.name}}_interface *{{interface.name}}_get_interface({{interface.as_arg}}); /* returns the message sending context from the given struct */ -{{target.ctype}} {{target.name}}_get_{{target.context}}({{target.as_arg}}); +{{target.ctype}} {{interface.name}}_get_{{target.context}}({{interface.as_arg}}); /* Returns the protocol object id from the given struct */ const struct brei_object * -{{target.name}}_get_proto_object({{target.as_arg}}); +{{interface.name}}_get_proto_object({{interface.as_arg}}); /* request opcodes */ {% for request in interface.requests %} @@ -71,10 +71,10 @@ const struct brei_object * /* Message sender functions */ {% for outgoing in interface.outgoing %} int -{{outgoing.fqdn}}({{target.as_arg}}{%- for arg in outgoing.arguments %}, {{arg.as_arg}}{% endfor %}) +{{outgoing.fqdn}}({{interface.as_arg}}{%- for arg in outgoing.arguments %}, {{arg.as_arg}}{% endfor %}) { - const struct brei_object *obj = {{target.name}}_get_proto_object({{target.name}}); - {{target.ctype}} ctx = {{target.name}}_get_{{target.context}}({{target.name}}); + const struct brei_object *obj = {{interface.name}}_get_proto_object({{interface.name}}); + {{target.ctype}} ctx = {{interface.name}}_get_{{target.context}}({{interface.name}}); return {{target.name}}_send_message( ctx, obj->id, {{outgoing.fqdn.upper()}}, "{{outgoing.signature}}", {{outgoing.arguments|length}}{%- for arg in outgoing.arguments %}, {{arg.name}}{% endfor -%} @@ -89,18 +89,18 @@ int */ static int {{interface.name}}_dispatcher( - {{target.as_arg}}, + {{interface.as_arg}}, uint32_t opcode, size_t nargs, union brei_arg *args ) { {% if interface.incoming|length %} - const struct {{interface.name}}_interface *interface = {{target.name}}_get_interface({{target.name}}); + const struct {{interface.name}}_interface *interface = {{interface.name}}_get_interface({{interface.name}}); switch (opcode) { {% for incoming in interface.incoming %} case {{incoming.fqdn.upper()}}: assert(interface->{{incoming.name}} != NULL); - return interface->{{incoming.name}}({{target.name}}{% for arg in incoming.arguments %}, (args + {{loop.index - 1}})->{{arg.argtype}}{% endfor %}); + return interface->{{incoming.name}}({{interface.name}}{% for arg in incoming.arguments %}, (args + {{loop.index - 1}})->{{arg.argtype}}{% endfor %}); {% endfor %} } {% endif %} diff --git a/proto/ei-proto.h.tmpl b/proto/ei-proto.h.tmpl index f3c2747..cd0af45 100644 --- a/proto/ei-proto.h.tmpl +++ b/proto/ei-proto.h.tmpl @@ -66,7 +66,7 @@ enum {{enum.fqdn}} { /* Message sender functions */ {% for outgoing in interface.outgoing %} extern int -{{outgoing.fqdn}}({{target.as_arg}}{%- for arg in outgoing.arguments %}, {{arg.as_arg}}{% endfor %}); +{{outgoing.fqdn}}({{interface.as_arg}}{%- for arg in outgoing.arguments %}, {{arg.as_arg}}{% endfor %}); {% endfor %} @@ -77,7 +77,7 @@ extern int */ struct {{interface.name}}_interface { {% for incoming in interface.incoming %} - int (*{{incoming.name}})({{target.as_arg}}{%- for arg in incoming.arguments %}, {{arg.as_arg}}{% endfor %}); + int (*{{incoming.name}})({{interface.as_arg}}{%- for arg in incoming.arguments %}, {{arg.as_arg}}{% endfor %}); {% endfor %} }; {% endfor %} diff --git a/proto/protocol.xml b/proto/protocol.xml index 85642c7..94a6f64 100644 --- a/proto/protocol.xml +++ b/proto/protocol.xml @@ -57,7 +57,7 @@ --> - + The core global object. This is a special singleton object. It is used for internal ei protocol features. diff --git a/proto/scanner.py b/proto/scanner.py index 620d392..5244c3a 100755 --- a/proto/scanner.py +++ b/proto/scanner.py @@ -244,6 +244,14 @@ class Interface: else: return self.requests # type: ignore + @property + def ctype(self) -> str: + return f"struct {self.name} *" + + @property + def as_arg(self) -> str: + return f"{self.ctype} {self.name}" + @classmethod def create(cls, name: str, version: int, mode: str = "ei") -> "Interface": assert mode in ["ei", "eis"] diff --git a/src/brei-shared.h b/src/brei-shared.h index fee6f60..ec2bb4e 100644 --- a/src/brei-shared.h +++ b/src/brei-shared.h @@ -30,6 +30,8 @@ #include #include +#include "util-list.h" + struct brei_interface; struct brei_message; struct brei_object; @@ -71,6 +73,7 @@ struct brei_object { void *implementation; /* pointer to the actual object */ uint32_t id; /* protocol object id */ uint32_t version; /* protocol object interface version */ + struct list link; /* in the ei/eis object list */ }; int diff --git a/src/libei-connection.c b/src/libei-connection.c new file mode 100644 index 0000000..8fca1a3 --- /dev/null +++ b/src/libei-connection.c @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023 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 + +#include "util-bits.h" +#include "util-macros.h" +#include "util-mem.h" +#include "util-io.h" +#include "util-strings.h" +#include "util-version.h" + +#include "libei-private.h" +#include "ei-proto.h" + +static void +ei_connection_destroy(struct ei_connection *connection) +{ + struct ei *ei = ei_connection_get_context(connection); + ei_unregister_object(ei, &connection->proto_object); +} + +OBJECT_IMPLEMENT_REF(ei_connection); +OBJECT_IMPLEMENT_UNREF_CLEANUP(ei_connection); + +static +OBJECT_IMPLEMENT_CREATE(ei_connection); +static +OBJECT_IMPLEMENT_PARENT(ei_connection, ei); +OBJECT_IMPLEMENT_GETTER_AS_REF(ei_connection, proto_object, const struct brei_object*); + +struct ei* +ei_connection_get_context(struct ei_connection *connection) +{ + assert(connection); + return ei_connection_parent(connection); +} + +const struct ei_connection_interface * +ei_connection_get_interface(struct ei_connection *connection) { + struct ei *ei = ei_connection_parent(connection); + return ei_get_interface(ei); +} + +struct ei_connection * +ei_connection_new(struct ei *ei) +{ + struct ei_connection *connection = ei_connection_create(&ei->object); + + connection->proto_object.id = ei_get_new_id(ei); + /* This is a special object and must have id 0 */ + assert(connection->proto_object.id == 0); + + connection->proto_object.implementation = connection; + connection->proto_object.interface = &ei_connection_proto_interface; + connection->proto_object.version = VERSION_V(1); + ei_register_object(ei, &connection->proto_object); + + return connection; /* ref owned by caller */ +} diff --git a/src/libei-connection.h b/src/libei-connection.h new file mode 100644 index 0000000..b72bfe3 --- /dev/null +++ b/src/libei-connection.h @@ -0,0 +1,46 @@ + +/* SPDX-License-Identifier: MIT */ +/* + * 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. + */ + +#pragma once + +#include "util-object.h" +#include "brei-shared.h" + +struct ei; + +/* This is a protocol-only object, not exposed in the API */ +struct ei_connection { + struct object object; + struct brei_object proto_object; +}; + +OBJECT_DECLARE_GETTER(ei_connection, context, struct ei*); +OBJECT_DECLARE_GETTER(ei_connection, proto_object, const struct brei_object*); +OBJECT_DECLARE_GETTER(ei_connection, interface, const struct ei_connection_interface *); +OBJECT_DECLARE_REF(ei_connection); +OBJECT_DECLARE_UNREF(ei_connection); + +struct ei_connection * +ei_connection_new(struct ei *ei); diff --git a/src/libei-private.h b/src/libei-private.h index 50cf8dc..1864366 100644 --- a/src/libei-private.h +++ b/src/libei-private.h @@ -35,6 +35,7 @@ #include "util-sources.h" #include "util-structs.h" +#include "libei-connection.h" #include "libei-seat.h" #include "libei-device.h" #include "libei-event.h" @@ -56,7 +57,10 @@ enum ei_state { struct ei { struct object object; - struct brei_object proto_object; + + struct ei_connection *connection; + struct list proto_objects; /* brei_object list */ + uint32_t next_object_id; void *user_data; struct sink *sink; @@ -78,7 +82,7 @@ struct ei { uint32_t client_version; }; -const struct ei_interface * +const struct ei_connection_interface * ei_get_interface(struct ei *ei); int @@ -87,12 +91,21 @@ ei_set_socket(struct ei *ei, int fd); void ei_disconnect(struct ei *ei); -const struct brei_object * -ei_get_proto_object(struct ei *ei); - struct ei * ei_get_context(struct ei *ei); +struct ei_connection * +ei_get_connection(struct ei *ei); + +uint32_t +ei_get_new_id(struct ei *ei); + +void +ei_register_object(struct ei *ei, struct brei_object *object); + +void +ei_unregister_object(struct ei *ei, struct brei_object *object); + int ei_send_message(struct ei *ei, uint32_t object_id, uint32_t opcode, const char *signature, size_t nargs, ...); diff --git a/src/libei.c b/src/libei.c index 0d5adb0..9977394 100644 --- a/src/libei.c +++ b/src/libei.c @@ -92,6 +92,7 @@ ei_destroy(struct ei *ei) if (ei->backend_interface.destroy) ei->backend_interface.destroy(ei, ei->backend); ei->backend = NULL; + ei_connection_unref(ei->connection); sink_unref(ei->sink); free(ei->name); } @@ -106,17 +107,11 @@ _public_ OBJECT_IMPLEMENT_SETTER(ei, user_data, void *); _public_ OBJECT_IMPLEMENT_GETTER(ei, user_data, void *); +OBJECT_IMPLEMENT_GETTER(ei, connection, struct ei_connection *); DEFINE_UNREF_CLEANUP_FUNC(ei_device); DEFINE_UNREF_CLEANUP_FUNC(ei_region); - -const struct brei_object * -ei_get_proto_object(struct ei *ei) -{ - return &ei->proto_object; -} - struct ei * ei_get_context(struct ei *ei) { @@ -129,11 +124,12 @@ ei_create_context(bool is_sender, void *user_data) _unref_(ei) *ei = ei_create(NULL); ei->state = EI_STATE_NEW; - ei->proto_object.id = 0; - ei->proto_object.implementation = ei; - ei->proto_object.interface = &ei_proto_interface; list_init(&ei->event_queue); list_init(&ei->seats); + list_init(&ei->proto_objects); + + ei->connection = ei_connection_new(ei); + ei->next_object_id = 1; ei_log_set_handler(ei, NULL); ei_log_set_priority(ei, EI_LOG_PRIORITY_INFO); @@ -148,6 +144,27 @@ ei_create_context(bool is_sender, void *user_data) return steal(&ei); } +uint32_t +ei_get_new_id(struct ei *ei) +{ + static const int server_range = 0xff000000; + return ei->next_object_id++ & ~server_range; +} + +void +ei_register_object(struct ei *ei, struct brei_object *object) +{ + log_debug(ei, "registering %s v%u object %#x", object->interface->name, object->version, object->id); + list_append(&ei->proto_objects, &object->link); +} + +void +ei_unregister_object(struct ei *ei, struct brei_object *object) +{ + log_debug(ei, "deregistering %s v%u object %#x", object->interface->name, object->version, object->id); + list_remove(&object->link); +} + _public_ bool ei_is_sender(struct ei *ei) { @@ -580,7 +597,7 @@ ei_disconnect(struct ei *ei) } if (state != EI_STATE_NEW) { - ei_request_disconnect(ei); + ei_connection_request_disconnect(ei->connection); } queue_disconnect_event(ei); ei->state = EI_STATE_DISCONNECTED; @@ -590,9 +607,11 @@ ei_disconnect(struct ei *ei) } static int -handle_msg_seat_added(struct ei *ei, uint32_t seatid, +handle_msg_seat_added(struct ei_connection *connection, uint32_t seatid, uint32_t capabilities, const char *name) { + struct ei *ei = ei_connection_get_context(connection); + log_debug(ei, "Added seat %#x '%s' with caps %#x", seatid, name, capabilities); @@ -607,8 +626,10 @@ handle_msg_seat_added(struct ei *ei, uint32_t seatid, } static int -handle_msg_seat_removed(struct ei *ei, uint32_t seatid) +handle_msg_seat_removed(struct ei_connection *connection, uint32_t seatid) { + struct ei *ei = ei_connection_get_context(connection); + log_debug(ei, "server removed seat %#x", seatid); struct ei_seat *seat = ei_find_seat(ei, seatid); @@ -620,10 +641,11 @@ handle_msg_seat_removed(struct ei *ei, uint32_t seatid) } static int -handle_msg_device_added(struct ei *ei, uint32_t deviceid, uint32_t capabilities, +handle_msg_device_added(struct ei_connection *connection, uint32_t deviceid, uint32_t capabilities, const char *name, uint32_t seatid, uint32_t type, uint32_t width, uint32_t height) { + struct ei *ei = ei_connection_get_context(connection); struct ei_seat *seat = ei_find_seat(ei, seatid); if (!seat) { @@ -671,10 +693,12 @@ handle_msg_device_added(struct ei *ei, uint32_t deviceid, uint32_t capabilities, } static int -handle_msg_device_keymap(struct ei *ei, uint32_t deviceid, +handle_msg_device_keymap(struct ei_connection *connection, uint32_t deviceid, enum ei_keymap_type keymap_type, uint32_t keymap_sz, int keymap_fd) { + struct ei *ei = ei_connection_get_context(connection); + log_debug(ei, "Adding keymap for %#x", deviceid); struct ei_device *device = ei_find_device(ei, deviceid); @@ -699,8 +723,10 @@ ei_insert_device_removed_event(struct ei_device *device) } static int -handle_msg_device_added_done(struct ei *ei, uint32_t deviceid) +handle_msg_device_added_done(struct ei_connection *connection, uint32_t deviceid) { + struct ei *ei = ei_connection_get_context(connection); + log_debug(ei, "Done with device %#x", deviceid); struct ei_device *device = ei_find_device(ei, deviceid); @@ -714,11 +740,13 @@ handle_msg_device_added_done(struct ei *ei, uint32_t deviceid) } static int -handle_msg_device_region(struct ei *ei, uint32_t deviceid, +handle_msg_device_region(struct ei_connection *connection, uint32_t deviceid, uint32_t x, uint32_t y, uint32_t w, uint32_t h, float scale) { + struct ei *ei = ei_connection_get_context(connection); + log_debug(ei, "Adding device region for %#x", deviceid); struct ei_device *device = ei_find_device(ei, deviceid); @@ -736,10 +764,12 @@ handle_msg_device_region(struct ei *ei, uint32_t deviceid, } static int -handle_msg_keyboard_modifiers(struct ei *ei, uint32_t deviceid, +handle_msg_keyboard_modifiers(struct ei_connection *connection, uint32_t deviceid, uint32_t depressed, uint32_t locked, uint32_t latched, uint32_t group) { + struct ei *ei = ei_connection_get_context(connection); + log_debug(ei, "Setting modifiers for %#x", deviceid); struct ei_device *device = ei_find_device(ei, deviceid); @@ -763,8 +793,10 @@ handle_msg_keyboard_modifiers(struct ei *ei, uint32_t deviceid, } static int -handle_msg_device_removed(struct ei *ei, uint32_t deviceid) +handle_msg_device_removed(struct ei_connection *connection, uint32_t deviceid) { + struct ei *ei = ei_connection_get_context(connection); + log_debug(ei, "Removed device %#x", deviceid); struct ei_device *device = ei_find_device(ei, deviceid); @@ -777,8 +809,10 @@ handle_msg_device_removed(struct ei *ei, uint32_t deviceid) } static int -handle_msg_device_resumed(struct ei *ei, uint32_t deviceid) +handle_msg_device_resumed(struct ei_connection *connection, uint32_t deviceid) { + struct ei *ei = ei_connection_get_context(connection); + log_debug(ei, "Resumed device %#x", deviceid); struct ei_device *device = ei_find_device(ei, deviceid); @@ -791,8 +825,10 @@ handle_msg_device_resumed(struct ei *ei, uint32_t deviceid) } static int -handle_msg_device_paused(struct ei *ei, uint32_t deviceid) +handle_msg_device_paused(struct ei_connection *connection, uint32_t deviceid) { + struct ei *ei = ei_connection_get_context(connection); + log_debug(ei, "Paused device %#x", deviceid); struct ei_device *device = ei_find_device(ei, deviceid); @@ -812,7 +848,7 @@ ei_send_close_device(struct ei_device *device) if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) return 0; - int rc = ei_request_close_device(ei, device->id); + int rc = ei_connection_request_close_device(ei->connection, device->id); if (rc) ei_disconnect(ei); return rc; @@ -826,7 +862,7 @@ ei_send_start_emulating(struct ei_device *device, uint32_t sequence) if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) return 0; - int rc = ei_request_start_emulating(ei, device->id, sequence); + int rc = ei_connection_request_start_emulating(ei->connection, device->id, sequence); if (rc) ei_disconnect(ei); return rc; @@ -840,7 +876,7 @@ ei_send_stop_emulating(struct ei_device *device) if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) return 0; - int rc = ei_request_stop_emulating(ei, device->id); + int rc = ei_connection_request_stop_emulating(ei->connection, device->id); if (rc) ei_disconnect(ei); return rc; @@ -854,7 +890,7 @@ ei_send_seat_bind(struct ei_seat *seat, uint32_t capabilities) if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) return 0; - int rc = ei_request_bind_seat(ei, seat->id, capabilities); + int rc = ei_connection_request_bind_seat(ei->connection, seat->id, capabilities); if (rc) ei_disconnect(ei); return rc; @@ -873,7 +909,7 @@ ei_send_frame(struct ei_device *device, uint64_t time) device->send_frame_event = false; - int rc = ei_request_frame(ei, device->id, us2ms(time), time % 1000); + int rc = ei_connection_request_frame(ei->connection, device->id, us2ms(time), time % 1000); if (rc) ei_disconnect(ei); return rc; @@ -889,7 +925,7 @@ ei_send_pointer_rel(struct ei_device *device, double x, double y) device->send_frame_event = true; - int rc = ei_request_pointer_relative(ei, device->id, x, y); + int rc = ei_connection_request_pointer_relative(ei->connection, device->id, x, y); if (rc) ei_disconnect(ei); return rc; @@ -905,7 +941,7 @@ ei_send_pointer_abs(struct ei_device *device, double x, double y) device->send_frame_event = true; - int rc = ei_request_pointer_absolute(ei, device->id, x, y); + int rc = ei_connection_request_pointer_absolute(ei->connection, device->id, x, y); if (rc) ei_disconnect(ei); return rc; @@ -921,7 +957,7 @@ ei_send_pointer_button(struct ei_device *device, uint32_t button, bool is_press) device->send_frame_event = true; - int rc = ei_request_pointer_button(ei, device->id, button, is_press); + int rc = ei_connection_request_pointer_button(ei->connection, device->id, button, is_press); if (rc) ei_disconnect(ei); return rc; @@ -936,7 +972,7 @@ int ei_send_pointer_scroll(struct ei_device *device, double x, double y) device->send_frame_event = true; - int rc = ei_request_pointer_scroll(ei, device->id, x, y); + int rc = ei_connection_request_pointer_scroll(ei->connection, device->id, x, y); if (rc) ei_disconnect(ei); return rc; @@ -951,7 +987,7 @@ int ei_send_pointer_scroll_stop(struct ei_device *device, double x, double y) device->send_frame_event = true; - int rc = ei_request_pointer_scroll_stop(ei, device->id, x, y, false); + int rc = ei_connection_request_pointer_scroll_stop(ei->connection, device->id, x, y, false); if (rc) ei_disconnect(ei); return rc; @@ -966,7 +1002,7 @@ int ei_send_pointer_scroll_cancel(struct ei_device *device, double x, double y) device->send_frame_event = true; - int rc = ei_request_pointer_scroll_stop(ei, device->id, x, y, true); + int rc = ei_connection_request_pointer_scroll_stop(ei->connection, device->id, x, y, true); if (rc) ei_disconnect(ei); return rc; @@ -982,7 +1018,7 @@ int ei_send_pointer_scroll_discrete(struct ei_device *device, int32_t x, int32_t device->send_frame_event = true; - int rc = ei_request_pointer_scroll_discrete(ei, device->id, x, y); + int rc = ei_connection_request_pointer_scroll_discrete(ei->connection, device->id, x, y); if (rc) ei_disconnect(ei); return rc; @@ -998,7 +1034,7 @@ ei_send_keyboard_key(struct ei_device *device, uint32_t key, bool is_press) device->send_frame_event = true; - int rc = ei_request_keyboard_key(ei, device->id, key, is_press); + int rc = ei_connection_request_keyboard_key(ei->connection, device->id, key, is_press); if (rc) ei_disconnect(ei); return rc; @@ -1015,7 +1051,7 @@ ei_send_touch_down(struct ei_device *device, uint32_t tid, device->send_frame_event = true; - int rc = ei_request_touch_down(ei, device->id, tid, x, y); + int rc = ei_connection_request_touch_down(ei->connection, device->id, tid, x, y); if (rc) ei_disconnect(ei); return rc; @@ -1032,7 +1068,7 @@ ei_send_touch_motion(struct ei_device *device, uint32_t tid, device->send_frame_event = true; - int rc = ei_request_touch_motion(ei, device->id, tid, x, y); + int rc = ei_connection_request_touch_motion(ei->connection, device->id, tid, x, y); if (rc) ei_disconnect(ei); return rc; @@ -1048,7 +1084,7 @@ ei_send_touch_up(struct ei_device *device, uint32_t tid) device->send_frame_event = true; - int rc = ei_request_touch_up(ei, device->id, tid); + int rc = ei_connection_request_touch_up(ei->connection, device->id, tid); if (rc) ei_disconnect(ei); return rc; @@ -1076,13 +1112,17 @@ ei_peek_event(struct ei *ei) return ei_event_ref(e); } -static int handle_msg_connected(struct ei *ei) { +static int handle_msg_connected(struct ei_connection *connection) +{ + struct ei *ei = ei_connection_get_context(connection); + ei->state = EI_STATE_CONNECTED; queue_connect_event(ei); return 0; } -static int handle_msg_disconnected(struct ei *ei) { +static int handle_msg_disconnected(struct ei_connection *connection) +{ return -ECANCELED; } @@ -1094,8 +1134,10 @@ static int handle_msg_disconnected(struct ei *ei) { } while(0) static int -handle_msg_start_emulating(struct ei *ei, uint32_t deviceid, uint32_t sequence) +handle_msg_start_emulating(struct ei_connection *connection, uint32_t deviceid, uint32_t sequence) { + struct ei *ei = ei_connection_get_context(connection); + DISCONNECT_IF_SENDER_CONTEXT(ei); struct ei_device *device = ei_find_device(ei, deviceid); @@ -1107,8 +1149,10 @@ handle_msg_start_emulating(struct ei *ei, uint32_t deviceid, uint32_t sequence) } static int -handle_msg_stop_emulating(struct ei *ei, uint32_t deviceid) +handle_msg_stop_emulating(struct ei_connection *connection, uint32_t deviceid) { + struct ei *ei = ei_connection_get_context(connection); + DISCONNECT_IF_SENDER_CONTEXT(ei); struct ei_device *device = ei_find_device(ei, deviceid); @@ -1120,8 +1164,10 @@ handle_msg_stop_emulating(struct ei *ei, uint32_t deviceid) } static int -handle_msg_frame(struct ei *ei, uint32_t deviceid, uint32_t time, uint32_t micros) +handle_msg_frame(struct ei_connection *connection, uint32_t deviceid, uint32_t time, uint32_t micros) { + struct ei *ei = ei_connection_get_context(connection); + DISCONNECT_IF_SENDER_CONTEXT(ei); struct ei_device *device = ei_find_device(ei, deviceid); @@ -1133,8 +1179,10 @@ handle_msg_frame(struct ei *ei, uint32_t deviceid, uint32_t time, uint32_t micro } static int -handle_msg_pointer_rel(struct ei *ei, uint32_t deviceid, float x, float y) +handle_msg_pointer_rel(struct ei_connection *connection, uint32_t deviceid, float x, float y) { + struct ei *ei = ei_connection_get_context(connection); + DISCONNECT_IF_SENDER_CONTEXT(ei); struct ei_device *device = ei_find_device(ei, deviceid); @@ -1146,8 +1194,10 @@ handle_msg_pointer_rel(struct ei *ei, uint32_t deviceid, float x, float y) } static int -handle_msg_pointer_abs(struct ei *ei, uint32_t deviceid, float x, float y) +handle_msg_pointer_abs(struct ei_connection *connection, uint32_t deviceid, float x, float y) { + struct ei *ei = ei_connection_get_context(connection); + DISCONNECT_IF_SENDER_CONTEXT(ei); struct ei_device *device = ei_find_device(ei, deviceid); @@ -1159,9 +1209,11 @@ handle_msg_pointer_abs(struct ei *ei, uint32_t deviceid, float x, float y) } static int -handle_msg_pointer_button(struct ei *ei, uint32_t deviceid, +handle_msg_pointer_button(struct ei_connection *connection, uint32_t deviceid, uint32_t button, uint32_t state) { + struct ei *ei = ei_connection_get_context(connection); + DISCONNECT_IF_SENDER_CONTEXT(ei); struct ei_device *device = ei_find_device(ei, deviceid); @@ -1173,8 +1225,10 @@ handle_msg_pointer_button(struct ei *ei, uint32_t deviceid, } static int -handle_msg_pointer_scroll(struct ei *ei, uint32_t deviceid, float x, float y) +handle_msg_pointer_scroll(struct ei_connection *connection, uint32_t deviceid, float x, float y) { + struct ei *ei = ei_connection_get_context(connection); + DISCONNECT_IF_SENDER_CONTEXT(ei); struct ei_device *device = ei_find_device(ei, deviceid); @@ -1186,9 +1240,11 @@ handle_msg_pointer_scroll(struct ei *ei, uint32_t deviceid, float x, float y) } static int -handle_msg_pointer_scroll_discrete(struct ei *ei, uint32_t deviceid, +handle_msg_pointer_scroll_discrete(struct ei_connection *connection, uint32_t deviceid, int32_t x, int32_t y) { + struct ei *ei = ei_connection_get_context(connection); + DISCONNECT_IF_SENDER_CONTEXT(ei); struct ei_device *device = ei_find_device(ei, deviceid); @@ -1200,9 +1256,11 @@ handle_msg_pointer_scroll_discrete(struct ei *ei, uint32_t deviceid, } static int -handle_msg_pointer_scroll_stop(struct ei *ei, uint32_t deviceid, +handle_msg_pointer_scroll_stop(struct ei_connection *connection, uint32_t deviceid, uint32_t x, uint32_t y, uint32_t is_cancel) { + struct ei *ei = ei_connection_get_context(connection); + DISCONNECT_IF_SENDER_CONTEXT(ei); struct ei_device *device = ei_find_device(ei, deviceid); @@ -1218,9 +1276,11 @@ handle_msg_pointer_scroll_stop(struct ei *ei, uint32_t deviceid, } static int -handle_msg_keyboard_key(struct ei *ei, uint32_t deviceid, +handle_msg_keyboard_key(struct ei_connection *connection, uint32_t deviceid, uint32_t key, uint32_t state) { + struct ei *ei = ei_connection_get_context(connection); + DISCONNECT_IF_SENDER_CONTEXT(ei); struct ei_device *device = ei_find_device(ei, deviceid); @@ -1232,9 +1292,11 @@ handle_msg_keyboard_key(struct ei *ei, uint32_t deviceid, } static int -handle_msg_touch_down(struct ei *ei, uint32_t deviceid, +handle_msg_touch_down(struct ei_connection *connection, uint32_t deviceid, uint32_t touchid, float x, float y) { + struct ei *ei = ei_connection_get_context(connection); + DISCONNECT_IF_SENDER_CONTEXT(ei); struct ei_device *device = ei_find_device(ei, deviceid); @@ -1246,9 +1308,11 @@ handle_msg_touch_down(struct ei *ei, uint32_t deviceid, } static int -handle_msg_touch_motion(struct ei *ei, uint32_t deviceid, +handle_msg_touch_motion(struct ei_connection *connection, uint32_t deviceid, uint32_t touchid, float x, float y) { + struct ei *ei = ei_connection_get_context(connection); + DISCONNECT_IF_SENDER_CONTEXT(ei); struct ei_device *device = ei_find_device(ei, deviceid); @@ -1260,8 +1324,10 @@ handle_msg_touch_motion(struct ei *ei, uint32_t deviceid, } static int -handle_msg_touch_up(struct ei *ei, uint32_t deviceid, uint32_t touchid) +handle_msg_touch_up(struct ei_connection *connection, uint32_t deviceid, uint32_t touchid) { + struct ei *ei = ei_connection_get_context(connection); + DISCONNECT_IF_SENDER_CONTEXT(ei); struct ei_device *device = ei_find_device(ei, deviceid); @@ -1273,8 +1339,9 @@ handle_msg_touch_up(struct ei *ei, uint32_t deviceid, uint32_t touchid) } static int -handle_msg_version(struct ei *ei, uint32_t version) +handle_msg_version(struct ei_connection *connection, uint32_t version) { + struct ei *ei = ei_connection_get_context(connection); if (version == 0) { log_bug(ei, "server version is zero"); return -EINVAL; @@ -1291,9 +1358,10 @@ handle_msg_version(struct ei *ei, uint32_t version) } static int -handle_msg_version_during_connection(struct ei *ei, uint32_t version) +handle_msg_version_during_connection(struct ei_connection *connection, uint32_t version) { - int rc = handle_msg_version(ei, version); + struct ei *ei = ei_connection_get_context(connection); + int rc = handle_msg_version(connection, version); if (rc != 0) return rc; @@ -1304,25 +1372,25 @@ handle_msg_version_during_connection(struct ei *ei, uint32_t version) return ei_finish_set_socket(ei, ei->client_version); } -static const struct ei_interface intf_state_backend = { +static const struct ei_connection_interface intf_state_backend = { .version = handle_msg_version_during_connection, /* Everything triggers -EPROTO */ .connected = NULL, }; -static const struct ei_interface intf_state_version_query = { +static const struct ei_connection_interface intf_state_version_query = { .version = handle_msg_version_during_connection, /* Everything else triggers -EPROTO */ .connected = NULL, }; -static const struct ei_interface intf_state_connecting = { +static const struct ei_connection_interface intf_state_connecting = { .connected = handle_msg_connected, .disconnected = handle_msg_disconnected, .version = handle_msg_version, }; -static const struct ei_interface intf_state_connected = { +static const struct ei_connection_interface intf_state_connected = { .disconnected = handle_msg_disconnected, .seat_added = handle_msg_seat_added, .seat_removed = handle_msg_seat_removed, @@ -1352,7 +1420,7 @@ static const struct ei_interface intf_state_connected = { .frame = handle_msg_frame, }; -static const struct ei_interface *interfaces[] = { +static const struct ei_connection_interface *interfaces[] = { [EI_STATE_NEW] = NULL, [EI_STATE_BACKEND] = &intf_state_backend, [EI_STATE_VERSION_QUERY] = &intf_state_version_query, @@ -1363,7 +1431,7 @@ static const struct ei_interface *interfaces[] = { }; -const struct ei_interface * +const struct ei_connection_interface * ei_get_interface(struct ei *ei) { assert(ei->state < ARRAY_LENGTH(interfaces)); @@ -1375,10 +1443,15 @@ lookup_object(uint32_t object_id, struct brei_object **object, void *userdata) { struct ei *ei = userdata; - assert(object_id == 0); /* We only have one object atm */ + struct brei_object *obj; + list_for_each(obj, &ei->proto_objects, link) { + if (obj->id == object_id) { + *object = obj; + return 0; + } + } - *object = &ei->proto_object; - return 0; + return -ENOENT; } static void @@ -1445,7 +1518,7 @@ ei_set_socket(struct ei *ei, int fd) if (ei->state == EI_STATE_BACKEND) { /* The server didn't send the version number, so request it. */ - rc = ei_request_get_version(ei); + rc = ei_connection_request_get_version(ei->connection); ei->state = EI_STATE_VERSION_QUERY; } } @@ -1458,10 +1531,10 @@ ei_set_socket(struct ei *ei, int fd) static int ei_finish_set_socket(struct ei *ei, uint32_t version) { - int rc = ei_request_connect(ei, version, ei->name, ei->is_sender); + int rc = ei_connection_request_connect(ei->connection, version, ei->name, ei->is_sender); if (rc == 0) { - rc = ei_request_connect_done(ei); + rc = ei_connection_request_connect_done(ei->connection); } if (rc == 0) { ei->state = EI_STATE_CONNECTING; diff --git a/src/libeis-client.c b/src/libeis-client.c index a6ad42f..6ff54b9 100644 --- a/src/libeis-client.c +++ b/src/libeis-client.c @@ -49,6 +49,7 @@ DEFINE_TRISTATE(started, finished, connected); static void eis_client_destroy(struct eis_client *client) { + eis_connection_unref(client->connection); free(client->name); source_remove(client->source); source_unref(client->source); @@ -82,7 +83,30 @@ eis_client_get_context(struct eis_client *client) const struct brei_object * eis_client_get_proto_object(struct eis_client *client) { - return &client->proto_object; + return &client->connection->proto_object; +} + +uint32_t +eis_client_get_new_id(struct eis_client *client) +{ + static const int offset = 0xff000000; + return offset | (client->next_object_id++ & ~offset); +} + +void +eis_client_register_object(struct eis_client *client, struct brei_object *object) +{ + struct eis *eis = eis_client_get_context(client); + log_debug(eis, "registering %s v%u object %#x", object->interface->name, object->version, object->id); + list_append(&client->proto_objects, &object->link); +} + +void +eis_client_unregister_object(struct eis_client *client, struct brei_object *object) +{ + struct eis *eis = eis_client_get_context(client); + log_debug(eis, "deregistering %s v%u object %#x", object->interface->name, object->version, object->id); + list_remove(&object->link); } struct eis_client * @@ -163,79 +187,79 @@ eis_client_send_message(struct eis_client *client, uint32_t object_id, static int client_send_version(struct eis_client *client, uint32_t version) { - return eis_event_version(client, version); + return eis_connection_event_version(client->connection, version); } static int client_send_disconnect(struct eis_client *client) { - return eis_event_disconnected(client); + return eis_connection_event_disconnected(client->connection); } static int client_send_connect(struct eis_client *client) { - return eis_event_connected(client); + return eis_connection_event_connected(client->connection); } static int client_send_seat_added(struct eis_client *client, struct eis_seat *seat) { - return eis_event_seat_added(client, seat->id, seat->capabilities_mask, seat->name); + return eis_connection_event_seat_added(client->connection, seat->id, seat->capabilities_mask, seat->name); } static int client_send_seat_removed(struct eis_client *client, struct eis_seat *seat) { - return eis_event_seat_removed(client, seat->id); + return eis_connection_event_seat_removed(client->connection, seat->id); } static int client_send_device_added(struct eis_client *client, struct eis_device *device) { struct eis_seat *seat = eis_device_get_seat(device); - int rc = eis_event_device_added(client, device->id, device->capabilities, + int rc = eis_connection_event_device_added(client->connection, device->id, device->capabilities, device->name, seat->id, device->type, device->width, device->height); if (rc >= 0 && device->keymap) - rc = eis_event_device_keymap(client, device->id, device->keymap->type, device->keymap->size, device->keymap->fd); + rc = eis_connection_event_device_keymap(client->connection, device->id, device->keymap->type, device->keymap->size, device->keymap->fd); if (rc >= 0 && device->type == EIS_DEVICE_TYPE_VIRTUAL) { struct eis_region *r; list_for_each(r, &device->regions, link) { - rc = eis_event_device_region(client, device->id, r->x, r->y, r->width, r->height, r->physical_scale); + rc = eis_connection_event_device_region(client->connection, device->id, r->x, r->y, r->width, r->height, r->physical_scale); } } if (rc >= 0) - rc = eis_event_device_done(client, device->id); + rc = eis_connection_event_device_done(client->connection, device->id); return rc; } static int client_send_device_removed(struct eis_client *client, struct eis_device *device) { - return eis_event_device_removed(client, device->id); + return eis_connection_event_device_removed(client->connection, device->id); } static int client_send_device_paused(struct eis_client *client, struct eis_device *device) { - return eis_event_device_paused(client, device->id); + return eis_connection_event_device_paused(client->connection, device->id); } static int client_send_device_resumed(struct eis_client *client, struct eis_device *device) { - return eis_event_device_resumed(client, device->id); + return eis_connection_event_device_resumed(client->connection, device->id); } static int client_send_keyboard_modifiers(struct eis_client *client, struct eis_device *device, const struct eis_xkb_modifiers *mods) { - return eis_event_keyboard_modifiers(client, device->id, + return eis_connection_event_keyboard_modifiers(client->connection, device->id, mods->depressed, mods->locked, mods->latched, mods->group); } @@ -292,8 +316,9 @@ eis_client_disconnect(struct eis_client *client) } static int -client_msg_close_device(struct eis_client *client, uint32_t deviceid) +client_msg_close_device(struct eis_connection *connection, uint32_t deviceid) { + struct eis_client *client = eis_connection_get_client(connection); struct eis_device *device = eis_client_find_device(client, deviceid); if (device) @@ -303,8 +328,9 @@ client_msg_close_device(struct eis_client *client, uint32_t deviceid) } static int -client_msg_bind_seat(struct eis_client *client, uint32_t seatid, uint32_t caps) +client_msg_bind_seat(struct eis_connection *connection, uint32_t seatid, uint32_t caps) { + struct eis_client *client = eis_connection_get_client(connection); struct eis_seat *seat = eis_client_find_seat(client, seatid); if (seat) @@ -322,8 +348,10 @@ client_msg_bind_seat(struct eis_client *client, uint32_t seatid, uint32_t caps) } while(0) static int -client_msg_start_emulating(struct eis_client *client, uint32_t deviceid, uint32_t sequence) +client_msg_start_emulating(struct eis_connection *connection, uint32_t deviceid, uint32_t sequence) { + struct eis_client *client = eis_connection_get_client(connection); + DISCONNECT_IF_RECEIVER_CONTEXT(client); struct eis_device *device = eis_client_find_device(client, deviceid); @@ -335,8 +363,10 @@ client_msg_start_emulating(struct eis_client *client, uint32_t deviceid, uint32_ } static int -client_msg_stop_emulating(struct eis_client *client, uint32_t deviceid) +client_msg_stop_emulating(struct eis_connection *connection, uint32_t deviceid) { + struct eis_client *client = eis_connection_get_client(connection); + DISCONNECT_IF_RECEIVER_CONTEXT(client); struct eis_device *device = eis_client_find_device(client, deviceid); @@ -348,8 +378,10 @@ client_msg_stop_emulating(struct eis_client *client, uint32_t deviceid) } static int -client_msg_frame(struct eis_client *client, uint32_t deviceid, uint32_t time, uint32_t micros) +client_msg_frame(struct eis_connection *connection, uint32_t deviceid, uint32_t time, uint32_t micros) { + struct eis_client *client = eis_connection_get_client(connection); + DISCONNECT_IF_RECEIVER_CONTEXT(client); struct eis_device *device = eis_client_find_device(client, deviceid); @@ -361,9 +393,11 @@ client_msg_frame(struct eis_client *client, uint32_t deviceid, uint32_t time, ui } static int -client_msg_pointer_rel(struct eis_client *client, uint32_t deviceid, +client_msg_pointer_rel(struct eis_connection *connection, uint32_t deviceid, float x, float y) { + struct eis_client *client = eis_connection_get_client(connection); + DISCONNECT_IF_RECEIVER_CONTEXT(client); struct eis_device *device = eis_client_find_device(client, deviceid); @@ -375,9 +409,11 @@ client_msg_pointer_rel(struct eis_client *client, uint32_t deviceid, } static int -client_msg_pointer_abs(struct eis_client *client, uint32_t deviceid, +client_msg_pointer_abs(struct eis_connection *connection, uint32_t deviceid, float x, float y) { + struct eis_client *client = eis_connection_get_client(connection); + DISCONNECT_IF_RECEIVER_CONTEXT(client); struct eis_device *device = eis_client_find_device(client, deviceid); @@ -389,9 +425,11 @@ client_msg_pointer_abs(struct eis_client *client, uint32_t deviceid, } static int -client_msg_pointer_button(struct eis_client *client, uint32_t deviceid, +client_msg_pointer_button(struct eis_connection *connection, uint32_t deviceid, uint32_t button, uint32_t state) { + struct eis_client *client = eis_connection_get_client(connection); + DISCONNECT_IF_RECEIVER_CONTEXT(client); struct eis_device *device = eis_client_find_device(client, deviceid); @@ -403,9 +441,11 @@ client_msg_pointer_button(struct eis_client *client, uint32_t deviceid, } static int -client_msg_pointer_scroll(struct eis_client *client, uint32_t deviceid, +client_msg_pointer_scroll(struct eis_connection *connection, uint32_t deviceid, float x, float y) { + struct eis_client *client = eis_connection_get_client(connection); + DISCONNECT_IF_RECEIVER_CONTEXT(client); struct eis_device *device = eis_client_find_device(client, deviceid); @@ -417,9 +457,11 @@ client_msg_pointer_scroll(struct eis_client *client, uint32_t deviceid, } static int -client_msg_pointer_scroll_discrete(struct eis_client *client, uint32_t deviceid, +client_msg_pointer_scroll_discrete(struct eis_connection *connection, uint32_t deviceid, int32_t x, int32_t y) { + struct eis_client *client = eis_connection_get_client(connection); + DISCONNECT_IF_RECEIVER_CONTEXT(client); struct eis_device *device = eis_client_find_device(client, deviceid); @@ -431,9 +473,11 @@ client_msg_pointer_scroll_discrete(struct eis_client *client, uint32_t deviceid, } static int -client_msg_pointer_scroll_stop(struct eis_client *client, uint32_t deviceid, +client_msg_pointer_scroll_stop(struct eis_connection *connection, uint32_t deviceid, uint32_t x, uint32_t y, uint32_t is_cancel) { + struct eis_client *client = eis_connection_get_client(connection); + DISCONNECT_IF_RECEIVER_CONTEXT(client); struct eis_device *device = eis_client_find_device(client, deviceid); @@ -449,9 +493,11 @@ client_msg_pointer_scroll_stop(struct eis_client *client, uint32_t deviceid, } static int -client_msg_keyboard_key(struct eis_client *client, uint32_t deviceid, +client_msg_keyboard_key(struct eis_connection *connection, uint32_t deviceid, uint32_t key, uint32_t state) { + struct eis_client *client = eis_connection_get_client(connection); + DISCONNECT_IF_RECEIVER_CONTEXT(client); struct eis_device *device = eis_client_find_device(client, deviceid); @@ -463,9 +509,11 @@ client_msg_keyboard_key(struct eis_client *client, uint32_t deviceid, } static int -client_msg_touch_down(struct eis_client *client, uint32_t deviceid, +client_msg_touch_down(struct eis_connection *connection, uint32_t deviceid, uint32_t touchid, float x, float y) { + struct eis_client *client = eis_connection_get_client(connection); + DISCONNECT_IF_RECEIVER_CONTEXT(client); struct eis_device *device = eis_client_find_device(client, deviceid); @@ -477,9 +525,11 @@ client_msg_touch_down(struct eis_client *client, uint32_t deviceid, } static int -client_msg_touch_motion(struct eis_client *client, uint32_t deviceid, +client_msg_touch_motion(struct eis_connection *connection, uint32_t deviceid, uint32_t touchid, float x, float y) { + struct eis_client *client = eis_connection_get_client(connection); + DISCONNECT_IF_RECEIVER_CONTEXT(client); struct eis_device *device = eis_client_find_device(client, deviceid); @@ -491,8 +541,10 @@ client_msg_touch_motion(struct eis_client *client, uint32_t deviceid, } static int -client_msg_touch_up(struct eis_client *client, uint32_t deviceid, uint32_t touchid) +client_msg_touch_up(struct eis_connection *connection, uint32_t deviceid, uint32_t touchid) { + struct eis_client *client = eis_connection_get_client(connection); + DISCONNECT_IF_RECEIVER_CONTEXT(client); struct eis_device *device = eis_client_find_device(client, deviceid); @@ -504,9 +556,11 @@ client_msg_touch_up(struct eis_client *client, uint32_t deviceid, uint32_t touch } static int -client_msg_connect(struct eis_client *client, uint32_t version, +client_msg_connect(struct eis_connection *connection, uint32_t version, const char *name, uint32_t is_sender) { + struct eis_client *client = eis_connection_get_client(connection); + if (client->version > EIS_PROTOCOL_VERSION) return -EPROTO; @@ -521,8 +575,10 @@ client_msg_connect(struct eis_client *client, uint32_t version, } static int -client_msg_connect_done(struct eis_client *client) +client_msg_connect_done(struct eis_connection *connection) { + struct eis_client *client = eis_connection_get_client(connection); + eis_queue_connect_event(client); client->state = EIS_CLIENT_STATE_CONNECTING; @@ -530,18 +586,19 @@ client_msg_connect_done(struct eis_client *client) } static int -client_msg_disconnect(struct eis_client *client) +client_msg_disconnect(struct eis_connection *connection) { return -ECANCELED; } static int -client_msg_get_version(struct eis_client *client) +client_msg_get_version(struct eis_connection *connection) { + struct eis_client *client = eis_connection_get_client(connection); return client_send_version(client, EI_PROTOCOL_VERSION); } -static const struct eis_interface intf_state_new = { +static const struct eis_connection_interface intf_state_new = { .connect = client_msg_connect, .connect_done = client_msg_connect_done, .disconnect = client_msg_disconnect, @@ -549,12 +606,12 @@ static const struct eis_interface intf_state_new = { }; /* Client is waiting for us, shouldn't send anything except disconnect */ -static const struct eis_interface intf_state_connecting = { +static const struct eis_connection_interface intf_state_connecting = { .disconnect = client_msg_disconnect, .get_version = client_msg_get_version, }; -static const struct eis_interface intf_state_connected = { +static const struct eis_connection_interface intf_state_connected = { .disconnect = client_msg_disconnect, .bind_seat = client_msg_bind_seat, .close_device = client_msg_close_device, @@ -576,14 +633,14 @@ static const struct eis_interface intf_state_connected = { .frame = client_msg_frame, }; -static const struct eis_interface *interfaces[] = { +static const struct eis_connection_interface *interfaces[] = { [EIS_CLIENT_STATE_NEW] = &intf_state_new, [EIS_CLIENT_STATE_CONNECTING] = &intf_state_connecting, [EIS_CLIENT_STATE_CONNECTED] = &intf_state_connected, [EIS_CLIENT_STATE_DISCONNECTED] = NULL, }; -const struct eis_interface * +const struct eis_connection_interface * eis_client_get_interface(struct eis_client *client) { assert(client->state < ARRAY_LENGTH(interfaces)); @@ -595,10 +652,15 @@ lookup_object(uint32_t object_id, struct brei_object **object, void *userdata) { struct eis_client *client = userdata; - assert(object_id == 0); /* We only have one object atm */ + struct brei_object *obj; + list_for_each(obj, &client->proto_objects, link) { + if (obj->id == object_id) { + *object = obj; + return 0; + } + } - *object = &client->proto_object; - return 0; + return -ENOENT; } static void @@ -642,14 +704,13 @@ eis_client_new(struct eis *eis, int fd) static uint32_t client_id; struct eis_client *client = eis_client_create(&eis->object); - client->proto_object.id = 0; - client->proto_object.implementation = client; - client->proto_object.interface = &eis_proto_interface; - client->is_sender = true; client->id = ++client_id; list_init(&client->seats); list_init(&client->seats_pending); + list_init(&client->proto_objects); + + client->connection = eis_connection_new(client); struct source *s = source_new(fd, client_dispatch, client); int rc = sink_add_source(eis->sink, s); diff --git a/src/libeis-client.h b/src/libeis-client.h index a4208d9..816e12b 100644 --- a/src/libeis-client.h +++ b/src/libeis-client.h @@ -39,7 +39,10 @@ enum eis_client_state { struct eis_client { struct object object; - struct brei_object proto_object; + struct eis_connection *connection; + + struct list proto_objects; /* struct brei_objects list */ + uint32_t next_object_id; void *user_data; struct list link; @@ -65,12 +68,21 @@ eis_client_new(struct eis *eis, int fd); struct eis_client * eis_client_get_client(struct eis_client *client); -const struct eis_interface * +const struct eis_connection_interface * eis_client_get_interface(struct eis_client *client); const struct brei_object * eis_client_get_proto_object(struct eis_client *client); +uint32_t +eis_client_get_new_id(struct eis_client *client); + +void +eis_client_register_object(struct eis_client *client, struct brei_object *object); + +void +eis_client_unregister_object(struct eis_client *client, struct brei_object *object); + void eis_add_client(struct eis *eis, struct eis_client *client); diff --git a/src/libeis-connection.c b/src/libeis-connection.c new file mode 100644 index 0000000..743f45f --- /dev/null +++ b/src/libeis-connection.c @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023 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 + +#include "util-bits.h" +#include "util-macros.h" +#include "util-mem.h" +#include "util-io.h" +#include "util-strings.h" +#include "util-version.h" + +#include "libeis-private.h" +#include "eis-proto.h" + +static void +eis_connection_destroy(struct eis_connection *connection) +{ + struct eis_client *client = eis_connection_get_client(connection); + eis_client_unregister_object(client, &connection->proto_object); +} + +OBJECT_IMPLEMENT_REF(eis_connection); +OBJECT_IMPLEMENT_UNREF_CLEANUP(eis_connection); +OBJECT_IMPLEMENT_GETTER_AS_REF(eis_connection, proto_object, const struct brei_object *); + +static +OBJECT_IMPLEMENT_CREATE(eis_connection); +static +OBJECT_IMPLEMENT_PARENT(eis_connection, eis_client); + +struct eis_client* +eis_connection_get_client(struct eis_connection *connection) +{ + return eis_connection_parent(connection); +} + +struct eis* +eis_connection_get_context(struct eis_connection *connection) +{ + struct eis_client *client = eis_connection_parent(connection); + return eis_client_get_context(client); +} + +const struct eis_connection_interface * +eis_connection_get_interface(struct eis_connection *connection) { + struct eis_client *client = eis_connection_parent(connection); + return eis_client_get_interface(client); +} + +struct eis_connection * +eis_connection_new(struct eis_client *client) +{ + struct eis_connection *connection = eis_connection_create(&client->object); + + connection->proto_object.id = eis_client_get_new_id(client); + connection->proto_object.implementation = connection; + connection->proto_object.interface = &eis_connection_proto_interface; + connection->proto_object.version = VERSION_V(1); + eis_client_register_object(client, &connection->proto_object); + + return connection; /* ref owned by caller */ +} diff --git a/src/libeis-connection.h b/src/libeis-connection.h new file mode 100644 index 0000000..1203674 --- /dev/null +++ b/src/libeis-connection.h @@ -0,0 +1,48 @@ + +/* SPDX-License-Identifier: MIT */ +/* + * 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. + */ + +#pragma once + +#include "util-object.h" +#include "brei-shared.h" + +struct eis; +struct eis_client; + +/* This is a protocol-only object, not exposed in the API */ +struct eis_connection { + struct object object; + struct brei_object proto_object; +}; + +OBJECT_DECLARE_GETTER(eis_connection, context, struct eis *); +OBJECT_DECLARE_GETTER(eis_connection, client, struct eis_client *); +OBJECT_DECLARE_GETTER(eis_connection, proto_object, const struct brei_object *); +OBJECT_DECLARE_GETTER(eis_connection, interface, const struct eis_connection_interface *); +OBJECT_DECLARE_REF(eis_connection); +OBJECT_DECLARE_UNREF(eis_connection); + +struct eis_connection * +eis_connection_new(struct eis_client *client); diff --git a/src/libeis-device.c b/src/libeis-device.c index d5ec597..556b9fe 100644 --- a/src/libeis-device.c +++ b/src/libeis-device.c @@ -311,12 +311,12 @@ eis_device_has_capability(struct eis_device *device, #define handle_request_noargs(device_, func_) { \ struct eis_client *client = eis_device_get_client(device); \ - eis_event_##func_(client, device->id); \ + eis_connection_event_##func_(client->connection, device->id); \ } #define handle_request(device_, func_, ...) { \ struct eis_client *client = eis_device_get_client(device); \ - eis_event_##func_(client, device->id, __VA_ARGS__); \ + eis_connection_event_##func_(client->connection, device->id, __VA_ARGS__); \ } static void diff --git a/src/libeis-private.h b/src/libeis-private.h index 3ba3a99..55cb02b 100644 --- a/src/libeis-private.h +++ b/src/libeis-private.h @@ -36,6 +36,7 @@ #include "util-structs.h" #include "libeis-client.h" +#include "libeis-connection.h" #include "libeis-device.h" #include "libeis-event.h" #include "libeis-region.h"