Refactored user-events protocol

Change-Id: I08afb96ef17a52c3795f5029acfc244a93ab57c7
diff --git a/android/protocol/user-events-proxy.c b/android/protocol/user-events-proxy.c
new file mode 100644
index 0000000..d35012f
--- /dev/null
+++ b/android/protocol/user-events-proxy.c
@@ -0,0 +1,180 @@
+/* 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 "console.h"
+#include "android/looper.h"
+#include "android/async-utils.h"
+#include "android/core-connection.h"
+#include "android/utils/debug.h"
+#include "android/protocol/user-events-protocol.h"
+#include "android/protocol/user-events-proxy.h"
+
+/* Descriptor for the user events client. */
+typedef struct UserEventsProxy {
+    /* Core connection instance for the user events client. */
+    CoreConnection* core_connection;
+
+    /* Socket for the client. */
+    int             sock;
+
+    /* Writes user events to the socket. */
+    SyncSocket*     sync_writer;
+} UserEventsProxy;
+
+/* One and only one user events client instance. */
+static UserEventsProxy _userEventsProxy = { 0 };
+
+/* Destroys CoreCmdProxy instance. */
+static void
+_userEventsProxy_destroy(void)
+{
+    if (_userEventsProxy.sync_writer != NULL) {
+        syncsocket_close(_userEventsProxy.sync_writer);
+        syncsocket_free(_userEventsProxy.sync_writer);
+        _userEventsProxy.sync_writer = NULL;
+    }
+    if (_userEventsProxy.core_connection != NULL) {
+        core_connection_close(_userEventsProxy.core_connection);
+        core_connection_free(_userEventsProxy.core_connection);
+        _userEventsProxy.core_connection = NULL;
+    }
+}
+
+/* Sends an event to the core.
+ * Parameters:
+ *  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
+_userEventsProxy_send(uint8_t event, const void* event_param, size_t size)
+{
+    int res;
+    UserEventHeader header;
+
+    header.event_type = event;
+    res = syncsocket_start_write(_userEventsProxy.sync_writer);
+    if (!res) {
+        // Send event type first (event header)
+        res = syncsocket_write(_userEventsProxy.sync_writer, &header,
+                               sizeof(header),
+                               core_connection_get_timeout(sizeof(header)));
+        if (res > 0) {
+            // Send event param next.
+            res = syncsocket_write(_userEventsProxy.sync_writer, event_param,
+                                   size,
+                                   core_connection_get_timeout(sizeof(size)));
+        }
+        res = syncsocket_result(res);
+        syncsocket_stop_write(_userEventsProxy.sync_writer);
+    }
+    if (res < 0) {
+        derror("Unable to send user event: %s\n", errno_str);
+    }
+    return res;
+}
+
+int
+userEventsProxy_create(SockAddress* console_socket)
+{
+    char* handshake = NULL;
+
+    // Connect to the user-events service.
+    _userEventsProxy.core_connection =
+        core_connection_create_and_switch(console_socket, "user-events",
+                                          &handshake);
+    if (_userEventsProxy.core_connection == NULL) {
+        derror("Unable to connect to the user-events service: %s\n",
+               errno_str);
+        return -1;
+    }
+
+    // Initialze event writer.
+    _userEventsProxy.sock =
+        core_connection_get_socket(_userEventsProxy.core_connection);
+    _userEventsProxy.sync_writer = syncsocket_init(_userEventsProxy.sock);
+    if (_userEventsProxy.sync_writer == NULL) {
+        derror("Unable to initialize UserEventsProxy writer: %s\n", errno_str);
+        _userEventsProxy_destroy();
+        return -1;
+    }
+
+    fprintf(stdout, "user-events is now connected to the core at %s.",
+            sock_address_to_string(console_socket));
+    if (handshake != NULL) {
+        if (handshake[0] != '\0') {
+            fprintf(stdout, " Handshake: %s", handshake);
+        }
+        free(handshake);
+    }
+    fprintf(stdout, "\n");
+
+    return 0;
+}
+
+void
+user_event_keycodes(int *kcodes, int count)
+{
+    int nn;
+    for (nn = 0; nn < count; nn++)
+        user_event_keycode(kcodes[nn]);
+}
+
+void
+user_event_keycode(int  kcode)
+{
+    UserEventKeycode    message;
+    message.keycode = kcode;
+    _userEventsProxy_send(AUSER_EVENT_KEYCODE, &message, sizeof(message));
+}
+
+void
+user_event_key(unsigned code, unsigned down)
+{
+    if(code == 0) {
+        return;
+    }
+    if (VERBOSE_CHECK(keys))
+        printf(">> KEY [0x%03x,%s]\n", (code & 0x1ff), down ? "down" : " up " );
+
+    user_event_keycode((code & 0x1ff) | (down ? 0x200 : 0));
+}
+
+
+void
+user_event_mouse(int dx, int dy, int dz, unsigned buttons_state)
+{
+    UserEventMouse    message;
+    message.dx = dx;
+    message.dy = dy;
+    message.dz = dz;
+    message.buttons_state = buttons_state;
+    _userEventsProxy_send(AUSER_EVENT_MOUSE, &message, sizeof(message));
+}
+
+void
+user_event_register_generic(void* opaque, QEMUPutGenericEvent *callback)
+{
+}
+
+void
+user_event_generic(int type, int code, int value)
+{
+    UserEventGeneric    message;
+    message.type = type;
+    message.code = code;
+    message.value = value;
+    _userEventsProxy_send(AUSER_EVENT_GENERIC, &message, sizeof(message));
+}