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 <string.h>
22 #include <unistd.h>
23 #include <dirent.h>
24 #include <sys/select.h>
25 #include <dlfcn.h>
26
27 #include <cutils/log.h>
28
29 #include "AkmSensor.h"
30
31 #define AKMD_DEFAULT_INTERVAL 200000000
32
33 /*****************************************************************************/
34
AkmSensor()35 AkmSensor::AkmSensor()
36 : SensorBase(NULL, "compass"),
37 mPendingMask(0),
38 mInputReader(32)
39 {
40 for (int i=0; i<numSensors; i++) {
41 mEnabled[i] = 0;
42 mDelay[i] = -1;
43 }
44 memset(mPendingEvents, 0, sizeof(mPendingEvents));
45
46 mPendingEvents[Accelerometer].version = sizeof(sensors_event_t);
47 mPendingEvents[Accelerometer].sensor = ID_A;
48 mPendingEvents[Accelerometer].type = SENSOR_TYPE_ACCELEROMETER;
49 mPendingEvents[Accelerometer].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;
50
51 mPendingEvents[MagneticField].version = sizeof(sensors_event_t);
52 mPendingEvents[MagneticField].sensor = ID_M;
53 mPendingEvents[MagneticField].type = SENSOR_TYPE_MAGNETIC_FIELD;
54 mPendingEvents[MagneticField].magnetic.status = SENSOR_STATUS_ACCURACY_HIGH;
55
56 mPendingEvents[Orientation ].version = sizeof(sensors_event_t);
57 mPendingEvents[Orientation ].sensor = ID_O;
58 mPendingEvents[Orientation ].type = SENSOR_TYPE_ORIENTATION;
59 mPendingEvents[Orientation ].orientation.status = SENSOR_STATUS_ACCURACY_HIGH;
60
61 if (data_fd) {
62 strcpy(input_sysfs_path, "/sys/class/compass/akm8975/");
63 input_sysfs_path_len = strlen(input_sysfs_path);
64 } else {
65 input_sysfs_path[0] = '\0';
66 input_sysfs_path_len = 0;
67 }
68 }
69
~AkmSensor()70 AkmSensor::~AkmSensor()
71 {
72 for (int i=0; i<numSensors; i++) {
73 setEnable(i, 0);
74 }
75 }
76
setEnable(int32_t handle,int enabled)77 int AkmSensor::setEnable(int32_t handle, int enabled)
78 {
79 int id = handle2id(handle);
80 int err = 0;
81 char buffer[2];
82
83 switch (id) {
84 case Accelerometer:
85 strcpy(&input_sysfs_path[input_sysfs_path_len], "enable_acc");
86 break;
87 case MagneticField:
88 strcpy(&input_sysfs_path[input_sysfs_path_len], "enable_mag");
89 break;
90 case Orientation:
91 strcpy(&input_sysfs_path[input_sysfs_path_len], "enable_ori");
92 break;
93 default:
94 ALOGE("AkmSensor: unknown handle (%d)", handle);
95 return -EINVAL;
96 }
97
98 buffer[0] = '\0';
99 buffer[1] = '\0';
100
101 if (mEnabled[id] <= 0) {
102 if(enabled) buffer[0] = '1';
103 } else if (mEnabled[id] == 1) {
104 if(!enabled) buffer[0] = '0';
105 }
106
107 if (buffer[0] != '\0') {
108 err = write_sys_attribute(input_sysfs_path, buffer, 1);
109 if (err != 0) {
110 return err;
111 }
112 ALOGD("AkmSensor: set %s to %s",
113 &input_sysfs_path[input_sysfs_path_len], buffer);
114
115 /* for AKMD specification */
116 if (buffer[0] == '1') {
117 setDelay(handle, AKMD_DEFAULT_INTERVAL);
118 } else {
119 setDelay(handle, -1);
120 }
121 }
122
123 if (enabled) {
124 (mEnabled[id])++;
125 if (mEnabled[id] > 32767) mEnabled[id] = 32767;
126 } else {
127 (mEnabled[id])--;
128 if (mEnabled[id] < 0) mEnabled[id] = 0;
129 }
130 ALOGD("AkmSensor: mEnabled[%d] = %d", id, mEnabled[id]);
131
132 return err;
133 }
134
setDelay(int32_t handle,int64_t ns)135 int AkmSensor::setDelay(int32_t handle, int64_t ns)
136 {
137 int id = handle2id(handle);
138 int err = 0;
139 char buffer[32];
140 int bytes;
141
142 if (ns < -1 || 2147483647 < ns) {
143 ALOGE("AkmSensor: invalid delay (%lld)", ns);
144 return -EINVAL;
145 }
146
147 switch (id) {
148 case Accelerometer:
149 strcpy(&input_sysfs_path[input_sysfs_path_len], "delay_acc");
150 break;
151 case MagneticField:
152 strcpy(&input_sysfs_path[input_sysfs_path_len], "delay_mag");
153 break;
154 case Orientation:
155 strcpy(&input_sysfs_path[input_sysfs_path_len], "delay_ori");
156 break;
157 default:
158 ALOGE("AkmSensor: unknown handle (%d)", handle);
159 return -EINVAL;
160 }
161
162 if (ns != mDelay[id]) {
163 bytes = sprintf(buffer, "%lld", ns);
164 err = write_sys_attribute(input_sysfs_path, buffer, bytes);
165 if (err == 0) {
166 mDelay[id] = ns;
167 ALOGD("AkmSensor: set %s to %f ms.",
168 &input_sysfs_path[input_sysfs_path_len], ns/1000000.0f);
169 }
170 }
171
172 return err;
173 }
174
getDelay(int32_t handle)175 int64_t AkmSensor::getDelay(int32_t handle)
176 {
177 int id = handle2id(handle);
178 if (id > 0) {
179 return mDelay[id];
180 } else {
181 return 0;
182 }
183 }
184
getEnable(int32_t handle)185 int AkmSensor::getEnable(int32_t handle)
186 {
187 int id = handle2id(handle);
188 if (id >= 0) {
189 return mEnabled[id];
190 } else {
191 return 0;
192 }
193 }
194
readEvents(sensors_event_t * data,int count)195 int AkmSensor::readEvents(sensors_event_t* data, int count)
196 {
197 if (count < 1)
198 return -EINVAL;
199
200 ssize_t n = mInputReader.fill(data_fd);
201 if (n < 0)
202 return n;
203
204 int numEventReceived = 0;
205 input_event const* event;
206
207 while (count && mInputReader.readEvent(&event)) {
208 int type = event->type;
209 if (type == EV_ABS) {
210 processEvent(event->code, event->value);
211 mInputReader.next();
212 } else if (type == EV_SYN) {
213 int64_t time = timevalToNano(event->time);
214 for (int j=0 ; count && mPendingMask && j<numSensors ; j++) {
215 if (mPendingMask & (1<<j)) {
216 mPendingMask &= ~(1<<j);
217 mPendingEvents[j].timestamp = time;
218 //ALOGD("data=%8.5f,%8.5f,%8.5f",
219 //mPendingEvents[j].data[0],
220 //mPendingEvents[j].data[1],
221 //mPendingEvents[j].data[2]);
222 if (mEnabled[j]) {
223 *data++ = mPendingEvents[j];
224 count--;
225 numEventReceived++;
226 }
227 }
228 }
229 if (!mPendingMask) {
230 mInputReader.next();
231 }
232 } else {
233 ALOGE("AkmSensor: unknown event (type=%d, code=%d)",
234 type, event->code);
235 mInputReader.next();
236 }
237 }
238 return numEventReceived;
239 }
240
setAccel(sensors_event_t * data)241 int AkmSensor::setAccel(sensors_event_t* data)
242 {
243 int err;
244 int16_t acc[3];
245
246 acc[0] = (int16_t)(data->acceleration.x / GRAVITY_EARTH * AKSC_LSG);
247 acc[1] = (int16_t)(data->acceleration.y / GRAVITY_EARTH * AKSC_LSG);
248 acc[2] = (int16_t)(data->acceleration.z / GRAVITY_EARTH * AKSC_LSG);
249
250 strcpy(&input_sysfs_path[input_sysfs_path_len], "accel");
251 err = write_sys_attribute(input_sysfs_path, (char*)acc, 6);
252 if (err < 0) {
253 ALOGD("AkmSensor: %s write failed.",
254 &input_sysfs_path[input_sysfs_path_len]);
255 }
256 return err;
257 }
258
handle2id(int32_t handle)259 int AkmSensor::handle2id(int32_t handle)
260 {
261 switch (handle) {
262 case ID_A:
263 return Accelerometer;
264 case ID_M:
265 return MagneticField;
266 case ID_O:
267 return Orientation;
268 default:
269 ALOGE("AkmSensor: unknown handle (%d)", handle);
270 return -EINVAL;
271 }
272 }
273
processEvent(int code,int value)274 void AkmSensor::processEvent(int code, int value)
275 {
276 switch (code) {
277 case EVENT_TYPE_ACCEL_X:
278 mPendingMask |= 1<<Accelerometer;
279 mPendingEvents[Accelerometer].acceleration.x = value * CONVERT_A;
280 break;
281 case EVENT_TYPE_ACCEL_Y:
282 mPendingMask |= 1<<Accelerometer;
283 mPendingEvents[Accelerometer].acceleration.y = value * CONVERT_A;
284 break;
285 case EVENT_TYPE_ACCEL_Z:
286 mPendingMask |= 1<<Accelerometer;
287 mPendingEvents[Accelerometer].acceleration.z = value * CONVERT_A;
288 break;
289
290 case EVENT_TYPE_MAGV_X:
291 mPendingMask |= 1<<MagneticField;
292 mPendingEvents[MagneticField].magnetic.x = value * CONVERT_M;
293 break;
294 case EVENT_TYPE_MAGV_Y:
295 mPendingMask |= 1<<MagneticField;
296 mPendingEvents[MagneticField].magnetic.y = value * CONVERT_M;
297 break;
298 case EVENT_TYPE_MAGV_Z:
299 mPendingMask |= 1<<MagneticField;
300 mPendingEvents[MagneticField].magnetic.z = value * CONVERT_M;
301 break;
302 case EVENT_TYPE_MAGV_STATUS:
303 mPendingMask |= 1<<MagneticField;
304 mPendingEvents[MagneticField].magnetic.status = value;
305 break;
306
307 case EVENT_TYPE_YAW:
308 mPendingMask |= 1<<Orientation;
309 mPendingEvents[Orientation].orientation.azimuth = value * CONVERT_O;
310 break;
311 case EVENT_TYPE_PITCH:
312 mPendingMask |= 1<<Orientation;
313 mPendingEvents[Orientation].orientation.pitch = value * CONVERT_O;
314 break;
315 case EVENT_TYPE_ROLL:
316 mPendingMask |= 1<<Orientation;
317 mPendingEvents[Orientation].orientation.roll = value * CONVERT_O;
318 break;
319 case EVENT_TYPE_ORIENT_STATUS:
320 mPendingMask |= 1<<Orientation;
321 mPendingEvents[Orientation].orientation.status = value;
322 break;
323 }
324 }
325