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