• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2007 The Android Open Source Project
3  *
4  * Magic entries in /sys/class/power_supply/.
5  */
6 #include "Common.h"
7 
8 #include <stdlib.h>
9 #include <string.h>
10 #include <ctype.h>
11 
12 #include <fcntl.h>
13 #include <sys/ioctl.h>
14 
15 /*
16  * Map filename to device index.
17  *
18  * [ not using DeviceIndex -- would be useful if we need to return something
19  * other than a static string ]
20  */
21 static const struct {
22     const char*     name;
23     //DeviceIndex     idx;
24     const char*     data;
25 } gDeviceMap[] = {
26     { "ac/online",
27         "0\n" },
28 
29     { "battery/batt_temp",
30         "281\n", },
31     { "battery/batt_vol",
32         "4170\n" },
33     { "battery/capacity",
34         "100\n" },
35     { "battery/health",
36         "Good\n" },
37     { "battery/present",
38         "0\n" },
39     { "battery/status",
40         "Full" },
41     { "battery/technology",
42         "Li-ion\n" },
43 
44     { "usb/online",
45         "1\n" },
46 };
47 
48 /*
49  * Power driver state.
50  *
51  * Right now we just ignore everything written.
52  */
53 typedef struct PowerState {
54     int         which;
55 } PowerState;
56 
57 
58 /*
59  * Figure out who we are, based on "pathName".
60  */
configureInitialState(const char * pathName,PowerState * powerState)61 static void configureInitialState(const char* pathName, PowerState* powerState)
62 {
63     const char* cp = pathName + strlen("/sys/class/power_supply/");
64     int i;
65 
66     powerState->which = -1;
67     for (i = 0; i < (int) (sizeof(gDeviceMap) / sizeof(gDeviceMap[0])); i++) {
68         if (strcmp(cp, gDeviceMap[i].name) == 0) {
69             powerState->which = i;
70             break;
71         }
72     }
73 
74     if (powerState->which == -1) {
75         wsLog("Warning: access to unknown power device '%s'\n", pathName);
76         return;
77     }
78 }
79 
80 /*
81  * Free up the state structure.
82  */
freeState(PowerState * powerState)83 static void freeState(PowerState* powerState)
84 {
85     free(powerState);
86 }
87 
88 /*
89  * Read data from the device.
90  *
91  * We don't try to keep track of how much was read -- existing clients just
92  * try to read into a large buffer.
93  */
readPower(FakeDev * dev,int fd,void * buf,size_t count)94 static ssize_t readPower(FakeDev* dev, int fd, void* buf, size_t count)
95 {
96     PowerState* state = (PowerState*) dev->state;
97     int dataLen;
98 
99     wsLog("%s: read %d\n", dev->debugName, count);
100 
101     if (state->which < 0 ||
102         state->which >= (int) (sizeof(gDeviceMap)/sizeof(gDeviceMap[0])))
103     {
104         return 0;
105     }
106 
107     const char* data = gDeviceMap[state->which].data;
108     size_t strLen = strlen(data);
109 
110     while(strLen == 0)
111         sleep(10); // block forever
112 
113     ssize_t copyCount = (strLen < count) ? strLen : count;
114     memcpy(buf, data, copyCount);
115     return copyCount;
116 }
117 
118 /*
119  * Ignore the request.
120  */
writePower(FakeDev * dev,int fd,const void * buf,size_t count)121 static ssize_t writePower(FakeDev* dev, int fd, const void* buf, size_t count)
122 {
123     wsLog("%s: write %d bytes\n", dev->debugName, count);
124     return count;
125 }
126 
127 /*
128  * Our Java classes want to be able to do ioctl(FIONREAD) on files.  The
129  * battery power manager is blowing up if we get an error other than
130  * ENOTTY (meaning a device that doesn't understand buffering).
131  */
ioctlPower(FakeDev * dev,int fd,int request,void * argp)132 static int ioctlPower(FakeDev* dev, int fd, int request, void* argp)
133 {
134     if (request == FIONREAD) {
135         wsLog("%s: ioctl(FIONREAD, %p)\n", dev->debugName, argp);
136         errno = ENOTTY;
137         return -1;
138     } else {
139         wsLog("%s: ioctl(0x%08x, %p) ??\n", dev->debugName, request, argp);
140         errno = EINVAL;
141         return -1;
142     }
143 }
144 
145 /*
146  * Free up our state before closing down the fake descriptor.
147  */
closePower(FakeDev * dev,int fd)148 static int closePower(FakeDev* dev, int fd)
149 {
150     freeState((PowerState*)dev->state);
151     dev->state = NULL;
152     return 0;
153 }
154 
155 /*
156  * Open a power device.
157  */
wsOpenDevPower(const char * pathName,int flags)158 FakeDev* wsOpenDevPower(const char* pathName, int flags)
159 {
160     FakeDev* newDev = wsCreateFakeDev(pathName);
161     if (newDev != NULL) {
162         newDev->read = readPower;
163         newDev->write = writePower;
164         newDev->ioctl = ioctlPower;
165         newDev->close = closePower;
166 
167         PowerState* powerState = calloc(1, sizeof(PowerState));
168 
169         configureInitialState(pathName, powerState);
170         newDev->state = powerState;
171     }
172 
173     return newDev;
174 }
175 
176