|  | /* | 
|  | * 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; | 
|  | } | 
|  |  |