• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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