• 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 
25 #include <linux/akm8975.h>
26 
27 #include <cutils/log.h>
28 
29 #include "AkmSensor.h"
30 
31 /*****************************************************************************/
32 
AkmSensor()33 AkmSensor::AkmSensor()
34     : SensorBase(AKM_DEVICE_NAME, "compass"),
35       mEnabled(0),
36       mPendingMask(0),
37       mInputReader(32)
38 {
39     memset(mPendingEvents, 0, sizeof(mPendingEvents));
40 
41     mPendingEvents[Accelerometer].version = sizeof(sensors_event_t);
42     mPendingEvents[Accelerometer].sensor = ID_A;
43     mPendingEvents[Accelerometer].type = SENSOR_TYPE_ACCELEROMETER;
44     mPendingEvents[Accelerometer].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;
45 
46     mPendingEvents[MagneticField].version = sizeof(sensors_event_t);
47     mPendingEvents[MagneticField].sensor = ID_M;
48     mPendingEvents[MagneticField].type = SENSOR_TYPE_MAGNETIC_FIELD;
49     mPendingEvents[MagneticField].magnetic.status = SENSOR_STATUS_ACCURACY_HIGH;
50 
51     mPendingEvents[Orientation  ].version = sizeof(sensors_event_t);
52     mPendingEvents[Orientation  ].sensor = ID_O;
53     mPendingEvents[Orientation  ].type = SENSOR_TYPE_ORIENTATION;
54     mPendingEvents[Orientation  ].orientation.status = SENSOR_STATUS_ACCURACY_HIGH;
55 
56     for (int i=0 ; i<numSensors ; i++)
57         mDelays[i] = 200000000; // 200 ms by default
58 
59     // read the actual value of all sensors if they're enabled already
60     struct input_absinfo absinfo;
61     short flags = 0;
62 
63     open_device();
64 
65     if (!ioctl(dev_fd, ECS_IOCTL_APP_GET_AFLAG, &flags)) {
66         if (flags)  {
67             mEnabled |= 1<<Accelerometer;
68         }
69     }
70     if (!ioctl(dev_fd, ECS_IOCTL_APP_GET_MVFLAG, &flags)) {
71         if (flags)  {
72             mEnabled |= 1<<MagneticField;
73         }
74     }
75     if (!ioctl(dev_fd, ECS_IOCTL_APP_GET_MFLAG, &flags)) {
76         if (flags)  {
77             mEnabled |= 1<<Orientation;
78         }
79     }
80     if (!mEnabled) {
81         close_device();
82     }
83 }
84 
~AkmSensor()85 AkmSensor::~AkmSensor() {
86 }
87 
enable(int32_t handle,int en)88 int AkmSensor::enable(int32_t handle, int en)
89 {
90     int what = -1;
91     switch (handle) {
92         case ID_A: what = Accelerometer; break;
93         case ID_M: what = MagneticField; break;
94         case ID_O: what = Orientation;   break;
95     }
96 
97     if (uint32_t(what) >= numSensors)
98         return -EINVAL;
99 
100     int newState  = en ? 1 : 0;
101     int err = 0;
102 
103     if ((uint32_t(newState)<<what) != (mEnabled & (1<<what))) {
104         if (!mEnabled) {
105             open_device();
106         }
107         int cmd;
108         switch (what) {
109             case Accelerometer: cmd = ECS_IOCTL_APP_SET_AFLAG;  break;
110             case MagneticField: cmd = ECS_IOCTL_APP_SET_MVFLAG; break;
111             case Orientation:   cmd = ECS_IOCTL_APP_SET_MFLAG;  break;
112         }
113         short flags = newState;
114         err = ioctl(dev_fd, cmd, &flags);
115         err = err<0 ? -errno : 0;
116         ALOGE_IF(err, "ECS_IOCTL_APP_SET_XXX failed (%s)", strerror(-err));
117         if (!err) {
118             mEnabled &= ~(1<<what);
119             mEnabled |= (uint32_t(flags)<<what);
120             update_delay();
121         }
122         if (!mEnabled) {
123             close_device();
124         }
125     }
126     return err;
127 }
128 
setDelay(int32_t handle,int64_t ns)129 int AkmSensor::setDelay(int32_t handle, int64_t ns)
130 {
131 #ifdef ECS_IOCTL_APP_SET_DELAY
132     int what = -1;
133     switch (handle) {
134         case ID_A: what = Accelerometer; break;
135         case ID_M: what = MagneticField; break;
136         case ID_O: what = Orientation;   break;
137     }
138 
139     if (uint32_t(what) >= numSensors)
140         return -EINVAL;
141 
142     if (ns < 0)
143         return -EINVAL;
144 
145     mDelays[what] = ns;
146     return update_delay();
147 #else
148     return -1;
149 #endif
150 }
151 
update_delay()152 int AkmSensor::update_delay()
153 {
154     if (mEnabled) {
155         uint64_t wanted = -1LLU;
156         for (int i=0 ; i<numSensors ; i++) {
157             if (mEnabled & (1<<i)) {
158                 uint64_t ns = mDelays[i];
159                 wanted = wanted < ns ? wanted : ns;
160             }
161         }
162         short delay = int64_t(wanted) / 1000000;
163         if (ioctl(dev_fd, ECS_IOCTL_APP_SET_DELAY, &delay)) {
164             return -errno;
165         }
166     }
167     return 0;
168 }
169 
readEvents(sensors_event_t * data,int count)170 int AkmSensor::readEvents(sensors_event_t* data, int count)
171 {
172     if (count < 1)
173         return -EINVAL;
174 
175     ssize_t n = mInputReader.fill(data_fd);
176     if (n < 0)
177         return n;
178 
179     int numEventReceived = 0;
180     input_event const* event;
181 
182     while (count && mInputReader.readEvent(&event)) {
183         int type = event->type;
184         if (type == EV_REL) {
185             processEvent(event->code, event->value);
186             mInputReader.next();
187         } else if (type == EV_SYN) {
188             int64_t time = timevalToNano(event->time);
189             for (int j=0 ; count && mPendingMask && j<numSensors ; j++) {
190                 if (mPendingMask & (1<<j)) {
191                     mPendingMask &= ~(1<<j);
192                     mPendingEvents[j].timestamp = time;
193                     if (mEnabled & (1<<j)) {
194                         *data++ = mPendingEvents[j];
195                         count--;
196                         numEventReceived++;
197                     }
198                 }
199             }
200             if (!mPendingMask) {
201                 mInputReader.next();
202             }
203         } else {
204             ALOGE("AkmSensor: unknown event (type=%d, code=%d)",
205                     type, event->code);
206             mInputReader.next();
207         }
208     }
209 
210     return numEventReceived;
211 }
212 
processEvent(int code,int value)213 void AkmSensor::processEvent(int code, int value)
214 {
215     switch (code) {
216         case EVENT_TYPE_ACCEL_X:
217             mPendingMask |= 1<<Accelerometer;
218             mPendingEvents[Accelerometer].acceleration.x = value * CONVERT_A_X;
219             break;
220         case EVENT_TYPE_ACCEL_Y:
221             mPendingMask |= 1<<Accelerometer;
222             mPendingEvents[Accelerometer].acceleration.y = value * CONVERT_A_Y;
223             break;
224         case EVENT_TYPE_ACCEL_Z:
225             mPendingMask |= 1<<Accelerometer;
226             mPendingEvents[Accelerometer].acceleration.z = value * CONVERT_A_Z;
227             break;
228 
229         case EVENT_TYPE_MAGV_X:
230             mPendingMask |= 1<<MagneticField;
231             mPendingEvents[MagneticField].magnetic.x = value * CONVERT_M_X;
232             break;
233         case EVENT_TYPE_MAGV_Y:
234             mPendingMask |= 1<<MagneticField;
235             mPendingEvents[MagneticField].magnetic.y = value * CONVERT_M_Y;
236             break;
237         case EVENT_TYPE_MAGV_Z:
238             mPendingMask |= 1<<MagneticField;
239             mPendingEvents[MagneticField].magnetic.z = value * CONVERT_M_Z;
240             break;
241 
242         case EVENT_TYPE_YAW:
243             mPendingMask |= 1<<Orientation;
244             mPendingEvents[Orientation].orientation.azimuth = value * CONVERT_O_Y;
245             break;
246         case EVENT_TYPE_PITCH:
247             mPendingMask |= 1<<Orientation;
248             mPendingEvents[Orientation].orientation.pitch = value * CONVERT_O_P;
249             break;
250         case EVENT_TYPE_ROLL:
251             mPendingMask |= 1<<Orientation;
252             mPendingEvents[Orientation].orientation.roll = value * CONVERT_O_R;
253             break;
254         case EVENT_TYPE_ORIENT_STATUS:
255             mPendingMask |= 1<<Orientation;
256             mPendingEvents[Orientation].orientation.status =
257                     uint8_t(value & SENSOR_STATE_MASK);
258             break;
259     }
260 }
261