summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorscottmg@google.com <scottmg@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-06 22:28:08 +0000
committerscottmg@google.com <scottmg@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-06 22:28:08 +0000
commit47ced5e4a552bee8e0d350804044cd16082242bb (patch)
tree5d34fb58e3305745d0d32f94db62f019526a91ae
parent77a3b1967055e8b3757d19e191ad1def92b2fe4a (diff)
downloadchromium_src-47ced5e4a552bee8e0d350804044cd16082242bb.zip
chromium_src-47ced5e4a552bee8e0d350804044cd16082242bb.tar.gz
chromium_src-47ced5e4a552bee8e0d350804044cd16082242bb.tar.bz2
Add gamepad data fetcher for Linux
BUG=79050 Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=116724 Review URL: http://codereview.chromium.org/8899017 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@116752 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--build/linux/system.gyp21
-rw-r--r--chrome/browser/about_flags.cc2
-rw-r--r--content/browser/gamepad/gamepad_provider.cc38
-rw-r--r--content/browser/gamepad/gamepad_provider.h8
-rw-r--r--content/browser/gamepad/gamepad_standard_mappings_linux.cc156
-rw-r--r--content/browser/gamepad/gamepad_standard_mappings_linux.h26
-rw-r--r--content/browser/gamepad/platform_data_fetcher.h47
-rw-r--r--content/browser/gamepad/platform_data_fetcher_linux.cc228
-rw-r--r--content/browser/gamepad/platform_data_fetcher_linux.h66
-rw-r--r--content/browser/gamepad/platform_data_fetcher_mac.h (renamed from content/browser/gamepad/data_fetcher_mac.h)10
-rw-r--r--content/browser/gamepad/platform_data_fetcher_mac.mm (renamed from content/browser/gamepad/data_fetcher_mac.mm)38
-rw-r--r--content/browser/gamepad/platform_data_fetcher_win.cc (renamed from content/browser/gamepad/data_fetcher_win.cc)10
-rw-r--r--content/browser/gamepad/platform_data_fetcher_win.h (renamed from content/browser/gamepad/data_fetcher_win.h)6
-rw-r--r--content/content_browser.gypi18
14 files changed, 603 insertions, 71 deletions
diff --git a/build/linux/system.gyp b/build/linux/system.gyp
index 90c8b45..cc50d59 100644
--- a/build/linux/system.gyp
+++ b/build/linux/system.gyp
@@ -625,5 +625,26 @@
}],
],
},
+ {
+ 'target_name': 'udev',
+ 'type': 'none',
+ 'conditions': [
+ ['_toolset=="target"', {
+ 'direct_dependent_settings': {
+ 'cflags': [
+ '<!@(<(pkg-config) --cflags libudev)'
+ ],
+ },
+ 'link_settings': {
+ 'ldflags': [
+ '<!@(<(pkg-config) --libs-only-L --libs-only-other libudev)',
+ ],
+ 'libraries': [
+ '<!@(<(pkg-config) --libs-only-l libudev)',
+ ],
+ },
+ }],
+ ],
+ },
],
}
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 6517f87..7fdf402 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -470,7 +470,7 @@ const Experiment kExperiments[] = {
"enable-gamepad",
IDS_FLAGS_ENABLE_GAMEPAD_NAME,
IDS_FLAGS_ENABLE_GAMEPAD_DESCRIPTION,
- kOsMac | kOsWin,
+ kOsAll,
SINGLE_VALUE_TYPE(switches::kEnableGamepad)
},
#if defined(USE_AURA)
diff --git a/content/browser/gamepad/gamepad_provider.cc b/content/browser/gamepad/gamepad_provider.cc
index 29492fa..4c00cc1 100644
--- a/content/browser/gamepad/gamepad_provider.cc
+++ b/content/browser/gamepad/gamepad_provider.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -11,41 +11,14 @@
#include "base/message_loop.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/browser/gamepad/gamepad_provider.h"
#include "content/browser/gamepad/data_fetcher.h"
+#include "content/browser/gamepad/gamepad_provider.h"
+#include "content/browser/gamepad/platform_data_fetcher.h"
#include "content/common/gamepad_messages.h"
-
-#if defined(OS_WIN)
-#include "content/browser/gamepad/data_fetcher_win.h"
-#elif defined(OS_MACOSX)
-#include "content/browser/gamepad/data_fetcher_mac.h"
-#endif
+#include "content/public/browser/browser_thread.h"
namespace content {
-// Define the default data fetcher that GamepadProvider will use if none is
-// supplied. (GamepadPlatformDataFetcher).
-#if defined(OS_WIN)
-
-typedef GamepadDataFetcherWindows GamepadPlatformDataFetcher;
-
-#elif defined(OS_MACOSX)
-
-typedef GamepadDataFetcherMac GamepadPlatformDataFetcher;
-
-#else
-
-class GamepadEmptyDataFetcher : public GamepadDataFetcher {
- public:
- void GetGamepadData(WebKit::WebGamepads* pads, bool) {
- pads->length = 0;
- }
-};
-typedef GamepadEmptyDataFetcher GamepadPlatformDataFetcher;
-
-#endif
-
GamepadProvider::GamepadProvider(GamepadDataFetcher* fetcher)
: is_paused_(false),
devices_changed_(true),
@@ -61,7 +34,8 @@ GamepadProvider::GamepadProvider(GamepadDataFetcher* fetcher)
memset(hwbuf, 0, sizeof(GamepadHardwareBuffer));
polling_thread_.reset(new base::Thread("Gamepad polling thread"));
- polling_thread_->Start();
+ polling_thread_->StartWithOptions(
+ base::Thread::Options(MessageLoop::TYPE_IO, 0));
MessageLoop* polling_loop = polling_thread_->message_loop();
polling_loop->PostTask(
diff --git a/content/browser/gamepad/gamepad_provider.h b/content/browser/gamepad/gamepad_provider.h
index f0e25de..b1bdb74 100644
--- a/content/browser/gamepad/gamepad_provider.h
+++ b/content/browser/gamepad/gamepad_provider.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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 CONTENT_BROWSER_GAMEPAD_PROVIDER_H_
-#define CONTENT_BROWSER_GAMEPAD_PROVIDER_H_
+#ifndef CONTENT_BROWSER_GAMEPAD_GAMEPAD_PROVIDER_H_
+#define CONTENT_BROWSER_GAMEPAD_GAMEPAD_PROVIDER_H_
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
@@ -88,4 +88,4 @@ class CONTENT_EXPORT GamepadProvider :
} // namespace content
-#endif // CONTENT_BROWSER_GAMEPAD_PROVIDER_H_
+#endif // CONTENT_BROWSER_GAMEPAD_GAMEPAD_PROVIDER_H_
diff --git a/content/browser/gamepad/gamepad_standard_mappings_linux.cc b/content/browser/gamepad/gamepad_standard_mappings_linux.cc
new file mode 100644
index 0000000..99d9ba7
--- /dev/null
+++ b/content/browser/gamepad/gamepad_standard_mappings_linux.cc
@@ -0,0 +1,156 @@
+// Copyright (c) 2012 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 "content/browser/gamepad/gamepad_standard_mappings_linux.h"
+
+#include "content/common/gamepad_hardware_buffer.h"
+
+namespace content {
+
+namespace {
+
+// This defines our canonical mapping order for gamepad-like devices. If these
+// items cannot all be satisfied, it is a case-by-case judgement as to whether
+// it is better to leave the device unmapped, or to partially map it. In
+// general, err towards leaving it *unmapped* so that content can handle
+// appropriately.
+
+enum CanonicalButtonIndex {
+ kButtonPrimary,
+ kButtonSecondary,
+ kButtonTertiary,
+ kButtonQuaternary,
+ kButtonLeftShoulder,
+ kButtonRightShoulder,
+ kButtonLeftTrigger,
+ kButtonRightTrigger,
+ kButtonBackSelect,
+ kButtonStart,
+ kButtonLeftThumbstick,
+ kButtonRightThumbstick,
+ kButtonDpadUp,
+ kButtonDpadDown,
+ kButtonDpadLeft,
+ kButtonDpadRight,
+ kButtonMeta,
+ kNumButtons
+};
+
+enum CanonicalAxisIndex {
+ kAxisLeftStickX,
+ kAxisLeftStickY,
+ kAxisRightStickX,
+ kAxisRightStickY,
+ kNumAxes
+};
+
+float AxisToButton(float input) {
+ return (input + 1.f) / 2.f;
+}
+
+float AxisNegativeAsButton(float input) {
+ return (input < -0.5f) ? 1.f : 0.f;
+}
+
+float AxisPositiveAsButton(float input) {
+ return (input > 0.5f) ? 1.f : 0.f;
+}
+
+void MapperXInputStyleGamepad(
+ const WebKit::WebGamepad& input,
+ WebKit::WebGamepad* mapped) {
+ *mapped = input;
+ mapped->buttons[kButtonLeftTrigger] = AxisToButton(input.axes[2]);
+ mapped->buttons[kButtonRightTrigger] = AxisToButton(input.axes[5]);
+ mapped->buttons[kButtonBackSelect] = input.buttons[6];
+ mapped->buttons[kButtonStart] = input.buttons[7];
+ mapped->buttons[kButtonLeftThumbstick] = input.buttons[9];
+ mapped->buttons[kButtonRightThumbstick] = input.buttons[10];
+ mapped->buttons[kButtonDpadUp] = AxisNegativeAsButton(input.axes[7]);
+ mapped->buttons[kButtonDpadDown] = AxisPositiveAsButton(input.axes[7]);
+ mapped->buttons[kButtonDpadLeft] = AxisNegativeAsButton(input.axes[6]);
+ mapped->buttons[kButtonDpadRight] = AxisPositiveAsButton(input.axes[6]);
+ mapped->buttons[kButtonMeta] = input.buttons[8];
+ mapped->axes[kAxisRightStickX] = input.axes[3];
+ mapped->axes[kAxisRightStickY] = input.axes[4];
+ mapped->buttonsLength = kNumButtons;
+ mapped->axesLength = kNumAxes;
+}
+
+void MapperMP8866(
+ const WebKit::WebGamepad& input,
+ WebKit::WebGamepad* mapped) {
+ *mapped = input;
+ mapped->buttons[kButtonPrimary] = input.buttons[2];
+ mapped->buttons[kButtonTertiary] = input.buttons[3];
+ mapped->buttons[kButtonQuaternary] = input.buttons[0];
+ mapped->buttons[kButtonLeftShoulder] = input.buttons[6];
+ mapped->buttons[kButtonRightShoulder] = input.buttons[7];
+ mapped->buttons[kButtonLeftTrigger] = input.buttons[4];
+ mapped->buttons[kButtonRightTrigger] = input.buttons[5];
+ mapped->buttons[kButtonBackSelect] = input.buttons[9];
+ mapped->buttons[kButtonStart] = input.buttons[8];
+ mapped->buttons[kButtonDpadUp] = AxisNegativeAsButton(input.axes[5]);
+ mapped->buttons[kButtonDpadDown] = AxisPositiveAsButton(input.axes[5]);
+ mapped->buttons[kButtonDpadLeft] = AxisNegativeAsButton(input.axes[4]);
+ mapped->buttons[kButtonDpadRight] = AxisPositiveAsButton(input.axes[4]);
+ mapped->buttonsLength = kNumButtons - 1; // no Meta on this device
+ mapped->axesLength = kNumAxes;
+}
+
+void MapperPlaystationSixAxis(
+ const WebKit::WebGamepad& input,
+ WebKit::WebGamepad* mapped) {
+ *mapped = input;
+ mapped->buttons[kButtonPrimary] = input.buttons[14];
+ mapped->buttons[kButtonSecondary] = input.buttons[13];
+ mapped->buttons[kButtonTertiary] = input.buttons[15];
+ mapped->buttons[kButtonQuaternary] = input.buttons[12];
+ mapped->buttons[kButtonLeftShoulder] = input.buttons[10];
+ mapped->buttons[kButtonRightShoulder] = input.buttons[11];
+ mapped->buttons[kButtonLeftTrigger] = AxisToButton(input.axes[12]);
+ mapped->buttons[kButtonRightTrigger] = AxisToButton(input.axes[13]);
+ mapped->buttons[kButtonBackSelect] = input.buttons[0];
+ mapped->buttons[kButtonStart] = input.buttons[3];
+ mapped->buttons[kButtonLeftThumbstick] = input.buttons[1];
+ mapped->buttons[kButtonRightThumbstick] = input.buttons[2];
+ mapped->buttons[kButtonDpadUp] = AxisToButton(input.axes[8]);
+ mapped->buttons[kButtonDpadDown] = AxisToButton(input.axes[10]);
+ mapped->buttons[kButtonDpadLeft] = input.buttons[7];
+ mapped->buttons[kButtonDpadRight] = AxisToButton(input.axes[9]);
+ mapped->buttons[kButtonMeta] = input.buttons[16];
+
+ mapped->buttonsLength = kNumButtons;
+ mapped->axesLength = kNumAxes;
+}
+
+struct MappingData {
+ const char* const vendor_id;
+ const char* const product_id;
+ GamepadStandardMappingFunction function;
+} AvailableMappings[] = {
+ // http://www.linux-usb.org/usb.ids
+ { "045e", "028e", MapperXInputStyleGamepad }, // Xbox 360 Controller
+ { "045e", "028f", MapperXInputStyleGamepad }, // Xbox 360 Wireless Controller
+ { "046d", "c21d", MapperXInputStyleGamepad }, // Logitech F310
+ { "046d", "c21e", MapperXInputStyleGamepad }, // Logitech F510
+ { "046d", "c21f", MapperXInputStyleGamepad }, // Logitech F710
+ { "054c", "0268", MapperPlaystationSixAxis }, // Playstation SIXAXIS
+ { "0925", "8866", MapperMP8866 }, // WiseGroup MP-8866
+};
+
+} // namespace
+
+GamepadStandardMappingFunction GetGamepadStandardMappingFunction(
+ const base::StringPiece& vendor_id,
+ const base::StringPiece& product_id) {
+ for (size_t i = 0; i < arraysize(AvailableMappings); ++i) {
+ MappingData& item = AvailableMappings[i];
+ if (vendor_id == item.vendor_id && product_id == item.product_id)
+ return item.function;
+ }
+ return NULL;
+}
+
+} // namespace content
diff --git a/content/browser/gamepad/gamepad_standard_mappings_linux.h b/content/browser/gamepad/gamepad_standard_mappings_linux.h
new file mode 100644
index 0000000..6d06fc6
--- /dev/null
+++ b/content/browser/gamepad/gamepad_standard_mappings_linux.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2012 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 CONTENT_BROWSER_GAMEPAD_GAMEPAD_STANDARD_MAPPINGS_LINUX_H_
+#define CONTENT_BROWSER_GAMEPAD_GAMEPAD_STANDARD_MAPPINGS_LINUX_H_
+
+#include "base/string_piece.h"
+
+namespace WebKit {
+class WebGamepad;
+}
+
+namespace content {
+
+typedef void (*GamepadStandardMappingFunction)(
+ const WebKit::WebGamepad& original,
+ WebKit::WebGamepad* mapped);
+
+GamepadStandardMappingFunction GetGamepadStandardMappingFunction(
+ const base::StringPiece& vendor_id,
+ const base::StringPiece& product_id);
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GAMEPAD_GAMEPAD_STANDARD_MAPPINGS_LINUX_H_
diff --git a/content/browser/gamepad/platform_data_fetcher.h b/content/browser/gamepad/platform_data_fetcher.h
new file mode 100644
index 0000000..b9f64af
--- /dev/null
+++ b/content/browser/gamepad/platform_data_fetcher.h
@@ -0,0 +1,47 @@
+// Copyright (c) 2012 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.
+
+// Define the default data fetcher that GamepadProvider will use if none is
+// supplied. (GamepadPlatformDataFetcher).
+
+#ifndef CONTENT_BROWSER_GAMEPAD_PLATFORM_DATA_FETCHER_H_
+#define CONTENT_BROWSER_GAMEPAD_PLATFORM_DATA_FETCHER_H_
+
+#if defined(OS_WIN)
+#include "content/browser/gamepad/platform_data_fetcher_win.h"
+#elif defined(OS_MACOSX)
+#include "content/browser/gamepad/platform_data_fetcher_mac.h"
+#elif defined(OS_LINUX)
+#include "content/browser/gamepad/platform_data_fetcher_linux.h"
+#endif
+
+namespace content {
+
+#if defined(OS_WIN)
+
+typedef GamepadPlatformDataFetcherWin GamepadPlatformDataFetcher;
+
+#elif defined(OS_MACOSX)
+
+typedef GamepadPlatformDataFetcherMac GamepadPlatformDataFetcher;
+
+#elif defined(OS_LINUX)
+
+typedef GamepadPlatformDataFetcherLinux GamepadPlatformDataFetcher;
+
+#else
+
+class GamepadDataFetcherEmpty : public GamepadDataFetcher {
+ public:
+ void GetGamepadData(WebKit::WebGamepads* pads, bool) {
+ pads->length = 0;
+ }
+};
+typedef GamepadDataFetcherEmpty GamepadPlatformDataFetcher;
+
+#endif
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GAMEPAD_PLATFORM_DATA_FETCHER_H_
diff --git a/content/browser/gamepad/platform_data_fetcher_linux.cc b/content/browser/gamepad/platform_data_fetcher_linux.cc
new file mode 100644
index 0000000..9c2a6bf
--- /dev/null
+++ b/content/browser/gamepad/platform_data_fetcher_linux.cc
@@ -0,0 +1,228 @@
+// Copyright (c) 2012 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 "content/browser/gamepad/platform_data_fetcher_linux.h"
+
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <libudev.h>
+#include <linux/joystick.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "base/debug/trace_event.h"
+#include "base/eintr_wrapper.h"
+#include "base/message_loop.h"
+#include "base/string_number_conversions.h"
+#include "base/stringprintf.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "content/common/gamepad_hardware_buffer.h"
+
+namespace content {
+
+using WebKit::WebGamepad;
+using WebKit::WebGamepads;
+
+GamepadPlatformDataFetcherLinux::GamepadPlatformDataFetcherLinux() {
+ for (size_t i = 0; i < arraysize(device_fds_); ++i)
+ device_fds_[i] = -1;
+
+ udev_ = udev_new();
+
+ monitor_ = udev_monitor_new_from_netlink(udev_, "udev");
+ udev_monitor_filter_add_match_subsystem_devtype(monitor_, "input", NULL);
+ udev_monitor_enable_receiving(monitor_);
+ monitor_fd_ = udev_monitor_get_fd(monitor_);
+ MessageLoopForIO::current()->WatchFileDescriptor(monitor_fd_, true,
+ MessageLoopForIO::WATCH_READ, &monitor_watcher_, this);
+
+ EnumerateDevices();
+}
+
+GamepadPlatformDataFetcherLinux::~GamepadPlatformDataFetcherLinux() {
+ monitor_watcher_.StopWatchingFileDescriptor();
+ udev_unref(udev_);
+ for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) {
+ if (device_fds_[i] >= 0)
+ close(device_fds_[i]);
+ }
+}
+
+void GamepadPlatformDataFetcherLinux::GetGamepadData(WebGamepads* pads, bool) {
+ TRACE_EVENT0("GAMEPAD", "GetGamepadData");
+
+ data_.length = WebGamepads::itemsLengthCap;
+
+ // Update our internal state.
+ for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) {
+ if (device_fds_[i] >= 0) {
+ ReadDeviceData(i);
+ }
+ }
+
+ // Copy to the current state to the output buffer, using the mapping
+ // function, if there is one available.
+ pads->length = data_.length;
+ for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) {
+ if (mappers_[i])
+ mappers_[i](data_.items[i], &pads->items[i]);
+ else
+ pads->items[i] = data_.items[i];
+ }
+}
+
+void GamepadPlatformDataFetcherLinux::OnFileCanReadWithoutBlocking(int fd) {
+ // Events occur when devices attached to the system are added, removed, or
+ // change state. udev_monitor_receive_device() will return a device object
+ // representing the device which changed and what type of change occured.
+ DCHECK(monitor_fd_ == fd);
+ udev_device* dev = udev_monitor_receive_device(monitor_);
+ RefreshDevice(dev);
+ udev_device_unref(dev);
+}
+
+void GamepadPlatformDataFetcherLinux::OnFileCanWriteWithoutBlocking(int fd) {
+}
+
+bool GamepadPlatformDataFetcherLinux::IsGamepad(
+ udev_device* dev,
+ int& index,
+ std::string& path) {
+ if (!udev_device_get_property_value(dev, "ID_INPUT_JOYSTICK"))
+ return false;
+
+ const char* node_path = udev_device_get_devnode(dev);
+ if (!node_path)
+ return false;
+
+ static const char kJoystickRoot[] = "/dev/input/js";
+ bool is_gamepad =
+ strncmp(kJoystickRoot, node_path, sizeof(kJoystickRoot) - 1) == 0;
+ if (is_gamepad) {
+ const int base_len = sizeof(kJoystickRoot) - 1;
+ if (!base::StringToInt(base::StringPiece(
+ &node_path[base_len],
+ strlen(node_path) - base_len),
+ &index))
+ return false;
+ if (index < 0 || index >= static_cast<int>(WebGamepads::itemsLengthCap))
+ return false;
+ path = std::string(node_path);
+ }
+ return is_gamepad;
+}
+
+// Used during enumeration, and monitor notifications.
+void GamepadPlatformDataFetcherLinux::RefreshDevice(udev_device* dev) {
+ int index;
+ std::string node_path;
+ if (IsGamepad(dev, index, node_path)) {
+ int& device_fd = device_fds_[index];
+ WebGamepad& pad = data_.items[index];
+ GamepadStandardMappingFunction& mapper = mappers_[index];
+
+ if (device_fd >= 0)
+ close(device_fd);
+
+ // The device pointed to by dev contains information about the input
+ // device. In order to get the information about the USB device, get the
+ // parent device with the subsystem/devtype pair of "usb"/"usb_device".
+ // This function walks up the tree several levels.
+ dev = udev_device_get_parent_with_subsystem_devtype(
+ dev,
+ "usb",
+ "usb_device");
+ if (!dev) {
+ // Unable to get device information, don't use this device.
+ device_fd = -1;
+ pad.connected = false;
+ return;
+ }
+
+ device_fd = HANDLE_EINTR(open(node_path.c_str(), O_RDONLY | O_NONBLOCK));
+ if (device_fd < 0) {
+ // Unable to open device, don't use.
+ pad.connected = false;
+ return;
+ }
+
+ const char* vendor_id = udev_device_get_sysattr_value(dev, "idVendor");
+ const char* product_id = udev_device_get_sysattr_value(dev, "idProduct");
+ mapper = GetGamepadStandardMappingFunction(vendor_id, product_id);
+
+ const char* manufacturer =
+ udev_device_get_sysattr_value(dev, "manufacturer");
+ const char* product = udev_device_get_sysattr_value(dev, "product");
+
+ // Driver returns utf-8 strings here, so combine in utf-8 and then convert
+ // to WebUChar to build the id string.
+ std::string id;
+ if (mapper) {
+ id = base::StringPrintf("%s %s (STANDARD GAMEPAD)",
+ manufacturer,
+ product);
+ } else {
+ id = base::StringPrintf("%s %s (Vendor: %s Product: %s)",
+ manufacturer,
+ product,
+ vendor_id,
+ product_id);
+ }
+ TruncateUTF8ToByteSize(id, WebGamepad::idLengthCap - 1, &id);
+ string16 tmp16 = UTF8ToUTF16(id);
+ memset(pad.id, 0, sizeof(pad.id));
+ tmp16.copy(pad.id, arraysize(pad.id) - 1);
+
+ pad.connected = true;
+ }
+}
+
+void GamepadPlatformDataFetcherLinux::EnumerateDevices() {
+ udev_enumerate* enumerate = udev_enumerate_new(udev_);
+ udev_enumerate_add_match_subsystem(enumerate, "input");
+ udev_enumerate_scan_devices(enumerate);
+
+ udev_list_entry* devices = udev_enumerate_get_list_entry(enumerate);
+ for (udev_list_entry* dev_list_entry = devices;
+ dev_list_entry != NULL;
+ dev_list_entry = udev_list_entry_get_next(dev_list_entry)) {
+ // Get the filename of the /sys entry for the device and create a
+ // udev_device object (dev) representing it
+ const char* path = udev_list_entry_get_name(dev_list_entry);
+ udev_device* dev = udev_device_new_from_syspath(udev_, path);
+ RefreshDevice(dev);
+ udev_device_unref(dev);
+ }
+ // Free the enumerator object
+ udev_enumerate_unref(enumerate);
+}
+
+void GamepadPlatformDataFetcherLinux::ReadDeviceData(size_t index) {
+ int& fd = device_fds_[index];
+ WebGamepad& pad = data_.items[index];
+ DCHECK(fd >= 0);
+
+ js_event event;
+ while (HANDLE_EINTR(read(fd, &event, sizeof(struct js_event)) > 0)) {
+ size_t item = event.number;
+ if (event.type & JS_EVENT_AXIS) {
+ if (item >= WebGamepad::axesLengthCap)
+ continue;
+ pad.axes[item] = event.value / 32767.f;
+ if (item >= pad.axesLength)
+ pad.axesLength = item + 1;
+ } else if (event.type & JS_EVENT_BUTTON) {
+ if (item >= WebGamepad::buttonsLengthCap)
+ continue;
+ pad.buttons[item] = event.value ? 1.0 : 0.0;
+ if (item >= pad.buttonsLength)
+ pad.buttonsLength = item + 1;
+ }
+ pad.timestamp = event.time;
+ }
+}
+
+
+} // namespace content
diff --git a/content/browser/gamepad/platform_data_fetcher_linux.h b/content/browser/gamepad/platform_data_fetcher_linux.h
new file mode 100644
index 0000000..3f395cf
--- /dev/null
+++ b/content/browser/gamepad/platform_data_fetcher_linux.h
@@ -0,0 +1,66 @@
+// Copyright (c) 2012 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 CONTENT_BROWSER_GAMEPAD_DATA_FETCHER_LINUX_H_
+#define CONTENT_BROWSER_GAMEPAD_DATA_FETCHER_LINUX_H_
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "base/message_pump_libevent.h"
+#include "build/build_config.h"
+#include "content/browser/gamepad/data_fetcher.h"
+#include "content/browser/gamepad/gamepad_standard_mappings_linux.h"
+#include "content/common/gamepad_hardware_buffer.h"
+
+extern "C" {
+struct udev;
+struct udev_device;
+struct udev_monitor;
+}
+
+namespace content {
+
+class GamepadPlatformDataFetcherLinux :
+ public GamepadDataFetcher,
+ public base::MessagePumpLibevent::Watcher {
+ public:
+ GamepadPlatformDataFetcherLinux();
+ virtual ~GamepadPlatformDataFetcherLinux();
+
+ // GamepadDataFetcher:
+ virtual void GetGamepadData(WebKit::WebGamepads* pads,
+ bool devices_changed_hint) OVERRIDE;
+
+ // base::MessagePump:Libevent::Watcher:
+ virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE;
+ virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE;
+
+ private:
+ bool IsGamepad(udev_device* dev, int& index, std::string& path);
+ void RefreshDevice(udev_device* dev);
+ void EnumerateDevices();
+ void ReadDeviceData(size_t index);
+
+ // libudev-related items, the main context, and the monitoring context to be
+ // notified about changes to device states.
+ udev* udev_;
+ udev_monitor* monitor_;
+ int monitor_fd_;
+ base::MessagePumpLibevent::FileDescriptorWatcher monitor_watcher_;
+
+ // File descriptors for the /dev/input/js* devices. -1 if not in use.
+ int device_fds_[WebKit::WebGamepads::itemsLengthCap];
+
+ // Functions to map from device data to standard layout, if available. May
+ // be null if no mapping is available.
+ GamepadStandardMappingFunction mappers_[WebKit::WebGamepads::itemsLengthCap];
+
+ // Data that's returned to the consumer.
+ WebKit::WebGamepads data_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GAMEPAD_DATA_FETCHER_LINUX_H_
diff --git a/content/browser/gamepad/data_fetcher_mac.h b/content/browser/gamepad/platform_data_fetcher_mac.h
index 34f7d4b..360a183 100644
--- a/content/browser/gamepad/data_fetcher_mac.h
+++ b/content/browser/gamepad/platform_data_fetcher_mac.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -23,10 +23,10 @@ class NSArray;
namespace content {
-class GamepadDataFetcherMac : public GamepadDataFetcher {
+class GamepadPlatformDataFetcherMac : public GamepadDataFetcher {
public:
- GamepadDataFetcherMac();
- virtual ~GamepadDataFetcherMac();
+ GamepadPlatformDataFetcherMac();
+ virtual ~GamepadPlatformDataFetcherMac();
virtual void GetGamepadData(WebKit::WebGamepads* pads,
bool devices_changed_hint) OVERRIDE;
virtual void PauseHint(bool paused) OVERRIDE;
@@ -34,7 +34,7 @@ class GamepadDataFetcherMac : public GamepadDataFetcher {
bool enabled_;
base::mac::ScopedCFTypeRef<IOHIDManagerRef> hid_manager_ref_;
- static GamepadDataFetcherMac* InstanceFromContext(void* context);
+ static GamepadPlatformDataFetcherMac* InstanceFromContext(void* context);
static void DeviceAddCallback(void* context,
IOReturn result,
void* sender,
diff --git a/content/browser/gamepad/data_fetcher_mac.mm b/content/browser/gamepad/platform_data_fetcher_mac.mm
index b06f01a..5e4ba8f 100644
--- a/content/browser/gamepad/data_fetcher_mac.mm
+++ b/content/browser/gamepad/platform_data_fetcher_mac.mm
@@ -1,8 +1,8 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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 "content/browser/gamepad/data_fetcher_mac.h"
+#include "content/browser/gamepad/platform_data_fetcher_mac.h"
#include "base/mac/foundation_util.h"
#include "base/memory/scoped_nsobject.h"
@@ -41,7 +41,8 @@ const uint32_t kAxisMaximumUsageNumber = 0x35;
} // namespace
-GamepadDataFetcherMac::GamepadDataFetcherMac() : enabled_(true) {
+GamepadPlatformDataFetcherMac::GamepadPlatformDataFetcherMac()
+ : enabled_(true) {
hid_manager_ref_.reset(IOHIDManagerCreate(kCFAllocatorDefault,
kIOHIDOptionsTypeNone));
if (CFGetTypeID(hid_manager_ref_) != IOHIDManagerGetTypeID()) {
@@ -61,7 +62,7 @@ GamepadDataFetcherMac::GamepadDataFetcherMac() : enabled_(true) {
RegisterForNotifications();
}
-void GamepadDataFetcherMac::RegisterForNotifications() {
+void GamepadPlatformDataFetcherMac::RegisterForNotifications() {
// Register for plug/unplug notifications.
IOHIDManagerRegisterDeviceMatchingCallback(
hid_manager_ref_,
@@ -87,7 +88,7 @@ void GamepadDataFetcherMac::RegisterForNotifications() {
kIOHIDOptionsTypeSeizeDevice) == kIOReturnSuccess;
}
-void GamepadDataFetcherMac::UnregisterFromNotifications() {
+void GamepadPlatformDataFetcherMac::UnregisterFromNotifications() {
IOHIDManagerUnscheduleFromRunLoop(
hid_manager_ref_,
CFRunLoopGetCurrent(),
@@ -95,44 +96,45 @@ void GamepadDataFetcherMac::UnregisterFromNotifications() {
IOHIDManagerClose(hid_manager_ref_, kIOHIDOptionsTypeNone);
}
-void GamepadDataFetcherMac::PauseHint(bool pause) {
+void GamepadPlatformDataFetcherMac::PauseHint(bool pause) {
if (pause)
UnregisterFromNotifications();
else
RegisterForNotifications();
}
-GamepadDataFetcherMac::~GamepadDataFetcherMac() {
+GamepadPlatformDataFetcherMac::~GamepadPlatformDataFetcherMac() {
UnregisterFromNotifications();
}
-GamepadDataFetcherMac* GamepadDataFetcherMac::InstanceFromContext(
+GamepadPlatformDataFetcherMac*
+GamepadPlatformDataFetcherMac::InstanceFromContext(
void* context) {
- return reinterpret_cast<GamepadDataFetcherMac*>(context);
+ return reinterpret_cast<GamepadPlatformDataFetcherMac*>(context);
}
-void GamepadDataFetcherMac::DeviceAddCallback(void* context,
+void GamepadPlatformDataFetcherMac::DeviceAddCallback(void* context,
IOReturn result,
void* sender,
IOHIDDeviceRef ref) {
InstanceFromContext(context)->DeviceAdd(ref);
}
-void GamepadDataFetcherMac::DeviceRemoveCallback(void* context,
+void GamepadPlatformDataFetcherMac::DeviceRemoveCallback(void* context,
IOReturn result,
void* sender,
IOHIDDeviceRef ref) {
InstanceFromContext(context)->DeviceRemove(ref);
}
-void GamepadDataFetcherMac::ValueChangedCallback(void* context,
+void GamepadPlatformDataFetcherMac::ValueChangedCallback(void* context,
IOReturn result,
void* sender,
IOHIDValueRef ref) {
InstanceFromContext(context)->ValueChanged(ref);
}
-void GamepadDataFetcherMac::AddButtonsAndAxes(NSArray* elements,
+void GamepadPlatformDataFetcherMac::AddButtonsAndAxes(NSArray* elements,
size_t slot) {
WebKit::WebGamepad& pad = data_.items[slot];
AssociatedData& associated = associated_[slot];
@@ -168,7 +170,7 @@ void GamepadDataFetcherMac::AddButtonsAndAxes(NSArray* elements,
}
}
-void GamepadDataFetcherMac::DeviceAdd(IOHIDDeviceRef device) {
+void GamepadPlatformDataFetcherMac::DeviceAdd(IOHIDDeviceRef device) {
using WebKit::WebGamepad;
using WebKit::WebGamepads;
using base::mac::CFToNSCast;
@@ -221,7 +223,7 @@ void GamepadDataFetcherMac::DeviceAdd(IOHIDDeviceRef device) {
data_.length = slot + 1;
}
-void GamepadDataFetcherMac::DeviceRemove(IOHIDDeviceRef device) {
+void GamepadPlatformDataFetcherMac::DeviceRemove(IOHIDDeviceRef device) {
using WebKit::WebGamepads;
size_t slot;
if (!enabled_)
@@ -238,7 +240,7 @@ void GamepadDataFetcherMac::DeviceRemove(IOHIDDeviceRef device) {
data_.items[slot].connected = false;
}
-void GamepadDataFetcherMac::ValueChanged(IOHIDValueRef value) {
+void GamepadPlatformDataFetcherMac::ValueChanged(IOHIDValueRef value) {
if (!enabled_)
return;
@@ -276,7 +278,9 @@ void GamepadDataFetcherMac::ValueChanged(IOHIDValueRef value) {
}
}
-void GamepadDataFetcherMac::GetGamepadData(WebKit::WebGamepads* pads, bool) {
+void GamepadPlatformDataFetcherMac::GetGamepadData(
+ WebKit::WebGamepads* pads,
+ bool) {
if (!enabled_) {
pads->length = 0;
return;
diff --git a/content/browser/gamepad/data_fetcher_win.cc b/content/browser/gamepad/platform_data_fetcher_win.cc
index 4cb874d..7f6f417 100644
--- a/content/browser/gamepad/data_fetcher_win.cc
+++ b/content/browser/gamepad/platform_data_fetcher_win.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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 "content/browser/gamepad/data_fetcher_win.h"
+#include "content/browser/gamepad/platform_data_fetcher_win.h"
#include "base/debug/trace_event.h"
#include "content/common/gamepad_messages.h"
@@ -78,11 +78,11 @@ bool EnableXInput() {
}
-GamepadDataFetcherWindows::GamepadDataFetcherWindows()
+GamepadPlatformDataFetcherWin::GamepadPlatformDataFetcherWin()
: xinput_available_(EnableXInput()) {
}
-void GamepadDataFetcherWindows::GetGamepadData(WebGamepads* pads,
+void GamepadPlatformDataFetcherWin::GetGamepadData(WebGamepads* pads,
bool devices_changed_hint) {
TRACE_EVENT0("GAMEPAD", "GetGamepadData");
@@ -113,7 +113,7 @@ void GamepadDataFetcherWindows::GetGamepadData(WebGamepads* pads,
pad.connected = true;
base::swprintf(pad.id,
WebGamepad::idLengthCap,
- L"Xbox 360 Controller (XInput %ls)",
+ L"Xbox 360 Controller (XInput STANDARD %ls)",
GamepadSubTypeName(caps.SubType));
}
}
diff --git a/content/browser/gamepad/data_fetcher_win.h b/content/browser/gamepad/platform_data_fetcher_win.h
index 9193f67..1c91059 100644
--- a/content/browser/gamepad/data_fetcher_win.h
+++ b/content/browser/gamepad/platform_data_fetcher_win.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -18,9 +18,9 @@
namespace content {
-class GamepadDataFetcherWindows : public GamepadDataFetcher {
+class GamepadPlatformDataFetcherWin : public GamepadDataFetcher {
public:
- GamepadDataFetcherWindows();
+ GamepadPlatformDataFetcherWin();
virtual void GetGamepadData(WebKit::WebGamepads* pads,
bool devices_changed_hint) OVERRIDE;
private:
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index 69db33a..1a5089c 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -232,14 +232,19 @@
'browser/font_list_async.cc',
'browser/font_list_async.h',
'browser/gamepad/data_fetcher.h',
- 'browser/gamepad/data_fetcher_mac.mm',
- 'browser/gamepad/data_fetcher_mac.h',
- 'browser/gamepad/data_fetcher_win.cc',
- 'browser/gamepad/data_fetcher_win.h',
'browser/gamepad/gamepad_provider.cc',
'browser/gamepad/gamepad_provider.h',
'browser/gamepad/gamepad_service.cc',
'browser/gamepad/gamepad_service.h',
+ 'browser/gamepad/gamepad_standard_mappings_linux.cc',
+ 'browser/gamepad/gamepad_standard_mappings_linux.h',
+ 'browser/gamepad/platform_data_fetcher.h',
+ 'browser/gamepad/platform_data_fetcher_linux.cc',
+ 'browser/gamepad/platform_data_fetcher_linux.h',
+ 'browser/gamepad/platform_data_fetcher_mac.h',
+ 'browser/gamepad/platform_data_fetcher_mac.mm',
+ 'browser/gamepad/platform_data_fetcher_win.cc',
+ 'browser/gamepad/platform_data_fetcher_win.h',
'browser/geolocation/arbitrator_dependency_factory.cc',
'browser/geolocation/arbitrator_dependency_factory.h',
'browser/geolocation/core_location_data_provider_mac.h',
@@ -706,6 +711,11 @@
}],
],
}],
+ ['OS=="linux"', {
+ 'dependencies': [
+ '../build/linux/system.gyp:udev',
+ ],
+ }],
['OS=="linux" and toolkit_uses_gtk==0', {
'dependencies': [
'../build/linux/system.gyp:dbus',