/*
* Copyright 2009 The Android Open Source Project
*
* Magic entries in /sys/power/.
*/
#include "Common.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
/*
* Map filename to device index.
*
* [ not using DeviceIndex -- would be useful if we need to return something
* other than a static string ]
*/
static const struct {
const char* name;
//DeviceIndex idx;
const char* data;
} gDeviceMap[] = {
{ "state",
"mem\n" },
{ "wake_lock",
"\n" },
{ "wake_unlock",
"KeyEvents PowerManagerService radio-interface\n" },
};
/*
* Power driver state.
*
* Right now we just ignore everything written.
*/
typedef struct PowerState {
int which;
} PowerState;
/*
* Figure out who we are, based on "pathName".
*/
static void configureInitialState(const char* pathName, PowerState* powerState)
{
const char* cp = pathName + strlen("/sys/power/");
int i;
powerState->which = -1;
for (i = 0; i < (int) (sizeof(gDeviceMap) / sizeof(gDeviceMap[0])); i++) {
if (strcmp(cp, gDeviceMap[i].name) == 0) {
powerState->which = i;
break;
}
}
if (powerState->which == -1) {
wsLog("Warning: access to unknown power device '%s'\n", pathName);
return;
}
}
/*
* Free up the state structure.
*/
static void freeState(PowerState* powerState)
{
free(powerState);
}
/*
* Read data from the device.
*
* We don't try to keep track of how much was read -- existing clients just
* try to read into a large buffer.
*/
static ssize_t readPower(FakeDev* dev, int fd, void* buf, size_t count)
{
PowerState* state = (PowerState*) dev->state;
int dataLen;
wsLog("%s: read %d\n", dev->debugName, count);
if (state->which < 0 ||
state->which >= (int) (sizeof(gDeviceMap)/sizeof(gDeviceMap[0])))
{
return 0;
}
const char* data = gDeviceMap[state->which].data;
size_t strLen = strlen(data);
while(strLen == 0)
sleep(10); // block forever
ssize_t copyCount = (strLen < count) ? strLen : count;
memcpy(buf, data, copyCount);
return copyCount;
}
/*
* Ignore the request.
*/
static ssize_t writePower(FakeDev* dev, int fd, const void* buf, size_t count)
{
wsLog("%s: write %d bytes\n", dev->debugName, count);
return count;
}
/*
* Free up our state before closing down the fake descriptor.
*/
static int closePower(FakeDev* dev, int fd)
{
freeState((PowerState*)dev->state);
dev->state = NULL;
return 0;
}
/*
* Open a power device.
*/
FakeDev* wsOpenSysPower(const char* pathName, int flags)
{
FakeDev* newDev = wsCreateFakeDev(pathName);
if (newDev != NULL) {
newDev->read = readPower;
newDev->write = writePower;
newDev->ioctl = NULL;
newDev->close = closePower;
PowerState* powerState = calloc(1, sizeof(PowerState));
configureInitialState(pathName, powerState);
newDev->state = powerState;
}
return newDev;
}