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 <cutils/log.h> 25 26#include "LightSensor.h" 27 28/*****************************************************************************/ 29 30LightSensor::LightSensor() 31 : SensorBase(NULL, "lightsensor-level"), 32 mEnabled(0), 33 mInputReader(4), 34 mHasPendingEvent(false) 35{ 36 mPendingEvent.version = sizeof(sensors_event_t); 37 mPendingEvent.sensor = ID_L; 38 mPendingEvent.type = SENSOR_TYPE_LIGHT; 39 memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data)); 40 41 if (data_fd) { 42 strcpy(input_sysfs_path, "/sys/class/input/"); 43 strcat(input_sysfs_path, input_name); 44 strcat(input_sysfs_path, "/device/"); 45 input_sysfs_path_len = strlen(input_sysfs_path); 46 enable(0, 1); 47 } 48} 49 50LightSensor::~LightSensor() { 51 if (mEnabled) { 52 enable(0, 0); 53 } 54} 55 56int LightSensor::setDelay(int32_t handle, int64_t ns) 57{ 58 int fd; 59 strcpy(&input_sysfs_path[input_sysfs_path_len], "poll_delay"); 60 fd = open(input_sysfs_path, O_RDWR); 61 if (fd >= 0) { 62 char buf[80]; 63 sprintf(buf, "%lld", ns); 64 write(fd, buf, strlen(buf)+1); 65 close(fd); 66 return 0; 67 } 68 return -1; 69} 70 71int LightSensor::enable(int32_t handle, int en) 72{ 73 int flags = en ? 1 : 0; 74 if (flags != mEnabled) { 75 int fd; 76 strcpy(&input_sysfs_path[input_sysfs_path_len], "enable"); 77 fd = open(input_sysfs_path, O_RDWR); 78 if (fd >= 0) { 79 char buf[2]; 80 int err; 81 buf[1] = 0; 82 if (flags) { 83 buf[0] = '1'; 84 } else { 85 buf[0] = '0'; 86 } 87 err = write(fd, buf, sizeof(buf)); 88 close(fd); 89 mEnabled = flags; 90 return 0; 91 } 92 return -1; 93 } 94 return 0; 95} 96 97bool LightSensor::hasPendingEvents() const { 98 return mHasPendingEvent; 99} 100 101int LightSensor::readEvents(sensors_event_t* data, int count) 102{ 103 if (count < 1) 104 return -EINVAL; 105 106 if (mHasPendingEvent) { 107 mHasPendingEvent = false; 108 mPendingEvent.timestamp = getTimestamp(); 109 *data = mPendingEvent; 110 return mEnabled ? 1 : 0; 111 } 112 113 ssize_t n = mInputReader.fill(data_fd); 114 if (n < 0) 115 return n; 116 117 int numEventReceived = 0; 118 input_event const* event; 119 120 while (count && mInputReader.readEvent(&event)) { 121 int type = event->type; 122 if (type == EV_ABS) { 123 if (event->code == EVENT_TYPE_LIGHT) { 124 // Convert adc value to lux assuming: 125 // I = 10 * log(Ev) uA 126 // R = 47kOhm 127 // Max adc value 4095 = 3.3V 128 // 1/4 of light reaches sensor 129 mPendingEvent.light = powf(10, event->value * (330.0f / 4095.0f / 47.0f)) * 4; 130 } 131 } else if (type == EV_SYN) { 132 mPendingEvent.timestamp = timevalToNano(event->time); 133 if (mEnabled) { 134 *data++ = mPendingEvent; 135 count--; 136 numEventReceived++; 137 } 138 } else { 139 ALOGE("LightSensor: unknown event (type=%d, code=%d)", 140 type, event->code); 141 } 142 mInputReader.next(); 143 } 144 145 return numEventReceived; 146} 147