blob: a39dff3badd71dca962b3d592baf4025466358d8 [file] [log] [blame]
Wentao Xudb82bb12013-01-14 18:26:04 -05001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <fcntl.h>
18#include <errno.h>
19#include <math.h>
20#include <poll.h>
21#include <unistd.h>
22#include <dirent.h>
23#include <sys/select.h>
24#include <cutils/log.h>
25
26#include "AccelSensor.h"
27#include "sensors.h"
28
29#define FETCH_FULL_EVENT_BEFORE_RETURN 1
30#define IGNORE_EVENT_TIME 10000000
31
32#define EVENT_TYPE_ACCEL_X ABS_X
33#define EVENT_TYPE_ACCEL_Y ABS_Y
34#define EVENT_TYPE_ACCEL_Z ABS_Z
35
Figo Wang6a20e3e2013-06-15 00:24:22 +080036#define ACCEL_CONVERT ((GRAVITY_EARTH) / 1024)
37#define CONVERT_ACCEL_X ACCEL_CONVERT
38#define CONVERT_ACCEL_Y ACCEL_CONVERT
39#define CONVERT_ACCEL_Z ACCEL_CONVERT
Wentao Xudb82bb12013-01-14 18:26:04 -050040
Xiaocheng Lidc760812013-07-08 19:11:41 -070041#define SYSFS_I2C_SLAVE_PATH "/device/device/"
42#define SYSFS_INPUT_DEV_PATH "/device/"
43
Wentao Xudb82bb12013-01-14 18:26:04 -050044/*****************************************************************************/
45
46AccelSensor::AccelSensor()
Figo Wang6a20e3e2013-06-15 00:24:22 +080047 : SensorBase(NULL, "accelerometer"),
Wentao Xudb82bb12013-01-14 18:26:04 -050048 mEnabled(0),
49 mInputReader(4),
50 mHasPendingEvent(false),
51 mEnabledTime(0)
52{
53 mPendingEvent.version = sizeof(sensors_event_t);
54 mPendingEvent.sensor = SENSORS_ACCELERATION_HANDLE;
55 mPendingEvent.type = SENSOR_TYPE_ACCELEROMETER;
56 memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));
57
58 if (data_fd) {
59 strcpy(input_sysfs_path, "/sys/class/input/");
60 strcat(input_sysfs_path, input_name);
Xiaocheng Lidc760812013-07-08 19:11:41 -070061 strcat(input_sysfs_path, SYSFS_I2C_SLAVE_PATH);
Wentao Xudb82bb12013-01-14 18:26:04 -050062 input_sysfs_path_len = strlen(input_sysfs_path);
Xiaocheng Lidc760812013-07-08 19:11:41 -070063#ifdef TARGET_8610
64 if (access(input_sysfs_path, F_OK)) {
65 input_sysfs_path_len -= strlen(SYSFS_I2C_SLAVE_PATH);
66 strcpy(&input_sysfs_path[input_sysfs_path_len],
67 SYSFS_INPUT_DEV_PATH);
68 input_sysfs_path_len += strlen(SYSFS_INPUT_DEV_PATH);
69 }
70#endif
Wentao Xudb82bb12013-01-14 18:26:04 -050071 enable(0, 1);
72 }
73}
74
Jie Cheng4b6344d2013-12-30 13:31:49 +080075AccelSensor::AccelSensor(char *name)
76 : SensorBase(NULL, "accelerometer"),
77 mEnabled(0),
78 mInputReader(4),
79 mHasPendingEvent(false),
80 mEnabledTime(0)
81{
82 mPendingEvent.version = sizeof(sensors_event_t);
83 mPendingEvent.sensor = SENSORS_ACCELERATION_HANDLE;
84 mPendingEvent.type = SENSOR_TYPE_ACCELEROMETER;
85 memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));
86
87 if (data_fd) {
88 strlcpy(input_sysfs_path, SYSFS_CLASS, sizeof(input_sysfs_path));
89 strlcat(input_sysfs_path, "/", sizeof(input_sysfs_path));
90 strlcat(input_sysfs_path, name, sizeof(input_sysfs_path));
91 strlcat(input_sysfs_path, "/", sizeof(input_sysfs_path));
92 input_sysfs_path_len = strlen(input_sysfs_path);
Jie Chengfab048f2014-01-06 15:48:40 +080093 ALOGI("The accel sensor path is %s",input_sysfs_path);
Jie Cheng4b6344d2013-12-30 13:31:49 +080094 enable(0, 1);
95 }
Jie Cheng4b6344d2013-12-30 13:31:49 +080096}
97
Wentao Xudb82bb12013-01-14 18:26:04 -050098AccelSensor::~AccelSensor() {
99 if (mEnabled) {
100 enable(0, 0);
101 }
102}
103
104int AccelSensor::setInitialState() {
105 struct input_absinfo absinfo_x;
106 struct input_absinfo absinfo_y;
107 struct input_absinfo absinfo_z;
108 float value;
109 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_X), &absinfo_x) &&
110 !ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Y), &absinfo_y) &&
111 !ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Z), &absinfo_z)) {
112 value = absinfo_x.value;
113 mPendingEvent.data[0] = value * CONVERT_ACCEL_X;
114 value = absinfo_y.value;
115 mPendingEvent.data[1] = value * CONVERT_ACCEL_Y;
116 value = absinfo_z.value;
117 mPendingEvent.data[2] = value * CONVERT_ACCEL_Z;
118 mHasPendingEvent = true;
119 }
120 return 0;
121}
122
123int AccelSensor::enable(int32_t, int en) {
124 int flags = en ? 1 : 0;
125 if (flags != mEnabled) {
Wentao Xudb82bb12013-01-14 18:26:04 -0500126 int fd;
Jie Chengfab048f2014-01-06 15:48:40 +0800127 strlcpy(&input_sysfs_path[input_sysfs_path_len],
128 SYSFS_ENABLE, SYSFS_MAXLEN);
Wentao Xudb82bb12013-01-14 18:26:04 -0500129 fd = open(input_sysfs_path, O_RDWR);
130 if (fd >= 0) {
131 char buf[2];
132 int err;
133 buf[1] = 0;
134 if (flags) {
135 buf[0] = '1';
136 mEnabledTime = getTimestamp() + IGNORE_EVENT_TIME;
137 } else {
138 buf[0] = '0';
139 }
140 err = write(fd, buf, sizeof(buf));
141 close(fd);
142 mEnabled = flags;
143 setInitialState();
144 return 0;
145 }
Figo Wang6a20e3e2013-06-15 00:24:22 +0800146 ALOGE("AccelSensor: failed to open %s", input_sysfs_path);
Wentao Xudb82bb12013-01-14 18:26:04 -0500147 return -1;
Wentao Xudb82bb12013-01-14 18:26:04 -0500148 }
149 return 0;
150}
151
152bool AccelSensor::hasPendingEvents() const {
153 return mHasPendingEvent;
154}
155
156int AccelSensor::setDelay(int32_t handle, int64_t delay_ns)
157{
158 int fd;
159 int delay_ms = delay_ns / 1000000;
Jie Chengfab048f2014-01-06 15:48:40 +0800160 strlcpy(&input_sysfs_path[input_sysfs_path_len],
161 SYSFS_POLL_DELAY, SYSFS_MAXLEN);
Wentao Xudb82bb12013-01-14 18:26:04 -0500162 fd = open(input_sysfs_path, O_RDWR);
163 if (fd >= 0) {
164 char buf[80];
165 sprintf(buf, "%d", delay_ms);
166 write(fd, buf, strlen(buf)+1);
167 close(fd);
168 return 0;
169 }
170 return -1;
171}
172
173int AccelSensor::readEvents(sensors_event_t* data, int count)
174{
175 if (count < 1)
176 return -EINVAL;
177
178 if (mHasPendingEvent) {
179 mHasPendingEvent = false;
180 mPendingEvent.timestamp = getTimestamp();
181 *data = mPendingEvent;
182 return mEnabled ? 1 : 0;
183 }
184
185 ssize_t n = mInputReader.fill(data_fd);
186 if (n < 0)
187 return n;
188
189 int numEventReceived = 0;
190 input_event const* event;
191
192#if FETCH_FULL_EVENT_BEFORE_RETURN
193again:
194#endif
195 while (count && mInputReader.readEvent(&event)) {
196 int type = event->type;
197 if (type == EV_ABS) {
198 float value = event->value;
199 if (event->code == EVENT_TYPE_ACCEL_X) {
200 mPendingEvent.data[0] = value * CONVERT_ACCEL_X;
201 } else if (event->code == EVENT_TYPE_ACCEL_Y) {
202 mPendingEvent.data[1] = value * CONVERT_ACCEL_Y;
203 } else if (event->code == EVENT_TYPE_ACCEL_Z) {
204 mPendingEvent.data[2] = value * CONVERT_ACCEL_Z;
205 }
206 } else if (type == EV_SYN) {
207 mPendingEvent.timestamp = timevalToNano(event->time);
208 if (mEnabled) {
209 if (mPendingEvent.timestamp >= mEnabledTime) {
210 *data++ = mPendingEvent;
211 numEventReceived++;
212 }
213 count--;
214 }
215 } else {
216 ALOGE("AccelSensor: unknown event (type=%d, code=%d)",
217 type, event->code);
218 }
219 mInputReader.next();
220 }
221
222#if FETCH_FULL_EVENT_BEFORE_RETURN
223 /* if we didn't read a complete event, see if we can fill and
224 try again instead of returning with nothing and redoing poll. */
225 if (numEventReceived == 0 && mEnabled == 1) {
226 n = mInputReader.fill(data_fd);
227 if (n)
228 goto again;
229 }
230#endif
231
232 return numEventReceived;
233}
234