• 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 <cutils/log.h>
25 
26 #include "AdxlSensor.h"
27 
28 #define ADXL_DATA_NAME				"ADXL34x accelerometer"
29 #define ADXL_MAX_SAMPLE_RATE_VAL	11 /* 200 Hz */
30 
31 #define ADXL_UNIT_CONVERSION(value) ((value) * GRAVITY_EARTH / (256.0f))
32 
33 /*****************************************************************************/
34 
AdxlSensor()35 AdxlSensor::AdxlSensor()
36     : SensorBase(NULL, ADXL_DATA_NAME),
37       mEnabled(0),
38       mDelay(-1),
39       mInputReader(4),
40       mHasPendingEvent(false)
41 {
42     mPendingEvent.version = sizeof(sensors_event_t);
43     mPendingEvent.sensor = ID_A;
44     mPendingEvent.type = SENSOR_TYPE_ACCELEROMETER;
45     memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));
46 
47     if (data_fd >= 0) {
48         strcpy(input_sysfs_path, "/sys/class/input/");
49         strcat(input_sysfs_path, input_name);
50         strcat(input_sysfs_path, "/device/device/");
51         input_sysfs_path_len = strlen(input_sysfs_path);
52 		ALOGD("AdxlSensor: sysfs_path=%s", input_sysfs_path);
53     } else {
54 		input_sysfs_path[0] = '\0';
55 		input_sysfs_path_len = 0;
56 	}
57 }
58 
~AdxlSensor()59 AdxlSensor::~AdxlSensor() {
60     if (mEnabled) {
61         setEnable(0, 0);
62     }
63 }
64 
setInitialState()65 int AdxlSensor::setInitialState() {
66     struct input_absinfo absinfo;
67 
68 	if (mEnabled) {
69     	if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_X), &absinfo)) {
70 			mPendingEvent.acceleration.x = ADXL_UNIT_CONVERSION(absinfo.value);
71 		}
72     	if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Y), &absinfo)) {
73 			mPendingEvent.acceleration.y = ADXL_UNIT_CONVERSION(absinfo.value);
74 		}
75 		if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Z), &absinfo)) {
76 			mPendingEvent.acceleration.z = ADXL_UNIT_CONVERSION(absinfo.value);
77 		}
78 	}
79     return 0;
80 }
81 
hasPendingEvents() const82 bool AdxlSensor::hasPendingEvents() const {
83     return mHasPendingEvent;
84 }
85 
setEnable(int32_t handle,int enabled)86 int AdxlSensor::setEnable(int32_t handle, int enabled) {
87     int err = 0;
88 	char buffer[2];
89 
90 	/* handle check */
91 	if (handle != ID_A) {
92 		ALOGE("AdxlSensor: Invalid handle (%d)", handle);
93 		return -EINVAL;
94 	}
95 
96 	buffer[0] = '\0';
97 	buffer[1] = '\0';
98 
99 	if (mEnabled <= 0) {
100 		if(enabled) buffer[0] = '0';
101 	} else if (mEnabled == 1) {
102 		if(!enabled) buffer[0] = '1';
103 	}
104     if (buffer[0] != '\0') {
105         strcpy(&input_sysfs_path[input_sysfs_path_len], "disable");
106 		err = write_sys_attribute(input_sysfs_path, buffer, 1);
107 		if (err != 0) {
108 			return err;
109 		}
110 		ALOGD("AdxlSensor: Control set %s", buffer);
111    		setInitialState();
112     }
113 
114 	if (enabled) {
115 		mEnabled++;
116 		if (mEnabled > 32767) mEnabled = 32767;
117 	} else {
118 		mEnabled--;
119 		if (mEnabled < 0) mEnabled = 0;
120 	}
121 	ALOGD("AdxlSensor: mEnabled = %d", mEnabled);
122 
123     return err;
124 }
125 
setDelay(int32_t handle,int64_t delay_ns)126 int AdxlSensor::setDelay(int32_t handle, int64_t delay_ns)
127 {
128 	int err = 0;
129 	int rate_val;
130 	int32_t us;
131 	char buffer[16];
132 	int bytes;
133 
134 	/* handle check */
135 	if (handle != ID_A) {
136 		ALOGE("AdxlSensor: Invalid handle (%d)", handle);
137 		return -EINVAL;
138 	}
139 
140 	if (mDelay != delay_ns) {
141 		/*
142 	 	* The ADXL34x Supports 16 sample rates ranging from 3200Hz-0.098Hz
143 	 	* Calculate best fit and limit to max 200Hz (rate_val 11)
144 	 	*/
145 
146 		us = (int32_t)(delay_ns / 1000);
147 		for (rate_val = 0; rate_val < 16; rate_val++)
148 			if (us  >= ((10000000) >> rate_val))
149 				break;
150 
151 		if (rate_val > ADXL_MAX_SAMPLE_RATE_VAL) {
152 			rate_val = ADXL_MAX_SAMPLE_RATE_VAL;
153 		}
154 
155     	strcpy(&input_sysfs_path[input_sysfs_path_len], "rate");
156    		bytes = sprintf(buffer, "%d", rate_val);
157 		err = write_sys_attribute(input_sysfs_path, buffer, bytes);
158 		if (err == 0) {
159 			mDelay = delay_ns;
160 			ALOGD("AdxlSensor: Control set delay %f ms requetsed, using %f ms",
161 				delay_ns/1000000.0f, 1e6 / (3200000 >> (15 - rate_val)));
162 		}
163 	}
164 
165 	return err;
166 }
167 
getDelay(int32_t handle)168 int64_t AdxlSensor::getDelay(int32_t handle)
169 {
170 	return (handle == ID_A) ? mDelay : 0;
171 }
172 
getEnable(int32_t handle)173 int AdxlSensor::getEnable(int32_t handle)
174 {
175 	return (handle == ID_A) ? mEnabled : 0;
176 }
177 
readEvents(sensors_event_t * data,int count)178 int AdxlSensor::readEvents(sensors_event_t* data, int count)
179 {
180     if (count < 1)
181         return -EINVAL;
182 
183     if (mHasPendingEvent) {
184         mHasPendingEvent = false;
185         mPendingEvent.timestamp = getTimestamp();
186         *data = mPendingEvent;
187         return mEnabled ? 1 : 0;
188     }
189 
190     ssize_t n = mInputReader.fill(data_fd);
191     if (n < 0)
192         return n;
193 
194     int numEventReceived = 0;
195     input_event const* event;
196 
197     while (count && mInputReader.readEvent(&event)) {
198         int type = event->type;
199         if (type == EV_ABS) {
200             float value = event->value;
201             if (event->code == EVENT_TYPE_ACCEL_X) {
202                 mPendingEvent.acceleration.x = ADXL_UNIT_CONVERSION(value);
203             } else if (event->code == EVENT_TYPE_ACCEL_Y) {
204                 mPendingEvent.acceleration.y = ADXL_UNIT_CONVERSION(value);
205             } else if (event->code == EVENT_TYPE_ACCEL_Z) {
206                 mPendingEvent.acceleration.z = ADXL_UNIT_CONVERSION(value);
207             }
208         } else if (type == EV_SYN) {
209             mPendingEvent.timestamp = timevalToNano(event->time);
210             if (mEnabled) {
211                 *data++ = mPendingEvent;
212                 count--;
213                 numEventReceived++;
214             }
215         } else {
216             ALOGE("AdxlSensor: unknown event (type=%d, code=%d)",
217                     type, event->code);
218         }
219         mInputReader.next();
220     }
221 
222     return numEventReceived;
223 }
224 
225