1// Copyright 2013 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/event_device_info.h"
6
7#include <linux/input.h>
8
9#include "base/logging.h"
10#include "base/threading/thread_restrictions.h"
11
12namespace ui {
13
14namespace {
15
16bool GetEventBits(int fd, unsigned int type, void* buf, unsigned int size) {
17  if (ioctl(fd, EVIOCGBIT(type, size), buf) < 0) {
18    DLOG(ERROR) << "failed EVIOCGBIT(" << type << ", " << size << ") on fd "
19                << fd;
20    return false;
21  }
22
23  return true;
24}
25
26bool GetPropBits(int fd, void* buf, unsigned int size) {
27  if (ioctl(fd, EVIOCGPROP(size), buf) < 0) {
28    DLOG(ERROR) << "failed EVIOCGPROP(" << size << ") on fd " << fd;
29    return false;
30  }
31
32  return true;
33}
34
35bool BitIsSet(const unsigned long* bits, unsigned int bit) {
36  return (bits[bit / EVDEV_LONG_BITS] & (1UL << (bit % EVDEV_LONG_BITS)));
37}
38
39bool GetAbsInfo(int fd, int code, struct input_absinfo* absinfo) {
40  if (ioctl(fd, EVIOCGABS(code), absinfo)) {
41    DLOG(ERROR) << "failed EVIOCGABS(" << code << ") on fd " << fd;
42    return false;
43  }
44  return true;
45}
46
47}  // namespace
48
49EventDeviceInfo::EventDeviceInfo() {
50  memset(ev_bits_, 0, sizeof(ev_bits_));
51  memset(key_bits_, 0, sizeof(key_bits_));
52  memset(rel_bits_, 0, sizeof(rel_bits_));
53  memset(abs_bits_, 0, sizeof(abs_bits_));
54  memset(msc_bits_, 0, sizeof(msc_bits_));
55  memset(sw_bits_, 0, sizeof(sw_bits_));
56  memset(led_bits_, 0, sizeof(led_bits_));
57  memset(prop_bits_, 0, sizeof(prop_bits_));
58  memset(abs_info_, 0, sizeof(abs_info_));
59}
60
61EventDeviceInfo::~EventDeviceInfo() {}
62
63bool EventDeviceInfo::Initialize(int fd) {
64  if (!GetEventBits(fd, 0, ev_bits_, sizeof(ev_bits_)))
65    return false;
66
67  if (!GetEventBits(fd, EV_KEY, key_bits_, sizeof(key_bits_)))
68    return false;
69
70  if (!GetEventBits(fd, EV_REL, rel_bits_, sizeof(rel_bits_)))
71    return false;
72
73  if (!GetEventBits(fd, EV_ABS, abs_bits_, sizeof(abs_bits_)))
74    return false;
75
76  if (!GetEventBits(fd, EV_MSC, msc_bits_, sizeof(msc_bits_)))
77    return false;
78
79  if (!GetEventBits(fd, EV_SW, sw_bits_, sizeof(sw_bits_)))
80    return false;
81
82  if (!GetEventBits(fd, EV_LED, led_bits_, sizeof(led_bits_)))
83    return false;
84
85  if (!GetPropBits(fd, prop_bits_, sizeof(prop_bits_)))
86    return false;
87
88  for (unsigned int i = 0; i < ABS_CNT; ++i)
89    if (HasAbsEvent(i))
90      if (!GetAbsInfo(fd, i, &abs_info_[i]))
91        return false;
92
93  return true;
94}
95
96bool EventDeviceInfo::HasEventType(unsigned int type) const {
97  if (type > EV_MAX)
98    return false;
99  return BitIsSet(ev_bits_, type);
100}
101
102bool EventDeviceInfo::HasKeyEvent(unsigned int code) const {
103  if (code > KEY_MAX)
104    return false;
105  return BitIsSet(key_bits_, code);
106}
107
108bool EventDeviceInfo::HasRelEvent(unsigned int code) const {
109  if (code > REL_MAX)
110    return false;
111  return BitIsSet(rel_bits_, code);
112}
113
114bool EventDeviceInfo::HasAbsEvent(unsigned int code) const {
115  if (code > ABS_MAX)
116    return false;
117  return BitIsSet(abs_bits_, code);
118}
119
120bool EventDeviceInfo::HasMscEvent(unsigned int code) const {
121  if (code > MSC_MAX)
122    return false;
123  return BitIsSet(msc_bits_, code);
124}
125
126bool EventDeviceInfo::HasSwEvent(unsigned int code) const {
127  if (code > SW_MAX)
128    return false;
129  return BitIsSet(sw_bits_, code);
130}
131
132bool EventDeviceInfo::HasLedEvent(unsigned int code) const {
133  if (code > LED_MAX)
134    return false;
135  return BitIsSet(led_bits_, code);
136}
137
138bool EventDeviceInfo::HasProp(unsigned int code) const {
139  if (code > INPUT_PROP_MAX)
140    return false;
141  return BitIsSet(prop_bits_, code);
142}
143
144int32 EventDeviceInfo::GetAbsMinimum(unsigned int code) const {
145  return abs_info_[code].minimum;
146}
147
148int32 EventDeviceInfo::GetAbsMaximum(unsigned int code) const {
149  return abs_info_[code].maximum;
150}
151
152bool EventDeviceInfo::HasAbsXY() const {
153  if (HasAbsEvent(ABS_X) && HasAbsEvent(ABS_Y))
154    return true;
155
156  if (HasAbsEvent(ABS_MT_POSITION_X) && HasAbsEvent(ABS_MT_POSITION_Y))
157    return true;
158
159  return false;
160}
161
162bool EventDeviceInfo::HasRelXY() const {
163  return HasRelEvent(REL_X) && HasRelEvent(REL_Y);
164}
165
166bool EventDeviceInfo::IsMappedToScreen() const {
167  // Device position is mapped directly to the screen.
168  if (HasProp(INPUT_PROP_DIRECT))
169    return true;
170
171  // Device position moves the cursor.
172  if (HasProp(INPUT_PROP_POINTER))
173    return false;
174
175  // Tablets are mapped to the screen.
176  if (HasKeyEvent(BTN_TOOL_PEN) || HasKeyEvent(BTN_STYLUS) ||
177      HasKeyEvent(BTN_STYLUS2))
178    return true;
179
180  // Touchpads are not mapped to the screen.
181  if (HasKeyEvent(BTN_LEFT) || HasKeyEvent(BTN_MIDDLE) ||
182      HasKeyEvent(BTN_RIGHT) || HasKeyEvent(BTN_TOOL_FINGER))
183    return false;
184
185  // Touchscreens are mapped to the screen.
186  return true;
187}
188
189}  // namespace ui
190