OLD | NEW |
(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 |
OLD | NEW |