blob: 49766c7a756f8387379cfbf1dc03355bf88408d0 [file] [log] [blame]
JP Abgrall5dcc6c92012-05-31 20:39:43 -07001/*
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
33template <typename T>
34static inline T min(T a, T b) {
35 return a<b ? a : b;
36}
37
38struct iio_event_data;
39
40InputEventCircularReader::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
50InputEventCircularReader::~InputEventCircularReader()
51{
52 delete [] mBuffer;
53}
54
55ssize_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
92bool 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
103void InputEventCircularReader::next()
104{
105 mCurr++;
106 if (mCurr >= mBufferEnd) {
107 mCurr = mBuffer;
108 }
109 if (mFreeEvents < mMaxEvents) {
110 mFreeEvents++;
111 }
112}