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 25 #include <linux/lightsensor.h> 26 27 #include <cutils/log.h> 28 29 #include "LightSensor.h" 30 31 /*****************************************************************************/ 32 33 LightSensor::LightSensor() 34 : SensorBase(LS_DEVICE_NAME, "lightsensor-level"), 35 mEnabled(0), 36 mInputReader(4), 37 mHasPendingEvent(false) 38 { 39 mPendingEvent.version = sizeof(sensors_event_t); 40 mPendingEvent.sensor = ID_L; 41 mPendingEvent.type = SENSOR_TYPE_LIGHT; 42 memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data)); 43 44 open_device(); 45 46 int flags = 0; 47 if (!ioctl(dev_fd, LIGHTSENSOR_IOCTL_GET_ENABLED, &flags)) { 48 if (flags) { 49 mEnabled = 1; 50 setInitialState(); 51 } 52 } 53 54 if (!mEnabled) { 55 close_device(); 56 } 57 } 58 59 LightSensor::~LightSensor() { 60 } 61 62 int LightSensor::setInitialState() { 63 struct input_absinfo absinfo; 64 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_LIGHT), &absinfo)) { 65 mPendingEvent.light = indexToValue(absinfo.value); 66 mHasPendingEvent = true; 67 } 68 return 0; 69 } 70 71 int LightSensor::enable(int32_t, int en) { 72 int flags = en ? 1 : 0; 73 int err = 0; 74 if (flags != mEnabled) { 75 if (!mEnabled) { 76 open_device(); 77 } 78 err = ioctl(dev_fd, LIGHTSENSOR_IOCTL_ENABLE, &flags); 79 err = err<0 ? -errno : 0; 80 LOGE_IF(err, "LIGHTSENSOR_IOCTL_ENABLE failed (%s)", strerror(-err)); 81 if (!err) { 82 mEnabled = en ? 1 : 0; 83 if (en) { 84 setInitialState(); 85 } 86 } 87 if (!mEnabled) { 88 close_device(); 89 } 90 } 91 return err; 92 } 93 94 bool LightSensor::hasPendingEvents() const { 95 return mHasPendingEvent; 96 } 97 98 int LightSensor::readEvents(sensors_event_t* data, int count) 99 { 100 if (count < 1) 101 return -EINVAL; 102 103 if (mHasPendingEvent) { 104 mHasPendingEvent = false; 105 mPendingEvent.timestamp = getTimestamp(); 106 *data = mPendingEvent; 107 return mEnabled ? 1 : 0; 108 } 109 110 ssize_t n = mInputReader.fill(data_fd); 111 if (n < 0) 112 return n; 113 114 int numEventReceived = 0; 115 input_event const* event; 116 117 while (count && mInputReader.readEvent(&event)) { 118 int type = event->type; 119 if (type == EV_ABS) { 120 if (event->code == EVENT_TYPE_LIGHT) { 121 if (event->value != -1) { 122 // FIXME: not sure why we're getting -1 sometimes 123 mPendingEvent.light = indexToValue(event->value); 124 } 125 } 126 } else if (type == EV_SYN) { 127 mPendingEvent.timestamp = timevalToNano(event->time); 128 if (mEnabled) { 129 *data++ = mPendingEvent; 130 count--; 131 numEventReceived++; 132 } 133 } else { 134 LOGE("LightSensor: unknown event (type=%d, code=%d)", 135 type, event->code); 136 } 137 mInputReader.next(); 138 } 139 140 return numEventReceived; 141 } 142 143 float LightSensor::indexToValue(size_t index) const 144 { 145 static const float luxValues[8] = { 146 10.0, 160.0, 225.0, 320.0, 147 640.0, 1280.0, 2600.0, 10240.0 148 }; 149 150 const size_t maxIndex = sizeof(luxValues)/sizeof(*luxValues) - 1; 151 if (index > maxIndex) 152 index = maxIndex; 153 return luxValues[index]; 154 } 155