1#include "EvdevInjector.h"
2
3#include <errno.h>
4#include <inttypes.h>
5#include <linux/input.h>
6#include <log/log.h>
7#include <string.h>
8#include <sys/fcntl.h>
9#include <unistd.h>
10
11namespace android {
12namespace dvr {
13
14int EvdevInjector::UInput::Open() {
15  errno = 0;
16  fd_.reset(open("/dev/uinput", O_WRONLY | O_NONBLOCK));
17  if (fd_.get() < 0) {
18    ALOGE("couldn't open uinput (r=%d errno=%d)", fd_.get(), errno);
19  }
20  return errno;
21}
22
23int EvdevInjector::UInput::Close() {
24  errno = 0;
25  fd_.reset();
26  return errno;
27}
28
29int EvdevInjector::UInput::Write(const void* buf, size_t count) {
30  ALOGV("UInput::Write(%zu, %02X...)", count, *static_cast<const char*>(buf));
31  errno = 0;
32  ssize_t r = write(fd_.get(), buf, count);
33  if (r != static_cast<ssize_t>(count)) {
34    ALOGE("write(%zu) failed (r=%zd errno=%d)", count, r, errno);
35  }
36  return errno;
37}
38
39int EvdevInjector::UInput::IoctlSetInt(int request, int value) {
40  ALOGV("UInput::IoctlSetInt(0x%X, 0x%X)", request, value);
41  errno = 0;
42  if (const int status = ioctl(fd_.get(), request, value)) {
43    ALOGE("ioctl(%d, 0x%X, 0x%X) failed (r=%d errno=%d)", fd_.get(), request,
44          value, status, errno);
45  }
46  return errno;
47}
48
49int EvdevInjector::UInput::IoctlVoid(int request) {
50  ALOGV("UInput::IoctlVoid(0x%X)", request);
51  errno = 0;
52  if (const int status = ioctl(fd_.get(), request)) {
53    ALOGE("ioctl(%d, 0x%X) failed (r=%d errno=%d)", fd_.get(), request, status,
54          errno);
55  }
56  return errno;
57}
58
59void EvdevInjector::Close() {
60  uinput_->Close();
61  state_ = State::CLOSED;
62}
63
64int EvdevInjector::ConfigureBegin(const char* device_name, int16_t bustype,
65                                  int16_t vendor, int16_t product,
66                                  int16_t version) {
67  ALOGV("ConfigureBegin %s 0x%04" PRIX16 " 0x%04" PRIX16 " 0x%04" PRIX16
68        " 0x%04" PRIX16 "",
69        device_name, bustype, vendor, product, version);
70  if (!device_name || strlen(device_name) >= UINPUT_MAX_NAME_SIZE) {
71    return Error(ERROR_DEVICE_NAME);
72  }
73  if (const int status = RequireState(State::NEW)) {
74    return status;
75  }
76  if (!uinput_) {
77    owned_uinput_.reset(new EvdevInjector::UInput());
78    uinput_ = owned_uinput_.get();
79  }
80  if (const int status = uinput_->Open()) {
81    // Without uinput we're dead in the water.
82    state_ = State::CLOSED;
83    return Error(status);
84  }
85  state_ = State::CONFIGURING;
86  // Initialize device setting structure.
87  memset(&uidev_, 0, sizeof(uidev_));
88  strncpy(uidev_.name, device_name, UINPUT_MAX_NAME_SIZE);
89  uidev_.id.bustype = bustype;
90  uidev_.id.vendor = vendor;
91  uidev_.id.product = product;
92  uidev_.id.version = version;
93  return 0;
94}
95
96int EvdevInjector::ConfigureInputProperty(int property) {
97  ALOGV("ConfigureInputProperty %d", property);
98  if (property < 0 || property >= INPUT_PROP_CNT) {
99    ALOGE("property 0x%X out of range [0,0x%X)", property, INPUT_PROP_CNT);
100    return Error(ERROR_PROPERTY_RANGE);
101  }
102  if (const int status = RequireState(State::CONFIGURING)) {
103    return status;
104  }
105  if (const int status = uinput_->IoctlSetInt(UI_SET_PROPBIT, property)) {
106    ALOGE("failed to set property %d", property);
107    return Error(status);
108  }
109  return 0;
110}
111
112int EvdevInjector::ConfigureKey(uint16_t key) {
113  ALOGV("ConfigureKey 0x%02" PRIX16 "", key);
114  if (key < 0 || key >= KEY_CNT) {
115    ALOGE("key 0x%X out of range [0,0x%X)", key, KEY_CNT);
116    return Error(ERROR_KEY_RANGE);
117  }
118  if (const int status = RequireState(State::CONFIGURING)) {
119    return status;
120  }
121  if (const int status = EnableEventType(EV_KEY)) {
122    return status;
123  }
124  if (const int status = uinput_->IoctlSetInt(UI_SET_KEYBIT, key)) {
125    ALOGE("failed to enable EV_KEY 0x%02" PRIX16 "", key);
126    return Error(status);
127  }
128  return 0;
129}
130
131int EvdevInjector::ConfigureAbs(uint16_t abs_type, int32_t min, int32_t max,
132                                int32_t fuzz, int32_t flat) {
133  ALOGV("ConfigureAbs 0x%" PRIX16 " %" PRId32 " %" PRId32 " %" PRId32
134        " %" PRId32 "",
135        abs_type, min, max, fuzz, flat);
136  if (abs_type < 0 || abs_type >= ABS_CNT) {
137    ALOGE("EV_ABS type 0x%" PRIX16 " out of range [0,0x%X)", abs_type, ABS_CNT);
138    return Error(ERROR_ABS_RANGE);
139  }
140  if (const int status = RequireState(State::CONFIGURING)) {
141    return status;
142  }
143  if (const int status = EnableEventType(EV_ABS)) {
144    return status;
145  }
146  if (const int status = uinput_->IoctlSetInt(UI_SET_ABSBIT, abs_type)) {
147    ALOGE("failed to enable EV_ABS 0x%" PRIX16 "", abs_type);
148    return Error(status);
149  }
150  uidev_.absmin[abs_type] = min;
151  uidev_.absmax[abs_type] = max;
152  uidev_.absfuzz[abs_type] = fuzz;
153  uidev_.absflat[abs_type] = flat;
154  return 0;
155}
156
157int EvdevInjector::ConfigureMultiTouchXY(int x0, int y0, int x1, int y1) {
158  if (const int status = ConfigureAbs(ABS_MT_POSITION_X, x0, x1, 0, 0)) {
159    return status;
160  }
161  if (const int status = ConfigureAbs(ABS_MT_POSITION_Y, y0, y1, 0, 0)) {
162    return status;
163  }
164  return 0;
165}
166
167int EvdevInjector::ConfigureAbsSlots(int slots) {
168  return ConfigureAbs(ABS_MT_SLOT, 0, slots, 0, 0);
169}
170
171int EvdevInjector::ConfigureEnd() {
172  ALOGV("ConfigureEnd:");
173  ALOGV("  name=\"%s\"", uidev_.name);
174  ALOGV("  id.bustype=0x%04" PRIX16, uidev_.id.bustype);
175  ALOGV("  id.vendor=0x%04" PRIX16, uidev_.id.vendor);
176  ALOGV("  id.product=0x%04" PRIX16, uidev_.id.product);
177  ALOGV("  id.version=0x%04" PRIX16, uidev_.id.version);
178  ALOGV("  ff_effects_max=%" PRIu32, uidev_.ff_effects_max);
179  for (int i = 0; i < ABS_CNT; ++i) {
180    if (uidev_.absmin[i]) {
181      ALOGV("  absmin[%d]=%" PRId32, i, uidev_.absmin[i]);
182    }
183    if (uidev_.absmax[i]) {
184      ALOGV("  absmax[%d]=%" PRId32, i, uidev_.absmax[i]);
185    }
186    if (uidev_.absfuzz[i]) {
187      ALOGV("  absfuzz[%d]=%" PRId32, i, uidev_.absfuzz[i]);
188    }
189    if (uidev_.absflat[i]) {
190      ALOGV("  absflat[%d]=%" PRId32, i, uidev_.absflat[i]);
191    }
192  }
193
194  if (const int status = RequireState(State::CONFIGURING)) {
195    return status;
196  }
197  // Write out device settings.
198  if (const int status = uinput_->Write(&uidev_, sizeof uidev_)) {
199    ALOGE("failed to write device settings");
200    return Error(status);
201  }
202  // Create device node.
203  if (const int status = uinput_->IoctlVoid(UI_DEV_CREATE)) {
204    ALOGE("failed to create device node");
205    return Error(status);
206  }
207  state_ = State::READY;
208  return 0;
209}
210
211int EvdevInjector::Send(uint16_t type, uint16_t code, int32_t value) {
212  ALOGV("Send(0x%" PRIX16 ", 0x%" PRIX16 ", 0x%" PRIX32 ")", type, code, value);
213  if (const int status = RequireState(State::READY)) {
214    return status;
215  }
216  struct input_event event;
217  memset(&event, 0, sizeof(event));
218  event.type = type;
219  event.code = code;
220  event.value = value;
221  if (const int status = uinput_->Write(&event, sizeof(event))) {
222    ALOGE("failed to write event 0x%" PRIX16 ", 0x%" PRIX16 ", 0x%" PRIX32,
223          type, code, value);
224    return Error(status);
225  }
226  return 0;
227}
228
229int EvdevInjector::SendSynReport() { return Send(EV_SYN, SYN_REPORT, 0); }
230
231int EvdevInjector::SendKey(uint16_t code, int32_t value) {
232  return Send(EV_KEY, code, value);
233}
234
235int EvdevInjector::SendAbs(uint16_t code, int32_t value) {
236  return Send(EV_ABS, code, value);
237}
238
239int EvdevInjector::SendMultiTouchSlot(int32_t slot) {
240  if (latest_slot_ != slot) {
241    if (const int status = SendAbs(ABS_MT_SLOT, slot)) {
242      return status;
243    }
244    latest_slot_ = slot;
245  }
246  return 0;
247}
248
249int EvdevInjector::SendMultiTouchXY(int32_t slot, int32_t id, int32_t x,
250                                    int32_t y) {
251  if (const int status = SendMultiTouchSlot(slot)) {
252    return status;
253  }
254  if (const int status = SendAbs(ABS_MT_TRACKING_ID, id)) {
255    return status;
256  }
257  if (const int status = SendAbs(ABS_MT_POSITION_X, x)) {
258    return status;
259  }
260  if (const int status = SendAbs(ABS_MT_POSITION_Y, y)) {
261    return status;
262  }
263  return 0;
264}
265
266int EvdevInjector::SendMultiTouchLift(int32_t slot) {
267  if (const int status = SendMultiTouchSlot(slot)) {
268    return status;
269  }
270  if (const int status = SendAbs(ABS_MT_TRACKING_ID, -1)) {
271    return status;
272  }
273  return 0;
274}
275
276int EvdevInjector::Error(int code) {
277  if (!error_) {
278    error_ = code;
279  }
280  return code;
281}
282
283int EvdevInjector::RequireState(State required_state) {
284  if (error_) {
285    return error_;
286  }
287  if (state_ != required_state) {
288    ALOGE("in state %d but require state %d", static_cast<int>(state_),
289          static_cast<int>(required_state));
290    return Error(ERROR_SEQUENCING);
291  }
292  return 0;
293}
294
295int EvdevInjector::EnableEventType(uint16_t type) {
296  if (const int status = RequireState(State::CONFIGURING)) {
297    return status;
298  }
299  if (enabled_event_types_.count(type) > 0) {
300    return 0;
301  }
302  if (const int status = uinput_->IoctlSetInt(UI_SET_EVBIT, type)) {
303    ALOGE("failed to enable event type 0x%X", type);
304    return Error(status);
305  }
306  enabled_event_types_.insert(type);
307  return 0;
308}
309
310void EvdevInjector::dumpInternal(String8& result) {
311  result.appendFormat("injector_state = %d\n", static_cast<int>(state_));
312  result.appendFormat("injector_error = %d\n", error_);
313}
314
315}  // namespace dvr
316}  // namespace android
317