Skip to content

Instantly share code, notes, and snippets.

@Tasssadar
Created July 16, 2014 14:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Tasssadar/3e2805d7ca4b7a40b00b to your computer and use it in GitHub Desktop.
Save Tasssadar/3e2805d7ca4b7a40b00b to your computer and use it in GitHub Desktop.
Small program for kindle paperwhite 2 which tracks touch events and shows battery percentage on screen when the user double taps on the bottom of the screen.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/input.h>
#include <string.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/poll.h>
#include <sys/time.h>
#include <stdint.h>
#define MAX_DEVICES 10
#define MAX_FINGERS 10
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
enum
{
TCHNG_POS = 0x01,
//TCHNG_PRESSURE = 0x02, // unused
TCHNG_ADDED = 0x04,
TCHNG_REMOVED = 0x08
};
typedef struct
{
int id;
int x;
int y;
int changed;
int consumed;
struct timeval time;
int64_t us_diff;
} touch_event;
static touch_event mt_events[MAX_FINGERS];
static struct pollfd ev_fds[MAX_DEVICES];
static unsigned ev_count = 0;
static int mt_slot = 0;
static int ev_init()
{
DIR *dir;
struct dirent *de;
int fd;
dir = opendir("/dev/input");
if(!dir)
return -1;
while((de = readdir(dir)))
{
if(strncmp(de->d_name,"event",5))
continue;
fd = openat(dirfd(dir), de->d_name, O_RDONLY);
if(fd < 0)
continue;
ev_fds[ev_count].fd = fd;
ev_fds[ev_count].events = POLLIN;
ev_count++;
if(ev_count == MAX_DEVICES)
break;
}
closedir(dir);
return 0;
}
static int ev_get(struct input_event *ev, unsigned dont_wait)
{
int r;
unsigned n;
do
{
r = poll(ev_fds, ev_count, dont_wait ? 0 : -1);
if(r <= 0)
continue;
for(n = 0; n < ev_count; n++)
{
if(ev_fds[n].revents & POLLIN)
{
r = read(ev_fds[n].fd, ev, sizeof(*ev));
if(r == sizeof(*ev))
return 0;
}
}
}
while(dont_wait == 0);
return -1;
}
static inline int64_t get_us_diff(struct timeval now, struct timeval prev)
{
return ((int64_t)(now.tv_sec - prev.tv_sec))*1000000+
(now.tv_usec - prev.tv_usec);
}
static void handle_abs_event(struct input_event *ev)
{
switch(ev->code)
{
case ABS_MT_SLOT:
if(ev->value < (int)ARRAY_SIZE(mt_events))
mt_slot = ev->value;
break;
case ABS_MT_TRACKING_ID:
{
if(ev->value != -1)
{
mt_events[mt_slot].id = ev->value;
mt_events[mt_slot].changed |= TCHNG_ADDED;
}
else
mt_events[mt_slot].changed |= TCHNG_REMOVED;
break;
}
case ABS_MT_POSITION_X:
case ABS_MT_POSITION_Y:
{
if(ev->code == ABS_MT_POSITION_X)
mt_events[mt_slot].x = ev->value;
else
mt_events[mt_slot].y = ev->value;
mt_events[mt_slot].changed |= TCHNG_POS;
break;
}
}
}
static void handle_touch_event(touch_event *ev)
{
static struct timeval last_time = { 0, 0 };
// show battery percentage after double tap on the bottom of the screen
if(!(ev->changed & TCHNG_REMOVED) || ev->y < 975)
return;
if(get_us_diff(ev->time, last_time) < 1500000)
{
pid_t pid = fork();
if(pid == 0)
{
char buff[32] = { 0 };
strcpy(buff, "Battery: ");
FILE *f = fopen("/sys/devices/system/wario_battery/wario_battery0/battery_capacity", "r");
if(f)
{
fgets(buff + 9, sizeof(buff) - 9, f);
fclose(f);
}
execl("/usr/sbin/eips", "/usr/sbin/eips", "17", "41", buff, (char*)NULL);
exit(0);
}
}
last_time = ev->time;
}
static void handle_syn_event(struct input_event *ev)
{
if(ev->code != SYN_REPORT)
return;
uint32_t i;
touch_event *tev;
for(i = 0; i < ARRAY_SIZE(mt_events); ++i)
{
tev = &mt_events[i];
tev->us_diff = get_us_diff(ev->time, tev->time);
tev->time = ev->time;
if(!tev->changed)
continue;
//printf("event %02d flags 0x%02X, [%d; %d]\n", tev->id, tev->changed, tev->x, tev->y);
handle_touch_event(tev);
tev->consumed = 0;
tev->changed = 0;
}
}
int main(void)
{
struct input_event ev;
ev_init();
while(1)
{
ev_get(&ev, 0);
switch(ev.type)
{
case EV_ABS:
handle_abs_event(&ev);
break;
case EV_SYN:
handle_syn_event(&ev);
break;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment