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
35AkmSensor::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
70AkmSensor::~AkmSensor()
71{
72	for (int i=0; i<numSensors; i++) {
73		setEnable(i, 0);
74	}
75}
76
77int 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
135int 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
175int64_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
185int 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
195int 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
241int 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
259int 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
274void 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