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