Skip to content

Commit

Permalink
Add sensors_input_cache for caching input devices
Browse files Browse the repository at this point in the history
The input cache will keep a list of input devices for swift lookup of
device names. It also includes some optimizations for startup time.

This code was moved to its own file from sensor_util.

Signed-off-by: Oskar Andero <oskar.andero@sonymobile.com>
  • Loading branch information
Oskar Andero committed Sep 21, 2012
1 parent 5ca57b5 commit 94ddfeb
Show file tree
Hide file tree
Showing 4 changed files with 186 additions and 95 deletions.
1 change: 1 addition & 0 deletions Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ LOCAL_SRC_FILES += sensors_module.c \
sensors_worker.c \
sensors_select.c \
sensors_wrapper.c \
sensors_input_cache.c \
sensors/sensor_util.c

LOCAL_CFLAGS += -I$(LOCAL_PATH)/sensors
Expand Down
120 changes: 25 additions & 95 deletions sensors/sensor_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,14 @@
#include <stddef.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/input.h>
#include "sensor_util.h"
#include <dirent.h>
#include <ctype.h>
#include "sensors_log.h"
#include <pthread.h>
#include "sensor_util_list.h"
#include "sensors_input_cache.h"

#define NSEC_PER_SEC 1000000000L
static int64_t timespec_to_ns(const struct timespec *ts)
Expand Down Expand Up @@ -61,116 +59,48 @@ void sensors_usleep(int us)
nanosleep(&t, NULL);
}

#define INPUT_EVENT_DIR "/dev/input/"
#define INPUT_EVENT_BASENAME "event"
#define INPUT_EVENT_PATH INPUT_EVENT_DIR INPUT_EVENT_BASENAME
#define MAX_INT_STRING_SIZE sizeof("4294967295")
static pthread_mutex_t util_mutex = PTHREAD_MUTEX_INITIALIZER;
struct input_dev_list {
struct list_node node;
char event_path[sizeof(INPUT_EVENT_PATH) + MAX_INT_STRING_SIZE];
char dev_name[32];
};

static struct list_node head;

int input_dev_path_by_name(char *name, char *path, int path_max)
{
int rc;
int fd;
DIR * dir;
struct dirent * item;
struct list_node *member;
struct input_dev_list *temp;
static int init;

pthread_mutex_lock(&util_mutex);
if (!init) {
init = 1;
dir = opendir(INPUT_EVENT_DIR);
if (!dir)
goto opendir_err;
node_init(&head);
while (NULL != (item = readdir(dir))) {
if (0 != strncmp(item->d_name, INPUT_EVENT_BASENAME,
sizeof(INPUT_EVENT_BASENAME) - 1)) {
continue;
}
temp = malloc(sizeof(*temp));
if (temp == NULL) {
ALOGE("%s: malloc error!\n", __func__);
goto malloc_err;
}

node_add(&head, &temp->node);
const struct sensors_input_cache_entry_t *input;

snprintf(temp->event_path, sizeof(temp->event_path),
"%s%s",
INPUT_EVENT_DIR, item->d_name);
fd = open(temp->event_path, O_RDONLY);
if (fd < 0)
goto open_err;

rc = ioctl(fd,
EVIOCGNAME(sizeof(temp->dev_name)),
temp->dev_name);
close(fd);
if (rc < 0)
goto open_err;
}
closedir(dir);
}
pthread_mutex_unlock(&util_mutex);

for (member = head.n; member != &head; member = member->n) {
temp = container_of(member, struct input_dev_list, node);
if (!strcmp(temp->dev_name, name)) {
strncpy(path, temp->event_path, path_max);
return 0;
}
}
input = sensors_input_cache_get(name);
if (!input)
return -1;

return -1;
strlcpy(path, input->event_path, path_max);

malloc_err:
open_err:
for (member = head.n; member != &head; member = head.n) {
temp = container_of(member, struct input_dev_list, node);
node_del(member);
free(temp);
}
closedir(dir);
opendir_err:
pthread_mutex_unlock(&util_mutex);
return -1;
return 0;
}

int open_input_dev_by_name(char *name, int flags)
{
char fname[sizeof(INPUT_EVENT_PATH) + MAX_INT_STRING_SIZE];
const struct sensors_input_cache_entry_t *input;

if (!input_dev_path_by_name(name, fname, sizeof(fname)))
return open(fname, flags);
input = sensors_input_cache_get(name);
if (!input)
return -1;

return -1;
return open(input->event_path, flags);
}

int open_input_dev_by_name_store_nr(char *name, int flags, char *nr,
size_t nr_size)
{
char fname[sizeof(INPUT_EVENT_PATH) + MAX_INT_STRING_SIZE];
const struct sensors_input_cache_entry_t *input;
size_t len;

if (!input_dev_path_by_name(name, fname, sizeof(fname))) {
size_t len = strnlen(fname, sizeof(fname));
while(iscntrl(fname[len]))
len--;
while(isdigit(fname[len]))
len--;
nr = strncpy(nr, &fname[len+1], nr_size);
return open(fname, flags);
}
input = sensors_input_cache_get(name);
if (!input)
return -1;

return -1;
len = strnlen(input->event_path, sizeof(input->event_path));
while(iscntrl(input->event_path[len]))
len--;
while(isdigit(input->event_path[len]))
len--;
strncpy(nr, &input->event_path[len+1], nr_size);

return open(input->event_path, flags);
}

#define test_bit(bit, array) (array[(bit) / 8] & (1 << ((bit) % 8)))
Expand Down
142 changes: 142 additions & 0 deletions sensors_input_cache.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#include <stdio.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <dirent.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <linux/input.h>
#include "sensors_log.h"
#include "sensor_util.h"
#include "sensor_util_list.h"
#include "sensors_input_cache.h"

#define MAX_EVENT_DRIVERS 100

static pthread_mutex_t util_mutex = PTHREAD_MUTEX_INITIALIZER;

struct input_dev_list {
struct list_node node;
struct sensors_input_cache_entry_t entry;
};

static struct list_node head;
static int list_initialized;

static void *close_input_dev_fd(void *arg)
{
close((int) arg); /* pass by copy */

return NULL;
}

static struct input_dev_list *lookup(const char *name, const char *path)
{
struct list_node *member;
struct input_dev_list *temp;

for (member = head.n; member != &head; member = member->n) {
temp = container_of(member, struct input_dev_list, node);
if (name && !strncmp(temp->entry.dev_name, name,
sizeof(temp->entry.dev_name) - 1))
return temp;
if (path && !strncmp(temp->entry.event_path, path,
sizeof(temp->entry.event_path) - 1))
return temp;
}

return NULL;
}

const struct sensors_input_cache_entry_t *sensors_input_cache_get(
const char *name)
{
int rc;
int fd;
DIR *dir;
struct dirent * item;
struct list_node *member;
struct input_dev_list *temp;
pthread_t id[MAX_EVENT_DRIVERS];
unsigned int i = 0;
unsigned int threads = 0;
const struct sensors_input_cache_entry_t *found = NULL;

pthread_mutex_lock(&util_mutex);
if (!list_initialized) {
node_init(&head);
list_initialized = 1;
}

temp = lookup(name, NULL);
if (temp) {
found = &temp->entry;
goto exit;
}

dir = opendir(INPUT_EVENT_DIR);
if (!dir) {
LOGE("%s: error opening '%s'\n", __func__,
INPUT_EVENT_DIR);
goto exit;
}

while ((item = readdir(dir)) != NULL) {
if (strncmp(item->d_name, INPUT_EVENT_BASENAME,
sizeof(INPUT_EVENT_BASENAME) - 1) != 0) {
continue;
}

temp = (temp ? temp : malloc(sizeof(*temp)));
if (temp == NULL) {
LOGE("%s: malloc error!\n", __func__);
break;
}

/* skip already cached entries */
snprintf(temp->entry.event_path, sizeof(temp->entry.event_path),
"%s%s", INPUT_EVENT_DIR, item->d_name);
if (lookup(NULL, temp->entry.event_path))
continue;

/* make sure we have access */
fd = open(temp->entry.event_path, O_RDONLY);
if (fd < 0) {
LOGE("%s: cant open %s", __func__,
item->d_name);
continue;
}

rc = ioctl(fd, EVIOCGNAME(sizeof(temp->entry.dev_name)),
temp->entry.dev_name);

/* close in parallell to optimize boot time */
pthread_create(&id[threads++], NULL,
close_input_dev_fd, (void*) fd);

if (rc < 0) {
LOGE("%s: cant get name from %s", __func__,
item->d_name);
continue;
}

temp->entry.nr = atoi(item->d_name +
sizeof(INPUT_EVENT_BASENAME) - 1);

node_add(&head, &temp->node);
if (!found && !strncmp(temp->entry.dev_name, name,
sizeof(temp->entry.dev_name) - 1))
found = &temp->entry;
temp = NULL;
}

closedir(dir);

for(i = 0; i < threads; ++i)
pthread_join(id[i], NULL);

exit:
pthread_mutex_unlock(&util_mutex);
return found;
}
18 changes: 18 additions & 0 deletions sensors_input_cache.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#ifndef SENSORS_INPUT_CACHE_H_
#define SENSORS_INPUT_CACHE_H_

#define INPUT_EVENT_DIR "/dev/input/"
#define INPUT_EVENT_BASENAME "event"
#define INPUT_EVENT_PATH INPUT_EVENT_DIR INPUT_EVENT_BASENAME
#define MAX_INT_STRING_SIZE sizeof("4294967295")

struct sensors_input_cache_entry_t {
int nr;
char dev_name[32];
char event_path[sizeof(INPUT_EVENT_PATH) + MAX_INT_STRING_SIZE];
};

const struct sensors_input_cache_entry_t *sensors_input_cache_get(
const char *name);

#endif

0 comments on commit 94ddfeb

Please sign in to comment.