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
12 namespace ui {
13
14 namespace {
15
GetEventBits(int fd,unsigned int type,void * buf,unsigned int size)16 bool 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
GetPropBits(int fd,void * buf,unsigned int size)26 bool 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
BitIsSet(const unsigned long * bits,unsigned int bit)35 bool BitIsSet(const unsigned long* bits, unsigned int bit) {
36 return (bits[bit / EVDEV_LONG_BITS] & (1UL << (bit % EVDEV_LONG_BITS)));
37 }
38
GetAbsInfo(int fd,int code,struct input_absinfo * absinfo)39 bool 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
EventDeviceInfo()49 EventDeviceInfo::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
~EventDeviceInfo()61 EventDeviceInfo::~EventDeviceInfo() {}
62
Initialize(int fd)63 bool 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
HasEventType(unsigned int type) const96 bool EventDeviceInfo::HasEventType(unsigned int type) const {
97 if (type > EV_MAX)
98 return false;
99 return BitIsSet(ev_bits_, type);
100 }
101
HasKeyEvent(unsigned int code) const102 bool EventDeviceInfo::HasKeyEvent(unsigned int code) const {
103 if (code > KEY_MAX)
104 return false;
105 return BitIsSet(key_bits_, code);
106 }
107
HasRelEvent(unsigned int code) const108 bool EventDeviceInfo::HasRelEvent(unsigned int code) const {
109 if (code > REL_MAX)
110 return false;
111 return BitIsSet(rel_bits_, code);
112 }
113
HasAbsEvent(unsigned int code) const114 bool EventDeviceInfo::HasAbsEvent(unsigned int code) const {
115 if (code > ABS_MAX)
116 return false;
117 return BitIsSet(abs_bits_, code);
118 }
119
HasMscEvent(unsigned int code) const120 bool EventDeviceInfo::HasMscEvent(unsigned int code) const {
121 if (code > MSC_MAX)
122 return false;
123 return BitIsSet(msc_bits_, code);
124 }
125
HasSwEvent(unsigned int code) const126 bool EventDeviceInfo::HasSwEvent(unsigned int code) const {
127 if (code > SW_MAX)
128 return false;
129 return BitIsSet(sw_bits_, code);
130 }
131
HasLedEvent(unsigned int code) const132 bool EventDeviceInfo::HasLedEvent(unsigned int code) const {
133 if (code > LED_MAX)
134 return false;
135 return BitIsSet(led_bits_, code);
136 }
137
HasProp(unsigned int code) const138 bool EventDeviceInfo::HasProp(unsigned int code) const {
139 if (code > INPUT_PROP_MAX)
140 return false;
141 return BitIsSet(prop_bits_, code);
142 }
143
GetAbsMinimum(unsigned int code) const144 int32 EventDeviceInfo::GetAbsMinimum(unsigned int code) const {
145 return abs_info_[code].minimum;
146 }
147
GetAbsMaximum(unsigned int code) const148 int32 EventDeviceInfo::GetAbsMaximum(unsigned int code) const {
149 return abs_info_[code].maximum;
150 }
151
HasAbsXY() const152 bool 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
HasRelXY() const162 bool EventDeviceInfo::HasRelXY() const {
163 return HasRelEvent(REL_X) && HasRelEvent(REL_Y);
164 }
165
IsMappedToScreen() const166 bool 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