2 * (c) Copyright Bosch Sensortec GmbH 2011
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following
12 * disclaimer in the documentation and/or other materials provided
13 * with the distribution.
14 * * Neither the name of the author nor the names of its
15 * contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
26 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
28 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
29 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 #include <linux/input.h>
45 #include <cutils/atomic.h>
46 #include <cutils/log.h>
47 #include <hardware/sensors.h>
49 #define DEBUG_SENSOR 0
51 #define CONVERT (GRAVITY_EARTH / 156.0f)
52 #define SENSOR_NAME "hdaps"
53 #define INPUT_DIR "/dev/input"
54 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
55 #define ID_ACCELERATION (SENSORS_HANDLE_BASE + 0)
57 #define AMIN(a,b) (((a)<(fabs(b)))?(a):(b))
58 #define SQUARE(x) ((x)*(x))
59 #define COS_ASIN(m,x) (sqrt(SQUARE(m)-SQUARE(AMIN(m,x))))
60 #define COS_ASIN_2D(m,x,y) (COS_ASIN(m,x)*COS_ASIN(m,y)/(m))
62 struct sensors_poll_context_t {
63 struct sensors_poll_device_t device;
68 static int common__close(struct hw_device_t *dev) {
69 struct sensors_poll_context_t *ctx = (struct sensors_poll_context_t *) dev;
77 static int device__activate(struct sensors_poll_device_t *dev, int handle,
83 static int device__set_delay(struct sensors_poll_device_t *device, int handle,
90 static int device__poll(struct sensors_poll_device_t *device,
91 sensors_event_t* data, int count) {
93 struct input_event event;
95 struct sensors_poll_context_t *dev =
96 (struct sensors_poll_context_t *) device;
103 ret = read(dev->fd, &event, sizeof(event));
106 LOGD("read event %d - %d - %d\n", event.type, event.code, event.value);
108 if (event.type == EV_ABS) {
109 switch (event.code) {
110 // Android imagines the device in portrait mode, but hdaps measures in landscape mode,
111 // so swap x and y axis!
113 data->acceleration.x = (float) event.value * CONVERT;
116 data->acceleration.y = -(float) event.value * CONVERT;
119 } else if (event.type == EV_SYN) {
120 data->timestamp = (int64_t) ((int64_t) event.time.tv_sec
121 * 1000000000 + (int64_t) event.time.tv_usec * 1000);
122 // hdaps doesn't have z-axis, so simulate it by rotation matrix solution
123 data ->acceleration.z
124 = COS_ASIN_2D(GRAVITY_EARTH, data->acceleration.x, data->acceleration.y);
125 data->sensor = ID_ACCELERATION;
126 data->type = SENSOR_TYPE_ACCELEROMETER;
127 data->acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;
135 static int sensor_get_class_path(struct sensors_poll_context_t *dev) {
136 char *dirname = "/sys/class/input";
144 dir = opendir(dirname);
148 while ((de = readdir(dir))) {
149 if (strncmp(de->d_name, "input", strlen("input")) != 0) {
153 sprintf(dev->class_path, "%s/%s", dirname, de->d_name);
154 snprintf(buf, sizeof(buf), "%s/name", dev->class_path);
156 fd = open(buf, O_RDONLY);
160 if ((res = read(fd, buf, sizeof(buf))) < 0) {
165 if (strcmp(buf, SENSOR_NAME) == 0) {
179 *dev->class_path = '\0';
185 static int open_input_device(void) {
192 dir = opendir(INPUT_DIR);
196 strcpy(devname, INPUT_DIR);
197 filename = devname + strlen(devname);
200 while ((de = readdir(dir))) {
201 if (de->d_name[0] == '.' && (de->d_name[1] == '\0' || (de->d_name[1]
202 == '.' && de->d_name[2] == '\0')))
204 strcpy(filename, de->d_name);
205 fd = open(devname, O_RDONLY);
210 if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
214 if (!strcmp(name, SENSOR_NAME)) {
216 LOGI("devname is %s \n", devname);
232 static const struct sensor_t sSensorList[] = { //
233 { .name = "HDAPS accelerometer", //
234 .vendor = "Linux kernel", //
236 .handle = ID_ACCELERATION, //
237 .type = SENSOR_TYPE_ACCELEROMETER, //
238 .maxRange = (GRAVITY_EARTH * 6.0f), //
239 .resolution = (GRAVITY_EARTH * 6.0f) / 1024.0f, //
245 static int open_sensors(const struct hw_module_t* module, const char* name,
246 struct hw_device_t** device);
248 static int sensors__get_sensors_list(struct sensors_module_t* module,
249 struct sensor_t const** list) {
252 return ARRAY_SIZE(sSensorList);
255 static struct hw_module_methods_t sensors_module_methods = {
256 .open = open_sensors };
258 const struct sensors_module_t HAL_MODULE_INFO_SYM = { //
260 .tag = HARDWARE_MODULE_TAG, //
261 .version_major = 1, //
262 .version_minor = 0, //
263 .id = SENSORS_HARDWARE_MODULE_ID, //
264 .name = "hdaps accelerometer sensor", //
265 .author = "Stefan Seidel", //
266 .methods = &sensors_module_methods, //
270 get_sensors_list : sensors__get_sensors_list //
273 static int open_sensors(const struct hw_module_t* module, const char* name,
274 struct hw_device_t** device) {
275 int status = -EINVAL;
277 struct sensors_poll_context_t *dev = malloc(
278 sizeof(struct sensors_poll_context_t));
279 memset(&dev->device, 0, sizeof(struct sensors_poll_device_t));
281 dev->device.common.tag = HARDWARE_DEVICE_TAG;
282 dev->device.common.version = 0;
283 dev->device.common.module = (struct hw_module_t*) module;
284 dev->device.common.close = common__close;
285 dev->device.activate = device__activate;
286 dev->device.setDelay = device__set_delay;
287 dev->device.poll = device__poll;
289 if (sensor_get_class_path(dev) < 0) {
290 LOGE("g sensor get class path error \n");
292 dev->fd = open_input_device();
293 *device = &dev->device.common;