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: