| /* Copyright (C) 2007-2008 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. |
| */ |
| |
| /* this file implements the support of the new 'hardware control' |
| * qemud communication channel, which is used by libs/hardware on |
| * the system image to communicate with the emulator program for |
| * emulating the following: |
| * |
| * - power management |
| * - led(s) brightness |
| * - vibrator |
| * - flashlight |
| */ |
| #include "android/hw-control.h" |
| #include "cbuffer.h" |
| #include "android/hw-qemud.h" |
| #include "android/globals.h" |
| #include "android/utils/misc.h" |
| #include "android/utils/debug.h" |
| #include "qemu-char.h" |
| #include <stdio.h> |
| #include <string.h> |
| |
| #define D(...) VERBOSE_PRINT(hw_control,__VA_ARGS__) |
| |
| /* define T_ACTIVE to 1 to debug transport communications */ |
| #define T_ACTIVE 0 |
| |
| #if T_ACTIVE |
| #define T(...) VERBOSE_PRINT(hw_control,__VA_ARGS__) |
| #else |
| #define T(...) ((void)0) |
| #endif |
| |
| typedef struct { |
| void* client; |
| AndroidHwControlFuncs client_funcs; |
| QemudService* service; |
| } HwControl; |
| |
| /* handle query */ |
| static void hw_control_do_query( HwControl* h, uint8_t* query, int querylen ); |
| |
| /* called when a qemud client sends a command */ |
| static void |
| _hw_control_qemud_client_recv( void* opaque, |
| uint8_t* msg, |
| int msglen, |
| QemudClient* client ) |
| { |
| hw_control_do_query(opaque, msg, msglen); |
| } |
| |
| /* called when a qemud client connects to the service */ |
| static QemudClient* |
| _hw_control_qemud_connect( void* opaque, |
| QemudService* service, |
| int channel, |
| const char* client_param ) |
| { |
| QemudClient* client; |
| |
| client = qemud_client_new( service, channel, client_param, |
| opaque, |
| _hw_control_qemud_client_recv, |
| NULL, NULL, NULL ); |
| |
| qemud_client_set_framing(client, 1); |
| return client; |
| } |
| |
| |
| static uint8_t* |
| if_starts_with( uint8_t* buf, int buflen, const char* prefix ) |
| { |
| int prefixlen = strlen(prefix); |
| |
| if (buflen < prefixlen || memcmp(buf, prefix, prefixlen)) |
| return NULL; |
| |
| return (uint8_t*)buf + prefixlen; |
| } |
| |
| |
| static void |
| hw_control_do_query( HwControl* h, |
| uint8_t* query, |
| int querylen ) |
| { |
| uint8_t* q; |
| |
| T("%s: query %4d '%.*s'", __FUNCTION__, querylen, querylen, query ); |
| |
| q = if_starts_with( query, querylen, "power:light:brightness:" ); |
| if (q != NULL) { |
| if (h->client_funcs.light_brightness && android_hw->hw_lcd_backlight) { |
| char* qq = strchr((const char*)q, ':'); |
| int value; |
| if (qq == NULL) { |
| D("%s: badly formatted", __FUNCTION__ ); |
| return; |
| } |
| *qq++ = 0; |
| value = atoi(qq); |
| h->client_funcs.light_brightness( h->client, (char*)q, value ); |
| } |
| return; |
| } |
| } |
| |
| |
| static void |
| hw_control_init( HwControl* control, |
| void* client, |
| const AndroidHwControlFuncs* client_funcs ) |
| { |
| control->client = client; |
| control->client_funcs = client_funcs[0]; |
| control->service = qemud_service_register( "hw-control", 0, |
| control, |
| _hw_control_qemud_connect, |
| NULL, NULL); |
| } |
| |
| const AndroidHwControlFuncs defaultControls = { |
| NULL, |
| }; |
| |
| static HwControl hwstate[1]; |
| |
| void |
| android_hw_control_init( void ) |
| { |
| hw_control_init(hwstate, NULL, &defaultControls); |
| D("%s: hw-control qemud handler initialized", __FUNCTION__); |
| } |
| |
| void |
| android_hw_control_set( void* opaque, const AndroidHwControlFuncs* funcs ) |
| { |
| hwstate->client = opaque; |
| hwstate->client_funcs = funcs[0]; |
| } |
| |