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)(uint32_t sensor_type, 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(uint32_t sensor_type, 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 // read the actual value of all sensors if they're enabled already 83 struct input_absinfo absinfo; 84 short flags = 0; 85 86 if (akm_is_sensor_enabled(SENSOR_TYPE_ACCELEROMETER)) { 87 mEnabled |= 1<<Accelerometer; 88 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_X), &absinfo)) { 89 mPendingEvents[Accelerometer].acceleration.x = absinfo.value * CONVERT_A_X; 90 } 91 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Y), &absinfo)) { 92 mPendingEvents[Accelerometer].acceleration.y = absinfo.value * CONVERT_A_Y; 93 } 94 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Z), &absinfo)) { 95 mPendingEvents[Accelerometer].acceleration.z = absinfo.value * CONVERT_A_Z; 96 } 97 } 98 if (akm_is_sensor_enabled(SENSOR_TYPE_MAGNETIC_FIELD)) { 99 mEnabled |= 1<<MagneticField; 100 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_X), &absinfo)) { 101 mPendingEvents[MagneticField].magnetic.x = absinfo.value * CONVERT_M_X; 102 } 103 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_Y), &absinfo)) { 104 mPendingEvents[MagneticField].magnetic.y = absinfo.value * CONVERT_M_Y; 105 } 106 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_Z), &absinfo)) { 107 mPendingEvents[MagneticField].magnetic.z = absinfo.value * CONVERT_M_Z; 108 } 109 } 110 if (akm_is_sensor_enabled(SENSOR_TYPE_ORIENTATION)) { 111 mEnabled |= 1<<Orientation; 112 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_YAW), &absinfo)) { 113 mPendingEvents[Orientation].orientation.azimuth = absinfo.value; 114 } 115 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_PITCH), &absinfo)) { 116 mPendingEvents[Orientation].orientation.pitch = absinfo.value; 117 } 118 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ROLL), &absinfo)) { 119 mPendingEvents[Orientation].orientation.roll = -absinfo.value; 120 } 121 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ORIENT_STATUS), &absinfo)) { 122 mPendingEvents[Orientation].orientation.status = uint8_t(absinfo.value & SENSOR_STATE_MASK); 123 } 124 } 125 126 // disable temperature sensor, since it is not supported 127 akm_disable_sensor(SENSOR_TYPE_TEMPERATURE); 128 } 129 130 AkmSensor::~AkmSensor() 131 { 132 if (mLibAKM) { 133 unsigned ref = ::dlclose(mLibAKM); 134 } 135 } 136 137 int AkmSensor::enable(int32_t handle, int en) 138 { 139 int what = -1; 140 141 switch (handle) { 142 case ID_A: what = Accelerometer; break; 143 case ID_M: what = MagneticField; break; 144 case ID_O: what = Orientation; break; 145 } 146 147 if (uint32_t(what) >= numSensors) 148 return -EINVAL; 149 150 int newState = en ? 1 : 0; 151 int err = 0; 152 153 if ((uint32_t(newState)<<what) != (mEnabled & (1<<what))) { 154 uint32_t sensor_type; 155 switch (what) { 156 case Accelerometer: sensor_type = SENSOR_TYPE_ACCELEROMETER; break; 157 case MagneticField: sensor_type = SENSOR_TYPE_MAGNETIC_FIELD; break; 158 case Orientation: sensor_type = SENSOR_TYPE_ORIENTATION; break; 159 } 160 short flags = newState; 161 if (en) 162 err = akm_enable_sensor(sensor_type); 163 else 164 err = akm_disable_sensor(sensor_type); 165 166 LOGE_IF(err, "Could not change sensor state (%s)", strerror(-err)); 167 if (!err) { 168 mEnabled &= ~(1<<what); 169 mEnabled |= (uint32_t(flags)<<what); 170 } 171 } 172 return err; 173 } 174 175 int AkmSensor::setDelay(int32_t handle, int64_t ns) 176 { 177 uint32_t sensor_type = 0; 178 179 if (ns < 0) 180 return -EINVAL; 181 182 switch (handle) { 183 case ID_A: sensor_type = SENSOR_TYPE_ACCELEROMETER; break; 184 case ID_M: sensor_type = SENSOR_TYPE_MAGNETIC_FIELD; break; 185 case ID_O: sensor_type = SENSOR_TYPE_ORIENTATION; break; 186 } 187 188 if (sensor_type == 0) 189 return -EINVAL; 190 191 return akm_set_delay(sensor_type, ns); 192 } 193 194 int AkmSensor::loadAKMLibrary() 195 { 196 mLibAKM = dlopen("libakm.so", RTLD_NOW); 197 198 if (!mLibAKM) { 199 akm_is_sensor_enabled = stub_is_sensor_enabled; 200 akm_enable_sensor = stub_enable_disable_sensor; 201 akm_disable_sensor = stub_enable_disable_sensor; 202 akm_set_delay = stub_set_delay; 203 LOGE("AkmSensor: unable to load AKM Library, %s", dlerror()); 204 return -ENOENT; 205 } 206 207 *(void **)&akm_is_sensor_enabled = dlsym(mLibAKM, "akm_is_sensor_enabled"); 208 *(void **)&akm_enable_sensor = dlsym(mLibAKM, "akm_enable_sensor"); 209 *(void **)&akm_disable_sensor = dlsym(mLibAKM, "akm_disable_sensor"); 210 *(void **)&akm_set_delay = dlsym(mLibAKM, "akm_set_delay"); 211 212 return 0; 213 } 214 215 int AkmSensor::readEvents(sensors_event_t* data, int count) 216 { 217 if (count < 1) 218 return -EINVAL; 219 220 ssize_t n = mInputReader.fill(data_fd); 221 if (n < 0) 222 return n; 223 224 int numEventReceived = 0; 225 input_event const* event; 226 227 while (count && mInputReader.readEvent(&event)) { 228 int type = event->type; 229 if (type == EV_REL) { 230 processEvent(event->code, event->value); 231 mInputReader.next(); 232 } else if (type == EV_SYN) { 233 int64_t time = timevalToNano(event->time); 234 for (int j=0 ; count && mPendingMask && j<numSensors ; j++) { 235 if (mPendingMask & (1<<j)) { 236 mPendingMask &= ~(1<<j); 237 mPendingEvents[j].timestamp = time; 238 if (mEnabled & (1<<j)) { 239 *data++ = mPendingEvents[j]; 240 count--; 241 numEventReceived++; 242 } 243 } 244 } 245 if (!mPendingMask) { 246 mInputReader.next(); 247 } 248 } else { 249 LOGE("AkmSensor: unknown event (type=%d, code=%d)", 250 type, event->code); 251 mInputReader.next(); 252 } 253 } 254 return numEventReceived; 255 } 256 257 void AkmSensor::processEvent(int code, int value) 258 { 259 switch (code) { 260 case EVENT_TYPE_ACCEL_X: 261 mPendingMask |= 1<<Accelerometer; 262 mPendingEvents[Accelerometer].acceleration.x = value * CONVERT_A_X; 263 break; 264 case EVENT_TYPE_ACCEL_Y: 265 mPendingMask |= 1<<Accelerometer; 266 mPendingEvents[Accelerometer].acceleration.y = value * CONVERT_A_Y; 267 break; 268 case EVENT_TYPE_ACCEL_Z: 269 mPendingMask |= 1<<Accelerometer; 270 mPendingEvents[Accelerometer].acceleration.z = value * CONVERT_A_Z; 271 break; 272 273 case EVENT_TYPE_MAGV_X: 274 mPendingMask |= 1<<MagneticField; 275 mPendingEvents[MagneticField].magnetic.x = value * CONVERT_M_X; 276 break; 277 case EVENT_TYPE_MAGV_Y: 278 mPendingMask |= 1<<MagneticField; 279 mPendingEvents[MagneticField].magnetic.y = value * CONVERT_M_Y; 280 break; 281 case EVENT_TYPE_MAGV_Z: 282 mPendingMask |= 1<<MagneticField; 283 mPendingEvents[MagneticField].magnetic.z = value * CONVERT_M_Z; 284 break; 285 286 case EVENT_TYPE_YAW: 287 mPendingMask |= 1<<Orientation; 288 mPendingEvents[Orientation].orientation.azimuth = value * CONVERT_O_A; 289 break; 290 case EVENT_TYPE_PITCH: 291 mPendingMask |= 1<<Orientation; 292 mPendingEvents[Orientation].orientation.pitch = value * CONVERT_O_P; 293 break; 294 case EVENT_TYPE_ROLL: 295 mPendingMask |= 1<<Orientation; 296 mPendingEvents[Orientation].orientation.roll = value * CONVERT_O_R; 297 break; 298 case EVENT_TYPE_ORIENT_STATUS: 299 uint8_t status = uint8_t(value & SENSOR_STATE_MASK); 300 if (status == 4) 301 status = 0; 302 mPendingMask |= 1<<Orientation; 303 mPendingEvents[Orientation].orientation.status = status; 304 break; 305 } 306 } 307