4 * Created on: 28.05.2012
5 * Author: Marek Vasut <marex@denx.de>
6 * Licensed under GPLv2 or later
9 #define LOG_TAG "W500Sensors"
11 #include <linux/types.h>
12 #include <linux/input.h>
14 #include <cutils/sockets.h>
15 #include <cutils/log.h>
16 #include <cutils/native_handle.h>
19 #include <hardware/sensors.h>
21 #define DRIVER_DESC "Acer BMA150 accelerometer"
26 #define ID_AMBIENT_LIGHT (SENSORS_HANDLE_BASE + SENS_LIGHT)
27 #define ID_ROTATION_VECTOR (SENSORS_HANDLE_BASE + SENS_ROTATE)
28 #define ID_ACCELEROMETER (SENSORS_HANDLE_BASE + SENS_ACCEL)
30 #define VALID_LIGHT (1 << 0)
31 #define VALID_ROTATE (1 << 1)
32 #define VALID_ACCEL (1 << 2)
34 #define VALID_ROTATE_X (1 << 0)
35 #define VALID_ROTATE_Y (1 << 1)
36 #define VALID_ROTATE_Z (1 << 2)
37 #define VALID_ROTATE_MASK (7 << 0)
39 struct sensor_context {
40 struct sensors_poll_device_t device;
43 struct timespec delay;
49 int orientation_data[3];
50 uint8_t orientation_valid;
53 static int open_accel_sensor(void)
55 const char *dirname = "/dev/input";
63 dir = opendir(dirname);
66 * Loop over all "eventXX" in /dev/input and look
69 ALOGD("%s[%i] Looping over all eventXX...", __func__, __LINE__);
70 while ((de = readdir(dir))) {
71 if (de->d_name[0] != 'e')
73 memset(name, 0, PATH_MAX);
74 snprintf(name, PATH_MAX, "%s/%s", dirname, de->d_name);
75 ALOGD("%s[%i] Open device %s", __func__, __LINE__, name);
77 fd = open(name, O_RDWR);
79 ALOGD("%s[%i] Could not open %s, %s", __func__,
80 __LINE__, name, strerror(errno));
84 name[PATH_MAX - 1] = '\0';
85 ret = ioctl(fd, EVIOCGNAME(PATH_MAX - 1), &name);
87 ALOGD("%s[%i] Could not get device name for "
88 "%s, %s\n", __func__, __LINE__,
89 name, strerror(errno));
93 ALOGI("%s[%i] Testing device %s",
94 __func__, __LINE__, name);
96 if (!strcmp(name, DRIVER_DESC)) {
97 ALOGI("%s[%i] Found device %s",
98 __func__, __LINE__, name);
105 ALOGD("%s[%i] stop loop and closing directory",
113 static int context__activate(struct sensors_poll_device_t *dev,
114 int handle, int enabled)
116 struct sensor_context* ctx = (struct sensor_context *)dev;
121 if (ctx->accel_fd >= 0)
124 fd = open_accel_sensor();
133 /* Light and fake accel need no activation. */
140 static int context__setDelay(struct sensors_poll_device_t *dev,
141 int handle, int64_t ns)
143 struct sensor_context* ctx = (struct sensor_context *)dev;
145 ctx->delay.tv_sec = 0;
146 ctx->delay.tv_nsec = ns;
151 static int context__close(struct hw_device_t *dev)
153 struct sensor_context* ctx = (struct sensor_context *)dev;
155 close(ctx->accel_fd);
162 static int poll_data(struct sensors_poll_device_t *dev, sensors_event_t *data)
164 struct input_event iev;
165 struct sensor_context *ctx = (struct sensor_context *)dev;
170 /* Orientation sensor */
172 res = read(ctx->accel_fd, &iev, sizeof(struct input_event));
173 if (res != sizeof(struct input_event))
176 if (iev.type != EV_ABS)
181 ctx->orientation_data[0] = iev.value;
182 ctx->orientation_valid |= VALID_ROTATE_X;
185 ctx->orientation_data[1] = iev.value;
186 ctx->orientation_valid |= VALID_ROTATE_Y;
189 ctx->orientation_data[2] = iev.value;
190 ctx->orientation_valid |= VALID_ROTATE_Z;
193 ctx->light_data = iev.value;
194 ctx->valid |= VALID_LIGHT;
200 if (ctx->orientation_valid == VALID_ROTATE_MASK) {
201 ctx->valid |= VALID_ROTATE;
209 static int craft_fake_accel(struct sensors_poll_device_t *dev, sensors_event_t *data)
211 struct sensor_context *ctx = (struct sensor_context *)dev;
213 const double angle = 20.0;
214 const double cos_angle = GRAVITY_EARTH * cos(angle / M_PI);
215 const double sin_angle = GRAVITY_EARTH * sin(angle / M_PI);
223 * x=max ---------+--------- x=min
231 if (ctx->orientation_data[0] >= 10000) {
233 data->acceleration.x = 0.0f;
234 data->acceleration.y = cos_angle;
235 data->acceleration.z = sin_angle;
236 } else if (ctx->orientation_data[0] <= -10000) {
237 /* Flipped landscape */
238 data->acceleration.x = 0.0f;
239 data->acceleration.y = -cos_angle;
240 data->acceleration.z = -sin_angle;
241 } else if (ctx->orientation_data[1] <= -10000) {
243 data->acceleration.x = cos_angle;
244 data->acceleration.y = 0.0f;
245 data->acceleration.z = sin_angle;
246 } else if (ctx->orientation_data[1] >= 10000) {
247 /* Flipped portrait */
248 data->acceleration.x = -cos_angle;
249 data->acceleration.y = 0.0f;
250 data->acceleration.z = -sin_angle;
260 static int submit_sensor(struct sensors_poll_device_t *dev, sensors_event_t *data)
262 struct sensor_context *ctx = (struct sensor_context *)dev;
265 const uint32_t end = ctx->sent;
266 uint32_t start = end;
267 ctx->sent = (ctx->sent + 1) % SENS_COUNT;
269 /* Get time for the event. */
270 memset(&t, 0, sizeof(t));
271 clock_gettime(CLOCK_MONOTONIC, &t);
272 data->timestamp = ((int64_t)(t.tv_sec) * 1000000000LL) + t.tv_nsec;
273 data->version = sizeof(*data);
276 start = (start + 1) % SENS_COUNT;
278 switch (ctx->valid & (1 << start)) {
280 data->sensor = ID_AMBIENT_LIGHT;
281 data->type = SENSOR_TYPE_LIGHT;
283 data->light = ctx->light_data;
285 ALOGD("%s[%i] LIGHT %d", __func__, __LINE__,
288 ctx->valid &= ~(1 << start);
291 data->sensor = ID_ROTATION_VECTOR;
292 data->type = SENSOR_TYPE_ROTATION_VECTOR;
293 data->orientation.status = SENSOR_STATUS_ACCURACY_MEDIUM;
295 float x = ctx->orientation_data[0];
296 float y = ctx->orientation_data[1];
297 float z = ctx->orientation_data[2];
299 data->orientation.x = x;
300 data->orientation.y = y;
301 data->orientation.z = z;
303 ALOGD("%s[%i] ROTATE %d %d %d -> %f %f %f",
305 ctx->orientation_data[0],
306 ctx->orientation_data[1],
307 ctx->orientation_data[2],
310 data->orientation.z);
312 ctx->valid &= ~(1 << start);
313 ctx->valid |= VALID_ACCEL;
316 data->sensor = ID_ACCELEROMETER;
317 data->type = SENSOR_TYPE_ACCELEROMETER;
318 data->acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;
320 ret = craft_fake_accel(dev, data);
322 ALOGD("%s[%i] ACCEL %f %f %f",
324 data->acceleration.x,
325 data->acceleration.y,
326 data->acceleration.z);
328 ctx->valid &= ~(1 << start);
331 } while (start != end);
336 static int context__poll(struct sensors_poll_device_t *dev, sensors_event_t *data, int count)
338 struct sensor_context *ctx = (struct sensor_context *)dev;
343 poll_data(dev, data);
345 ret = submit_sensor(dev, data);
349 nanosleep(&ctx->delay, &ctx->delay);
355 static const struct sensor_t sensor_list[] = {
357 .name = "W500 Ambient Light sensor",
360 .handle = ID_AMBIENT_LIGHT,
361 .type = SENSOR_TYPE_LIGHT,
368 .name = "W500 Gyro sensor",
369 .vendor = "BOSCH Sensortec",
371 .handle = ID_ROTATION_VECTOR,
372 .type = SENSOR_TYPE_ROTATION_VECTOR,
373 .maxRange = 35000.0f,
379 .name = "W500 Fake accelerometer",
380 .vendor = "FooBar Technology Group",
382 .handle = ID_ACCELEROMETER,
383 .type = SENSOR_TYPE_ACCELEROMETER,
385 .resolution = 1.0f/4032.0f,
391 static int sensors__get_sensors_list(struct sensors_module_t *module,
392 const struct sensor_t **list)
395 return sizeof(sensor_list)/sizeof(sensor_list[0]);
399 static int open_sensors(const struct hw_module_t *module, const char* id,
400 struct hw_device_t **device)
402 struct sensor_context *ctx;
405 if (strcmp(id, SENSORS_HARDWARE_POLL))
408 /* Allocate context */
409 ctx = malloc(sizeof(*ctx));
413 memset(ctx, 0, sizeof(*ctx));
416 ctx->delay.tv_sec = 0;
417 ctx->delay.tv_nsec = 100;
419 /* Do common setup */
420 ctx->device.common.tag = HARDWARE_DEVICE_TAG;
421 ctx->device.common.version = 0;
422 ctx->device.common.module = (struct hw_module_t *)module;
423 ctx->device.common.close = context__close;
425 ctx->device.activate = context__activate;
426 ctx->device.setDelay = context__setDelay;
427 ctx->device.poll = context__poll;
429 *device = &ctx->device.common;
434 close(ctx->accel_fd);
440 static struct hw_module_methods_t sensors_module_methods = {
444 struct sensors_module_t HAL_MODULE_INFO_SYM = {
446 .tag = HARDWARE_MODULE_TAG,
449 .id = SENSORS_HARDWARE_MODULE_ID,
450 .name = "W500 SENSORS Module",
451 .author = "Marek Vasut",
452 .methods = &sensors_module_methods,
454 .get_sensors_list = sensors__get_sensors_list,