diff options
Diffstat (limited to 'android/protocol/user-events-impl.c')
-rw-r--r-- | android/protocol/user-events-impl.c | 206 |
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; + } +} |