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