• 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