blob: dd17afc7a4ded12b237cb9822798d7b06a7638b4 [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 <linux/akm8975.h>
25#include <cutils/log.h>
26#include "AkmSensor.h"
27#include "sensors.h"
28
29#define SENSOR_STATE_MASK (0x7FFF)
30
31#define AKM_DEVICE_NAME "/dev/akm8975_aot"
32
33#define ID_A SENSORS_ACCELERATION_HANDLE
34#define ID_M SENSORS_MAGNETIC_FIELD_HANDLE
35#define ID_O SENSORS_ORIENTATION_HANDLE
36
37#define EVENT_TYPE_ACCEL_X REL_X
38#define EVENT_TYPE_ACCEL_Y REL_Y
39#define EVENT_TYPE_ACCEL_Z REL_Z
40
41#define EVENT_TYPE_YAW REL_RX
42#define EVENT_TYPE_PITCH REL_RY
43#define EVENT_TYPE_ROLL REL_RZ
44#define EVENT_TYPE_ORIENT_STATUS REL_HWHEEL
45
46#define EVENT_TYPE_MAGV_X REL_DIAL
47#define EVENT_TYPE_MAGV_Y REL_WHEEL
48#define EVENT_TYPE_MAGV_Z REL_MISC
49
50// 1024 LSG = 1G
51#define LSG (1024.0f)
52#define MAX_RANGE_A (2*GRAVITY_EARTH)
53// conversion of acceleration data to SI units (m/s^2)
54#define CONVERT_A (GRAVITY_EARTH / LSG)
55#define CONVERT_A_X (CONVERT_A)
56#define CONVERT_A_Y (CONVERT_A)
57#define CONVERT_A_Z (CONVERT_A)
58
59// conversion of magnetic data to uT units
60#define CONVERT_M (1.0f/16.0f)
61#define CONVERT_M_X (CONVERT_M)
62#define CONVERT_M_Y (CONVERT_M)
63#define CONVERT_M_Z (CONVERT_M)
64
65#define CONVERT_O (1.0f/64.0f)
66#define CONVERT_O_Y (CONVERT_O)
67#define CONVERT_O_P (CONVERT_O)
68#define CONVERT_O_R (-CONVERT_O)
69
70/*****************************************************************************/
71
72AkmSensor::AkmSensor()
73 : SensorBase(AKM_DEVICE_NAME, "compass"),
74 mEnabled(0),
75 mPendingMask(0),
76 mInputReader(32)
77{
78 memset(mPendingEvents, 0, sizeof(mPendingEvents));
79
80 mPendingEvents[Accelerometer].version = sizeof(sensors_event_t);
81 mPendingEvents[Accelerometer].sensor = ID_A;
82 mPendingEvents[Accelerometer].type = SENSOR_TYPE_ACCELEROMETER;
83 mPendingEvents[Accelerometer].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;
84
85 mPendingEvents[MagneticField].version = sizeof(sensors_event_t);
86 mPendingEvents[MagneticField].sensor = ID_M;
87 mPendingEvents[MagneticField].type = SENSOR_TYPE_MAGNETIC_FIELD;
88 mPendingEvents[MagneticField].magnetic.status = SENSOR_STATUS_ACCURACY_HIGH;
89
90 mPendingEvents[Orientation ].version = sizeof(sensors_event_t);
91 mPendingEvents[Orientation ].sensor = ID_O;
92 mPendingEvents[Orientation ].type = SENSOR_TYPE_ORIENTATION;
93 mPendingEvents[Orientation ].orientation.status = SENSOR_STATUS_ACCURACY_HIGH;
94
95 for (int i=0 ; i<numSensors ; i++)
96 mDelays[i] = 200000000; // 200 ms by default
97
98 // read the actual value of all sensors if they're enabled already
99 struct input_absinfo absinfo;
100 short flags = 0;
101
102 open_device();
103
104 if (!ioctl(dev_fd, ECS_IOCTL_APP_GET_AFLAG, &flags)) {
105 if (flags) {
106 mEnabled |= 1<<Accelerometer;
107 }
108 }
109 if (!ioctl(dev_fd, ECS_IOCTL_APP_GET_MVFLAG, &flags)) {
110 if (flags) {
111 mEnabled |= 1<<MagneticField;
112 }
113 }
114 if (!ioctl(dev_fd, ECS_IOCTL_APP_GET_MFLAG, &flags)) {
115 if (flags) {
116 mEnabled |= 1<<Orientation;
117 }
118 }
119 if (!mEnabled) {
120 close_device();
121 }
122}
123
124AkmSensor::~AkmSensor() {
125}
126
127int AkmSensor::enable(int32_t handle, int en)
128{
129 int what = -1;
130 switch (handle) {
131 case ID_A: what = Accelerometer; break;
132 case ID_M: what = MagneticField; break;
133 case ID_O: what = Orientation; break;
134 }
135
136 if (uint32_t(what) >= numSensors)
137 return -EINVAL;
138
139 int newState = en ? 1 : 0;
140 int err = 0;
141
142 if ((uint32_t(newState)<<what) != (mEnabled & (1<<what))) {
143 if (!mEnabled) {
144 open_device();
145 }
146 int cmd;
147 switch (what) {
148 case Accelerometer: cmd = ECS_IOCTL_APP_SET_AFLAG; break;
149 case MagneticField: cmd = ECS_IOCTL_APP_SET_MVFLAG; break;
150 case Orientation: cmd = ECS_IOCTL_APP_SET_MFLAG; break;
151 }
152 short flags = newState;
153 err = ioctl(dev_fd, cmd, &flags);
154 err = err<0 ? -errno : 0;
155 ALOGE_IF(err, "ECS_IOCTL_APP_SET_XXX failed (%s)", strerror(-err));
156 if (!err) {
157 mEnabled &= ~(1<<what);
158 mEnabled |= (uint32_t(flags)<<what);
159 update_delay();
160 }
161 if (!mEnabled) {
162 close_device();
163 }
164 }
165 return err;
166}
167
168int AkmSensor::setDelay(int32_t handle, int64_t ns)
169{
170#ifdef ECS_IOCTL_APP_SET_DELAY
171 int what = -1;
172 switch (handle) {
173 case ID_A: what = Accelerometer; break;
174 case ID_M: what = MagneticField; break;
175 case ID_O: what = Orientation; break;
176 }
177
178 if (uint32_t(what) >= numSensors)
179 return -EINVAL;
180
181 if (ns < 0)
182 return -EINVAL;
183
184 mDelays[what] = ns;
185 return update_delay();
186#else
187 return -1;
188#endif
189}
190
191int AkmSensor::update_delay()
192{
193 if (mEnabled) {
194 uint64_t wanted = -1LLU;
195 for (int i=0 ; i<numSensors ; i++) {
196 if (mEnabled & (1<<i)) {
197 uint64_t ns = mDelays[i];
198 wanted = wanted < ns ? wanted : ns;
199 }
200 }
201 short delay = int64_t(wanted) / 1000000;
202 if (ioctl(dev_fd, ECS_IOCTL_APP_SET_DELAY, &delay)) {
203 return -errno;
204 }
205 }
206 return 0;
207}
208
209int AkmSensor::readEvents(sensors_event_t* data, int count)
210{
211 if (count < 1)
212 return -EINVAL;
213
214 ssize_t n = mInputReader.fill(data_fd);
215 if (n < 0)
216 return n;
217
218 int numEventReceived = 0;
219 input_event const* event;
220
221 while (count && mInputReader.readEvent(&event)) {
222 int type = event->type;
223 if (type == EV_REL) {
224 processEvent(event->code, event->value);
225 mInputReader.next();
226 } else if (type == EV_SYN) {
227 int64_t time = timevalToNano(event->time);
228 for (int j=0 ; count && mPendingMask && j<numSensors ; j++) {
229 if (mPendingMask & (1<<j)) {
230 mPendingMask &= ~(1<<j);
231 mPendingEvents[j].timestamp = time;
232 if (mEnabled & (1<<j)) {
233 *data++ = mPendingEvents[j];
234 count--;
235 numEventReceived++;
236 }
237 }
238 }
239 if (!mPendingMask) {
240 mInputReader.next();
241 }
242 } else {
243 ALOGE("AkmSensor: unknown event (type=%d, code=%d)",
244 type, event->code);
245 mInputReader.next();
246 }
247 }
248
249 return numEventReceived;
250}
251
252void AkmSensor::processEvent(int code, int value)
253{
254 switch (code) {
255 case EVENT_TYPE_ACCEL_X:
256 mPendingMask |= 1<<Accelerometer;
257 mPendingEvents[Accelerometer].acceleration.x = value * CONVERT_A_X;
258 break;
259 case EVENT_TYPE_ACCEL_Y:
260 mPendingMask |= 1<<Accelerometer;
261 mPendingEvents[Accelerometer].acceleration.y = value * CONVERT_A_Y;
262 break;
263 case EVENT_TYPE_ACCEL_Z:
264 mPendingMask |= 1<<Accelerometer;
265 mPendingEvents[Accelerometer].acceleration.z = value * CONVERT_A_Z;
266 break;
267
268 case EVENT_TYPE_MAGV_X:
269 mPendingMask |= 1<<MagneticField;
270 mPendingEvents[MagneticField].magnetic.x = value * CONVERT_M_X;
271 break;
272 case EVENT_TYPE_MAGV_Y:
273 mPendingMask |= 1<<MagneticField;
274 mPendingEvents[MagneticField].magnetic.y = value * CONVERT_M_Y;
275 break;
276 case EVENT_TYPE_MAGV_Z:
277 mPendingMask |= 1<<MagneticField;
278 mPendingEvents[MagneticField].magnetic.z = value * CONVERT_M_Z;
279 break;
280
281 case EVENT_TYPE_YAW:
282 mPendingMask |= 1<<Orientation;
283 mPendingEvents[Orientation].orientation.azimuth = value * CONVERT_O_Y;
284 break;
285 case EVENT_TYPE_PITCH:
286 mPendingMask |= 1<<Orientation;
287 mPendingEvents[Orientation].orientation.pitch = value * CONVERT_O_P;
288 break;
289 case EVENT_TYPE_ROLL:
290 mPendingMask |= 1<<Orientation;
291 mPendingEvents[Orientation].orientation.roll = value * CONVERT_O_R;
292 break;
293 case EVENT_TYPE_ORIENT_STATUS:
294 mPendingMask |= 1<<Orientation;
295 mPendingEvents[Orientation].orientation.status =
296 uint8_t(value & SENSOR_STATE_MASK);
297 break;
298 }
299}