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>
20 #include <hardware/sensors.h>
22 #define DRIVER_DESC "Acer BMA150 accelerometer"
27 #define ID_AMBIENT_LIGHT (SENSORS_HANDLE_BASE + SENS_LIGHT)
28 #define ID_ROTATION_VECTOR (SENSORS_HANDLE_BASE + SENS_ROTATE)
29 #define ID_ACCELEROMETER (SENSORS_HANDLE_BASE + SENS_ACCEL)
31 #define VALID_LIGHT (1 << 0)
32 #define VALID_ROTATE (1 << 1)
33 #define VALID_ACCEL (1 << 2)
35 #define VALID_ROTATE_X (1 << 0)
36 #define VALID_ROTATE_Y (1 << 1)
37 #define VALID_ROTATE_Z (1 << 2)
38 #define VALID_ROTATE_MASK (7 << 0)
40 struct sensor_context {
41 struct sensors_poll_device_1 device;
44 struct timespec delay;
50 int orientation_data[3];
51 uint8_t orientation_valid;
54 static int open_accel_sensor(void)
56 const char *dirname = "/dev/input";
64 dir = opendir(dirname);
67 * Loop over all "eventXX" in /dev/input and look
70 ALOGD("%s[%i] Looping over all eventXX...", __func__, __LINE__);
71 while ((de = readdir(dir))) {
72 if (de->d_name[0] != 'e')
74 memset(name, 0, PATH_MAX);
75 snprintf(name, PATH_MAX, "%s/%s", dirname, de->d_name);
76 ALOGD("%s[%i] Open device %s", __func__, __LINE__, name);
78 fd = open(name, O_RDWR);
80 ALOGD("%s[%i] Could not open %s, %s", __func__,
81 __LINE__, name, strerror(errno));
85 name[PATH_MAX - 1] = '\0';
86 ret = ioctl(fd, EVIOCGNAME(PATH_MAX - 1), &name);
88 ALOGD("%s[%i] Could not get device name for "
89 "%s, %s\n", __func__, __LINE__,
90 name, strerror(errno));
94 ALOGI("%s[%i] Testing device %s",
95 __func__, __LINE__, name);
97 if (!strcmp(name, DRIVER_DESC)) {
98 ALOGI("%s[%i] Found device %s",
99 __func__, __LINE__, name);
106 ALOGD("%s[%i] stop loop and closing directory",
114 static int context__activate(struct sensors_poll_device_t *dev,
115 int handle, int enabled)
117 struct sensor_context* ctx = (struct sensor_context *)dev;
122 if (ctx->accel_fd >= 0)
125 fd = open_accel_sensor();
134 /* Light and fake accel need no activation. */
141 static int context__setDelay(struct sensors_poll_device_t *dev,
142 int handle, int64_t ns)
144 struct sensor_context* ctx = (struct sensor_context *)dev;
146 ctx->delay.tv_sec = 0;
147 ctx->delay.tv_nsec = ns;
152 static int context__close(struct hw_device_t *dev)
154 struct sensor_context* ctx = (struct sensor_context *)dev;
156 close(ctx->accel_fd);
163 static int poll_data(struct sensors_poll_device_t *dev, sensors_event_t *data)
165 struct input_event iev;
166 struct sensor_context *ctx = (struct sensor_context *)dev;
171 /* Orientation sensor */
173 res = read(ctx->accel_fd, &iev, sizeof(struct input_event));
174 if (res != sizeof(struct input_event))
177 if (iev.type != EV_ABS)
182 ctx->orientation_data[0] = iev.value;
183 ctx->orientation_valid |= VALID_ROTATE_X;
186 ctx->orientation_data[1] = iev.value;
187 ctx->orientation_valid |= VALID_ROTATE_Y;
190 ctx->orientation_data[2] = iev.value;
191 ctx->orientation_valid |= VALID_ROTATE_Z;
194 ctx->light_data = iev.value;
195 ctx->valid |= VALID_LIGHT;
201 if (ctx->orientation_valid == VALID_ROTATE_MASK) {
202 ctx->valid |= VALID_ROTATE;
210 static int craft_fake_accel(struct sensors_poll_device_t *dev, sensors_event_t *data)
212 struct sensor_context *ctx = (struct sensor_context *)dev;
214 const double angle = 20.0;
215 const double cos_angle = GRAVITY_EARTH * cos(angle / M_PI);
216 const double sin_angle = GRAVITY_EARTH * sin(angle / M_PI);
224 * x=max ---------+--------- x=min
232 if (ctx->orientation_data[0] >= 10000) {
234 data->acceleration.x = 0.0f;
235 data->acceleration.y = cos_angle;
236 data->acceleration.z = sin_angle;
237 } else if (ctx->orientation_data[0] <= -10000) {
238 /* Flipped landscape */
239 data->acceleration.x = 0.0f;
240 data->acceleration.y = -cos_angle;
241 data->acceleration.z = -sin_angle;
242 } else if (ctx->orientation_data[1] <= -10000) {
244 data->acceleration.x = cos_angle;
245 data->acceleration.y = 0.0f;
246 data->acceleration.z = sin_angle;
247 } else if (ctx->orientation_data[1] >= 10000) {
248 /* Flipped portrait */
249 data->acceleration.x = -cos_angle;
250 data->acceleration.y = 0.0f;
251 data->acceleration.z = -sin_angle;
261 static int submit_sensor(struct sensors_poll_device_t *dev, sensors_event_t *data)
263 struct sensor_context *ctx = (struct sensor_context *)dev;
266 const uint32_t end = ctx->sent;
267 uint32_t start = end;
268 ctx->sent = (ctx->sent + 1) % SENS_COUNT;
270 /* Get time for the event. */
271 memset(&t, 0, sizeof(t));
272 clock_gettime(CLOCK_MONOTONIC, &t);
273 data->timestamp = ((int64_t)(t.tv_sec) * 1000000000LL) + t.tv_nsec;
274 data->version = sizeof(*data);
277 start = (start + 1) % SENS_COUNT;
279 switch (ctx->valid & (1 << start)) {
281 data->sensor = ID_AMBIENT_LIGHT;
282 data->type = SENSOR_TYPE_LIGHT;
284 data->light = ctx->light_data;
286 ALOGD("%s[%i] LIGHT %d", __func__, __LINE__,
289 ctx->valid &= ~(1 << start);
292 data->sensor = ID_ROTATION_VECTOR;
293 data->type = SENSOR_TYPE_ROTATION_VECTOR;
294 data->orientation.status = SENSOR_STATUS_ACCURACY_MEDIUM;
296 float x = ctx->orientation_data[0];
297 float y = ctx->orientation_data[1];
298 float z = ctx->orientation_data[2];
300 data->orientation.x = x;
301 data->orientation.y = y;
302 data->orientation.z = z;
304 ALOGD("%s[%i] ROTATE %d %d %d -> %f %f %f",
306 ctx->orientation_data[0],
307 ctx->orientation_data[1],
308 ctx->orientation_data[2],
311 data->orientation.z);
313 ctx->valid &= ~(1 << start);
314 ctx->valid |= VALID_ACCEL;
317 data->sensor = ID_ACCELEROMETER;
318 data->type = SENSOR_TYPE_ACCELEROMETER;
319 data->acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;
321 ret = craft_fake_accel(dev, data);
323 ALOGD("%s[%i] ACCEL %f %f %f",
325 data->acceleration.x,
326 data->acceleration.y,
327 data->acceleration.z);
329 ctx->valid &= ~(1 << start);
332 } while (start != end);
337 static int context__poll(struct sensors_poll_device_t *dev, sensors_event_t *data, int count)
339 struct sensor_context *ctx = (struct sensor_context *)dev;
344 poll_data(dev, data);
346 ret = submit_sensor(dev, data);
350 nanosleep(&ctx->delay, &ctx->delay);
356 static int context__batch(struct sensors_poll_device_1* dev, int sensor_handle,
357 int flags, int64_t sampling_period_ns, int64_t max_report_latency_ns)
359 ALOGD("%s: dev=%p sensor_handle=%d flags=%d sampling_period_ns=%" PRId64 " max_report_latency_ns=%" PRId64,
360 __FUNCTION__, dev, sensor_handle, flags, sampling_period_ns, max_report_latency_ns);
362 return context__setDelay(&dev->v0, sensor_handle, sampling_period_ns);
365 static int context__flush(struct sensors_poll_device_1* dev, int sensor_handle)
367 ALOGD("%s: dev=%p sensor_handle=%d", __FUNCTION__, dev, sensor_handle);
371 static const struct sensor_t sensor_list[] = {
373 .name = "W500 Ambient Light sensor",
376 .handle = ID_AMBIENT_LIGHT,
377 .type = SENSOR_TYPE_LIGHT,
384 .name = "W500 Gyro sensor",
385 .vendor = "BOSCH Sensortec",
387 .handle = ID_ROTATION_VECTOR,
388 .type = SENSOR_TYPE_ROTATION_VECTOR,
389 .maxRange = 35000.0f,
395 .name = "W500 Fake accelerometer",
396 .vendor = "FooBar Technology Group",
398 .handle = ID_ACCELEROMETER,
399 .type = SENSOR_TYPE_ACCELEROMETER,
401 .resolution = 1.0f/4032.0f,
407 static int sensors__get_sensors_list(struct sensors_module_t *module,
408 const struct sensor_t **list)
411 return sizeof(sensor_list)/sizeof(sensor_list[0]);
415 static int open_sensors(const struct hw_module_t *module, const char* id,
416 struct hw_device_t **device)
418 struct sensor_context *ctx;
421 if (strcmp(id, SENSORS_HARDWARE_POLL))
424 /* Allocate context */
425 ctx = malloc(sizeof(*ctx));
429 memset(ctx, 0, sizeof(*ctx));
432 ctx->delay.tv_sec = 0;
433 ctx->delay.tv_nsec = 100;
435 /* Do common setup */
436 ctx->device.common.tag = HARDWARE_DEVICE_TAG;
437 ctx->device.common.version = SENSORS_DEVICE_API_VERSION_1_3;
438 ctx->device.common.module = (struct hw_module_t *)module;
439 ctx->device.common.close = context__close;
441 ctx->device.activate = context__activate;
442 ctx->device.setDelay = context__setDelay;
443 ctx->device.poll = context__poll;
444 ctx->device.batch = context__batch;
445 ctx->device.flush = context__flush;
447 *device = &ctx->device.common;
452 close(ctx->accel_fd);
458 static struct hw_module_methods_t sensors_module_methods = {
462 struct sensors_module_t HAL_MODULE_INFO_SYM = {
464 .tag = HARDWARE_MODULE_TAG,
465 .module_api_version = 1,
466 .hal_api_version = 0,
467 .id = SENSORS_HARDWARE_MODULE_ID,
468 .name = "W500 SENSORS Module",
469 .author = "Marek Vasut",
470 .methods = &sensors_module_methods,
472 .get_sensors_list = sensors__get_sensors_list,