• 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 input_event;
39 
InputEventCircularReader(size_t numEvents)40 InputEventCircularReader::InputEventCircularReader(size_t numEvents)
41     : mBuffer(new input_event[numEvents]),
42       mBufferEnd(mBuffer + numEvents),
43       mHead(mBuffer),
44       mCurr(mBuffer),
45       mEvents(numEvents),
46       mFreeSpace(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 (mFreeSpace) {
59         struct iovec iov[2];
60 
61         const size_t numFirst = min(mFreeSpace, (size_t)(mBufferEnd - mHead));
62         const size_t numSecond = mFreeSpace - numFirst;
63 
64         int iovcnt = 1;
65         iov[0].iov_base = mHead;
66         iov[0].iov_len = numFirst * sizeof(input_event);
67 
68         if (numSecond > 0)
69         {
70             iovcnt++;
71             iov[1].iov_base = mBuffer;
72             iov[1].iov_len = numSecond * sizeof(input_event);
73         }
74 
75         const ssize_t nread = readv(fd, iov, iovcnt);
76         if (nread < 0 || nread % sizeof(input_event)) {
77             // we got a partial event!!
78             return nread < 0 ? -errno : -EINVAL;
79         }
80 
81         numEventsRead = nread / sizeof(input_event);
82         if (numEventsRead) {
83             mHead += numEventsRead;
84             mFreeSpace -= numEventsRead;
85             if (mHead >= mBufferEnd)
86                 mHead -= mBufferEnd - mBuffer;
87         }
88     }
89 
90     return numEventsRead;
91 }
92 
readEvent(int fd,input_event const ** events)93 bool InputEventCircularReader::readEvent(int fd, input_event const** events)
94 {
95     if (mFreeSpace >= mEvents) {
96         ssize_t eventCount = fill(fd);
97         if (eventCount <= 0)
98             return false;
99     }
100     *events = mCurr;
101     return true;
102 }
103 
next()104 void InputEventCircularReader::next()
105 {
106     mCurr++;
107     mFreeSpace++;
108     if (mCurr >= mBufferEnd) {
109         mCurr = mBuffer;
110     }
111 }
112