blob: 3bd0bee5791f872bb2ef041ad6761cb4a8dc41a2 [file] [log] [blame]
/* 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 "android/user-events.h"
#include "ui/console.h"
#include "android/looper.h"
#include "android/async-utils.h"
#include "android/utils/debug.h"
#include "android/protocol/core-connection.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 };
/* 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
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;
}
}
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));
}