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 <string.h> 22#include <unistd.h> 23#include <dirent.h> 24#include <sys/select.h> 25#include <dlfcn.h> 26 27#include <cutils/log.h> 28 29#include "AkmSensor.h" 30 31#define AKMD_DEFAULT_INTERVAL 200000000 32 33/*****************************************************************************/ 34 35AkmSensor::AkmSensor() 36: SensorBase(NULL, "compass"), 37 mPendingMask(0), 38 mInputReader(32) 39{ 40 for (int i=0; i<numSensors; i++) { 41 mEnabled[i] = 0; 42 mDelay[i] = -1; 43 } 44 memset(mPendingEvents, 0, sizeof(mPendingEvents)); 45 46 mPendingEvents[Accelerometer].version = sizeof(sensors_event_t); 47 mPendingEvents[Accelerometer].sensor = ID_A; 48 mPendingEvents[Accelerometer].type = SENSOR_TYPE_ACCELEROMETER; 49 mPendingEvents[Accelerometer].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH; 50 51 mPendingEvents[MagneticField].version = sizeof(sensors_event_t); 52 mPendingEvents[MagneticField].sensor = ID_M; 53 mPendingEvents[MagneticField].type = SENSOR_TYPE_MAGNETIC_FIELD; 54 mPendingEvents[MagneticField].magnetic.status = SENSOR_STATUS_ACCURACY_HIGH; 55 56 mPendingEvents[Orientation ].version = sizeof(sensors_event_t); 57 mPendingEvents[Orientation ].sensor = ID_O; 58 mPendingEvents[Orientation ].type = SENSOR_TYPE_ORIENTATION; 59 mPendingEvents[Orientation ].orientation.status = SENSOR_STATUS_ACCURACY_HIGH; 60 61 if (data_fd) { 62 strcpy(input_sysfs_path, "/sys/class/compass/akm8975/"); 63 input_sysfs_path_len = strlen(input_sysfs_path); 64 } else { 65 input_sysfs_path[0] = '\0'; 66 input_sysfs_path_len = 0; 67 } 68} 69 70AkmSensor::~AkmSensor() 71{ 72 for (int i=0; i<numSensors; i++) { 73 setEnable(i, 0); 74 } 75} 76 77int AkmSensor::setEnable(int32_t handle, int enabled) 78{ 79 int id = handle2id(handle); 80 int err = 0; 81 char buffer[2]; 82 83 switch (id) { 84 case Accelerometer: 85 strcpy(&input_sysfs_path[input_sysfs_path_len], "enable_acc"); 86 break; 87 case MagneticField: 88 strcpy(&input_sysfs_path[input_sysfs_path_len], "enable_mag"); 89 break; 90 case Orientation: 91 strcpy(&input_sysfs_path[input_sysfs_path_len], "enable_ori"); 92 break; 93 default: 94 ALOGE("AkmSensor: unknown handle (%d)", handle); 95 return -EINVAL; 96 } 97 98 buffer[0] = '\0'; 99 buffer[1] = '\0'; 100 101 if (mEnabled[id] <= 0) { 102 if(enabled) buffer[0] = '1'; 103 } else if (mEnabled[id] == 1) { 104 if(!enabled) buffer[0] = '0'; 105 } 106 107 if (buffer[0] != '\0') { 108 err = write_sys_attribute(input_sysfs_path, buffer, 1); 109 if (err != 0) { 110 return err; 111 } 112 ALOGD("AkmSensor: set %s to %s", 113 &input_sysfs_path[input_sysfs_path_len], buffer); 114 115 /* for AKMD specification */ 116 if (buffer[0] == '1') { 117 setDelay(handle, AKMD_DEFAULT_INTERVAL); 118 } else { 119 setDelay(handle, -1); 120 } 121 } 122 123 if (enabled) { 124 (mEnabled[id])++; 125 if (mEnabled[id] > 32767) mEnabled[id] = 32767; 126 } else { 127 (mEnabled[id])--; 128 if (mEnabled[id] < 0) mEnabled[id] = 0; 129 } 130 ALOGD("AkmSensor: mEnabled[%d] = %d", id, mEnabled[id]); 131 132 return err; 133} 134 135int AkmSensor::setDelay(int32_t handle, int64_t ns) 136{ 137 int id = handle2id(handle); 138 int err = 0; 139 char buffer[32]; 140 int bytes; 141 142 if (ns < -1 || 2147483647 < ns) { 143 ALOGE("AkmSensor: invalid delay (%lld)", ns); 144 return -EINVAL; 145 } 146 147 switch (id) { 148 case Accelerometer: 149 strcpy(&input_sysfs_path[input_sysfs_path_len], "delay_acc"); 150 break; 151 case MagneticField: 152 strcpy(&input_sysfs_path[input_sysfs_path_len], "delay_mag"); 153 break; 154 case Orientation: 155 strcpy(&input_sysfs_path[input_sysfs_path_len], "delay_ori"); 156 break; 157 default: 158 ALOGE("AkmSensor: unknown handle (%d)", handle); 159 return -EINVAL; 160 } 161 162 if (ns != mDelay[id]) { 163 bytes = sprintf(buffer, "%lld", ns); 164 err = write_sys_attribute(input_sysfs_path, buffer, bytes); 165 if (err == 0) { 166 mDelay[id] = ns; 167 ALOGD("AkmSensor: set %s to %f ms.", 168 &input_sysfs_path[input_sysfs_path_len], ns/1000000.0f); 169 } 170 } 171 172 return err; 173} 174 175int64_t AkmSensor::getDelay(int32_t handle) 176{ 177 int id = handle2id(handle); 178 if (id > 0) { 179 return mDelay[id]; 180 } else { 181 return 0; 182 } 183} 184 185int AkmSensor::getEnable(int32_t handle) 186{ 187 int id = handle2id(handle); 188 if (id >= 0) { 189 return mEnabled[id]; 190 } else { 191 return 0; 192 } 193} 194 195int AkmSensor::readEvents(sensors_event_t* data, int count) 196{ 197 if (count < 1) 198 return -EINVAL; 199 200 ssize_t n = mInputReader.fill(data_fd); 201 if (n < 0) 202 return n; 203 204 int numEventReceived = 0; 205 input_event const* event; 206 207 while (count && mInputReader.readEvent(&event)) { 208 int type = event->type; 209 if (type == EV_ABS) { 210 processEvent(event->code, event->value); 211 mInputReader.next(); 212 } else if (type == EV_SYN) { 213 int64_t time = timevalToNano(event->time); 214 for (int j=0 ; count && mPendingMask && j<numSensors ; j++) { 215 if (mPendingMask & (1<<j)) { 216 mPendingMask &= ~(1<<j); 217 mPendingEvents[j].timestamp = time; 218 //ALOGD("data=%8.5f,%8.5f,%8.5f", 219 //mPendingEvents[j].data[0], 220 //mPendingEvents[j].data[1], 221 //mPendingEvents[j].data[2]); 222 if (mEnabled[j]) { 223 *data++ = mPendingEvents[j]; 224 count--; 225 numEventReceived++; 226 } 227 } 228 } 229 if (!mPendingMask) { 230 mInputReader.next(); 231 } 232 } else { 233 ALOGE("AkmSensor: unknown event (type=%d, code=%d)", 234 type, event->code); 235 mInputReader.next(); 236 } 237 } 238 return numEventReceived; 239} 240 241int AkmSensor::setAccel(sensors_event_t* data) 242{ 243 int err; 244 int16_t acc[3]; 245 246 acc[0] = (int16_t)(data->acceleration.x / GRAVITY_EARTH * AKSC_LSG); 247 acc[1] = (int16_t)(data->acceleration.y / GRAVITY_EARTH * AKSC_LSG); 248 acc[2] = (int16_t)(data->acceleration.z / GRAVITY_EARTH * AKSC_LSG); 249 250 strcpy(&input_sysfs_path[input_sysfs_path_len], "accel"); 251 err = write_sys_attribute(input_sysfs_path, (char*)acc, 6); 252 if (err < 0) { 253 ALOGD("AkmSensor: %s write failed.", 254 &input_sysfs_path[input_sysfs_path_len]); 255 } 256 return err; 257} 258 259int AkmSensor::handle2id(int32_t handle) 260{ 261 switch (handle) { 262 case ID_A: 263 return Accelerometer; 264 case ID_M: 265 return MagneticField; 266 case ID_O: 267 return Orientation; 268 default: 269 ALOGE("AkmSensor: unknown handle (%d)", handle); 270 return -EINVAL; 271 } 272} 273 274void AkmSensor::processEvent(int code, int value) 275{ 276 switch (code) { 277 case EVENT_TYPE_ACCEL_X: 278 mPendingMask |= 1<<Accelerometer; 279 mPendingEvents[Accelerometer].acceleration.x = value * CONVERT_A; 280 break; 281 case EVENT_TYPE_ACCEL_Y: 282 mPendingMask |= 1<<Accelerometer; 283 mPendingEvents[Accelerometer].acceleration.y = value * CONVERT_A; 284 break; 285 case EVENT_TYPE_ACCEL_Z: 286 mPendingMask |= 1<<Accelerometer; 287 mPendingEvents[Accelerometer].acceleration.z = value * CONVERT_A; 288 break; 289 290 case EVENT_TYPE_MAGV_X: 291 mPendingMask |= 1<<MagneticField; 292 mPendingEvents[MagneticField].magnetic.x = value * CONVERT_M; 293 break; 294 case EVENT_TYPE_MAGV_Y: 295 mPendingMask |= 1<<MagneticField; 296 mPendingEvents[MagneticField].magnetic.y = value * CONVERT_M; 297 break; 298 case EVENT_TYPE_MAGV_Z: 299 mPendingMask |= 1<<MagneticField; 300 mPendingEvents[MagneticField].magnetic.z = value * CONVERT_M; 301 break; 302 case EVENT_TYPE_MAGV_STATUS: 303 mPendingMask |= 1<<MagneticField; 304 mPendingEvents[MagneticField].magnetic.status = value; 305 break; 306 307 case EVENT_TYPE_YAW: 308 mPendingMask |= 1<<Orientation; 309 mPendingEvents[Orientation].orientation.azimuth = value * CONVERT_O; 310 break; 311 case EVENT_TYPE_PITCH: 312 mPendingMask |= 1<<Orientation; 313 mPendingEvents[Orientation].orientation.pitch = value * CONVERT_O; 314 break; 315 case EVENT_TYPE_ROLL: 316 mPendingMask |= 1<<Orientation; 317 mPendingEvents[Orientation].orientation.roll = value * CONVERT_O; 318 break; 319 case EVENT_TYPE_ORIENT_STATUS: 320 mPendingMask |= 1<<Orientation; 321 mPendingEvents[Orientation].orientation.status = value; 322 break; 323 } 324} 325