blob: e010c6ff0e1c0d2f8717b013fbb7e32bc9aa7ed0 [file] [log] [blame]
/* 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];
}