summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorspang@chromium.org <spang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-07 00:19:58 +0000
committerspang@chromium.org <spang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-07 00:19:58 +0000
commitc2d77073d898ca313a9c54d9cfc09033971dde22 (patch)
tree8737ad89015d639b4b402af16733835ab5b0d531 /ui
parent3772282de897cfc2a66bc95c3bd06d0c2a3fd65f (diff)
downloadchromium_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.gyp2
-rw-r--r--ui/events/ozone/evdev/event_device_info.cc134
-rw-r--r--ui/events/ozone/evdev/event_device_info.h57
-rw-r--r--ui/events/ozone/evdev/event_factory.cc35
-rw-r--r--ui/events/ozone/evdev/touch_event_converter.cc13
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;
}
}
}