1777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine/* Copyright (C) 2010 The Android Open Source Project
2777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine**
3777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine** This software is licensed under the terms of the GNU General Public
4777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine** License version 2, as published by the Free Software Foundation, and
5777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine** may be copied, distributed, and modified under those terms.
6777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine**
7777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine** This program is distributed in the hope that it will be useful,
8777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine** but WITHOUT ANY WARRANTY; without even the implied warranty of
9777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine** GNU General Public License for more details.
11777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine*/
12777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
13777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine/*
14777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine * Contains the UI-side implementation of the "core-ui-control" service that is
15777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine * part of the UI control protocol. Here we handle UI control commands received
16777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine * from the Core.
17777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine */
18777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
19b6c168bbb6477145e843bb4a2e56e72e6d47822dDavid 'Digit' Turner#include <unistd.h>
20777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine#include "android/looper.h"
21777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine#include "android/async-utils.h"
22777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine#include "android/sync-utils.h"
23777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine#include "android/utils/system.h"
24777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine#include "android/utils/debug.h"
25777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine#include "android/utils/panic.h"
26e993126c6704029cb1c656922a66a32bd09b6089David 'Digit' Turner#include "android/protocol/core-connection.h"
27777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine#include "android/protocol/ui-commands-impl.h"
28777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine#include "android/protocol/ui-commands-api.h"
29777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
30777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine/* Enumerates states for the command reader in UICmdImpl instance. */
31777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkinetypedef enum UICmdImplState {
32777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    /* The reader is waiting on command header. */
33777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    EXPECTS_HEADER,
34777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
35777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    /* The reader is waiting on command parameters. */
36777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    EXPECTS_PARAMETERS,
37777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine} UICmdImplState;
38777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
39777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine/* Descriptor for the UI-side of the "core-ui-control" service. */
40777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkinetypedef struct UICmdImpl {
41777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    /* Core connection established for this service. */
42777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    CoreConnection* core_connection;
43777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
44777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    /* Socket descriptor for the UI service. */
45777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    int             sock;
46777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
47b6c168bbb6477145e843bb4a2e56e72e6d47822dDavid 'Digit' Turner    /* Custom i/o handler */
48b6c168bbb6477145e843bb4a2e56e72e6d47822dDavid 'Digit' Turner    LoopIo          io[1];
49b6c168bbb6477145e843bb4a2e56e72e6d47822dDavid 'Digit' Turner
50777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    /* Command reader state. */
51777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    UICmdImplState  reader_state;
52777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
53777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    /* Incoming command header. */
54777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    UICmdHeader     cmd_header;
55777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
56777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    /* Reader's buffer. This field can point to the cmd_header field of this
57777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine     * structure (when we expect a command header), or to a buffer allocated for
58777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine     * the (when we expect command parameters). */
59777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    uint8_t*        reader_buffer;
60777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
61777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    /* Offset in the reader's buffer where to read next chunk of data. */
62777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    size_t          reader_offset;
63777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
64777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    /* Total number of bytes the reader expects to read. */
65777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    size_t          reader_bytes;
66777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine} UICmdImpl;
67777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
68777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine/* Implemented in android/qemulator.c */
69777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkineextern void android_emulator_set_window_scale(double scale, int is_dpi);
70777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
71777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine/* One and only one UICmdImpl instance. */
72777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkinestatic UICmdImpl  _uiCmdImpl;
73777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
74777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine/* Display brightness change callback. */
75777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkinestatic AndroidHwLightBrightnessCallback _brightness_change_callback = NULL;
76777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkinestatic void* _brightness_change_callback_param = NULL;
77777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
78777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine/* Handles UI control command received from the core.
79777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine * Param:
80777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine *  uicmd - UICmdImpl instance that received the command.
81777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine *  header - UI control command header.
82777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine *  data - Command parameters formatted accordingly to the command type.
83777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine */
84777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkinestatic void
85777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine_uiCmdImpl_handle_command(UICmdImpl* uicmd,
86777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine                          const UICmdHeader* header,
87777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine                          const uint8_t* data)
88777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine{
89777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    switch (header->cmd_type) {
90777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine        case AUICMD_SET_WINDOWS_SCALE:
91777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine        {
92777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            UICmdSetWindowsScale* cmd = (UICmdSetWindowsScale*)data;
93777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            android_emulator_set_window_scale(cmd->scale, cmd->is_dpi);
94777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            break;
95777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine        }
96777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
97777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine        case AUICMD_CHANGE_DISP_BRIGHTNESS:
98777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine        {
99777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            UICmdChangeDispBrightness* cmd = (UICmdChangeDispBrightness*)data;
100777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            if (_brightness_change_callback != NULL) {
101777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine                _brightness_change_callback(_brightness_change_callback_param,
102777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine                                            cmd->light, cmd->brightness);
103777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            }
104777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            break;
105777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine        }
106777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
107777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine        default:
108777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            derror("Unknown command %d is received from the Core\n",
109777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine                   header->cmd_type);
110777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            break;
111777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    }
112777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine}
113777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
114777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine/* Asynchronous I/O callback reading UI control commands.
115777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine * Param:
116777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine *  opaque - UICmdImpl instance.
117777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine */
118777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkinestatic void
119b6c168bbb6477145e843bb4a2e56e72e6d47822dDavid 'Digit' Turner_uiCmdImpl_io_callback(void* opaque, int fd, unsigned events)
120777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine{
121777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    UICmdImpl* uicmd = opaque;
122777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    int status;
123777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
124777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    // Read requests while they are immediately available.
125777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    for (;;) {
126777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine        // Read next chunk of data.
12717ecca637df2f573edc3ecb8246c0e38a5b32465Vladimir Chtchetkine        status = socket_recv(uicmd->sock,
12817ecca637df2f573edc3ecb8246c0e38a5b32465Vladimir Chtchetkine                             uicmd->reader_buffer + uicmd->reader_offset,
12917ecca637df2f573edc3ecb8246c0e38a5b32465Vladimir Chtchetkine                             uicmd->reader_bytes - uicmd->reader_offset);
130777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine        if (status == 0) {
13107db34976ba1dd045a51c4ab2c7f52479cddcc57David 'Digit' Turner            /* Disconnection, meaning that the core process got terminated. */
132777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            fprintf(stderr, "core-ui-control service got disconnected\n");
13385276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine            uiCmdImpl_destroy();
134777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            return;
135777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine        }
136777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine        if (status < 0) {
137777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            if (errno == EINTR) {
138777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine                /* loop on EINTR */
139777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine                continue;
140777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            } else if (errno == EWOULDBLOCK || errno == EAGAIN) {
141777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine                // Chunk is not avalable at this point. Come back later.
142777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine                return;
143777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            }
144777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine        }
145777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
146777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine        uicmd->reader_offset += status;
147777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine        if (uicmd->reader_offset != uicmd->reader_bytes) {
148777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            // There are still some data left in the pipe.
149777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            continue;
150777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine        }
151777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
152777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine        // All expected data has been read. Time to change the state.
153777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine        if (uicmd->reader_state == EXPECTS_HEADER) {
154777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            // Header has been read.
155777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            if (uicmd->cmd_header.cmd_param_size) {
156777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine                // Prepare for the command parameters.
157777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine                uicmd->reader_state = EXPECTS_PARAMETERS;
158777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine                uicmd->reader_offset = 0;
159777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine                uicmd->reader_bytes = uicmd->cmd_header.cmd_param_size;
160777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine                uicmd->reader_buffer = malloc(uicmd->reader_bytes);
161777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine                if (uicmd->reader_buffer == NULL) {
162777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine                    APANIC("Unable to allocate memory for UI command parameters.\n");
163777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine                }
164777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            } else {
165777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine                // This command doesn't have any parameters. Handle it now.
166777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine                _uiCmdImpl_handle_command(uicmd, &uicmd->cmd_header, NULL);
167777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine                // Prepare for the next command header.
168777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine                uicmd->reader_state = EXPECTS_HEADER;
169777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine                uicmd->reader_offset = 0;
170777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine                uicmd->reader_bytes = sizeof(uicmd->cmd_header);
171777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine                uicmd->reader_buffer = (uint8_t*)&uicmd->cmd_header;
172777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            }
173777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine        } else {
174777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            // All command data is in. Handle it.
175777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            _uiCmdImpl_handle_command(uicmd, &uicmd->cmd_header,
176777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine                                      uicmd->reader_buffer);
177777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            // Prepare for the next command header.
178777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            free(uicmd->reader_buffer);
179777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            uicmd->reader_state = EXPECTS_HEADER;
180777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            uicmd->reader_offset = 0;
181777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            uicmd->reader_bytes = sizeof(uicmd->cmd_header);
182777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            uicmd->reader_buffer = (uint8_t*)&uicmd->cmd_header;
183777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine        }
184777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    }
185777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine}
186777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
187777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkineint
188b6c168bbb6477145e843bb4a2e56e72e6d47822dDavid 'Digit' TurneruiCmdImpl_create(SockAddress* console_socket, Looper* looper)
189777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine{
19021cbdd244bfd12e16c034c910e2f667b44143de0David 'Digit' Turner    UICmdImpl* uicmd = &_uiCmdImpl;
191777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    char* handshake = NULL;
192777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
193777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    // Setup command reader.
19421cbdd244bfd12e16c034c910e2f667b44143de0David 'Digit' Turner    uicmd->reader_buffer = (uint8_t*)&uicmd->cmd_header;
19521cbdd244bfd12e16c034c910e2f667b44143de0David 'Digit' Turner    uicmd->reader_state = EXPECTS_HEADER;
19621cbdd244bfd12e16c034c910e2f667b44143de0David 'Digit' Turner    uicmd->reader_offset = 0;
19721cbdd244bfd12e16c034c910e2f667b44143de0David 'Digit' Turner    uicmd->reader_bytes = sizeof(UICmdHeader);
198777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
199777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    // Connect to the core-ui-control service.
20021cbdd244bfd12e16c034c910e2f667b44143de0David 'Digit' Turner    uicmd->core_connection =
201777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine        core_connection_create_and_switch(console_socket, "core-ui-control",
202777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine                                          &handshake);
20321cbdd244bfd12e16c034c910e2f667b44143de0David 'Digit' Turner    if (uicmd->core_connection == NULL) {
204777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine        derror("Unable to connect to the core-ui-control service: %s\n",
205777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine               errno_str);
206777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine        return -1;
207777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    }
208777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
20907db34976ba1dd045a51c4ab2c7f52479cddcc57David 'Digit' Turner    // Initialize UI command reader.
21021cbdd244bfd12e16c034c910e2f667b44143de0David 'Digit' Turner    uicmd->sock = core_connection_get_socket(uicmd->core_connection);
21121cbdd244bfd12e16c034c910e2f667b44143de0David 'Digit' Turner    loopIo_init(uicmd->io, looper, uicmd->sock,
212b6c168bbb6477145e843bb4a2e56e72e6d47822dDavid 'Digit' Turner                _uiCmdImpl_io_callback,
213b6c168bbb6477145e843bb4a2e56e72e6d47822dDavid 'Digit' Turner                &_uiCmdImpl);
21421cbdd244bfd12e16c034c910e2f667b44143de0David 'Digit' Turner    loopIo_wantRead(uicmd->io);
215777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
216777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    fprintf(stdout, "core-ui-control is now connected to the core at %s.",
217777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            sock_address_to_string(console_socket));
218777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    if (handshake != NULL) {
219777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine        if (handshake[0] != '\0') {
220777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine            fprintf(stdout, " Handshake: %s", handshake);
221777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine        }
222777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine        free(handshake);
223777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    }
224777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    fprintf(stdout, "\n");
225777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
226777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    return 0;
227777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine}
228777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
22985276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkinevoid
23085276806ec6ac969d7befa2496c1de59adaaac74Vladimir ChtchetkineuiCmdImpl_destroy(void)
23185276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine{
23221cbdd244bfd12e16c034c910e2f667b44143de0David 'Digit' Turner    UICmdImpl* uicmd = &_uiCmdImpl;
23321cbdd244bfd12e16c034c910e2f667b44143de0David 'Digit' Turner
23421cbdd244bfd12e16c034c910e2f667b44143de0David 'Digit' Turner    if (uicmd->core_connection != NULL) {
23585276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine        // Disable I/O callbacks.
23621cbdd244bfd12e16c034c910e2f667b44143de0David 'Digit' Turner        loopIo_done(uicmd->io);
23721cbdd244bfd12e16c034c910e2f667b44143de0David 'Digit' Turner        core_connection_close(uicmd->core_connection);
23821cbdd244bfd12e16c034c910e2f667b44143de0David 'Digit' Turner        core_connection_free(uicmd->core_connection);
23921cbdd244bfd12e16c034c910e2f667b44143de0David 'Digit' Turner        uicmd->core_connection = NULL;
24085276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    }
24185276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    // Properly deallocate the reader buffer.
24221cbdd244bfd12e16c034c910e2f667b44143de0David 'Digit' Turner    if (uicmd->reader_buffer != NULL &&
24321cbdd244bfd12e16c034c910e2f667b44143de0David 'Digit' Turner        uicmd->reader_buffer != (uint8_t*)&uicmd->cmd_header) {
24421cbdd244bfd12e16c034c910e2f667b44143de0David 'Digit' Turner        free(uicmd->reader_buffer);
24521cbdd244bfd12e16c034c910e2f667b44143de0David 'Digit' Turner        uicmd->reader_buffer = (uint8_t*)&uicmd->cmd_header;
24685276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    }
24785276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine}
24885276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine
249777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkineint
250777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkineuicmd_set_brightness_change_callback(AndroidHwLightBrightnessCallback callback,
251777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine                                     void* opaque)
252777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine{
253777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    _brightness_change_callback = callback;
254777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    _brightness_change_callback_param = opaque;
255777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    return 0;
256777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine}
257