aboutsummaryrefslogtreecommitdiffstats
path: root/android/protocol/user-events-impl.c
diff options
context:
space:
mode:
Diffstat (limited to 'android/protocol/user-events-impl.c')
-rw-r--r--android/protocol/user-events-impl.c206
1 files changed, 206 insertions, 0 deletions
diff --git a/android/protocol/user-events-impl.c b/android/protocol/user-events-impl.c
new file mode 100644
index 0000000..5c9525e
--- /dev/null
+++ b/android/protocol/user-events-impl.c
@@ -0,0 +1,206 @@
+/* Copyright (C) 2010 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+
+/*
+ * Contains the Core-side of the "user events" service. Here we receive and
+ * handle user events sent from the UI.
+ */
+
+#include "user-events.h"
+#include "android/globals.h"
+#include "android/android.h"
+#include "android/looper.h"
+#include "android/async-utils.h"
+#include "android/sync-utils.h"
+#include "android/utils/system.h"
+#include "android/utils/debug.h"
+#include "android/protocol/user-events-protocol.h"
+#include "android/protocol/user-events-impl.h"
+
+/* Enumerates state values for the event reader in the UserEventsImpl descriptor.
+ */
+typedef enum UserEventsImplState {
+ /* The reader is waiting on event header. */
+ EXPECTS_HEADER,
+
+ /* The reader is waiting on event parameters. */
+ EXPECTS_PARAMETERS,
+} UserEventsImplState;
+
+
+/* Core user events service descriptor. */
+typedef struct UserEventsImpl {
+ /* Reader to receive user events. */
+ AsyncReader user_events_reader;
+
+ /* I/O associated with this descriptor. */
+ LoopIo io;
+
+ /* Looper used to communicate user events. */
+ Looper* looper;
+
+ /* Socket for this service. */
+ int sock;
+
+ /* State of the service (see UE_STATE_XXX for possible values). */
+ UserEventsImplState state;
+
+ /* Current event header. */
+ UserEventHeader event_header;
+
+ /* Current event parameters. */
+ union {
+ UserEventGeneric generic_event;
+ UserEventMouse mouse_event;
+ UserEventKeycode keycode_event;
+ };
+} UserEventsImpl;
+
+/* Implemented in android/console.c */
+extern void destroy_user_events_client(void);
+
+/* One and only one UserEventsImpl instance. */
+static UserEventsImpl _UserEventsImpl;
+
+/* Asynchronous I/O callback reading user events.
+ * Param:
+ * opaque - UserEventsImpl instance.
+ */
+static void
+_userEventsImpl_io_func(void* opaque, int fd, unsigned events)
+{
+ UserEventsImpl* ueimpl;
+ AsyncStatus status;
+
+ if (events & LOOP_IO_WRITE) {
+ // We don't use async writer here, so we don't expect
+ // any write callbacks.
+ derror("Unexpected LOOP_IO_WRITE in _userEventsImpl_io_func\n");
+ return;
+ }
+
+ ueimpl = (UserEventsImpl*)opaque;
+ // Read whatever is expected from the socket.
+ status = asyncReader_read(&ueimpl->user_events_reader, &ueimpl->io);
+
+
+ switch (status) {
+ case ASYNC_COMPLETE:
+ switch (ueimpl->state) {
+ case EXPECTS_HEADER:
+ // We just read event header. Now we expect event parameters.
+ ueimpl->state = EXPECTS_PARAMETERS;
+ // Setup the reader depending on the event type.
+ switch (ueimpl->event_header.event_type) {
+ case AUSER_EVENT_MOUSE:
+ asyncReader_init(&ueimpl->user_events_reader,
+ &ueimpl->mouse_event,
+ sizeof(ueimpl->mouse_event),
+ &ueimpl->io);
+ break;
+
+ case AUSER_EVENT_KEYCODE:
+ asyncReader_init(&ueimpl->user_events_reader,
+ &ueimpl->keycode_event,
+ sizeof(ueimpl->keycode_event),
+ &ueimpl->io);
+ break;
+
+ case AUSER_EVENT_GENERIC:
+ asyncReader_init(&ueimpl->user_events_reader,
+ &ueimpl->generic_event,
+ sizeof(ueimpl->generic_event),
+ &ueimpl->io);
+ break;
+
+ default:
+ derror("Unexpected user event type %d\n",
+ ueimpl->event_header.event_type);
+ break;
+ }
+ break;
+
+ case EXPECTS_PARAMETERS:
+ // We just read event parameters. Lets fire the event.
+ switch (ueimpl->event_header.event_type) {
+ case AUSER_EVENT_MOUSE:
+ user_event_mouse(ueimpl->mouse_event.dx,
+ ueimpl->mouse_event.dy,
+ ueimpl->mouse_event.dz,
+ ueimpl->mouse_event.buttons_state);
+ break;
+
+ case AUSER_EVENT_KEYCODE:
+ user_event_keycode(ueimpl->keycode_event.keycode);
+ break;
+
+ case AUSER_EVENT_GENERIC:
+ user_event_generic(ueimpl->generic_event.type,
+ ueimpl->generic_event.code,
+ ueimpl->generic_event.value);
+ break;
+
+ default:
+ derror("Unexpected user event type %d\n",
+ ueimpl->event_header.event_type);
+ break;
+ }
+ // Prepare to receive the next event header.
+ ueimpl->event_header.event_type = -1;
+ ueimpl->state = EXPECTS_HEADER;
+ asyncReader_init(&ueimpl->user_events_reader,
+ &ueimpl->event_header,
+ sizeof(ueimpl->event_header), &ueimpl->io);
+ break;
+ }
+ break;
+ case ASYNC_ERROR:
+ loopIo_dontWantRead(&ueimpl->io);
+ if (errno == ECONNRESET) {
+ // UI has exited. We need to destroy user event service.
+ destroy_user_events_client();
+ } else {
+ derror("User event read error %d -> %s\n", errno, errno_str);
+ }
+ break;
+
+ case ASYNC_NEED_MORE:
+ // Transfer will eventually come back into this routine.
+ return;
+ }
+}
+
+int
+userEventsImpl_create(int fd)
+{
+ _UserEventsImpl.sock = fd;
+ _UserEventsImpl.event_header.event_type = -1;
+ _UserEventsImpl.state = EXPECTS_HEADER;
+ _UserEventsImpl.looper = looper_newCore();
+ loopIo_init(&_UserEventsImpl.io, _UserEventsImpl.looper, _UserEventsImpl.sock,
+ _userEventsImpl_io_func, &_UserEventsImpl);
+ asyncReader_init(&_UserEventsImpl.user_events_reader,
+ &_UserEventsImpl.event_header,
+ sizeof(_UserEventsImpl.event_header), &_UserEventsImpl.io);
+ return 0;
+}
+
+void
+userEventsImpl_destroy(void)
+{
+ if (_UserEventsImpl.looper != NULL) {
+ // Stop all I/O that may still be going on.
+ loopIo_done(&_UserEventsImpl.io);
+ looper_free(_UserEventsImpl.looper);
+ _UserEventsImpl.looper = NULL;
+ }
+}