• 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 <stdint.h>
18 #include <errno.h>
19 #include <unistd.h>
20 #include <poll.h>
21 
22 #include <sys/cdefs.h>
23 #include <sys/types.h>
24 
25 #include <linux/input.h>
26 
27 #include <cutils/log.h>
28 
29 #include "InputEventReader.h"
30 
31 /*****************************************************************************/
32 
33 template <typename T>
min(T a,T b)34 static inline T min(T a, T b) {
35     return a<b ? a : b;
36 }
37 
38 struct iio_event_data;
39 
InputEventCircularReader(size_t numEvents)40 InputEventCircularReader::InputEventCircularReader(size_t numEvents)
41     : mBuffer(new iio_event_data[numEvents]),
42       mBufferEnd(mBuffer + numEvents),
43       mHead(mBuffer),
44       mCurr(mBuffer),
45       mMaxEvents(numEvents),
46       mFreeEvents(numEvents)
47 {
48 }
49 
~InputEventCircularReader()50 InputEventCircularReader::~InputEventCircularReader()
51 {
52     delete [] mBuffer;
53 }
54 
fill(int fd)55 ssize_t InputEventCircularReader::fill(int fd)
56 {
57     size_t numEventsRead = 0;
58     if (mFreeEvents) {
59         struct iovec iov[2];
60 
61         const size_t numFirst = min(mFreeEvents, (size_t)(mBufferEnd - mHead));
62         const ssize_t numSecond = mFreeEvents - numFirst;
63 
64         int iovcnt = 1;
65         iov[0].iov_base = mHead;
66         iov[0].iov_len = numFirst * sizeof(iio_event_data);
67 
68         if (numSecond > 0) {
69             iovcnt++;
70             iov[1].iov_base = mBuffer;
71             iov[1].iov_len = numSecond * sizeof(iio_event_data);
72         }
73 
74         const ssize_t nread = readv(fd, iov, iovcnt);
75         if (nread < 0 || nread % sizeof(iio_event_data)) {
76             // we got a partial event!!
77             return nread < 0 ? -errno : -EINVAL;
78         }
79 
80         numEventsRead = nread / sizeof(iio_event_data);
81         if (numEventsRead) {
82             mHead += numEventsRead;
83             mFreeEvents -= numEventsRead;
84             if (mHead >= mBufferEnd)
85                 mHead -= mMaxEvents;
86         }
87     }
88 
89     return numEventsRead;
90 }
91 
readEvent(int fd,iio_event_data const ** events)92 bool InputEventCircularReader::readEvent(int fd, iio_event_data const** events)
93 {
94     if (mFreeEvents >= mMaxEvents) {
95         ssize_t eventCount = fill(fd);
96         if (eventCount <= 0)
97             return false;
98     }
99     *events = mCurr;
100     return true;
101 }
102 
next()103 void InputEventCircularReader::next()
104 {
105     mCurr++;
106     if (mCurr >= mBufferEnd) {
107         mCurr = mBuffer;
108     }
109     if (mFreeEvents < mMaxEvents) {
110        mFreeEvents++;
111     }
112 }
113