68
64
static int slave_addr[512];
69
65
static int (*open_libc)(const char *, int, mode_t);
70
66
static int (*close_libc)(int);
71
static int (*ioctl_libc)(int, int, ...);
67
static int (*ioctl_libc)(int, int, void *);
73
69
__attribute__((constructor)) static void init() {
76
fprintf(stderr, "libbqioctl: init\n");
79
file = fopen("/sys/class/power_supply/bq27200-0/uevent", "r");
83
fprintf(stderr, "libbqioctl: /sys/class/power_supply/bq27200-0/uevent: cannot open file: %s\n", strerror(errno));
84
fprintf(stderr, "libbqioctl: is kernel module bq27x00_battery loaded?\n");
80
91
handle = dlopen("libc.so.6", RTLD_LOCAL | RTLD_LAZY);
84
fprintf(stderr, "%s\n", dlerror());
95
fprintf(stderr, "libbqioctl: %s\n", dlerror());
85
96
exit(EXIT_FAILURE);
91
//*(void **) (&open_libc) = dlsym(handle, "open");
92
102
open_libc = dlsym(handle, "open");
94
if ( ( error = dlerror() ) != NULL ) {
104
if ( ( error = dlerror() ) || ! open_libc ) {
96
fprintf(stderr, "%s\n", dlerror());
106
fprintf(stderr, "libbqioctl: %s\n", error);
97
107
exit(EXIT_FAILURE);
101
//*(void **) (&close_libc) = dlsym(handle, "close");
102
111
close_libc = dlsym(handle, "close");
104
if ( ( error = dlerror() ) != NULL ) {
113
if ( ( error = dlerror() ) || ! close_libc ) {
106
fprintf(stderr, "%s\n", dlerror());
115
fprintf(stderr, "libbqioctl: %s\n", error);
107
116
exit(EXIT_FAILURE);
111
//*(void **) (&ioctl_libc) = dlsym(handle, "ioctl");
112
120
ioctl_libc = dlsym(handle, "ioctl");
114
if ( ( error = dlerror() ) != NULL ) {
122
if ( ( error = dlerror() ) || ! ioctl_libc ) {
116
fprintf(stderr, "%s\n", dlerror());
124
fprintf(stderr, "libbqioctl: %s\n", error);
117
125
exit(EXIT_FAILURE);
125
133
int open(const char * pathname, int flags, mode_t mode) {
127
printf("open: %s %d\n", pathname, flags);
129
int ret = open_libc(pathname, flags, mode);
131
if ( strcmp(pathname, "/dev/i2c-2") == 0 && ret >= 0 && ret < (int)sizeof(slave_addr) )
138
fprintf(stderr, "libbqioctl: open(\"%s\", %d, 0x%x)\n", pathname, flags, mode);
141
ret = open_libc(pathname, flags, mode);
143
if ( strcmp(pathname, "/dev/i2c-2") == 0 && ret >= 0 && ret < (int)sizeof(slave_addr) ) {
146
fprintf(stderr, "libbqioctl: register slave address for fd %d\n", ret);
132
149
slave_addr[ret] = 0;
138
157
int close(int fd) {
140
printf("close: %d\n", fd);
142
int ret = close_libc(fd);
144
if ( ret == 0 && fd >= 0 && fd <= (int)sizeof(slave_addr) && slave_addr[fd] >= 0 )
162
fprintf(stderr, "libbqioctl: close(%d)\n", fd);
165
ret = close_libc(fd);
167
if ( ret == 0 && fd >= 0 && fd <= (int)sizeof(slave_addr) && slave_addr[fd] >= 0 ) {
170
fprintf(stderr, "libbqioctl: unregister slave address for fd %d\n", fd);
145
173
slave_addr[fd] = -1;
174
207
if ( reg == 0x06 ) // TEMP
175
208
return ( bq_read_value("/sys/class/power_supply/bq27200-0/temp", ok) * 2 + 5463 ) / 5;
176
209
else if ( reg == 0x08 ) // VOLT
177
return bq_read_value("/sys/class/power_supply/bq27200-0/voltage_now", ok);
210
return bq_read_value("/sys/class/power_supply/bq27200-0/voltage_now", ok) / 1000;
178
211
else if ( reg == 0x14 ) // AI
179
return bq_read_value("/sys/class/power_supply/bq27200-0/current_now", ok);
212
return bq_read_value("/sys/class/power_supply/bq27200-0/current_now", ok) * 20 / 3570;
180
213
else if ( reg == 0x0A ) // FLAGS
182
215
else if ( reg == 0x16 ) // TTE
183
return bq_read_value("/sys/class/power_supply/bq27200-0/time_to_empty_now", ok);
216
return bq_read_value("/sys/class/power_supply/bq27200-0/time_to_empty_now", ok) / 60;
217
else if ( reg == 0x26 ) // TTECP
218
return bq_read_value("/sys/class/power_supply/bq27200-0/time_to_empty_avg", ok) / 60;
219
else if ( reg == 0x18 ) // TTF
220
return bq_read_value("/sys/class/power_supply/bq27200-0/time_to_full_now", ok) / 60;
221
else if ( reg == 0x0C ) // NAC
223
else if ( reg == 0x12 ) // LMD
225
else if ( reg == 0x2A ) // CYCT
227
else if ( reg == 0x22 ) // AE
229
else if ( reg == 0x0B ) // RSOC
231
else if ( reg == 0x76 ) // ILMD
189
int ioctl(int fd, int request, ...) {
238
int ioctl(int fd, int request, void * arg) {
191
printf("ioclt: %d %d\n", fd, request);
241
fprintf(stderr, "libbqioctl: ioclt(%d, 0x%x, %p)\n", fd, request, arg);
193
244
if ( fd >= 0 && fd <= (int)sizeof(slave_addr) && slave_addr[fd] >= 0 ) {
246
printf("request=0x%x I2C_SLAVE=0x%x I2C_SMBUS=0x%x\n", request, I2C_SLAVE, I2C_SMBUS);
195
248
if ( request == I2C_SLAVE ) {
197
slave_addr[fd] = *(&request + 1);
250
slave_addr[fd] = *((int *)(&arg));
253
fprintf(stderr, "libbqioctl: change slave address for fd %d to 0x%x\n", fd, slave_addr[fd]);
199
256
if ( slave_addr[fd] == 0x55 )
202
259
} else if ( request == I2C_SMBUS && slave_addr[fd] == 0x55 ) {
204
struct i2c_smbus_ioctl_data * data = *((void **)(&request + 1));
261
struct i2c_smbus_ioctl_data * data = arg;
206
263
if ( data->read_write == I2C_SMBUS_READ ) {
266
fprintf(stderr, "libbqioctl: read bq register %d\n", data->command);
209
270
int val = bq_read_reg(data->command, &ok);