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