2 * HDAPS accelerometer sensor
4 * Copyright (C) 2011 The Android-x86 Open Source Project
6 * by Stefan Seidel <stefans@android-x86.org>
8 * Licensed under GPLv2 or later
12 #define LOG_TAG "HdapsSensors"
25 #include <linux/input.h>
27 #include <cutils/atomic.h>
28 #include <cutils/log.h>
29 #include <hardware/sensors.h>
31 //#define DEBUG_SENSOR 1
33 #define CONVERT (GRAVITY_EARTH / 156.0f)
34 #define SENSOR_NAME "hdaps"
35 #define INPUT_DIR "/dev/input"
36 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
37 #define ID_ACCELERATION (SENSORS_HANDLE_BASE + 0)
39 #define AMIN(a,b) (((a)<(fabs(b)))?(a):(b))
40 #define SQUARE(x) ((x)*(x))
41 #define COS_ASIN(m,x) (sqrt(SQUARE(m)-SQUARE(AMIN(m,x))))
42 #define COS_ASIN_2D(m,x,y) (COS_ASIN(m,x)*COS_ASIN(m,y)/(m))
44 static unsigned int forced_delay = 0;
46 struct sensors_poll_context_t {
47 struct sensors_poll_device_t device;
51 static int common__close(struct hw_device_t *dev) {
52 struct sensors_poll_context_t *ctx = (struct sensors_poll_context_t *) dev;
60 static int device__activate(struct sensors_poll_device_t *dev, int handle,
66 static int device__set_delay(struct sensors_poll_device_t *device, int handle,
68 forced_delay = ns / 1000;
73 static int device__poll(struct sensors_poll_device_t *device,
74 sensors_event_t* data, int count) {
76 struct input_event event;
78 struct sensors_poll_context_t *dev =
79 (struct sensors_poll_context_t *) device;
86 ret = read(dev->fd, &event, sizeof(event));
89 ALOGD("hdaps event %d - %d - %d\n", event.type, event.code, event.value);
91 if (event.type == EV_ABS) {
93 // Even though this mapping results in wrong results with some apps,
94 // it just means that these apps are broken, i.e. they rely on the
95 // fact that phone have portrait displays. Laptops/tablets however
96 // have landscape displays, and the axes are relative to the default
97 // screen orientation, not relative to portrait orientation.
98 // See the nVidia Tegra accelerometer docs if you want to know for sure.
100 data->acceleration.x = (float) event.value * CONVERT;
103 // we invert the y-axis here because we assume the laptop is
104 // in tablet mode (and thus the display is rotated 180 degrees.
105 data->acceleration.y = -(float) event.value * CONVERT;
108 } else if (event.type == EV_SYN) {
109 data->timestamp = (int64_t) ((int64_t) event.time.tv_sec
110 * 1000000000 + (int64_t) event.time.tv_usec * 1000);
111 // hdaps doesn't have z-axis, so simulate it by rotation matrix solution
112 data ->acceleration.z = COS_ASIN_2D(GRAVITY_EARTH, data->acceleration.x, data->acceleration.y);
113 data->sensor = ID_ACCELERATION;
114 data->type = SENSOR_TYPE_ACCELEROMETER;
115 data->acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;
116 // spare the CPU if desired
118 usleep(forced_delay);
126 static int open_input_device(void) {
133 dir = opendir(INPUT_DIR);
137 strcpy(devname, INPUT_DIR);
138 filename = devname + strlen(devname);
141 while ((de = readdir(dir))) {
142 if (de->d_name[0] == '.' && (de->d_name[1] == '\0' || (de->d_name[1] == '.' && de->d_name[2] == '\0')))
144 strcpy(filename, de->d_name);
145 fd = open(devname, O_RDONLY);
150 if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
154 if (!strcmp(name, SENSOR_NAME)) {
156 ALOGI("devname is %s \n", devname);
172 static const struct sensor_t sSensorList[] = {
173 { .name = "HDAPS accelerometer",
174 .vendor = "Linux kernel",
176 .handle = ID_ACCELERATION,
177 .type = SENSOR_TYPE_ACCELEROMETER,
178 .maxRange = (GRAVITY_EARTH * 6.0f),
179 .resolution = (GRAVITY_EARTH * 6.0f) / 1024.0f,
185 static int open_sensors(const struct hw_module_t* module, const char* name,
186 struct hw_device_t** device);
188 static int sensors__get_sensors_list(struct sensors_module_t* module,
189 struct sensor_t const** list) {
192 return ARRAY_SIZE(sSensorList);
195 static struct hw_module_methods_t sensors_module_methods = {
196 .open = open_sensors };
198 struct sensors_module_t HAL_MODULE_INFO_SYM = {
200 .tag = HARDWARE_MODULE_TAG,
203 .id = SENSORS_HARDWARE_MODULE_ID,
204 .name = "hdaps accelerometer sensor",
205 .author = "Stefan Seidel",
206 .methods = &sensors_module_methods,
210 .get_sensors_list = sensors__get_sensors_list
213 static int open_sensors(const struct hw_module_t* module, const char* name,
214 struct hw_device_t** device) {
215 int status = -EINVAL;
217 struct sensors_poll_context_t *dev = malloc(
218 sizeof(struct sensors_poll_context_t));
219 memset(&dev->device, 0, sizeof(struct sensors_poll_device_t));
221 dev->device.common.tag = HARDWARE_DEVICE_TAG;
222 dev->device.common.version = 0;
223 dev->device.common.module = (struct hw_module_t*) module;
224 dev->device.common.close = common__close;
225 dev->device.activate = device__activate;
226 dev->device.setDelay = device__set_delay;
227 dev->device.poll = device__poll;
229 if ((dev->fd = open_input_device()) < 0) {
230 ALOGE("g sensor get class path error \n");
232 *device = &dev->device.common;