Implement user event transmission between the UI and the core

Change-Id: I503aa691cada5250b76167a923d4a226d20ee41d
diff --git a/Makefile.android b/Makefile.android
index b502344..b9a6fa5 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -1058,6 +1058,7 @@
               android/looper-generic.c \
               android/display-core.c \
               android/framebuffer-core.c \
+              android/user-events-core.c \
 
 # Add common system libraries
 #
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 @@
 
 /* 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 @@
         }
         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 @@
 
     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 @@
     { "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 @@
     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 @@
         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 @@
     }
 }
 
+/* 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 @@
         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 @@
 };
 
 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 @@
 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 */
diff --git a/user-events-ui.c b/user-events-ui.c
index f295ade..cef3689 100644
--- a/user-events-ui.c
+++ b/user-events-ui.c
@@ -11,9 +11,110 @@
 */
 #include "user-events.h"
 #include "android/utils/debug.h"
+#include "android/user-events-common.h"
 #include "console.h"
 #include <stdio.h>
 
+#include "android/looper.h"
+#include "android/async-utils.h"
+#include "android/core-connection.h"
+
+/* Descriptor for the user events client. */
+typedef struct ClientUserEvents {
+    /* Core connection instance for the user events client. */
+    CoreConnection* core_connection;
+
+    /* Socket for the client. */
+    int             sock;
+
+    /* Socket wrapper for sync I/O. */
+    SyncSocket*     sync_socket;
+} ClientUserEvents;
+
+/* One and only one user events client instance. */
+static ClientUserEvents _client_ue = { 0 };
+
+int
+clientue_create(SockAddress* console_socket)
+{
+    char* connect_message = NULL;
+    char switch_cmd[256];
+
+    // Connect to the framebuffer service.
+    _client_ue.core_connection = core_connection_create(console_socket);
+    if (_client_ue.core_connection == NULL) {
+        derror("User events client is unable to connect to the console: %s\n",
+               errno_str);
+        return -1;
+    }
+    if (core_connection_open(_client_ue.core_connection)) {
+        core_connection_free(_client_ue.core_connection);
+        _client_ue.core_connection = NULL;
+        derror("User events client is unable to open the console: %s\n",
+               errno_str);
+        return -1;
+    }
+    snprintf(switch_cmd, sizeof(switch_cmd), "user events");
+    if (core_connection_switch_stream(_client_ue.core_connection, switch_cmd,
+                                      &connect_message)) {
+        derror("Unable to connect to the user events service: %s\n",
+               connect_message ? connect_message : "");
+        if (connect_message != NULL) {
+            free(connect_message);
+        }
+        core_connection_close(_client_ue.core_connection);
+        core_connection_free(_client_ue.core_connection);
+        _client_ue.core_connection = NULL;
+        return -1;
+    }
+
+    // Now that we're connected lets initialize the descriptor.
+    _client_ue.sock = core_connection_get_socket(_client_ue.core_connection);
+    _client_ue.sync_socket = syncsocket_init(_client_ue.sock);
+    if (connect_message != NULL) {
+        free(connect_message);
+    }
+
+    fprintf(stdout, "User events client is now attached to the core %s\n",
+            sock_address_to_string(console_socket));
+
+    return 0;
+}
+
+/* Sends an event to the core.
+ * Parameters:
+ *  ue - User events client instance.
+ *  event - Event type. Must be one of the AUSER_EVENT_XXX.
+ *  event_param - Event parameters.
+ *  size - Byte size of the event parameters buffer.
+ * Return:
+ *  0 on success, or -1 on failure.
+ */
+static int
+clientue_send(ClientUserEvents* ue,
+              uint8_t event,
+              const void* event_param,
+              size_t size)
+{
+    int res;
+    UserEventHeader header;
+
+    header.event_type = event;
+    syncsocket_start_write(ue->sync_socket);
+    // Send event type first (event header)
+    res = syncsocket_write(ue->sync_socket, &header, sizeof(header), 500);
+    if (res < 0) {
+        return -1;
+    }
+    // Send event param next.
+    res = syncsocket_write(ue->sync_socket, event_param, size, 500);
+    if (res < 0) {
+        return -1;
+    }
+    syncsocket_stop_write(ue->sync_socket);
+    return 0;
+}
+
 void
 user_event_keycodes(int *kcodes, int count)
 {
@@ -25,9 +126,9 @@
 void
 user_event_keycode(int  kcode)
 {
-#if 0 /* TODO */
-    kbd_put_keycode(kcode);
-#endif
+    UserEventKeycode    message;
+    message.keycode = kcode;
+    clientue_send(&_client_ue, AUSER_EVENT_KEYCODE, &message, sizeof(message));
 }
 
 void
@@ -46,29 +147,24 @@
 void
 user_event_mouse(int dx, int dy, int dz, unsigned buttons_state)
 {
-#if 0 /* TODO */
-    kbd_mouse_event(dx, dy, dz, buttons_state);
-#endif
+    UserEventMouse    message;
+    message.dx = dx;
+    message.dy = dy;
+    message.dz = dz;
+    message.buttons_state = buttons_state;
+    clientue_send(&_client_ue, AUSER_EVENT_MOUSE, &message, sizeof(message));
 }
 
-#if 0
-static QEMUPutGenericEvent *generic_event_callback;
-static void*                generic_event_opaque;
-#endif
-
 void  user_event_register_generic(void* opaque, QEMUPutGenericEvent *callback)
 {
-#if 0 /* TODO */
-    generic_event_callback = callback;
-    generic_event_opaque   = opaque;
-#endif
 }
 
 void
 user_event_generic(int type, int code, int value)
 {
-#if 0 /* TODO */
-    if (generic_event_callback)
-        generic_event_callback(generic_event_opaque, type, code, value);
-#endif
+    UserEventGeneric    message;
+    message.type = type;
+    message.code = code;
+    message.value = value;
+    clientue_send(&_client_ue, AUSER_EVENT_GENERIC, &message, sizeof(message));
 }