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/capella_cm3602.h>
26
27 #include <cutils/log.h>
28
29 #include "ProximitySensor.h"
30
31 /*****************************************************************************/
32
ProximitySensor()33 ProximitySensor::ProximitySensor()
34 : SensorBase(CM_DEVICE_NAME, "proximity"),
35 mEnabled(0),
36 mInputReader(4),
37 mHasPendingEvent(false)
38 {
39 mPendingEvent.version = sizeof(sensors_event_t);
40 mPendingEvent.sensor = ID_P;
41 mPendingEvent.type = SENSOR_TYPE_PROXIMITY;
42 memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));
43
44 open_device();
45
46 int flags = 0;
47 if (!ioctl(dev_fd, CAPELLA_CM3602_IOCTL_GET_ENABLED, &flags)) {
48 mEnabled = 1;
49 if (flags) {
50 setInitialState();
51 }
52 }
53 if (!mEnabled) {
54 close_device();
55 }
56 }
57
~ProximitySensor()58 ProximitySensor::~ProximitySensor() {
59 }
60
setInitialState()61 int ProximitySensor::setInitialState() {
62 struct input_absinfo absinfo;
63 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_PROXIMITY), &absinfo)) {
64 // make sure to report an event immediately
65 mHasPendingEvent = true;
66 mPendingEvent.distance = indexToValue(absinfo.value);
67 }
68 return 0;
69 }
70
enable(int32_t,int en)71 int ProximitySensor::enable(int32_t, int en) {
72 int newState = en ? 1 : 0;
73 int err = 0;
74 if (newState != mEnabled) {
75 if (!mEnabled) {
76 open_device();
77 }
78 int flags = newState;
79 err = ioctl(dev_fd, CAPELLA_CM3602_IOCTL_ENABLE, &flags);
80 err = err<0 ? -errno : 0;
81 LOGE_IF(err, "CAPELLA_CM3602_IOCTL_ENABLE failed (%s)", strerror(-err));
82 if (!err) {
83 mEnabled = newState;
84 if (en) {
85 setInitialState();
86 }
87 }
88 if (!mEnabled) {
89 close_device();
90 }
91 }
92 return err;
93 }
94
hasPendingEvents() const95 bool ProximitySensor::hasPendingEvents() const {
96 return mHasPendingEvent;
97 }
98
readEvents(sensors_event_t * data,int count)99 int ProximitySensor::readEvents(sensors_event_t* data, int count)
100 {
101 if (count < 1)
102 return -EINVAL;
103
104 if (mHasPendingEvent) {
105 mHasPendingEvent = false;
106 mPendingEvent.timestamp = getTimestamp();
107 *data = mPendingEvent;
108 return mEnabled ? 1 : 0;
109 }
110
111 ssize_t n = mInputReader.fill(data_fd);
112 if (n < 0)
113 return n;
114
115 int numEventReceived = 0;
116 input_event const* event;
117
118 while (count && mInputReader.readEvent(&event)) {
119 int type = event->type;
120 if (type == EV_ABS) {
121 if (event->code == EVENT_TYPE_PROXIMITY) {
122 mPendingEvent.distance = indexToValue(event->value);
123 }
124 } else if (type == EV_SYN) {
125 mPendingEvent.timestamp = timevalToNano(event->time);
126 if (mEnabled) {
127 *data++ = mPendingEvent;
128 count--;
129 numEventReceived++;
130 }
131 } else {
132 LOGE("ProximitySensor: unknown event (type=%d, code=%d)",
133 type, event->code);
134 }
135 mInputReader.next();
136 }
137
138 return numEventReceived;
139 }
140
indexToValue(size_t index) const141 float ProximitySensor::indexToValue(size_t index) const
142 {
143 return index * PROXIMITY_THRESHOLD_CM;
144 }
145