• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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