diff options
author | Vladimir Chtchetkine <vchtchetkine@google.com> | 2011-01-26 11:19:19 -0800 |
---|---|---|
committer | Vladimir Chtchetkine <vchtchetkine@google.com> | 2011-01-28 09:14:01 -0800 |
commit | 777eb68eb60cac18f4b62e2e1b14a906875cbe7a (patch) | |
tree | 5850f03e01bb348ad7fc4e92dd08695416650c48 /android/protocol/core-commands-proxy.c | |
parent | 316669d58104cb260e2ffa1848f24547b71af49c (diff) | |
download | external_qemu-777eb68eb60cac18f4b62e2e1b14a906875cbe7a.zip external_qemu-777eb68eb60cac18f4b62e2e1b14a906875cbe7a.tar.gz external_qemu-777eb68eb60cac18f4b62e2e1b14a906875cbe7a.tar.bz2 |
Refactored ui-core-control and core-ui-control protocols
Also cleaned the code up from obsolete ui-core-protocol.* and
core-ui-protocol.*
Change-Id: I194bec669d25b68a10c32b2be50bc9da50c52ebb
Diffstat (limited to 'android/protocol/core-commands-proxy.c')
-rw-r--r-- | android/protocol/core-commands-proxy.c | 374 |
1 files changed, 374 insertions, 0 deletions
diff --git a/android/protocol/core-commands-proxy.c b/android/protocol/core-commands-proxy.c new file mode 100644 index 0000000..6bd3d4e --- /dev/null +++ b/android/protocol/core-commands-proxy.c @@ -0,0 +1,374 @@ +/* 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 UI-side implementation of the "ui-core-control" service that is + * part of the UI control protocol. Here we send UI control commands to the Core. + */ + +#include "console.h" +#include "android/looper.h" +#include "android/core-connection.h" +#include "android/async-utils.h" +#include "android/sync-utils.h" +#include "android/utils/debug.h" +#include "android/utils/panic.h" +#include "android/protocol/core-commands.h" +#include "android/protocol/core-commands-proxy.h" +#include "android/protocol/core-commands-api.h" + +/* Descriptor for the UI-side "ui-core-control" service. */ +typedef struct CoreCmdProxy { + /* Core connection established for this service. */ + CoreConnection* core_connection; + + /* Socket descriptor for the UI service. */ + int sock; + + /* Socket wrapper for sync srites. */ + SyncSocket* sync_writer; + + /* Socket wrapper for sync reads. */ + SyncSocket* sync_reader; +} CoreCmdProxy; + +/* One and only one CoreCmdProxy instance. */ +static CoreCmdProxy _coreCmdProxy = { 0 }; + +/* Sends UI command to the core. + * Param: + * cmd_type, cmd_param, cmd_param_size - Define the command. + * Return: + * 0 On success, or < 0 on failure. + */ +static int +_coreCmdProxy_send_command(uint8_t cmd_type, + void* cmd_param, + uint32_t cmd_param_size) +{ + int status; + UICmdHeader header; + + // Prepare the command header. + header.cmd_type = cmd_type; + header.cmd_param_size = cmd_param_size; + status = syncsocket_start_write(_coreCmdProxy.sync_writer); + if (!status) { + // Send the header. + status = syncsocket_write(_coreCmdProxy.sync_writer, &header, + sizeof(header), + core_connection_get_timeout(sizeof(header))); + // If there is request data, send it too. + if (status > 0 && cmd_param != NULL && cmd_param_size > 0) { + status = syncsocket_write(_coreCmdProxy.sync_writer, cmd_param, + cmd_param_size, + core_connection_get_timeout(cmd_param_size)); + } + status = syncsocket_result(status); + syncsocket_stop_write(_coreCmdProxy.sync_writer); + } + if (status < 0) { + derror("Unable to send UI control command %d (size %u): %s\n", + cmd_type, cmd_param_size, errno_str); + } + return status; +} + +/* Reads UI control command response from the core. + * Param: + * resp - Upon success contains command response header. + * resp_data - Upon success contains allocated reponse data (if any). The caller + * is responsible for deallocating the memory returned here. + * Return: + * 0 on success, or < 0 on failure. + */ +static int +_coreCmdProxy_get_response(UICmdRespHeader* resp, void** resp_data) +{ + int status = syncsocket_start_read(_coreCmdProxy.sync_reader); + if (!status) { + // Read the header. + status = syncsocket_read(_coreCmdProxy.sync_reader, resp, + sizeof(UICmdRespHeader), + core_connection_get_timeout(sizeof(UICmdRespHeader))); + // Read response data (if any). + if (status > 0 && resp->resp_data_size) { + *resp_data = malloc(resp->resp_data_size); + if (*resp_data == NULL) { + APANIC("_coreCmdProxy_get_response is unable to allocate response data buffer.\n"); + } + status = syncsocket_read(_coreCmdProxy.sync_reader, *resp_data, + resp->resp_data_size, + core_connection_get_timeout(resp->resp_data_size)); + } + status = syncsocket_result(status); + syncsocket_stop_read(_coreCmdProxy.sync_reader); + } + if (status < 0) { + derror("Unable to get UI command response from the Core: %s\n", + errno_str); + } + return status; +} + +/* Destroys CoreCmdProxy instance. */ +static void +_coreCmdProxy_destroy(void) +{ + if (_coreCmdProxy.sync_writer != NULL) { + syncsocket_close(_coreCmdProxy.sync_writer); + syncsocket_free(_coreCmdProxy.sync_writer); + } + if (_coreCmdProxy.sync_reader != NULL) { + syncsocket_close(_coreCmdProxy.sync_reader); + syncsocket_free(_coreCmdProxy.sync_reader); + } + if (_coreCmdProxy.core_connection != NULL) { + core_connection_close(_coreCmdProxy.core_connection); + core_connection_free(_coreCmdProxy.core_connection); + _coreCmdProxy.core_connection = NULL; + } +} + +int +corecmd_set_coarse_orientation(AndroidCoarseOrientation orient) +{ + UICmdSetCoarseOrientation cmd; + cmd.orient = orient; + return _coreCmdProxy_send_command(AUICMD_SET_COARSE_ORIENTATION, + &cmd, sizeof(cmd)); +} + +int +corecmd_toggle_network() +{ + return _coreCmdProxy_send_command(AUICMD_TOGGLE_NETWORK, NULL, 0); +} + +int +corecmd_trace_control(int start) +{ + UICmdTraceControl cmd; + cmd.start = start; + return _coreCmdProxy_send_command(AUICMD_TRACE_CONTROL, + &cmd, sizeof(cmd)); +} + +int +corecmd_is_network_disabled() +{ + UICmdRespHeader resp; + void* tmp = NULL; + int status; + + status = _coreCmdProxy_send_command(AUICMD_CHK_NETWORK_DISABLED, NULL, 0); + if (status < 0) { + return status; + } + status = _coreCmdProxy_get_response(&resp, &tmp); + if (status < 0) { + return status; + } + return resp.result; +} + +int +corecmd_get_netspeed(int index, NetworkSpeed** netspeed) +{ + UICmdGetNetSpeed req; + UICmdRespHeader resp; + UICmdGetNetSpeedResp* resp_data = NULL; + int status; + + // Initialize and send the query. + req.index = index; + status = _coreCmdProxy_send_command(AUICMD_GET_NETSPEED, &req, sizeof(req)); + if (status < 0) { + return status; + } + + // Obtain the response from the core. + status = _coreCmdProxy_get_response(&resp, (void**)&resp_data); + if (status < 0) { + return status; + } + if (!resp.result) { + NetworkSpeed* ret; + // Allocate memory for the returning NetworkSpeed instance. + // It includes: NetworkSpeed structure + + // size of zero-terminated "name" and "display" strings saved in + // resp_data. + *netspeed = malloc(sizeof(NetworkSpeed) + 1 + + resp.resp_data_size - sizeof(UICmdGetNetSpeedResp)); + ret = *netspeed; + + // Copy data obtained from the core to the returning NetworkSpeed + // instance. + ret->upload = resp_data->upload; + ret->download = resp_data->download; + ret->name = (char*)ret + sizeof(NetworkSpeed); + strcpy((char*)ret->name, resp_data->name); + ret->display = ret->name + strlen(ret->name) + 1; + strcpy((char*)ret->display, resp_data->name + strlen(resp_data->name) + 1); + } + if (resp_data != NULL) { + free(resp_data); + } + return resp.result; +} + +int +corecmd_get_netdelay(int index, NetworkLatency** netdelay) +{ + UICmdGetNetDelay req; + UICmdRespHeader resp; + UICmdGetNetDelayResp* resp_data = NULL; + int status; + + // Initialize and send the query. + req.index = index; + status = _coreCmdProxy_send_command(AUICMD_GET_NETDELAY, &req, sizeof(req)); + if (status < 0) { + return status; + } + + // Obtain the response from the core. + status = _coreCmdProxy_get_response(&resp, (void**)&resp_data); + if (status < 0) { + return status; + } + if (!resp.result) { + NetworkLatency* ret; + // Allocate memory for the returning NetworkLatency instance. + // It includes: NetworkLatency structure + + // size of zero-terminated "name" and "display" strings saved in + // resp_data. + *netdelay = malloc(sizeof(NetworkLatency) + 1 + + resp.resp_data_size - sizeof(UICmdGetNetDelayResp)); + ret = *netdelay; + + // Copy data obtained from the core to the returning NetworkLatency + // instance. + ret->min_ms = resp_data->min_ms; + ret->max_ms = resp_data->max_ms; + ret->name = (char*)ret + sizeof(NetworkLatency); + strcpy((char*)ret->name, resp_data->name); + ret->display = ret->name + strlen(ret->name) + 1; + strcpy((char*)ret->display, resp_data->name + strlen(resp_data->name) + 1); + } + if (resp_data != NULL) { + free(resp_data); + } + return resp.result; +} + +int +corecmd_get_qemu_path(int type, + const char* filename, + char* path, + size_t path_buf_size) +{ + UICmdRespHeader resp; + char* resp_data = NULL; + int status; + + // Initialize and send the query. + uint32_t cmd_data_size = sizeof(UICmdGetQemuPath) + strlen(filename) + 1; + UICmdGetQemuPath* req = (UICmdGetQemuPath*)malloc(cmd_data_size); + if (req == NULL) { + APANIC("corecmd_get_qemu_path is unable to allocate %u bytes\n", + cmd_data_size); + } + req->type = type; + strcpy(req->filename, filename); + status = _coreCmdProxy_send_command(AUICMD_GET_QEMU_PATH, req, + cmd_data_size); + if (status < 0) { + return status; + } + + // Obtain the response from the core. + status = _coreCmdProxy_get_response(&resp, (void**)&resp_data); + if (status < 0) { + return status; + } + if (!resp.result && resp_data != NULL) { + strncpy(path, resp_data, path_buf_size); + path[path_buf_size - 1] = '\0'; + } + if (resp_data != NULL) { + free(resp_data); + } + return resp.result; +} + +int +corecmd_get_hw_lcd_density(void) +{ + UICmdRespHeader resp; + void* tmp = NULL; + int status; + + status = _coreCmdProxy_send_command(AUICMD_GET_LCD_DENSITY, NULL, 0); + if (status < 0) { + return status; + } + status = _coreCmdProxy_get_response(&resp, &tmp); + if (status < 0) { + return status; + } + return resp.result; +} + +int +coreCmdProxy_create(SockAddress* console_socket) +{ + char* handshake = NULL; + + // Connect to the ui-core-control service. + _coreCmdProxy.core_connection = + core_connection_create_and_switch(console_socket, "ui-core-control", + &handshake); + if (_coreCmdProxy.core_connection == NULL) { + derror("Unable to connect to the ui-core-control service: %s\n", + errno_str); + return -1; + } + + // Initialze command writer and response reader. + _coreCmdProxy.sock = core_connection_get_socket(_coreCmdProxy.core_connection); + _coreCmdProxy.sync_writer = syncsocket_init(_coreCmdProxy.sock); + if (_coreCmdProxy.sync_writer == NULL) { + derror("Unable to initialize CoreCmdProxy writer: %s\n", errno_str); + _coreCmdProxy_destroy(); + return -1; + } + _coreCmdProxy.sync_reader = syncsocket_init(_coreCmdProxy.sock); + if (_coreCmdProxy.sync_reader == NULL) { + derror("Unable to initialize CoreCmdProxy reader: %s\n", errno_str); + _coreCmdProxy_destroy(); + return -1; + } + + + fprintf(stdout, "ui-core-control 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; +} |