Landing Recent QUIC Changes.
[chromium-blink-merge.git] / ui / events / ozone / evdev / event_device_info.cc
blob847eebf9a847f73795c09db263c57fc0fc525afd
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.
5 #include "ui/events/ozone/evdev/event_device_info.h"
7 #include <linux/input.h>
9 #include "base/logging.h"
10 #include "base/threading/thread_restrictions.h"
12 #if !defined(EVIOCGMTSLOTS)
13 #define EVIOCGMTSLOTS(len) _IOC(_IOC_READ, 'E', 0x0a, len)
14 #endif
16 namespace ui {
18 namespace {
20 bool GetEventBits(int fd, unsigned int type, void* buf, unsigned int size) {
21 if (ioctl(fd, EVIOCGBIT(type, size), buf) < 0) {
22 DLOG(ERROR) << "failed EVIOCGBIT(" << type << ", " << size << ") on fd "
23 << fd;
24 return false;
27 return true;
30 bool GetPropBits(int fd, void* buf, unsigned int size) {
31 if (ioctl(fd, EVIOCGPROP(size), buf) < 0) {
32 DLOG(ERROR) << "failed EVIOCGPROP(" << size << ") on fd " << fd;
33 return false;
36 return true;
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;
44 return true;
47 // |request| needs to be the equivalent to:
48 // struct input_mt_request_layout {
49 // uint32_t code;
50 // int32_t values[num_slots];
51 // };
53 // |size| is num_slots + 1 (for code).
54 bool GetSlotValues(int fd, int32_t* request, unsigned int size) {
55 if (ioctl(fd,
56 EVIOCGMTSLOTS(sizeof(int32_t) * size),
57 request) < 0) {
58 DLOG(ERROR) << "failed EVIOCGMTSLOTS(" << request[0] << ") on fd " << fd;
59 return false;
62 return true;
65 } // namespace
67 EventDeviceInfo::EventDeviceInfo() {
68 memset(ev_bits_, 0, sizeof(ev_bits_));
69 memset(key_bits_, 0, sizeof(key_bits_));
70 memset(rel_bits_, 0, sizeof(rel_bits_));
71 memset(abs_bits_, 0, sizeof(abs_bits_));
72 memset(msc_bits_, 0, sizeof(msc_bits_));
73 memset(sw_bits_, 0, sizeof(sw_bits_));
74 memset(led_bits_, 0, sizeof(led_bits_));
75 memset(prop_bits_, 0, sizeof(prop_bits_));
76 memset(abs_info_, 0, sizeof(abs_info_));
79 EventDeviceInfo::~EventDeviceInfo() {}
81 bool EventDeviceInfo::Initialize(int fd) {
82 if (!GetEventBits(fd, 0, ev_bits_, sizeof(ev_bits_)))
83 return false;
85 if (!GetEventBits(fd, EV_KEY, key_bits_, sizeof(key_bits_)))
86 return false;
88 if (!GetEventBits(fd, EV_REL, rel_bits_, sizeof(rel_bits_)))
89 return false;
91 if (!GetEventBits(fd, EV_ABS, abs_bits_, sizeof(abs_bits_)))
92 return false;
94 if (!GetEventBits(fd, EV_MSC, msc_bits_, sizeof(msc_bits_)))
95 return false;
97 if (!GetEventBits(fd, EV_SW, sw_bits_, sizeof(sw_bits_)))
98 return false;
100 if (!GetEventBits(fd, EV_LED, led_bits_, sizeof(led_bits_)))
101 return false;
103 if (!GetPropBits(fd, prop_bits_, sizeof(prop_bits_)))
104 return false;
106 for (unsigned int i = 0; i < ABS_CNT; ++i)
107 if (HasAbsEvent(i))
108 if (!GetAbsInfo(fd, i, &abs_info_[i]))
109 return false;
111 int max_num_slots = abs_info_[ABS_MT_SLOT].maximum + 1;
112 // |request| is MT code + slots.
113 int32_t request[max_num_slots + 1];
114 for (unsigned int i = ABS_MT_SLOT + 1; i < ABS_MAX; ++i) {
115 memset(request, 0, sizeof(request));
116 request[0] = i;
117 if (HasAbsEvent(i))
118 if (!GetSlotValues(fd, request, max_num_slots + 1))
119 LOG(WARNING) << "Failed to get multitouch values for code " << i;
121 slot_values_[i - ABS_MT_SLOT - 1].assign(
122 request + 1, request + max_num_slots + 1);
125 return true;
128 bool EventDeviceInfo::HasEventType(unsigned int type) const {
129 if (type > EV_MAX)
130 return false;
131 return EvdevBitIsSet(ev_bits_, type);
134 bool EventDeviceInfo::HasKeyEvent(unsigned int code) const {
135 if (code > KEY_MAX)
136 return false;
137 return EvdevBitIsSet(key_bits_, code);
140 bool EventDeviceInfo::HasRelEvent(unsigned int code) const {
141 if (code > REL_MAX)
142 return false;
143 return EvdevBitIsSet(rel_bits_, code);
146 bool EventDeviceInfo::HasAbsEvent(unsigned int code) const {
147 if (code > ABS_MAX)
148 return false;
149 return EvdevBitIsSet(abs_bits_, code);
152 bool EventDeviceInfo::HasMscEvent(unsigned int code) const {
153 if (code > MSC_MAX)
154 return false;
155 return EvdevBitIsSet(msc_bits_, code);
158 bool EventDeviceInfo::HasSwEvent(unsigned int code) const {
159 if (code > SW_MAX)
160 return false;
161 return EvdevBitIsSet(sw_bits_, code);
164 bool EventDeviceInfo::HasLedEvent(unsigned int code) const {
165 if (code > LED_MAX)
166 return false;
167 return EvdevBitIsSet(led_bits_, code);
170 bool EventDeviceInfo::HasProp(unsigned int code) const {
171 if (code > INPUT_PROP_MAX)
172 return false;
173 return EvdevBitIsSet(prop_bits_, code);
176 int32 EventDeviceInfo::GetAbsMinimum(unsigned int code) const {
177 return abs_info_[code].minimum;
180 int32 EventDeviceInfo::GetAbsMaximum(unsigned int code) const {
181 return abs_info_[code].maximum;
184 int32 EventDeviceInfo::GetSlotValue(unsigned int code,
185 unsigned int slot) const {
186 const std::vector<int32_t>& slots = GetMtSlotsForCode(code);
187 DCHECK_LE(0u, slot) << slot << " is an invalid slot";
188 DCHECK_LT(slot, slots.size()) << slot << " is an invalid slot";
189 return slots[slot];
192 bool EventDeviceInfo::HasAbsXY() const {
193 return HasAbsEvent(ABS_X) && HasAbsEvent(ABS_Y);
196 bool EventDeviceInfo::HasMTAbsXY() const {
197 return HasAbsEvent(ABS_MT_POSITION_X) && HasAbsEvent(ABS_MT_POSITION_Y);
200 bool EventDeviceInfo::HasRelXY() const {
201 return HasRelEvent(REL_X) && HasRelEvent(REL_Y);
204 bool EventDeviceInfo::IsMappedToScreen() const {
205 // Device position is mapped directly to the screen.
206 if (HasProp(INPUT_PROP_DIRECT))
207 return true;
209 // Tablets are mapped to the screen.
210 if (HasKeyEvent(BTN_TOOL_PEN) || HasKeyEvent(BTN_STYLUS) ||
211 HasKeyEvent(BTN_STYLUS2))
212 return true;
214 // Device position moves the cursor.
215 if (HasProp(INPUT_PROP_POINTER))
216 return false;
218 // Touchpads are not mapped to the screen.
219 if (HasKeyEvent(BTN_LEFT) || HasKeyEvent(BTN_MIDDLE) ||
220 HasKeyEvent(BTN_RIGHT) || HasKeyEvent(BTN_TOOL_FINGER))
221 return false;
223 // Touchscreens are mapped to the screen.
224 return true;
227 bool EventDeviceInfo::HasKeyboard() const {
228 if (!HasEventType(EV_KEY))
229 return false;
231 // Check first 31 keys: If we have all of them, consider it a full
232 // keyboard. This is exactly what udev does for ID_INPUT_KEYBOARD.
233 for (int key = KEY_ESC; key <= KEY_D; ++key)
234 if (!HasKeyEvent(key))
235 return false;
237 return true;
240 bool EventDeviceInfo::HasMouse() const {
241 return HasRelXY();
244 bool EventDeviceInfo::HasTouchpad() const {
245 return (HasAbsXY() || HasMTAbsXY()) && !IsMappedToScreen();
248 const std::vector<int32_t>& EventDeviceInfo::GetMtSlotsForCode(int code) const {
249 int index = code - ABS_MT_SLOT - 1;
250 DCHECK_LE(0, index) << code << " is not a valid multi-touch code";
251 DCHECK_LT(index, EVDEV_ABS_MT_COUNT)
252 << code << " is not a valid multi-touch code";
253 return slot_values_[index];
256 } // namespace ui