From c4601b7196a744e21cacbfdf65ab2ee71af143c7 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 19 Aug 2020 13:39:32 +1000 Subject: [PATCH] Implement device suspend/resume with starting state of "suspended" This was already spelled out in the documentation but just not yet implemented. New starting state for any device added by EIS is "suspended", the server needs to explicitly resume it before events are accepted. Signed-off-by: Peter Hutterer --- proto/ei.proto | 17 ++++- src/libei-device.c | 20 ++++-- src/libei-private.h | 9 ++- src/libei-proto.c | 18 +++++ src/libei-proto.h | 8 +++ src/libei.c | 75 +++++++++++++++++++- src/libeis-client.c | 24 +++++++ src/libeis-device.c | 28 ++++++-- src/libeis-private.h | 10 ++- src/libeis-proto.c | 30 ++++++++ src/libeis-proto.h | 8 +++ test/eierpecken.c | 35 +++++++++- test/eierpecken.h | 12 +++- test/test-ei.c | 4 ++ test/test-eis.c | 141 ++++++++++++++++++++++++++++++++++++++ tools/ei-socket-client.c | 14 +++- tools/eis-socket-server.c | 1 + 17 files changed, 430 insertions(+), 24 deletions(-) diff --git a/proto/ei.proto b/proto/ei.proto index ab7b756..825b407 100644 --- a/proto/ei.proto +++ b/proto/ei.proto @@ -18,9 +18,10 @@ syntax = "proto3"; * 3. - client sends "AddDevice" * 3.a - server replies with "DeviceAdded" or * 3.b - server replies with "DeviceRemoved" - * 4. - client sends "PointerRelative" or any other event - * 5. - client sends "RemoveDevice" - * 6. - client sends "Disconnect" and closes its end of the socket + * 4. - server sends "DeviceResumed" + * 5. - client sends "PointerRelative" or any other event + * 6. - client sends "RemoveDevice" + * 7. - client sends "Disconnect" and closes its end of the socket * * The server may send Disconnect at any time. * The server may send Removed for a device at any time after that device's @@ -139,12 +140,22 @@ message DeviceRemoved { uint32 deviceid = 1; } +message DeviceResumed { + uint32 deviceid = 1; +} + +message DeviceSuspended { + uint32 deviceid = 1; +} + message ServerMessage { oneof msg { Connected connected = 2; Disconnected disconnected = 3; DeviceAdded device_added = 4; DeviceRemoved device_removed = 5; + DeviceResumed device_resumed = 6; + DeviceSuspended device_suspended = 7; } } diff --git a/src/libei-device.c b/src/libei-device.c index b949ae1..cd38c6d 100644 --- a/src/libei-device.c +++ b/src/libei-device.c @@ -156,10 +156,22 @@ ei_device_remove(struct ei_device *device) ei_remove_device(device); } +void +ei_device_resumed(struct ei_device *device) +{ + device->state = EI_DEVICE_STATE_RESUMED; +} + +void +ei_device_suspended(struct ei_device *device) +{ + device->state = EI_DEVICE_STATE_SUSPENDED; +} + void ei_device_added(struct ei_device *device) { - device->state = EI_DEVICE_STATE_ADDED; + ei_device_suspended(device); } void @@ -214,7 +226,7 @@ ei_device_pointer_motion(struct ei_device *device, if (!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER)) return; - if (device->state != EI_DEVICE_STATE_ADDED) + if (device->state != EI_DEVICE_STATE_RESUMED) return; ei_pointer_rel(device, x, y); @@ -227,7 +239,7 @@ ei_device_pointer_button(struct ei_device *device, if (!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER)) return; - if (device->state != EI_DEVICE_STATE_ADDED) + if (device->state != EI_DEVICE_STATE_RESUMED) return; ei_pointer_button(device, button, is_press); @@ -240,7 +252,7 @@ ei_device_keyboard_key(struct ei_device *device, if (!ei_device_has_capability(device, EI_DEVICE_CAP_KEYBOARD)) return; - if (device->state != EI_DEVICE_STATE_ADDED) + if (device->state != EI_DEVICE_STATE_RESUMED) return; ei_keyboard_key(device, key, is_press); diff --git a/src/libei-private.h b/src/libei-private.h index 8353e05..4d944ab 100644 --- a/src/libei-private.h +++ b/src/libei-private.h @@ -60,7 +60,8 @@ struct ei { enum ei_device_state { EI_DEVICE_STATE_NEW, EI_DEVICE_STATE_CONNECTING, - EI_DEVICE_STATE_ADDED, + EI_DEVICE_STATE_SUSPENDED, + EI_DEVICE_STATE_RESUMED, EI_DEVICE_STATE_REMOVED, }; @@ -120,6 +121,12 @@ ei_keyboard_key(struct ei_device *device, void ei_device_added(struct ei_device *device); +void +ei_device_suspended(struct ei_device *device); + +void +ei_device_resumed(struct ei_device *device); + void ei_device_set_capabilities(struct ei_device *device, uint32_t capabilities); diff --git a/src/libei-proto.c b/src/libei-proto.c index 9a37dd4..3c96570 100644 --- a/src/libei-proto.c +++ b/src/libei-proto.c @@ -92,6 +92,24 @@ ei_proto_parse_message(const char *msgdata, size_t msglen, size_t *consumed) }; } break; + case SERVER_MESSAGE__MSG_DEVICE_RESUMED: + { + DeviceResumed *r = proto->device_resumed; + *msg = (struct message) { + .type = MESSAGE_DEVICE_RESUMED, + .resumed.deviceid = r->deviceid, + }; + } + break; + case SERVER_MESSAGE__MSG_DEVICE_SUSPENDED: + { + DeviceSuspended *r = proto->device_suspended; + *msg = (struct message) { + .type = MESSAGE_DEVICE_SUSPENDED, + .suspended.deviceid = r->deviceid, + }; + } + break; default: success = false; break; diff --git a/src/libei-proto.h b/src/libei-proto.h index 0b5f482..0444450 100644 --- a/src/libei-proto.h +++ b/src/libei-proto.h @@ -36,6 +36,8 @@ enum message_type { MESSAGE_DISCONNECTED, MESSAGE_DEVICE_ADDED, MESSAGE_DEVICE_REMOVED, + MESSAGE_DEVICE_RESUMED, + MESSAGE_DEVICE_SUSPENDED, }; struct message { @@ -54,6 +56,12 @@ struct message { struct message_device_removed { uint32_t deviceid; } removed; + struct message_device_resumed { + uint32_t deviceid; + } resumed; + struct message_device_suspended { + uint32_t deviceid; + } suspended; }; }; diff --git a/src/libei.c b/src/libei.c index 9526f1e..73d432e 100644 --- a/src/libei.c +++ b/src/libei.c @@ -48,9 +48,11 @@ ei_event_destroy(struct ei_event *event) case EI_EVENT_DISCONNECT: case EI_EVENT_DEVICE_ADDED: case EI_EVENT_DEVICE_REMOVED: + case EI_EVENT_DEVICE_SUSPENDED: + case EI_EVENT_DEVICE_RESUMED: break; default: - abort(); /* not yet implemented */ + assert(!"destroy not implemented for this type"); } ei_device_unref(event->device); } @@ -179,6 +181,30 @@ ei_queue_removed_event(struct ei_device *device) ei_queue_event(ei, e); } +static void +ei_queue_suspended_event(struct ei_device *device) +{ + struct ei *ei= ei_device_get_context(device); + + struct ei_event *e = ei_event_create(&ei->object); + e->type = EI_EVENT_DEVICE_SUSPENDED; + e->device = ei_device_ref(device); + + ei_queue_event(ei, e); +} + +static void +ei_queue_resumed_event(struct ei_device *device) +{ + struct ei *ei= ei_device_get_context(device); + + struct ei_event *e = ei_event_create(&ei->object); + e->type = EI_EVENT_DEVICE_RESUMED; + e->device = ei_device_ref(device); + + ei_queue_event(ei, e); +} + static int connection_send_connect(struct ei *ei) { @@ -349,9 +375,44 @@ ei_removed(struct ei *ei, uint32_t deviceid) } } - return -0; + return 0; } +static int +ei_resumed(struct ei *ei, uint32_t deviceid) +{ + struct ei_device *d; + + log_debug(ei, "Resumed device %d\n", deviceid); + + list_for_each(d, &ei->devices, link) { + if (d->id == deviceid) { + ei_device_resumed(d); + ei_queue_resumed_event(d); + break; + } + } + + return 0; +} + +static int +ei_suspended(struct ei *ei, uint32_t deviceid) +{ + struct ei_device *d; + + log_debug(ei, "Suspended device %d\n", deviceid); + + list_for_each(d, &ei->devices, link) { + if (d->id == deviceid) { + ei_device_suspended(d); + ei_queue_suspended_event(d); + break; + } + } + + return 0; +} int ei_pointer_rel(struct ei_device *device, double x, double y) @@ -415,6 +476,8 @@ connection_new_handle_msg(struct ei *ei, struct message *msg) case MESSAGE_DISCONNECTED: case MESSAGE_DEVICE_ADDED: case MESSAGE_DEVICE_REMOVED: + case MESSAGE_DEVICE_RESUMED: + case MESSAGE_DEVICE_SUSPENDED: rc = -EPROTO; break; } @@ -437,6 +500,8 @@ connection_connecting_handle_msg(struct ei *ei, struct message *msg) break; case MESSAGE_DEVICE_ADDED: case MESSAGE_DEVICE_REMOVED: + case MESSAGE_DEVICE_RESUMED: + case MESSAGE_DEVICE_SUSPENDED: rc = -EPROTO; break; } @@ -462,6 +527,12 @@ connection_connected_handle_msg(struct ei *ei, struct message *msg) case MESSAGE_DEVICE_REMOVED: rc = ei_removed(ei, msg->removed.deviceid); break; + case MESSAGE_DEVICE_RESUMED: + rc = ei_resumed(ei, msg->resumed.deviceid); + break; + case MESSAGE_DEVICE_SUSPENDED: + rc = ei_suspended(ei, msg->resumed.deviceid); + break; } return rc; diff --git a/src/libeis-client.c b/src/libeis-client.c index 8de86f1..1fca727 100644 --- a/src/libeis-client.c +++ b/src/libeis-client.c @@ -94,6 +94,18 @@ client_send_device_removed(struct eis_client *client, struct eis_device *device) return eis_proto_send_device_removed(client, device); } +static int +client_send_device_suspended(struct eis_client *client, struct eis_device *device) +{ + return eis_proto_send_device_suspended(client, device); +} + +static int +client_send_device_resumed(struct eis_client *client, struct eis_device *device) +{ + return eis_proto_send_device_resumed(client, device); +} + _public_ void eis_client_connect(struct eis_client *client) { @@ -481,3 +493,15 @@ eis_client_disconnect_device(struct eis_client *client, struct eis_device *devic list_remove(&device->link); eis_device_unref(device); } + +void +eis_client_suspend_device(struct eis_client *client, struct eis_device *device) +{ + client_send_device_suspended(client, device); +} + +void +eis_client_resume_device(struct eis_client *client, struct eis_device *device) +{ + client_send_device_resumed(client, device); +} diff --git a/src/libeis-device.c b/src/libeis-device.c index baf9173..741de6d 100644 --- a/src/libeis-device.c +++ b/src/libeis-device.c @@ -138,7 +138,7 @@ eis_device_pointer_rel(struct eis_device *device, if (!eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER)) return -EINVAL; - if (device->state != EIS_DEVICE_STATE_ACCEPTED) + if (device->state != EIS_DEVICE_STATE_RESUMED) return -EINVAL; eis_queue_pointer_rel_event(device, x, y); @@ -153,7 +153,7 @@ eis_device_pointer_button(struct eis_device *device, if (!eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER)) return -EINVAL; - if (device->state != EIS_DEVICE_STATE_ACCEPTED) + if (device->state != EIS_DEVICE_STATE_RESUMED) return -EINVAL; eis_queue_pointer_button_event(device, button, is_press); @@ -168,7 +168,7 @@ eis_device_keyboard_key(struct eis_device *device, if (!eis_device_has_capability(device, EIS_DEVICE_CAP_KEYBOARD)) return -EINVAL; - if (device->state != EIS_DEVICE_STATE_ACCEPTED) + if (device->state != EIS_DEVICE_STATE_RESUMED) return -EINVAL; eis_queue_keyboard_key_event(device, key, is_press); @@ -182,7 +182,7 @@ eis_device_connect(struct eis_device *device) if (device->state != EIS_DEVICE_STATE_NEW) return; - device->state = EIS_DEVICE_STATE_ACCEPTED; + device->state = EIS_DEVICE_STATE_SUSPENDED; eis_client_connect_device(eis_device_get_client(device), device); } @@ -195,3 +195,23 @@ eis_device_disconnect(struct eis_device *device) device->state = EIS_DEVICE_STATE_REMOVED; eis_client_disconnect_device(eis_device_get_client(device), device); } + +_public_ void +eis_device_suspend(struct eis_device *device) +{ + if (device->state != EIS_DEVICE_STATE_RESUMED) + return; + + device->state = EIS_DEVICE_STATE_SUSPENDED; + eis_client_suspend_device(eis_device_get_client(device), device); +} + +_public_ void +eis_device_resume(struct eis_device *device) +{ + if (device->state != EIS_DEVICE_STATE_SUSPENDED) + return; + + device->state = EIS_DEVICE_STATE_RESUMED; + eis_client_resume_device(eis_device_get_client(device), device); +} diff --git a/src/libeis-private.h b/src/libeis-private.h index 8043231..5baaa21 100644 --- a/src/libeis-private.h +++ b/src/libeis-private.h @@ -75,7 +75,8 @@ struct eis_client { enum eis_device_state { EIS_DEVICE_STATE_NEW, - EIS_DEVICE_STATE_ACCEPTED, + EIS_DEVICE_STATE_SUSPENDED, + EIS_DEVICE_STATE_RESUMED, EIS_DEVICE_STATE_REMOVED, }; @@ -136,6 +137,13 @@ void eis_client_disconnect_device(struct eis_client *client, struct eis_device *device); +void +eis_client_resume_device(struct eis_client *client, + struct eis_device *device); +void +eis_client_suspend_device(struct eis_client *client, + struct eis_device *device); + struct eis_device * eis_device_new(struct eis_client *client, uint32_t id, diff --git a/src/libeis-proto.c b/src/libeis-proto.c index 0800040..6364ad2 100644 --- a/src/libeis-proto.c +++ b/src/libeis-proto.c @@ -65,6 +65,8 @@ log_wire_message(struct eis *eis, const ServerMessage *msg) MSG_STRING_CASE(DISCONNECTED); MSG_STRING_CASE(DEVICE_ADDED); MSG_STRING_CASE(DEVICE_REMOVED); + MSG_STRING_CASE(DEVICE_RESUMED); + MSG_STRING_CASE(DEVICE_SUSPENDED); break; default: assert(!"Unimplemented message type"); @@ -144,6 +146,34 @@ eis_proto_send_device_removed(struct eis_client *client, struct eis_device *devi return eis_proto_send_msg(client, &msg); } +int +eis_proto_send_device_suspended(struct eis_client *client, struct eis_device *device) +{ + ServerMessage msg = SERVER_MESSAGE__INIT; + DeviceSuspended suspended = DEVICE_SUSPENDED__INIT; + + suspended.deviceid = device->id; + + msg.device_suspended = &suspended; + msg.msg_case = SERVER_MESSAGE__MSG_DEVICE_SUSPENDED; + + return eis_proto_send_msg(client, &msg); +} + +int +eis_proto_send_device_resumed(struct eis_client *client, struct eis_device *device) +{ + ServerMessage msg = SERVER_MESSAGE__INIT; + DeviceResumed resumed = DEVICE_RESUMED__INIT; + + resumed.deviceid = device->id; + + msg.device_resumed = &resumed; + msg.msg_case = SERVER_MESSAGE__MSG_DEVICE_RESUMED; + + return eis_proto_send_msg(client, &msg); +} + struct message * eis_proto_parse_message(const char *msgdata, size_t msglen, size_t *consumed) { diff --git a/src/libeis-proto.h b/src/libeis-proto.h index 97c19e8..e7f7580 100644 --- a/src/libeis-proto.h +++ b/src/libeis-proto.h @@ -107,5 +107,13 @@ int eis_proto_send_device_removed(struct eis_client *client, struct eis_device *device); +int +eis_proto_send_device_suspended(struct eis_client *client, + struct eis_device *device); + +int +eis_proto_send_device_resumed(struct eis_client *client, + struct eis_device *device); + struct message * eis_proto_parse_message(const char *data, size_t len, size_t *consumed); diff --git a/test/eierpecken.c b/test/eierpecken.c index d112c41..d44c8fe 100644 --- a/test/eierpecken.c +++ b/test/eierpecken.c @@ -79,7 +79,7 @@ peck_new(void) rc = ei_setup_backend_fd(ei, sv[0]); munit_assert_int(rc, ==, 0); peck->ei = ei; - peck->ei_behavior = bit(PECK_EI_BEHAVIOR_AUTOCONNNECT); + flag_set(peck->ei_behavior, PECK_EI_BEHAVIOR_AUTOCONNNECT); struct eis *eis = eis_new(NULL); rc = eis_setup_backend_fd(eis); @@ -105,6 +105,7 @@ peck_enable_eis_behavior(struct peck *peck, enum peck_eis_behavior behavior) case PECK_EIS_BEHAVIOR_ACCEPT_ALL: peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT); peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_DEVICE); + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_RESUME_DEVICE); break; case PECK_EIS_BEHAVIOR_REJECT_ALL: peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_REJECT_CLIENT); @@ -143,6 +144,14 @@ peck_enable_eis_behavior(struct peck *peck, enum peck_eis_behavior behavior) case PECK_EIS_BEHAVIOR_HANDLE_DEVICE: flag_set(peck->eis_behavior, behavior); break; + case PECK_EIS_BEHAVIOR_RESUME_DEVICE: + flag_clear(peck->eis_behavior, PECK_EIS_BEHAVIOR_SUSPEND_DEVICE); + flag_set(peck->eis_behavior, behavior); + break; + case PECK_EIS_BEHAVIOR_SUSPEND_DEVICE: + flag_clear(peck->eis_behavior, PECK_EIS_BEHAVIOR_RESUME_DEVICE); + flag_set(peck->eis_behavior, behavior); + break; } } @@ -166,6 +175,10 @@ peck_enable_ei_behavior(struct peck *peck, enum peck_ei_behavior behavior) case PECK_EI_BEHAVIOR_HANDLE_ADDED_TOUCH: flag_set(peck->ei_behavior, behavior); break; + case PECK_EI_BEHAVIOR_HANDLE_RESUMED: + case PECK_EI_BEHAVIOR_HANDLE_SUSPENDED: + flag_set(peck->ei_behavior, behavior); + break; } } @@ -173,6 +186,7 @@ static inline void peck_handle_eis_connect(struct peck *peck, struct eis_event *e) { struct eis_client *client = eis_event_get_client(e); + if (flag_is_set(peck->eis_behavior, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT)) { log_debug(peck, "EIS accepting client: %s\n", eis_client_get_name(client)); eis_client_connect(client); @@ -182,7 +196,7 @@ peck_handle_eis_connect(struct peck *peck, struct eis_event *e) } } -static inline void +static inline bool peck_handle_eis_added(struct peck *peck, struct eis_event *e) { struct eis_device *device = eis_event_get_device(e); @@ -212,9 +226,11 @@ peck_handle_eis_added(struct peck *peck, struct eis_event *e) if (!mask) { log_debug(peck, "EIS refusing device\n"); eis_device_disconnect(eis_event_get_device(e)); + return false; } else { log_debug(peck, "EIS adding device\n"); eis_device_connect(eis_event_get_device(e)); + return true; } } @@ -276,7 +292,9 @@ peck_dispatch_eis(struct peck *peck) eis_client_disconnect(eis_event_get_client(e)); break; case EIS_EVENT_DEVICE_ADDED: - peck_handle_eis_added(peck, e); + if (peck_handle_eis_added(peck, e) && + flag_is_set(peck->eis_behavior, PECK_EIS_BEHAVIOR_RESUME_DEVICE)) + eis_device_resume(eis_event_get_device(e)); break; case EIS_EVENT_DEVICE_REMOVED: log_debug(peck, "EIS removing device\n"); @@ -334,6 +352,15 @@ peck_dispatch_ei(struct peck *peck) break; case EI_EVENT_DEVICE_ADDED: process_event = peck_check_ei_added(peck, e); + break; + case EI_EVENT_DEVICE_RESUMED: + if (flag_is_set(peck->ei_behavior, PECK_EI_BEHAVIOR_HANDLE_RESUMED)) + process_event = tristate_yes; + break; + case EI_EVENT_DEVICE_SUSPENDED: + if (flag_is_set(peck->ei_behavior, PECK_EI_BEHAVIOR_HANDLE_SUSPENDED)) + process_event = tristate_yes; + break; default: break; } @@ -358,6 +385,8 @@ peck_dispatch_ei(struct peck *peck) /* Nothing to do here */ break; case EI_EVENT_DEVICE_ADDED: + case EI_EVENT_DEVICE_RESUMED: + case EI_EVENT_DEVICE_SUSPENDED: /* Nothing to do here */ break; default: diff --git a/test/eierpecken.h b/test/eierpecken.h index 9acc17a..3865bf0 100644 --- a/test/eierpecken.h +++ b/test/eierpecken.h @@ -39,12 +39,12 @@ */ enum peck_eis_behavior { /** - * Behavior of EIS is implemented in the test case. This is the - * default. + * Behavior of EIS is implemented in the test case. */ PECK_EIS_BEHAVIOR_NONE, /** - * Accept all client connection requests and device additions. + * Accept all client connection requests and device additions + * **and** resume any device immediately after add. */ PECK_EIS_BEHAVIOR_ACCEPT_ALL, /** @@ -76,6 +76,9 @@ enum peck_eis_behavior { PECK_EIS_BEHAVIOR_ACCEPT_TOUCH, PECK_EIS_BEHAVIOR_DROP_TOUCH, + + PECK_EIS_BEHAVIOR_RESUME_DEVICE, + PECK_EIS_BEHAVIOR_SUSPEND_DEVICE, }; enum peck_ei_behavior { @@ -86,6 +89,9 @@ enum peck_ei_behavior { PECK_EI_BEHAVIOR_HANDLE_ADDED_POINTER, PECK_EI_BEHAVIOR_HANDLE_ADDED_KEYBOARD, PECK_EI_BEHAVIOR_HANDLE_ADDED_TOUCH, + + PECK_EI_BEHAVIOR_HANDLE_RESUMED, + PECK_EI_BEHAVIOR_HANDLE_SUSPENDED, }; struct peck; diff --git a/test/test-ei.c b/test/test-ei.c index e4fd67b..096c70d 100644 --- a/test/test-ei.c +++ b/test/test-ei.c @@ -196,6 +196,8 @@ MUNIT_TEST(test_ei_disconnect_after_remove_before_received) with_client(peck) { _cleanup_ei_event_ struct ei_event *added = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); + _cleanup_ei_event_ struct ei_event *resumed = + peck_ei_next_event(ei, EI_EVENT_DEVICE_RESUMED); ei_device_remove(device); } @@ -249,6 +251,8 @@ MUNIT_TEST(test_ei_disconnect_after_remove_after_received) with_client(peck) { _cleanup_ei_event_ struct ei_event *added = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); + _cleanup_ei_event_ struct ei_event *resumed = + peck_ei_next_event(ei, EI_EVENT_DEVICE_RESUMED); ei_device_remove(device); } diff --git a/test/test-eis.c b/test/test-eis.c index 91e3522..98e3e66 100644 --- a/test/test-eis.c +++ b/test/test-eis.c @@ -109,6 +109,147 @@ MUNIT_TEST(eistest_ranges) return MUNIT_OK; } +MUNIT_TEST(eistest_device_resume_suspend_twice) +{ + _cleanup_peck_ struct peck *peck = peck_new(); + _cleanup_eis_device_ struct eis_device *device = NULL; + + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT); + peck_dispatch_until_stable(peck); + + with_client(peck) { + _cleanup_ei_device_ struct ei_device *d = ei_device_new(ei); + ei_device_configure_capability(d, EI_DEVICE_CAP_POINTER); + ei_device_add(d); + } + + peck_dispatch_until_stable(peck); + + with_server(peck) { + _cleanup_eis_event_ struct eis_event *added = + peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED); + + device = eis_device_ref(eis_event_get_device(added)); + + eis_device_connect(device); + /* Resuming multiple times should only trigger one event */ + eis_device_resume(device); + eis_device_resume(device); /* noop */ + eis_device_resume(device); /* noop */ + } + + peck_dispatch_until_stable(peck); + + with_client(peck) { + _cleanup_ei_event_ struct ei_event *added = + peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); + + _cleanup_ei_event_ struct ei_event *resumed = + peck_ei_next_event(ei, EI_EVENT_DEVICE_RESUMED); + + peck_assert_no_ei_events(ei); + } + + /* Suspending multiple times should only trigger one event */ + with_server(peck) { + eis_device_suspend(device); + eis_device_suspend(device); /* noop */ + eis_device_suspend(device); /* noop */ + } + + peck_dispatch_until_stable(peck); + + with_client(peck) { + _cleanup_ei_event_ struct ei_event *suspended = + peck_ei_next_event(ei, EI_EVENT_DEVICE_SUSPENDED); + + peck_assert_no_ei_events(ei); + } + + return MUNIT_OK; +} + +MUNIT_TEST(eistest_device_ignore_suspended) +{ + _cleanup_peck_ struct peck *peck = peck_new(); + _cleanup_eis_device_ struct eis_device *device = NULL; + + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT); + peck_dispatch_until_stable(peck); + + with_client(peck) { + _cleanup_ei_device_ struct ei_device *d = ei_device_new(ei); + ei_device_configure_capability(d, EI_DEVICE_CAP_POINTER); + ei_device_add(d); + } + + peck_dispatch_until_stable(peck); + + with_server(peck) { + _cleanup_eis_event_ struct eis_event *added = + peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED); + + device = eis_device_ref(eis_event_get_device(added)); + + eis_device_connect(device); + } + + peck_dispatch_until_stable(peck); + + with_client(peck) { + _cleanup_ei_event_ struct ei_event *added = + peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); + struct ei_device *device = ei_event_get_device(added); + + peck_assert_no_ei_events(ei); + ei_device_pointer_motion(device, 1, 1); + } + + for (size_t i = 0; i < 3; i++) { + /* Device is suspended */ + with_server(peck) { + peck_assert_no_eis_events(eis); + eis_device_resume(device); + } + + peck_dispatch_until_stable(peck); + + /* Device is resumed */ + with_client(peck) { + _cleanup_ei_event_ struct ei_event *resumed = + peck_ei_next_event(ei, EI_EVENT_DEVICE_RESUMED); + struct ei_device *device = ei_event_get_device(resumed); + + peck_assert_no_ei_events(ei); + ei_device_pointer_motion(device, 1, 1); + } + + peck_dispatch_until_stable(peck); + + /* Device is resumed */ + with_server(peck) { + _cleanup_eis_event_ struct eis_event *rel = + peck_eis_next_event(eis, EIS_EVENT_POINTER_MOTION); + peck_assert_no_eis_events(eis); + eis_device_suspend(device); + } + + peck_dispatch_until_stable(peck); + + /* Device is suspended */ + with_client(peck) { + _cleanup_ei_event_ struct ei_event *suspended = + peck_ei_next_event(ei, EI_EVENT_DEVICE_SUSPENDED); + struct ei_device *device = ei_event_get_device(suspended); + + peck_assert_no_ei_events(ei); + ei_device_pointer_motion(device, 1, 1); + } + } + + return MUNIT_OK; +} + int main(int argc, char **argv) { diff --git a/tools/ei-socket-client.c b/tools/ei-socket-client.c index 3173e7e..bef9504 100644 --- a/tools/ei-socket-client.c +++ b/tools/ei-socket-client.c @@ -91,14 +91,22 @@ int main(int argc, char **argv) break; } case EI_EVENT_DEVICE_ADDED: - { - printf("client: our device was accepted\n"); + printf("client: our device was accepted, waiting for resume\n"); + break; + case EI_EVENT_DEVICE_RESUMED: + printf("client: our device was resumed\n"); if (ei_event_get_device(e) == ptr) have_ptr = true; if (ei_event_get_device(e) == kbd) have_kbd = true; break; - } + case EI_EVENT_DEVICE_SUSPENDED: + printf("client: our device was suspended\n"); + if (ei_event_get_device(e) == ptr) + have_ptr = false; + if (ei_event_get_device(e) == kbd) + have_kbd = false; + break; case EI_EVENT_DEVICE_REMOVED: { printf("client: our device was removed\n"); diff --git a/tools/eis-socket-server.c b/tools/eis-socket-server.c index fcbb355..4964bef 100644 --- a/tools/eis-socket-server.c +++ b/tools/eis-socket-server.c @@ -117,6 +117,7 @@ int main(int argc, char **argv) eis_device_has_capability(device, EIS_DEVICE_CAP_TOUCH) ? " touch" : ""); /* insert sophisticated device checks here */ eis_device_connect(device); + eis_device_resume(device); break; } case EIS_EVENT_DEVICE_REMOVED: