OSDN Git Service

hdaps: support Pegatron Lucid Tablet Accelerometer
[android-x86/hardware-libsensors.git] / hdaps.c
diff --git a/hdaps.c b/hdaps.c
index 3429720..556d4e9 100644 (file)
--- a/hdaps.c
+++ b/hdaps.c
@@ -31,7 +31,7 @@
 //#define DEBUG_SENSOR         1
 
 #define CONVERT                        (GRAVITY_EARTH / 156.0f)
-#define SENSOR_NAME            "hdaps"
+#define CONVERT_PEGA           (GRAVITY_EARTH / 256.0f)
 #define INPUT_DIR              "/dev/input"
 #define ARRAY_SIZE(a)          (sizeof(a) / sizeof(a[0]))
 #define ID_ACCELERATION                (SENSORS_HANDLE_BASE + 0)
 #define COS_ASIN(m,x)          (sqrt(SQUARE(m)-SQUARE(AMIN(m,x))))
 #define COS_ASIN_2D(m,x,y)     (COS_ASIN(m,x)*COS_ASIN(m,y)/(m))
 
+typedef struct {
+       const char *name;
+       float conv[3];
+       int avg_cnt;
+} accel_params;
+
+static accel_params accel_list[] = {
+       { "hdaps", { CONVERT, -CONVERT, 0 }, 1 },
+       { "Pegatron Lucid Tablet Accelerometer", { CONVERT_PEGA, CONVERT_PEGA, CONVERT_PEGA }, 4 },
+};
+
+static accel_params accelerometer;
+static sensors_vec_t *events_q = NULL;
+static int event_cnt = 0;
 static unsigned int forced_delay = 0;
 
 struct sensors_poll_context_t {
@@ -50,9 +64,9 @@ struct sensors_poll_context_t {
 
 static int common__close(struct hw_device_t *dev) {
        struct sensors_poll_context_t *ctx = (struct sensors_poll_context_t *) dev;
-       if (ctx) {
-               free(ctx);
-       }
+       free(ctx);
+       free(events_q);
+       events_q = NULL;
 
        return 0;
 }
@@ -71,7 +85,7 @@ static int device__set_delay(struct sensors_poll_device_t *device, int handle,
 }
 
 static int device__poll(struct sensors_poll_device_t *device,
-               sensors_event_tdata, int count) {
+               sensors_event_t *data, int count) {
 
        struct input_event event;
        int ret;
@@ -96,23 +110,30 @@ static int device__poll(struct sensors_poll_device_t *device,
                        // have landscape displays, and the axes are relative to the default
                        // screen orientation, not relative to portrait orientation.
                        // See the nVidia Tegra accelerometer docs if you want to know for sure.
-                       case ABS_X:
-                               data->acceleration.x = (float) event.value * CONVERT;
-                               break;
-                       case ABS_Y:
-                               // we invert the y-axis here because we assume the laptop is
-                               // in tablet mode (and thus the display is rotated 180 degrees.
-                               data->acceleration.y = -(float) event.value * CONVERT;
+                       case ABS_X: // 0x00
+                       case ABS_Y: // 0x01
+                       case ABS_Z: // 0x02
+                               events_q[event_cnt].v[event.code] = accelerometer.conv[event.code] * event.value;
                                break;
                        }
                } else if (event.type == EV_SYN) {
+                       int i;
                        data->timestamp = (int64_t) ((int64_t) event.time.tv_sec
                                        * 1000000000 + (int64_t) event.time.tv_usec * 1000);
                        // hdaps doesn't have z-axis, so simulate it by rotation matrix solution
-                       data ->acceleration.z = COS_ASIN_2D(GRAVITY_EARTH, data->acceleration.x, data->acceleration.y);
+                       if (accelerometer.conv[2] == 0)
+                               events_q[event_cnt].z = COS_ASIN_2D(GRAVITY_EARTH, events_q[event_cnt].x, events_q[event_cnt].y);
+                       memset(&data->acceleration, 0, sizeof(sensors_vec_t));
+                       for (i = 0; i < accelerometer.avg_cnt; ++i) {
+                               data->acceleration.x += events_q[i].x;
+                               data->acceleration.y += events_q[i].y;
+                               data->acceleration.z += events_q[i].z;
+                       }
                        data->sensor = ID_ACCELERATION;
                        data->type = SENSOR_TYPE_ACCELEROMETER;
                        data->acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;
+                       if (++event_cnt >= accelerometer.avg_cnt)
+                               event_cnt = 0;
                        // spare the CPU if desired
                        if (forced_delay)
                                usleep(forced_delay);
@@ -125,7 +146,7 @@ static int device__poll(struct sensors_poll_device_t *device,
 
 static int open_input_device(void) {
        char *filename;
-       int fd;
+       int fd = -1;
        DIR *dir;
        struct dirent *de;
        char name[80];
@@ -139,34 +160,44 @@ static int open_input_device(void) {
        *filename++ = '/';
 
        while ((de = readdir(dir))) {
-               if (de->d_name[0] == '.' && (de->d_name[1] == '\0' || (de->d_name[1] == '.' && de->d_name[2] == '\0')))
+               int f;
+               size_t i;
+               if (de->d_name[0] == '.')
                        continue;
                strcpy(filename, de->d_name);
-               fd = open(devname, O_RDONLY);
-               if (fd < 0) {
+               f = open(devname, O_RDONLY);
+               if (f < 0) {
                        continue;
                }
 
-               if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
+               if (ioctl(f, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
                        name[0] = '\0';
                }
 
-               if (!strcmp(name, SENSOR_NAME)) {
 #ifdef DEBUG_SENSOR
-                       ALOGI("devname is %s \n", devname);
+               ALOGD("%s name is %s", devname, name);
 #endif
-               } else {
-                       close(fd);
-                       continue;
+               for (i = 0; i < ARRAY_SIZE(accel_list); ++i) {
+                       if (!strcmp(name, accel_list[i].name)) {
+                               int c = accel_list[i].avg_cnt;
+                               accelerometer.avg_cnt = c;
+                               accelerometer.conv[0] = accel_list[i].conv[0] / c;
+                               accelerometer.conv[1] = accel_list[i].conv[1] / c;
+                               accelerometer.conv[2] = accel_list[i].conv[2] / c;
+                               events_q = calloc(c, sizeof(sensors_vec_t));
+                               ALOGI("found %s at %s", name, devname);
+                               break;
+                       }
                }
-               closedir(dir);
-
-               return fd;
-
+               if (events_q) {
+                       fd = f;
+                       break;
+               }
+               close(f);
        }
        closedir(dir);
 
-       return -1;
+       return fd;
 }
 
 static const struct sensor_t sSensorList[] = {
@@ -193,13 +224,14 @@ static int sensors__get_sensors_list(struct sensors_module_t* module,
 }
 
 static struct hw_module_methods_t sensors_module_methods = {
-               .open = open_sensors };
+       .open = open_sensors
+};
 
 struct sensors_module_t HAL_MODULE_INFO_SYM = {
        .common = {
                .tag = HARDWARE_MODULE_TAG,
-               .version_major = 1,
-               .version_minor = 1,
+               .version_major = 2,
+               .version_minor = 0,
                .id = SENSORS_HARDWARE_MODULE_ID,
                .name = "hdaps accelerometer sensor",
                .author = "Stefan Seidel",
@@ -214,9 +246,8 @@ static int open_sensors(const struct hw_module_t* module, const char* name,
                struct hw_device_t** device) {
        int status = -EINVAL;
 
-       struct sensors_poll_context_t *dev = malloc(
+       struct sensors_poll_context_t *dev = calloc(1,
                        sizeof(struct sensors_poll_context_t));
-       memset(&dev->device, 0, sizeof(struct sensors_poll_device_t));
 
        dev->device.common.tag = HARDWARE_DEVICE_TAG;
        dev->device.common.version = 0;