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