| /* |
| * Copyright 2007 The Android Open Source Project |
| * |
| * Magic entries in /sys/class/power_supply/. |
| */ |
| #include "Common.h" |
| |
| #include <stdlib.h> |
| #include <string.h> |
| #include <ctype.h> |
| |
| #include <fcntl.h> |
| #include <sys/ioctl.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[] = { |
| { "ac/online", |
| "0\n" }, |
| |
| { "battery/batt_temp", |
| "281\n", }, |
| { "battery/batt_vol", |
| "4170\n" }, |
| { "battery/capacity", |
| "100\n" }, |
| { "battery/health", |
| "Good\n" }, |
| { "battery/present", |
| "0\n" }, |
| { "battery/status", |
| "Full" }, |
| { "battery/technology", |
| "Li-ion\n" }, |
| |
| { "usb/online", |
| "1\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/class/power_supply/"); |
| 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; |
| } |
| |
| /* |
| * Our Java classes want to be able to do ioctl(FIONREAD) on files. The |
| * battery power manager is blowing up if we get an error other than |
| * ENOTTY (meaning a device that doesn't understand buffering). |
| */ |
| static int ioctlPower(FakeDev* dev, int fd, int request, void* argp) |
| { |
| if (request == FIONREAD) { |
| wsLog("%s: ioctl(FIONREAD, %p)\n", dev->debugName, argp); |
| errno = ENOTTY; |
| return -1; |
| } else { |
| wsLog("%s: ioctl(0x%08x, %p) ??\n", dev->debugName, request, argp); |
| errno = EINVAL; |
| return -1; |
| } |
| } |
| |
| /* |
| * 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* wsOpenDevPower(const char* pathName, int flags) |
| { |
| FakeDev* newDev = wsCreateFakeDev(pathName); |
| if (newDev != NULL) { |
| newDev->read = readPower; |
| newDev->write = writePower; |
| newDev->ioctl = ioctlPower; |
| newDev->close = closePower; |
| |
| PowerState* powerState = calloc(1, sizeof(PowerState)); |
| |
| configureInitialState(pathName, powerState); |
| newDev->state = powerState; |
| } |
| |
| return newDev; |
| } |
| |