diff options
author | spang@chromium.org <spang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-07 00:19:58 +0000 |
---|---|---|
committer | spang@chromium.org <spang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-07 00:19:58 +0000 |
commit | c2d77073d898ca313a9c54d9cfc09033971dde22 (patch) | |
tree | 8737ad89015d639b4b402af16733835ab5b0d531 /ui | |
parent | 3772282de897cfc2a66bc95c3bd06d0c2a3fd65f (diff) | |
download | chromium_src-c2d77073d898ca313a9c54d9cfc09033971dde22.zip chromium_src-c2d77073d898ca313a9c54d9cfc09033971dde22.tar.gz chromium_src-c2d77073d898ca313a9c54d9cfc09033971dde22.tar.bz2 |
evdev: Fix crashing with touch devices
The touchscreen crashes because of BTN_TOUCH events that hit NOTREACHED.
The touchpad crashes for similar reasons. We don't have touchpad support
here at all, so ignore these devices.
NOTRY=true
Review URL: https://codereview.chromium.org/58473003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@233431 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r-- | ui/events/events.gyp | 2 | ||||
-rw-r--r-- | ui/events/ozone/evdev/event_device_info.cc | 134 | ||||
-rw-r--r-- | ui/events/ozone/evdev/event_device_info.h | 57 | ||||
-rw-r--r-- | ui/events/ozone/evdev/event_factory.cc | 35 | ||||
-rw-r--r-- | ui/events/ozone/evdev/touch_event_converter.cc | 13 |
5 files changed, 232 insertions, 9 deletions
diff --git a/ui/events/events.gyp b/ui/events/events.gyp index 6684622..0103988 100644 --- a/ui/events/events.gyp +++ b/ui/events/events.gyp @@ -79,6 +79,8 @@ 'gestures/gesture_util.h', 'gestures/velocity_calculator.cc', 'gestures/velocity_calculator.h', + 'ozone/evdev/event_device_info.cc', + 'ozone/evdev/event_device_info.h', 'ozone/evdev/event_factory.cc', 'ozone/evdev/event_factory.h', 'ozone/evdev/event_modifiers.cc', diff --git a/ui/events/ozone/evdev/event_device_info.cc b/ui/events/ozone/evdev/event_device_info.cc new file mode 100644 index 0000000..9621646 --- /dev/null +++ b/ui/events/ozone/evdev/event_device_info.cc @@ -0,0 +1,134 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/events/ozone/evdev/event_device_info.h" + +#include <linux/input.h> + +#include "base/logging.h" +#include "base/threading/thread_restrictions.h" + +namespace ui { + +namespace { + +bool GetEventBits(int fd, unsigned int type, void* buf, unsigned int size) { + base::ThreadRestrictions::AssertIOAllowed(); + + if (ioctl(fd, EVIOCGBIT(type, size), buf) < 0) { + DLOG(ERROR) << "failed EVIOCGBIT(" << type << ", " << size << ") on fd " + << fd; + return false; + } + + return true; +} + +bool GetPropBits(int fd, void* buf, unsigned int size) { + base::ThreadRestrictions::AssertIOAllowed(); + + if (ioctl(fd, EVIOCGPROP(size), buf) < 0) { + DLOG(ERROR) << "failed EVIOCGPROP(" << size << ") on fd " << fd; + return false; + } + + return true; +} + +bool BitIsSet(const unsigned long* bits, unsigned int bit) { + return (bits[bit / EVDEV_LONG_BITS] & (1UL << (bit % EVDEV_LONG_BITS))); +} + +} // namespace + +EventDeviceInfo::EventDeviceInfo() { + memset(ev_bits_, 0, sizeof(ev_bits_)); + memset(key_bits_, 0, sizeof(key_bits_)); + memset(rel_bits_, 0, sizeof(rel_bits_)); + memset(abs_bits_, 0, sizeof(abs_bits_)); + memset(msc_bits_, 0, sizeof(msc_bits_)); + memset(sw_bits_, 0, sizeof(sw_bits_)); + memset(led_bits_, 0, sizeof(led_bits_)); + memset(prop_bits_, 0, sizeof(prop_bits_)); +} + +EventDeviceInfo::~EventDeviceInfo() {} + +bool EventDeviceInfo::Initialize(int fd) { + if (!GetEventBits(fd, 0, ev_bits_, sizeof(ev_bits_))) + return false; + + if (!GetEventBits(fd, EV_KEY, key_bits_, sizeof(key_bits_))) + return false; + + if (!GetEventBits(fd, EV_REL, rel_bits_, sizeof(rel_bits_))) + return false; + + if (!GetEventBits(fd, EV_ABS, abs_bits_, sizeof(abs_bits_))) + return false; + + if (!GetEventBits(fd, EV_MSC, msc_bits_, sizeof(msc_bits_))) + return false; + + if (!GetEventBits(fd, EV_SW, sw_bits_, sizeof(sw_bits_))) + return false; + + if (!GetEventBits(fd, EV_LED, led_bits_, sizeof(led_bits_))) + return false; + + if (!GetPropBits(fd, prop_bits_, sizeof(prop_bits_))) + return false; + + return true; +} + +bool EventDeviceInfo::HasEventType(unsigned int type) const { + if (type > EV_MAX) + return false; + return BitIsSet(ev_bits_, type); +} + +bool EventDeviceInfo::HasKeyEvent(unsigned int code) const { + if (code > KEY_MAX) + return false; + return BitIsSet(key_bits_, code); +} + +bool EventDeviceInfo::HasRelEvent(unsigned int code) const { + if (code > REL_MAX) + return false; + return BitIsSet(rel_bits_, code); +} + +bool EventDeviceInfo::HasAbsEvent(unsigned int code) const { + if (code > ABS_MAX) + return false; + return BitIsSet(abs_bits_, code); +} + +bool EventDeviceInfo::HasMscEvent(unsigned int code) const { + if (code > MSC_MAX) + return false; + return BitIsSet(msc_bits_, code); +} + +bool EventDeviceInfo::HasSwEvent(unsigned int code) const { + if (code > SW_MAX) + return false; + return BitIsSet(sw_bits_, code); +} + +bool EventDeviceInfo::HasLedEvent(unsigned int code) const { + if (code > LED_MAX) + return false; + return BitIsSet(led_bits_, code); +} + +bool EventDeviceInfo::HasProp(unsigned int code) const { + if (code > INPUT_PROP_MAX) + return false; + return BitIsSet(prop_bits_, code); +} + +} // namespace ui diff --git a/ui/events/ozone/evdev/event_device_info.h b/ui/events/ozone/evdev/event_device_info.h new file mode 100644 index 0000000..b4b1c05 --- /dev/null +++ b/ui/events/ozone/evdev/event_device_info.h @@ -0,0 +1,57 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_EVENTS_OZONE_EVDEV_EVENT_DEVICE_INFO_H_ +#define UI_EVENTS_OZONE_EVDEV_EVENT_DEVICE_INFO_H_ + +#include <limits.h> +#include <linux/input.h> + +#include "base/basictypes.h" + +#define EVDEV_LONG_BITS (CHAR_BIT * sizeof(long)) +#define EVDEV_BITS_TO_LONGS(x) (((x) + EVDEV_LONG_BITS - 1) / EVDEV_LONG_BITS) + +namespace ui { + +// Device information for Linux input devices +// +// This stores and queries information about input devices; in +// particular it knows which events the device can generate. +class EventDeviceInfo { + public: + EventDeviceInfo(); + ~EventDeviceInfo(); + + // Initialize device information from an open device. + bool Initialize(int fd); + + // Check events this device can generate. + bool HasEventType(unsigned int type) const; + bool HasKeyEvent(unsigned int code) const; + bool HasRelEvent(unsigned int code) const; + bool HasAbsEvent(unsigned int code) const; + bool HasMscEvent(unsigned int code) const; + bool HasSwEvent(unsigned int code) const; + bool HasLedEvent(unsigned int code) const; + + // Check input device properties. + bool HasProp(unsigned int code) const; + + private: + unsigned long ev_bits_[EVDEV_BITS_TO_LONGS(EV_CNT)]; + unsigned long key_bits_[EVDEV_BITS_TO_LONGS(KEY_CNT)]; + unsigned long rel_bits_[EVDEV_BITS_TO_LONGS(REL_CNT)]; + unsigned long abs_bits_[EVDEV_BITS_TO_LONGS(ABS_CNT)]; + unsigned long msc_bits_[EVDEV_BITS_TO_LONGS(MSC_CNT)]; + unsigned long sw_bits_[EVDEV_BITS_TO_LONGS(SW_CNT)]; + unsigned long led_bits_[EVDEV_BITS_TO_LONGS(LED_CNT)]; + unsigned long prop_bits_[EVDEV_BITS_TO_LONGS(INPUT_PROP_CNT)]; + + DISALLOW_COPY_AND_ASSIGN(EventDeviceInfo); +}; + +} // namspace ui + +#endif // UI_EVENTS_OZONE_EVDEV_EVENT_DEVICE_INFO_H_ diff --git a/ui/events/ozone/evdev/event_factory.cc b/ui/events/ozone/evdev/event_factory.cc index 37e1f02..3dc3c57 100644 --- a/ui/events/ozone/evdev/event_factory.cc +++ b/ui/events/ozone/evdev/event_factory.cc @@ -11,12 +11,29 @@ #include <unistd.h> #include "base/strings/stringprintf.h" +#include "ui/events/ozone/evdev/event_device_info.h" #include "ui/events/ozone/evdev/key_event_converter.h" #include "ui/events/ozone/evdev/touch_event_converter.h" #include "ui/events/ozone/event_factory_ozone.h" namespace ui { +namespace { + +bool IsTouchPad(const EventDeviceInfo& devinfo) { + if (!devinfo.HasEventType(EV_ABS)) + return false; + + return devinfo.HasKeyEvent(BTN_LEFT) || devinfo.HasKeyEvent(BTN_MIDDLE) || + devinfo.HasKeyEvent(BTN_RIGHT) || devinfo.HasKeyEvent(BTN_TOOL_FINGER); +} + +bool IsTouchScreen(const EventDeviceInfo& devinfo) { + return devinfo.HasEventType(EV_ABS) && !IsTouchPad(devinfo); +} + +} // namespace + EventFactoryEvdev::EventFactoryEvdev() {} EventFactoryEvdev::~EventFactoryEvdev() {} @@ -34,19 +51,25 @@ void EventFactoryEvdev::StartProcessingEvents() { DLOG(ERROR) << "Cannot open '" << path << "': " << strerror(errno); break; } - size_t evtype = 0; - COMPILE_ASSERT(sizeof(evtype) * 8 >= EV_MAX, evtype_wide_enough); - if (ioctl(fd, EVIOCGBIT(0, sizeof(evtype)), &evtype) == -1) { - DLOG(ERROR) << "failed ioctl EVIOCGBIT 0" << path; + + EventDeviceInfo devinfo; + if (!devinfo.Initialize(fd)) { + DLOG(ERROR) << "failed to get device information for " << path; + close(fd); + continue; + } + + if (IsTouchPad(devinfo)) { + LOG(WARNING) << "touchpad device not supported: " << path; close(fd); continue; } scoped_ptr<EventConverterOzone> converter; // TODO(rjkroege) Add more device types. Support hot-plugging. - if (evtype & (1 << EV_ABS)) + if (IsTouchScreen(devinfo)) converter.reset(new TouchEventConverterEvdev(fd, id)); - else if (evtype & (1 << EV_KEY)) + else if (devinfo.HasEventType(EV_KEY)) converter.reset(new KeyEventConverterEvdev(&modifiers_)); if (converter) { diff --git a/ui/events/ozone/evdev/touch_event_converter.cc b/ui/events/ozone/evdev/touch_event_converter.cc index 70752ba..d95ebb6 100644 --- a/ui/events/ozone/evdev/touch_event_converter.cc +++ b/ui/events/ozone/evdev/touch_event_converter.cc @@ -146,7 +146,7 @@ void TouchEventConverterEvdev::OnFileCanReadWithoutBlocking(int fd) { altered_slots_.set(current_slot_); break; default: - NOTREACHED(); + NOTREACHED() << "invalid code for EV_ABS: " << input.code; } } else if (input.type == EV_SYN) { switch (input.code) { @@ -178,11 +178,18 @@ void TouchEventConverterEvdev::OnFileCanReadWithoutBlocking(int fd) { case SYN_MT_REPORT: case SYN_CONFIG: case SYN_DROPPED: - NOTREACHED() << "SYN_MT events not supported."; + NOTREACHED() << "invalid code for EV_SYN: " << input.code; break; } + } else if (input.type == EV_KEY) { + switch (input.code) { + case BTN_TOUCH: + break; + default: + NOTREACHED() << "invalid code for EV_KEY: " << input.code; + } } else { - NOTREACHED(); + NOTREACHED() << "invalid type: " << input.type; } } } |