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/akm8973.h> 26 27 #include <cutils/log.h> 28 29 #include "AkmSensor.h" 30 31 /*****************************************************************************/ 32 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 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_X), &absinfo)) { 69 mPendingEvents[Accelerometer].acceleration.x = absinfo.value * CONVERT_A_X; 70 } 71 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Y), &absinfo)) { 72 mPendingEvents[Accelerometer].acceleration.y = absinfo.value * CONVERT_A_Y; 73 } 74 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Z), &absinfo)) { 75 mPendingEvents[Accelerometer].acceleration.z = absinfo.value * CONVERT_A_Z; 76 } 77 } 78 } 79 if (!ioctl(dev_fd, ECS_IOCTL_APP_GET_MVFLAG, &flags)) { 80 if (flags) { 81 mEnabled |= 1<<MagneticField; 82 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_X), &absinfo)) { 83 mPendingEvents[MagneticField].magnetic.x = absinfo.value * CONVERT_M_X; 84 } 85 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_Y), &absinfo)) { 86 mPendingEvents[MagneticField].magnetic.y = absinfo.value * CONVERT_M_Y; 87 } 88 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_Z), &absinfo)) { 89 mPendingEvents[MagneticField].magnetic.z = absinfo.value * CONVERT_M_Z; 90 } 91 } 92 } 93 if (!ioctl(dev_fd, ECS_IOCTL_APP_GET_MFLAG, &flags)) { 94 if (flags) { 95 mEnabled |= 1<<Orientation; 96 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_YAW), &absinfo)) { 97 mPendingEvents[Orientation].orientation.azimuth = absinfo.value; 98 } 99 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_PITCH), &absinfo)) { 100 mPendingEvents[Orientation].orientation.pitch = absinfo.value; 101 } 102 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ROLL), &absinfo)) { 103 mPendingEvents[Orientation].orientation.roll = -absinfo.value; 104 } 105 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ORIENT_STATUS), &absinfo)) { 106 mPendingEvents[Orientation].orientation.status = uint8_t(absinfo.value & SENSOR_STATE_MASK); 107 } 108 } 109 } 110 111 // disable temperature sensor, since it is not reported 112 flags = 0; 113 ioctl(dev_fd, ECS_IOCTL_APP_SET_TFLAG, &flags); 114 115 if (!mEnabled) { 116 close_device(); 117 } 118 } 119 120 AkmSensor::~AkmSensor() { 121 } 122 123 int AkmSensor::enable(int32_t handle, int en) 124 { 125 int what = -1; 126 switch (handle) { 127 case ID_A: what = Accelerometer; break; 128 case ID_M: what = MagneticField; break; 129 case ID_O: what = Orientation; break; 130 } 131 132 if (uint32_t(what) >= numSensors) 133 return -EINVAL; 134 135 int newState = en ? 1 : 0; 136 int err = 0; 137 138 if ((uint32_t(newState)<<what) != (mEnabled & (1<<what))) { 139 if (!mEnabled) { 140 open_device(); 141 } 142 int cmd; 143 switch (what) { 144 case Accelerometer: cmd = ECS_IOCTL_APP_SET_AFLAG; break; 145 case MagneticField: cmd = ECS_IOCTL_APP_SET_MVFLAG; break; 146 case Orientation: cmd = ECS_IOCTL_APP_SET_MFLAG; break; 147 } 148 short flags = newState; 149 err = ioctl(dev_fd, cmd, &flags); 150 err = err<0 ? -errno : 0; 151 LOGE_IF(err, "ECS_IOCTL_APP_SET_XXX failed (%s)", strerror(-err)); 152 if (!err) { 153 mEnabled &= ~(1<<what); 154 mEnabled |= (uint32_t(flags)<<what); 155 update_delay(); 156 } 157 if (!mEnabled) { 158 close_device(); 159 } 160 } 161 return err; 162 } 163 164 int AkmSensor::setDelay(int32_t handle, int64_t ns) 165 { 166 #ifdef ECS_IOCTL_APP_SET_DELAY 167 int what = -1; 168 switch (handle) { 169 case ID_A: what = Accelerometer; break; 170 case ID_M: what = MagneticField; break; 171 case ID_O: what = Orientation; break; 172 } 173 174 if (uint32_t(what) >= numSensors) 175 return -EINVAL; 176 177 if (ns < 0) 178 return -EINVAL; 179 180 mDelays[what] = ns; 181 return update_delay(); 182 #else 183 return -1; 184 #endif 185 } 186 187 int AkmSensor::update_delay() 188 { 189 if (mEnabled) { 190 uint64_t wanted = -1LLU; 191 for (int i=0 ; i<numSensors ; i++) { 192 if (mEnabled & (1<<i)) { 193 uint64_t ns = mDelays[i]; 194 wanted = wanted < ns ? wanted : ns; 195 } 196 } 197 short delay = int64_t(wanted) / 1000000; 198 if (ioctl(dev_fd, ECS_IOCTL_APP_SET_DELAY, &delay)) { 199 return -errno; 200 } 201 } 202 return 0; 203 } 204 205 int AkmSensor::readEvents(sensors_event_t* data, int count) 206 { 207 if (count < 1) 208 return -EINVAL; 209 210 ssize_t n = mInputReader.fill(data_fd); 211 if (n < 0) 212 return n; 213 214 int numEventReceived = 0; 215 input_event const* event; 216 217 while (count && mInputReader.readEvent(&event)) { 218 int type = event->type; 219 if (type == EV_ABS) { 220 processEvent(event->code, event->value); 221 mInputReader.next(); 222 } else if (type == EV_SYN) { 223 int64_t time = timevalToNano(event->time); 224 for (int j=0 ; count && mPendingMask && j<numSensors ; j++) { 225 if (mPendingMask & (1<<j)) { 226 mPendingMask &= ~(1<<j); 227 mPendingEvents[j].timestamp = time; 228 if (mEnabled & (1<<j)) { 229 *data++ = mPendingEvents[j]; 230 count--; 231 numEventReceived++; 232 } 233 } 234 } 235 if (!mPendingMask) { 236 mInputReader.next(); 237 } 238 } else { 239 LOGE("AkmSensor: unknown event (type=%d, code=%d)", 240 type, event->code); 241 mInputReader.next(); 242 } 243 } 244 245 return numEventReceived; 246 } 247 248 void AkmSensor::processEvent(int code, int value) 249 { 250 switch (code) { 251 case EVENT_TYPE_ACCEL_X: 252 mPendingMask |= 1<<Accelerometer; 253 mPendingEvents[Accelerometer].acceleration.x = value * CONVERT_A_X; 254 break; 255 case EVENT_TYPE_ACCEL_Y: 256 mPendingMask |= 1<<Accelerometer; 257 mPendingEvents[Accelerometer].acceleration.y = value * CONVERT_A_Y; 258 break; 259 case EVENT_TYPE_ACCEL_Z: 260 mPendingMask |= 1<<Accelerometer; 261 mPendingEvents[Accelerometer].acceleration.z = value * CONVERT_A_Z; 262 break; 263 264 case EVENT_TYPE_MAGV_X: 265 mPendingMask |= 1<<MagneticField; 266 mPendingEvents[MagneticField].magnetic.x = value * CONVERT_M_X; 267 break; 268 case EVENT_TYPE_MAGV_Y: 269 mPendingMask |= 1<<MagneticField; 270 mPendingEvents[MagneticField].magnetic.y = value * CONVERT_M_Y; 271 break; 272 case EVENT_TYPE_MAGV_Z: 273 mPendingMask |= 1<<MagneticField; 274 mPendingEvents[MagneticField].magnetic.z = value * CONVERT_M_Z; 275 break; 276 277 case EVENT_TYPE_YAW: 278 mPendingMask |= 1<<Orientation; 279 mPendingEvents[Orientation].orientation.azimuth = value * CONVERT_O_Y; 280 break; 281 case EVENT_TYPE_PITCH: 282 mPendingMask |= 1<<Orientation; 283 mPendingEvents[Orientation].orientation.pitch = value * CONVERT_O_P; 284 break; 285 case EVENT_TYPE_ROLL: 286 mPendingMask |= 1<<Orientation; 287 mPendingEvents[Orientation].orientation.roll = value * CONVERT_O_R; 288 break; 289 case EVENT_TYPE_ORIENT_STATUS: 290 mPendingMask |= 1<<Orientation; 291 mPendingEvents[Orientation].orientation.status = 292 uint8_t(value & SENSOR_STATE_MASK); 293 break; 294 } 295 } 296