Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(86)

Side by Side Diff: ui/events/ozone/evdev/event_device_info.cc

Issue 1287103004: Sync ui/events to chromium @ https://codereview.chromium.org/1210203002 (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: rebased Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 #if !defined(EVIOCGMTSLOTS)
13 #define EVIOCGMTSLOTS(len) _IOC(_IOC_READ, 'E', 0x0a, len)
14 #endif
15
16 namespace ui {
17
18 namespace {
19
20 // USB vendor and product strings are pragmatically limited to 126
21 // characters each, so device names more than twice that should be
22 // unusual.
23 const size_t kMaximumDeviceNameLength = 256;
24
25 bool GetEventBits(int fd, unsigned int type, void* buf, unsigned int size) {
26 if (ioctl(fd, EVIOCGBIT(type, size), buf) < 0) {
27 PLOG(ERROR) << "EVIOCGBIT(" << type << ", " << size << ") on fd " << fd;
28 return false;
29 }
30
31 return true;
32 }
33
34 bool GetPropBits(int fd, void* buf, unsigned int size) {
35 if (ioctl(fd, EVIOCGPROP(size), buf) < 0) {
36 PLOG(ERROR) << "EVIOCGPROP(" << size << ") on fd " << fd;
37 return false;
38 }
39
40 return true;
41 }
42
43 bool GetAbsInfo(int fd, int code, struct input_absinfo* absinfo) {
44 if (ioctl(fd, EVIOCGABS(code), absinfo)) {
45 PLOG(ERROR) << "EVIOCGABS(" << code << ") on fd " << fd;
46 return false;
47 }
48 return true;
49 }
50
51 bool GetDeviceName(int fd, std::string* name) {
52 char device_name[kMaximumDeviceNameLength];
53 if (ioctl(fd, EVIOCGNAME(kMaximumDeviceNameLength - 1), &device_name) < 0) {
54 PLOG(INFO) << "Can't read device name on fd " << fd;
55 return false;
56 }
57 *name = device_name;
58 return true;
59 }
60
61 bool GetDeviceIdentifiers(int fd, uint16_t* vendor, uint16_t* product) {
62 struct input_id evdev_id;
63 if (ioctl(fd, EVIOCGID, &evdev_id) < 0) {
64 PLOG(INFO) << "Can't read device name on fd " << fd;
65 return false;
66 }
67 *vendor = evdev_id.vendor;
68 *product = evdev_id.product;
69 return true;
70 }
71
72 // |request| needs to be the equivalent to:
73 // struct input_mt_request_layout {
74 // uint32_t code;
75 // int32_t values[num_slots];
76 // };
77 //
78 // |size| is num_slots + 1 (for code).
79 bool GetSlotValues(int fd, int32_t* request, unsigned int size) {
80 size_t data_size = size * sizeof(*request);
81
82 if (ioctl(fd, EVIOCGMTSLOTS(data_size), request) < 0) {
83 PLOG(ERROR) << "EVIOCGMTSLOTS(" << request[0] << ") on fd " << fd;
84 return false;
85 }
86
87 return true;
88 }
89
90 void AssignBitset(const unsigned long* src,
91 size_t src_len,
92 unsigned long* dst,
93 size_t dst_len) {
94 memcpy(dst, src, std::min(src_len, dst_len) * sizeof(unsigned long));
95 if (src_len < dst_len)
96 memset(&dst[src_len], 0, (dst_len - src_len) * sizeof(unsigned long));
97 }
98
99 } // namespace
100
101 EventDeviceInfo::EventDeviceInfo() {
102 memset(ev_bits_, 0, sizeof(ev_bits_));
103 memset(key_bits_, 0, sizeof(key_bits_));
104 memset(rel_bits_, 0, sizeof(rel_bits_));
105 memset(abs_bits_, 0, sizeof(abs_bits_));
106 memset(msc_bits_, 0, sizeof(msc_bits_));
107 memset(sw_bits_, 0, sizeof(sw_bits_));
108 memset(led_bits_, 0, sizeof(led_bits_));
109 memset(prop_bits_, 0, sizeof(prop_bits_));
110 memset(abs_info_, 0, sizeof(abs_info_));
111 }
112
113 EventDeviceInfo::~EventDeviceInfo() {}
114
115 bool EventDeviceInfo::Initialize(int fd) {
116 if (!GetEventBits(fd, 0, ev_bits_, sizeof(ev_bits_)))
117 return false;
118
119 if (!GetEventBits(fd, EV_KEY, key_bits_, sizeof(key_bits_)))
120 return false;
121
122 if (!GetEventBits(fd, EV_REL, rel_bits_, sizeof(rel_bits_)))
123 return false;
124
125 if (!GetEventBits(fd, EV_ABS, abs_bits_, sizeof(abs_bits_)))
126 return false;
127
128 if (!GetEventBits(fd, EV_MSC, msc_bits_, sizeof(msc_bits_)))
129 return false;
130
131 if (!GetEventBits(fd, EV_SW, sw_bits_, sizeof(sw_bits_)))
132 return false;
133
134 if (!GetEventBits(fd, EV_LED, led_bits_, sizeof(led_bits_)))
135 return false;
136
137 if (!GetPropBits(fd, prop_bits_, sizeof(prop_bits_)))
138 return false;
139
140 for (unsigned int i = 0; i < ABS_CNT; ++i)
141 if (HasAbsEvent(i))
142 if (!GetAbsInfo(fd, i, &abs_info_[i]))
143 return false;
144
145 int max_num_slots = GetAbsMtSlotCount();
146
147 // |request| is MT code + slots.
148 int32_t request[max_num_slots + 1];
149 int32_t* request_code = &request[0];
150 int32_t* request_slots = &request[1];
151 for (unsigned int i = EVDEV_ABS_MT_FIRST; i <= EVDEV_ABS_MT_LAST; ++i) {
152 if (!HasAbsEvent(i))
153 continue;
154
155 memset(request, 0, sizeof(request));
156 *request_code = i;
157 if (!GetSlotValues(fd, request, max_num_slots + 1))
158 LOG(WARNING) << "Failed to get multitouch values for code " << i;
159
160 std::vector<int32_t>* slots = &slot_values_[i - EVDEV_ABS_MT_FIRST];
161 slots->assign(request_slots, request_slots + max_num_slots);
162 }
163
164 if (!GetDeviceName(fd, &name_))
165 return false;
166
167 if (!GetDeviceIdentifiers(fd, &vendor_id_, &product_id_))
168 return false;
169
170 return true;
171 }
172
173 void EventDeviceInfo::SetEventTypes(const unsigned long* ev_bits, size_t len) {
174 AssignBitset(ev_bits, len, ev_bits_, arraysize(ev_bits_));
175 }
176
177 void EventDeviceInfo::SetKeyEvents(const unsigned long* key_bits, size_t len) {
178 AssignBitset(key_bits, len, key_bits_, arraysize(key_bits_));
179 }
180
181 void EventDeviceInfo::SetRelEvents(const unsigned long* rel_bits, size_t len) {
182 AssignBitset(rel_bits, len, rel_bits_, arraysize(rel_bits_));
183 }
184
185 void EventDeviceInfo::SetAbsEvents(const unsigned long* abs_bits, size_t len) {
186 AssignBitset(abs_bits, len, abs_bits_, arraysize(abs_bits_));
187 }
188
189 void EventDeviceInfo::SetMscEvents(const unsigned long* msc_bits, size_t len) {
190 AssignBitset(msc_bits, len, msc_bits_, arraysize(msc_bits_));
191 }
192
193 void EventDeviceInfo::SetSwEvents(const unsigned long* sw_bits, size_t len) {
194 AssignBitset(sw_bits, len, sw_bits_, arraysize(sw_bits_));
195 }
196
197 void EventDeviceInfo::SetLedEvents(const unsigned long* led_bits, size_t len) {
198 AssignBitset(led_bits, len, led_bits_, arraysize(led_bits_));
199 }
200
201 void EventDeviceInfo::SetProps(const unsigned long* prop_bits, size_t len) {
202 AssignBitset(prop_bits, len, prop_bits_, arraysize(prop_bits_));
203 }
204
205 void EventDeviceInfo::SetAbsInfo(unsigned int code,
206 const input_absinfo& abs_info) {
207 if (code > ABS_MAX)
208 return;
209
210 memcpy(&abs_info_[code], &abs_info, sizeof(abs_info));
211 }
212
213 void EventDeviceInfo::SetAbsMtSlots(unsigned int code,
214 const std::vector<int32_t>& values) {
215 DCHECK_EQ(GetAbsMtSlotCount(), values.size());
216 int index = code - EVDEV_ABS_MT_FIRST;
217 if (index < 0 || index >= EVDEV_ABS_MT_COUNT)
218 return;
219 slot_values_[index] = values;
220 }
221
222 void EventDeviceInfo::SetAbsMtSlot(unsigned int code,
223 unsigned int slot,
224 uint32_t value) {
225 int index = code - EVDEV_ABS_MT_FIRST;
226 if (index < 0 || index >= EVDEV_ABS_MT_COUNT)
227 return;
228 slot_values_[index][slot] = value;
229 }
230
231 bool EventDeviceInfo::HasEventType(unsigned int type) const {
232 if (type > EV_MAX)
233 return false;
234 return EvdevBitIsSet(ev_bits_, type);
235 }
236
237 bool EventDeviceInfo::HasKeyEvent(unsigned int code) const {
238 if (code > KEY_MAX)
239 return false;
240 return EvdevBitIsSet(key_bits_, code);
241 }
242
243 bool EventDeviceInfo::HasRelEvent(unsigned int code) const {
244 if (code > REL_MAX)
245 return false;
246 return EvdevBitIsSet(rel_bits_, code);
247 }
248
249 bool EventDeviceInfo::HasAbsEvent(unsigned int code) const {
250 if (code > ABS_MAX)
251 return false;
252 return EvdevBitIsSet(abs_bits_, code);
253 }
254
255 bool EventDeviceInfo::HasMscEvent(unsigned int code) const {
256 if (code > MSC_MAX)
257 return false;
258 return EvdevBitIsSet(msc_bits_, code);
259 }
260
261 bool EventDeviceInfo::HasSwEvent(unsigned int code) const {
262 if (code > SW_MAX)
263 return false;
264 return EvdevBitIsSet(sw_bits_, code);
265 }
266
267 bool EventDeviceInfo::HasLedEvent(unsigned int code) const {
268 if (code > LED_MAX)
269 return false;
270 return EvdevBitIsSet(led_bits_, code);
271 }
272
273 bool EventDeviceInfo::HasProp(unsigned int code) const {
274 if (code > INPUT_PROP_MAX)
275 return false;
276 return EvdevBitIsSet(prop_bits_, code);
277 }
278
279 int32_t EventDeviceInfo::GetAbsMinimum(unsigned int code) const {
280 return abs_info_[code].minimum;
281 }
282
283 int32_t EventDeviceInfo::GetAbsMaximum(unsigned int code) const {
284 return abs_info_[code].maximum;
285 }
286
287 int32_t EventDeviceInfo::GetAbsValue(unsigned int code) const {
288 return abs_info_[code].value;
289 }
290
291 uint32_t EventDeviceInfo::GetAbsMtSlotCount() const {
292 if (!HasAbsEvent(ABS_MT_SLOT))
293 return 0;
294 return GetAbsMaximum(ABS_MT_SLOT) + 1;
295 }
296
297 int32_t EventDeviceInfo::GetAbsMtSlotValue(unsigned int code,
298 unsigned int slot) const {
299 unsigned int index = code - EVDEV_ABS_MT_FIRST;
300 DCHECK(index < EVDEV_ABS_MT_COUNT);
301 return slot_values_[index][slot];
302 }
303
304 int32_t EventDeviceInfo::GetAbsMtSlotValueWithDefault(
305 unsigned int code,
306 unsigned int slot,
307 int32_t default_value) const {
308 if (!HasAbsEvent(code))
309 return default_value;
310 return GetAbsMtSlotValue(code, slot);
311 }
312
313 bool EventDeviceInfo::HasAbsXY() const {
314 return HasAbsEvent(ABS_X) && HasAbsEvent(ABS_Y);
315 }
316
317 bool EventDeviceInfo::HasMTAbsXY() const {
318 return HasAbsEvent(ABS_MT_POSITION_X) && HasAbsEvent(ABS_MT_POSITION_Y);
319 }
320
321 bool EventDeviceInfo::HasRelXY() const {
322 return HasRelEvent(REL_X) && HasRelEvent(REL_Y);
323 }
324
325 bool EventDeviceInfo::HasMultitouch() const {
326 return HasAbsEvent(ABS_MT_SLOT);
327 }
328
329 bool EventDeviceInfo::HasDirect() const {
330 bool has_direct = HasProp(INPUT_PROP_DIRECT);
331 bool has_pointer = HasProp(INPUT_PROP_POINTER);
332 if (has_direct || has_pointer)
333 return has_direct;
334
335 switch (ProbeLegacyAbsoluteDevice()) {
336 case LegacyAbsoluteDeviceType::LADT_TOUCHSCREEN:
337 return true;
338
339 case LegacyAbsoluteDeviceType::LADT_TABLET:
340 case LegacyAbsoluteDeviceType::LADT_TOUCHPAD:
341 case LegacyAbsoluteDeviceType::LADT_NONE:
342 return false;
343 }
344
345 NOTREACHED();
346 return false;
347 }
348
349 bool EventDeviceInfo::HasPointer() const {
350 bool has_direct = HasProp(INPUT_PROP_DIRECT);
351 bool has_pointer = HasProp(INPUT_PROP_POINTER);
352 if (has_direct || has_pointer)
353 return has_pointer;
354
355 switch (ProbeLegacyAbsoluteDevice()) {
356 case LegacyAbsoluteDeviceType::LADT_TOUCHPAD:
357 case LegacyAbsoluteDeviceType::LADT_TABLET:
358 return true;
359
360 case LegacyAbsoluteDeviceType::LADT_TOUCHSCREEN:
361 case LegacyAbsoluteDeviceType::LADT_NONE:
362 return false;
363 }
364
365 NOTREACHED();
366 return false;
367 }
368
369 bool EventDeviceInfo::HasStylus() const {
370 return HasKeyEvent(BTN_TOOL_PEN) || HasKeyEvent(BTN_STYLUS) ||
371 HasKeyEvent(BTN_STYLUS2);
372 }
373
374 bool EventDeviceInfo::HasKeyboard() const {
375 if (!HasEventType(EV_KEY))
376 return false;
377
378 // Check first 31 keys: If we have all of them, consider it a full
379 // keyboard. This is exactly what udev does for ID_INPUT_KEYBOARD.
380 for (int key = KEY_ESC; key <= KEY_D; ++key)
381 if (!HasKeyEvent(key))
382 return false;
383
384 return true;
385 }
386
387 bool EventDeviceInfo::HasMouse() const {
388 return HasRelXY();
389 }
390
391 bool EventDeviceInfo::HasTouchpad() const {
392 return HasAbsXY() && HasPointer() && !HasStylus();
393 }
394
395 bool EventDeviceInfo::HasTablet() const {
396 return HasAbsXY() && HasPointer() && HasStylus();
397 }
398
399 bool EventDeviceInfo::HasTouchscreen() const {
400 return HasAbsXY() && HasDirect();
401 }
402
403 EventDeviceInfo::LegacyAbsoluteDeviceType
404 EventDeviceInfo::ProbeLegacyAbsoluteDevice() const {
405 if (!HasAbsXY())
406 return LegacyAbsoluteDeviceType::LADT_NONE;
407
408 if (HasStylus())
409 return LegacyAbsoluteDeviceType::LADT_TABLET;
410
411 if (HasKeyEvent(BTN_TOOL_FINGER) && HasKeyEvent(BTN_TOUCH))
412 return LegacyAbsoluteDeviceType::LADT_TOUCHPAD;
413
414 if (HasKeyEvent(BTN_TOUCH) || HasKeyEvent(BTN_LEFT))
415 return LegacyAbsoluteDeviceType::LADT_TOUCHSCREEN;
416
417 return LegacyAbsoluteDeviceType::LADT_NONE;
418 }
419
420 } // namespace ui
OLDNEW
« no previous file with comments | « ui/events/ozone/evdev/event_device_info.h ('k') | ui/events/ozone/evdev/event_device_info_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698