aboutsummaryrefslogtreecommitdiffstats
path: root/android
diff options
context:
space:
mode:
authorVladimir Chtchetkine <vchtchetkine@google.com>2011-01-19 18:29:27 -0800
committerVladimir Chtchetkine <vchtchetkine@google.com>2011-01-19 18:29:27 -0800
commit9411a562e1ab772732a4d5147c9103a638837c82 (patch)
treebf11eddce29c02b4376bc0cb76e5f9233791cf39 /android
parenta9edc435e6592fcc001e21e150391a84bde114a6 (diff)
downloadexternal_qemu-9411a562e1ab772732a4d5147c9103a638837c82.zip
external_qemu-9411a562e1ab772732a4d5147c9103a638837c82.tar.gz
external_qemu-9411a562e1ab772732a4d5147c9103a638837c82.tar.bz2
Implement user event transmission between the UI and the core
Change-Id: I503aa691cada5250b76167a923d4a226d20ee41d
Diffstat (limited to 'android')
-rw-r--r--android/console.c42
-rw-r--r--android/framebuffer-core.c4
-rw-r--r--android/main-ui.c7
-rw-r--r--android/sync-utils.c18
-rw-r--r--android/sync-utils.h11
-rw-r--r--android/user-events-common.h57
-rw-r--r--android/user-events-core.c172
-rw-r--r--android/user-events-core.h37
8 files changed, 342 insertions, 6 deletions
diff --git a/android/console.c b/android/console.c
index 96cc005..6f9e26b 100644
--- a/android/console.c
+++ b/android/console.c
@@ -53,6 +53,7 @@
#include "android/core-ui-protocol.h"
#include "android/display-core.h"
#include "android/framebuffer-core.h"
+#include "android/user-events-core.h"
#if defined(CONFIG_SLIRP)
#include "libslirp.h"
@@ -119,6 +120,12 @@ ControlClient attached_ui_client = NULL;
/* Core framebuffer service client. */
ControlClient framebuffer_client = NULL;
+
+/* User events service client. */
+ControlClient user_events_client = NULL;
+
+/* User events service. */
+CoreUserEvents* core_ue = NULL;
#endif // CONFIG_STANDALONE_CORE
/* -android-avdname option value. Defined in vl-android.c */
@@ -236,6 +243,11 @@ control_client_destroy( ControlClient client )
}
framebuffer_client = NULL;
}
+
+ if (client == user_events_client) {
+ coreue_destroy(core_ue);
+ user_events_client = NULL;
+ }
#endif // CONFIG_STANDALONE_CORE
sock = control_client_detach( client );
@@ -2537,6 +2549,32 @@ do_create_framebuffer_service( ControlClient client, char* args )
return 0;
}
+
+static int
+do_create_user_events_service( ControlClient client, char* args )
+{
+ // Make sure that there are no framebuffer client already existing.
+ if (user_events_client != NULL) {
+ control_write( client, "KO: Another user events service is already existing!\r\n" );
+ control_client_destroy(client);
+ return -1;
+ }
+
+ core_ue = coreue_create(client->sock);
+ if (core_ue != NULL) {
+ char reply_buf[4096];
+ user_events_client = client;
+ // Reply "OK" with the framebuffer's bits per pixel
+ snprintf(reply_buf, sizeof(reply_buf), "OK\r\n");
+ control_write( client, reply_buf);
+ } else {
+ control_write( client, "KO\r\n" );
+ control_client_destroy(client);
+ return -1;
+ }
+
+ return 0;
+}
#endif // CONFIG_STANDALONE_CORE
static const CommandDefRec qemu_commands[] =
@@ -2553,6 +2591,10 @@ static const CommandDefRec qemu_commands[] =
{ "framebuffer", "create framebuffer service",
"Create framebuffer service\r\n",
NULL, do_create_framebuffer_service, NULL },
+
+ { "user events", "create user events service",
+ "Create user events service\r\n",
+ NULL, do_create_user_events_service, NULL },
#endif // CONFIG_STANDALONE_CORE
{ NULL, NULL, NULL, NULL, NULL, NULL }
diff --git a/android/framebuffer-core.c b/android/framebuffer-core.c
index f4f53a7..978bfc0 100644
--- a/android/framebuffer-core.c
+++ b/android/framebuffer-core.c
@@ -229,7 +229,6 @@ corefb_update(CoreFramebuffer* core_fb, struct DisplayState* ds,
if (core_fb->fb_update_tail != NULL) {
core_fb->fb_update_tail->next_fb_update = descr;
core_fb->fb_update_tail = descr;
- printf("PENDED\n");
return;
}
@@ -243,16 +242,13 @@ corefb_update(CoreFramebuffer* core_fb, struct DisplayState* ds,
case ASYNC_COMPLETE:
fbupdatenotify_delete(descr);
core_fb->fb_update_head = core_fb->fb_update_tail = NULL;
- printf("COMPLETED\n");
return;
case ASYNC_ERROR:
- printf("FAILED: %s\n", errno_str);
fbupdatenotify_delete(descr);
core_fb->fb_update_head = core_fb->fb_update_tail = NULL;
return;
case ASYNC_NEED_MORE:
// Update transfer will eventually complete in corefb_io_func
- printf("PARTIAL\n");
return;
}
}
diff --git a/android/main-ui.c b/android/main-ui.c
index 7a4d746..4d8560c 100644
--- a/android/main-ui.c
+++ b/android/main-ui.c
@@ -852,6 +852,9 @@ list_running_cores(const char* host)
}
}
+/* Implemented in user-events-ui.c */
+extern int clientue_create(SockAddress* console_socket);
+
/* Attaches starting UI to a running core process.
* This routine is called from main() when -attach-core parameter is set,
* indicating that this UI instance should attach to a running core, rather than
@@ -955,6 +958,10 @@ attach_to_core(AndroidOptions* opts) {
return -1;
}
+ if (clientue_create(&console_socket)) {
+ return -1;
+ }
+
return 0;
}
diff --git a/android/sync-utils.c b/android/sync-utils.c
index c5674b2..32c803c 100644
--- a/android/sync-utils.c
+++ b/android/sync-utils.c
@@ -25,6 +25,7 @@
#include "sockets.h"
#include "android/utils/debug.h"
#include "android/sync-utils.h"
+#include "android/utils/system.h"
#define D(...) do { if (VERBOSE_CHECK(init)) dprint(__VA_ARGS__); } while (0)
@@ -37,11 +38,24 @@ struct SyncSocket {
};
SyncSocket*
+syncsocket_init(int fd)
+{
+ SyncSocket* sync_socket;
+ ANEW0(sync_socket);
+
+ socket_set_nonblock(fd);
+ sync_socket->iolooper = iolooper_new();
+ sync_socket->fd = fd;
+
+ return sync_socket;
+}
+
+SyncSocket*
syncsocket_connect(int fd, SockAddress* sockaddr, int timeout)
{
- IoLooper* looper = NULL;
+ IoLooper* looper;
int connect_status;
- SyncSocket* sync_socket;
+ SyncSocket* sync_socket = NULL;
socket_set_nonblock(fd);
diff --git a/android/sync-utils.h b/android/sync-utils.h
index 726b310..110a143 100644
--- a/android/sync-utils.h
+++ b/android/sync-utils.h
@@ -39,6 +39,17 @@ typedef struct SyncSocket SyncSocket;
SyncSocket* syncsocket_connect(int fd, SockAddress* sockaddr, int timeout);
/*
+ * Initializes a non-blocking socket for further synchronous I/O.
+ * Note: this routine will explicitly call socket_set_nonblock on the fd passed
+ * to this routine.
+ * Param:
+ * fd - File descriptor for the already connected.
+ * Return:
+ * Initialized SyncSocket descriptor on success, or NULL on failure.
+ */
+SyncSocket* syncsocket_init(int fd);
+
+/*
* Closes SyncSocket descriptor obtained from syncsocket_connect routine.
* Param:
* ssocket - SyncSocket descriptor obtained from syncsocket_connect routine.
diff --git a/android/user-events-common.h b/android/user-events-common.h
new file mode 100644
index 0000000..4d02c09
--- /dev/null
+++ b/android/user-events-common.h
@@ -0,0 +1,57 @@
+/* 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.
+*/
+
+#ifndef _ANDROID_USER_EVENTS_COMMON_H
+#define _ANDROID_USER_EVENTS_COMMON_H
+
+#include "globals.h"
+
+/* Mouse event. */
+#define AUSER_EVENT_MOUSE 0
+/* Keycode event. */
+#define AUSER_EVENT_KEYCODE 1
+/* Generic event. */
+#define AUSER_EVENT_GENERIC 2
+
+/* Header for user event message sent from UI to the core. */
+typedef struct UserEventHeader {
+ /* Event type. See AUSER_EVENT_XXX for possible values. */
+ uint8_t event_type;
+} UserEventHeader;
+
+/* Formats mouse event message (AUSER_EVENT_MOUSE) sent from
+ * UI to the core.
+ */
+typedef struct UserEventMouse {
+ int dx;
+ int dy;
+ int dz;
+ unsigned buttons_state;
+} UserEventMouse;
+
+/* Formats keycode event message (AUSER_EVENT_KEYCODE) sent from
+ * UI to the core.
+ */
+typedef struct UserEventKeycode {
+ int keycode;
+} UserEventKeycode;
+
+/* Formats generic event message (AUSER_EVENT_GENERIC) sent from
+ * UI to the core.
+ */
+typedef struct UserEventGeneric {
+ int type;
+ int code;
+ int value;
+} UserEventGeneric;
+
+#endif /* _ANDROID_USER_EVENTS_COMMON_H */
diff --git a/android/user-events-core.c b/android/user-events-core.c
new file mode 100644
index 0000000..a732791
--- /dev/null
+++ b/android/user-events-core.c
@@ -0,0 +1,172 @@
+/* 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.
+*/
+
+#include "user-events.h"
+#include "android/globals.h"
+#include "android/android.h"
+#include "android/looper.h"
+#include "android/async-utils.h"
+#include "android/utils/system.h"
+#include "android/utils/debug.h"
+#include "android/user-events-common.h"
+#include "android/user-events-core.h"
+#include "android/sync-utils.h"
+
+/* States of the core user events service.
+ */
+
+/* Event header is expected in the pipe. */
+#define UE_STATE_EVENT_HEADER 0
+/* Event parameters are expected in the pipe. */
+#define UE_STATE_EVENT_PARAM 1
+
+/* Core user events service descriptor. */
+struct CoreUserEvents {
+ /* 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). */
+ int state;
+
+ /* Current event header. */
+ UserEventHeader event_header;
+
+ /* Current event parameters. */
+ union {
+ UserEventGeneric generic_event;
+ UserEventMouse mouse_event;
+ UserEventKeycode keycode_event;
+ };
+};
+
+
+/*
+ * Asynchronous I/O callback launched when reading user events from the socket.
+ * Param:
+ * opaque - CoreUserEvents instance.
+ */
+static void
+coreue_io_func(void* opaque, int fd, unsigned events)
+{
+ CoreUserEvents* ue = opaque;
+ // Read whatever is expected from the socket.
+ const AsyncStatus status = asyncReader_read(&ue->user_events_reader, &ue->io);
+
+ switch (status) {
+ case ASYNC_COMPLETE:
+ switch (ue->state) {
+ case UE_STATE_EVENT_HEADER:
+ // We just read event header. Now we expect event parameters.
+ ue->state = UE_STATE_EVENT_PARAM;
+ // Setup the reader depending on the event type.
+ switch (ue->event_header.event_type) {
+ case AUSER_EVENT_MOUSE:
+ asyncReader_init(&ue->user_events_reader,
+ &ue->mouse_event,
+ sizeof(ue->mouse_event),
+ &ue->io);
+ break;
+ case AUSER_EVENT_KEYCODE:
+ asyncReader_init(&ue->user_events_reader,
+ &ue->keycode_event,
+ sizeof(ue->keycode_event),
+ &ue->io);
+ break;
+ case AUSER_EVENT_GENERIC:
+ asyncReader_init(&ue->user_events_reader,
+ &ue->generic_event,
+ sizeof(ue->generic_event),
+ &ue->io);
+ break;
+ default:
+ derror("Unexpected event type %d\n",
+ ue->event_header.event_type);
+ break;
+ }
+ break;
+
+ case UE_STATE_EVENT_PARAM:
+ // We just read event parameters. Lets fire the event.
+ switch (ue->event_header.event_type) {
+ case AUSER_EVENT_MOUSE:
+ user_event_mouse(ue->mouse_event.dx,
+ ue->mouse_event.dy,
+ ue->mouse_event.dz,
+ ue->mouse_event.buttons_state);
+ break;
+ case AUSER_EVENT_KEYCODE:
+ user_event_keycode(ue->keycode_event.keycode);
+ break;
+ case AUSER_EVENT_GENERIC:
+ user_event_generic(ue->generic_event.type,
+ ue->generic_event.code,
+ ue->generic_event.value);
+ break;
+ default:
+ derror("Unexpected event type %d\n",
+ ue->event_header.event_type);
+ break;
+ }
+ // Now we expect event header.
+ ue->event_header.event_type = -1;
+ ue->state = UE_STATE_EVENT_HEADER;
+ asyncReader_init(&ue->user_events_reader, &ue->event_header,
+ sizeof(ue->event_header), &ue->io);
+ break;
+ }
+ break;
+ case ASYNC_ERROR:
+ loopIo_dontWantRead(&ue->io);
+ break;
+
+ case ASYNC_NEED_MORE:
+ // Transfer will eventually come back into this routine.
+ return;
+ }
+}
+
+CoreUserEvents*
+coreue_create(int fd)
+{
+ CoreUserEvents* ue;
+ ANEW0(ue);
+ ue->sock = fd;
+ ue->state = UE_STATE_EVENT_HEADER;
+ ue->looper = looper_newCore();
+ loopIo_init(&ue->io, ue->looper, ue->sock, coreue_io_func, ue);
+ asyncReader_init(&ue->user_events_reader, &ue->event_header,
+ sizeof(ue->event_header), &ue->io);
+ return ue;
+}
+
+void
+coreue_destroy(CoreUserEvents* ue)
+{
+ if (ue != NULL) {
+ if (ue->looper != NULL) {
+ // Stop all I/O that may still be going on.
+ loopIo_done(&ue->io);
+ looper_free(ue->looper);
+ ue->looper = NULL;
+ }
+ free(ue);
+ }
+}
diff --git a/android/user-events-core.h b/android/user-events-core.h
new file mode 100644
index 0000000..04bab6c
--- /dev/null
+++ b/android/user-events-core.h
@@ -0,0 +1,37 @@
+/* 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 recepient of user events sent from the UI.
+ */
+
+#ifndef _ANDROID_USER_EVENTS_CORE_H
+#define _ANDROID_USER_EVENTS_CORE_H
+
+/* Descriptor for a core user events instance */
+typedef struct CoreUserEvents CoreUserEvents;
+
+/*
+ * Creates and initializes core user events instance.
+ * Param:
+ * fd - Socket descriptor for the service.
+ */
+extern CoreUserEvents* coreue_create(int fd);
+
+/*
+ * Destroys core user events service.
+ * Param:
+ * ue - User event service descriptor to destroy.
+ */
+extern void coreue_destroy(CoreUserEvents* ue);
+
+#endif /* _ANDROID_USER_EVENTS_CORE_H */