1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.h"
6
7#include <errno.h>
8#include <libevdev/libevdev.h>
9#include <linux/input.h>
10
11#include "base/message_loop/message_loop.h"
12#include "base/strings/string_util.h"
13#include "base/strings/stringprintf.h"
14
15namespace ui {
16
17namespace {
18
19std::string FormatLog(const char* fmt, va_list args) {
20  std::string msg = base::StringPrintV(fmt, args);
21  if (!msg.empty() && msg[msg.size() - 1] == '\n')
22    msg.erase(msg.end() - 1, msg.end());
23  return msg;
24}
25
26}  // namespace
27
28EventReaderLibevdevCros::EventReaderLibevdevCros(int fd,
29                                                 const base::FilePath& path,
30                                                 scoped_ptr<Delegate> delegate)
31    : EventConverterEvdev(fd, path), delegate_(delegate.Pass()) {
32  memset(&evdev_, 0, sizeof(evdev_));
33  evdev_.log = OnLogMessage;
34  evdev_.log_udata = this;
35  evdev_.syn_report = OnSynReport;
36  evdev_.syn_report_udata = this;
37  evdev_.fd = fd;
38
39  memset(&evstate_, 0, sizeof(evstate_));
40  evdev_.evstate = &evstate_;
41  Event_Init(&evdev_);
42
43  Event_Open(&evdev_);
44
45  delegate_->OnLibEvdevCrosOpen(&evdev_, &evstate_);
46}
47
48EventReaderLibevdevCros::~EventReaderLibevdevCros() {
49  Stop();
50  EvdevClose(&evdev_);
51}
52
53EventReaderLibevdevCros::Delegate::~Delegate() {}
54
55void EventReaderLibevdevCros::OnFileCanReadWithoutBlocking(int fd) {
56  if (EvdevRead(&evdev_)) {
57    if (errno == EINTR || errno == EAGAIN)
58      return;
59    if (errno != ENODEV)
60      PLOG(ERROR) << "error reading device " << path_.value();
61    Stop();
62    return;
63  }
64}
65
66// static
67void EventReaderLibevdevCros::OnSynReport(void* data,
68                                          EventStateRec* evstate,
69                                          struct timeval* tv) {
70  EventReaderLibevdevCros* reader = static_cast<EventReaderLibevdevCros*>(data);
71  reader->delegate_->OnLibEvdevCrosEvent(&reader->evdev_, evstate, *tv);
72}
73
74// static
75void EventReaderLibevdevCros::OnLogMessage(void* data,
76                                           int level,
77                                           const char* fmt,
78                                           ...) {
79  va_list args;
80  va_start(args, fmt);
81  if (level >= LOGLEVEL_ERROR)
82    LOG(ERROR) << "libevdev: " << FormatLog(fmt, args);
83  else if (level >= LOGLEVEL_WARNING)
84    LOG(WARNING) << "libevdev: " << FormatLog(fmt, args);
85  else
86    VLOG(3) << "libevdev: " << FormatLog(fmt, args);
87  va_end(args);
88}
89
90}  // namespace ui
91