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