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 "ak8973b.h" 27 28 #include <cutils/log.h> 29 30 #include "AkmSensor.h" 31 32 /*****************************************************************************/ 33 34 int (*akm_is_sensor_enabled)(uint32_t sensor_type); 35 int (*akm_enable_sensor)(uint32_t sensor_type); 36 int (*akm_disable_sensor)(uint32_t sensor_type); 37 int (*akm_set_delay)(uint64_t delay); 38 39 int stub_is_sensor_enabled(uint32_t sensor_type) { 40 return 0; 41 } 42 43 int stub_enable_disable_sensor(uint32_t sensor_type) { 44 return -ENODEV; 45 } 46 47 int stub_set_delay(uint64_t delay) { 48 return -ENODEV; 49 } 50 51 AkmSensor::AkmSensor() 52 : SensorBase(NULL, NULL), 53 mEnabled(0), 54 mPendingMask(0), 55 mInputReader(32) 56 { 57 /* Open the library before opening the input device. The library 58 * creates a uinput device. 59 */ 60 if (loadAKMLibrary() == 0) { 61 data_name = "compass"; 62 data_fd = openInput("compass"); 63 } 64 65 memset(mPendingEvents, 0, sizeof(mPendingEvents)); 66 67 mPendingEvents[Accelerometer].version = sizeof(sensors_event_t); 68 mPendingEvents[Accelerometer].sensor = ID_A; 69 mPendingEvents[Accelerometer].type = SENSOR_TYPE_ACCELEROMETER; 70 mPendingEvents[Accelerometer].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH; 71 72 mPendingEvents[MagneticField].version = sizeof(sensors_event_t); 73 mPendingEvents[MagneticField].sensor = ID_M; 74 mPendingEvents[MagneticField].type = SENSOR_TYPE_MAGNETIC_FIELD; 75 mPendingEvents[MagneticField].magnetic.status = SENSOR_STATUS_ACCURACY_HIGH; 76 77 mPendingEvents[Orientation ].version = sizeof(sensors_event_t); 78 mPendingEvents[Orientation ].sensor = ID_O; 79 mPendingEvents[Orientation ].type = SENSOR_TYPE_ORIENTATION; 80 mPendingEvents[Orientation ].orientation.status = SENSOR_STATUS_ACCURACY_HIGH; 81 82 for (int i=0 ; i<numSensors ; i++) 83 mDelays[i] = 200000000; // 200 ms by default 84 85 // read the actual value of all sensors if they're enabled already 86 struct input_absinfo absinfo; 87 short flags = 0; 88 89 if (akm_is_sensor_enabled(SENSOR_TYPE_ACCELEROMETER)) { 90 mEnabled |= 1<<Accelerometer; 91 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_X), &absinfo)) { 92 mPendingEvents[Accelerometer].acceleration.x = absinfo.value * CONVERT_A_X; 93 } 94 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Y), &absinfo)) { 95 mPendingEvents[Accelerometer].acceleration.y = absinfo.value * CONVERT_A_Y; 96 } 97 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Z), &absinfo)) { 98 mPendingEvents[Accelerometer].acceleration.z = absinfo.value * CONVERT_A_Z; 99 } 100 } 101 if (akm_is_sensor_enabled(SENSOR_TYPE_MAGNETIC_FIELD)) { 102 mEnabled |= 1<<MagneticField; 103 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_X), &absinfo)) { 104 mPendingEvents[MagneticField].magnetic.x = absinfo.value * CONVERT_M_X; 105 } 106 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_Y), &absinfo)) { 107 mPendingEvents[MagneticField].magnetic.y = absinfo.value * CONVERT_M_Y; 108 } 109 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_Z), &absinfo)) { 110 mPendingEvents[MagneticField].magnetic.z = absinfo.value * CONVERT_M_Z; 111 } 112 } 113 if (akm_is_sensor_enabled(SENSOR_TYPE_ORIENTATION)) { 114 mEnabled |= 1<<Orientation; 115 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_YAW), &absinfo)) { 116 mPendingEvents[Orientation].orientation.azimuth = absinfo.value; 117 } 118 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_PITCH), &absinfo)) { 119 mPendingEvents[Orientation].orientation.pitch = absinfo.value; 120 } 121 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ROLL), &absinfo)) { 122 mPendingEvents[Orientation].orientation.roll = -absinfo.value; 123 } 124 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ORIENT_STATUS), &absinfo)) { 125 mPendingEvents[Orientation].orientation.status = uint8_t(absinfo.value & SENSOR_STATE_MASK); 126 } 127 } 128 129 // disable temperature sensor, since it is not supported 130 akm_disable_sensor(SENSOR_TYPE_TEMPERATURE); 131 } 132 133 AkmSensor::~AkmSensor() 134 { 135 if (mLibAKM) { 136 unsigned ref = ::dlclose(mLibAKM); 137 } 138 } 139 140 int AkmSensor::enable(int32_t handle, int en) 141 { 142 int what = -1; 143 144 switch (handle) { 145 case ID_A: what = Accelerometer; break; 146 case ID_M: what = MagneticField; break; 147 case ID_O: what = Orientation; break; 148 } 149 150 if (uint32_t(what) >= numSensors) 151 return -EINVAL; 152 153 int newState = en ? 1 : 0; 154 int err = 0; 155 156 if ((uint32_t(newState)<<what) != (mEnabled & (1<<what))) { 157 uint32_t sensor_type; 158 switch (what) { 159 case Accelerometer: sensor_type = SENSOR_TYPE_ACCELEROMETER; break; 160 case MagneticField: sensor_type = SENSOR_TYPE_MAGNETIC_FIELD; break; 161 case Orientation: sensor_type = SENSOR_TYPE_ORIENTATION; break; 162 } 163 short flags = newState; 164 if (en) 165 err = akm_enable_sensor(sensor_type); 166 else 167 err = akm_disable_sensor(sensor_type); 168 169 LOGE_IF(err, "Could not change sensor state (%s)", strerror(-err)); 170 if (!err) { 171 mEnabled &= ~(1<<what); 172 mEnabled |= (uint32_t(flags)<<what); 173 update_delay(); 174 } 175 } 176 return err; 177 } 178 179 int AkmSensor::setDelay(int32_t handle, int64_t ns) 180 { 181 int what = -1; 182 switch (handle) { 183 case ID_A: what = Accelerometer; break; 184 case ID_M: what = MagneticField; break; 185 case ID_O: what = Orientation; break; 186 } 187 188 if (uint32_t(what) >= numSensors) 189 return -EINVAL; 190 191 if (ns < 0) 192 return -EINVAL; 193 194 mDelays[what] = ns; 195 return update_delay(); 196 } 197 198 int AkmSensor::update_delay() 199 { 200 if (mEnabled) { 201 uint64_t wanted = -1LLU; 202 for (int i=0 ; i<numSensors ; i++) { 203 if (mEnabled & (1<<i)) { 204 uint64_t ns = mDelays[i]; 205 wanted = wanted < ns ? wanted : ns; 206 } 207 } 208 return akm_set_delay(int64_t(wanted)); 209 } 210 return 0; 211 } 212 213 int AkmSensor::loadAKMLibrary() 214 { 215 mLibAKM = dlopen("libakm.so", RTLD_NOW); 216 217 if (!mLibAKM) { 218 akm_is_sensor_enabled = stub_is_sensor_enabled; 219 akm_enable_sensor = stub_enable_disable_sensor; 220 akm_disable_sensor = stub_enable_disable_sensor; 221 akm_set_delay = stub_set_delay; 222 LOGE("AkmSensor: unable to load AKM Library, %s", dlerror()); 223 return -ENOENT; 224 } 225 226 *(void **)&akm_is_sensor_enabled = dlsym(mLibAKM, "akm_is_sensor_enabled"); 227 *(void **)&akm_enable_sensor = dlsym(mLibAKM, "akm_enable_sensor"); 228 *(void **)&akm_disable_sensor = dlsym(mLibAKM, "akm_disable_sensor"); 229 *(void **)&akm_set_delay = dlsym(mLibAKM, "akm_set_delay"); 230 231 return 0; 232 } 233 234 int AkmSensor::readEvents(sensors_event_t* data, int count) 235 { 236 if (count < 1) 237 return -EINVAL; 238 239 ssize_t n = mInputReader.fill(data_fd); 240 if (n < 0) 241 return n; 242 243 int numEventReceived = 0; 244 input_event const* event; 245 246 while (count && mInputReader.readEvent(&event)) { 247 int type = event->type; 248 if (type == EV_REL) { 249 processEvent(event->code, event->value); 250 mInputReader.next(); 251 } else if (type == EV_SYN) { 252 int64_t time = timevalToNano(event->time); 253 for (int j=0 ; count && mPendingMask && j<numSensors ; j++) { 254 if (mPendingMask & (1<<j)) { 255 mPendingMask &= ~(1<<j); 256 mPendingEvents[j].timestamp = time; 257 if (mEnabled & (1<<j)) { 258 *data++ = mPendingEvents[j]; 259 count--; 260 numEventReceived++; 261 } 262 } 263 } 264 if (!mPendingMask) { 265 mInputReader.next(); 266 } 267 } else { 268 LOGE("AkmSensor: unknown event (type=%d, code=%d)", 269 type, event->code); 270 mInputReader.next(); 271 } 272 } 273 return numEventReceived; 274 } 275 276 void AkmSensor::processEvent(int code, int value) 277 { 278 switch (code) { 279 case EVENT_TYPE_ACCEL_X: 280 mPendingMask |= 1<<Accelerometer; 281 mPendingEvents[Accelerometer].acceleration.x = value * CONVERT_A_X; 282 break; 283 case EVENT_TYPE_ACCEL_Y: 284 mPendingMask |= 1<<Accelerometer; 285 mPendingEvents[Accelerometer].acceleration.y = value * CONVERT_A_Y; 286 break; 287 case EVENT_TYPE_ACCEL_Z: 288 mPendingMask |= 1<<Accelerometer; 289 mPendingEvents[Accelerometer].acceleration.z = value * CONVERT_A_Z; 290 break; 291 292 case EVENT_TYPE_MAGV_X: 293 mPendingMask |= 1<<MagneticField; 294 mPendingEvents[MagneticField].magnetic.x = value * CONVERT_M_X; 295 break; 296 case EVENT_TYPE_MAGV_Y: 297 mPendingMask |= 1<<MagneticField; 298 mPendingEvents[MagneticField].magnetic.y = value * CONVERT_M_Y; 299 break; 300 case EVENT_TYPE_MAGV_Z: 301 mPendingMask |= 1<<MagneticField; 302 mPendingEvents[MagneticField].magnetic.z = value * CONVERT_M_Z; 303 break; 304 305 case EVENT_TYPE_YAW: 306 mPendingMask |= 1<<Orientation; 307 mPendingEvents[Orientation].orientation.azimuth = value * CONVERT_O_A; 308 break; 309 case EVENT_TYPE_PITCH: 310 mPendingMask |= 1<<Orientation; 311 mPendingEvents[Orientation].orientation.pitch = value * CONVERT_O_P; 312 break; 313 case EVENT_TYPE_ROLL: 314 mPendingMask |= 1<<Orientation; 315 mPendingEvents[Orientation].orientation.roll = value * CONVERT_O_R; 316 break; 317 case EVENT_TYPE_ORIENT_STATUS: 318 mPendingMask |= 1<<Orientation; 319 mPendingEvents[Orientation].orientation.status = 320 uint8_t(value & SENSOR_STATE_MASK); 321 break; 322 } 323 } 324