| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/gamepad/platform_data_fetcher_linux.h" | 5 #include "content/browser/gamepad/platform_data_fetcher_linux.h" |
| 6 | 6 |
| 7 #include <fcntl.h> | 7 #include <fcntl.h> |
| 8 #include <libudev.h> | 8 #include <libudev.h> |
| 9 #include <linux/joystick.h> | 9 #include <linux/joystick.h> |
| 10 #include <string.h> | 10 #include <string.h> |
| 11 #include <sys/stat.h> | 11 #include <sys/stat.h> |
| 12 #include <sys/types.h> | 12 #include <sys/types.h> |
| 13 #include <unistd.h> | 13 #include <unistd.h> |
| 14 | 14 |
| 15 #include "base/debug/trace_event.h" | 15 #include "base/debug/trace_event.h" |
| 16 #include "base/eintr_wrapper.h" | 16 #include "base/eintr_wrapper.h" |
| 17 #include "base/message_loop.h" | 17 #include "base/message_loop.h" |
| 18 #include "base/string_number_conversions.h" | 18 #include "base/string_number_conversions.h" |
| 19 #include "base/string_util.h" | 19 #include "base/string_util.h" |
| 20 #include "base/stringprintf.h" | 20 #include "base/stringprintf.h" |
| 21 #include "base/utf_string_conversions.h" | 21 #include "base/utf_string_conversions.h" |
| 22 #include "content/browser/udev_linux.h" |
| 22 | 23 |
| 23 namespace { | 24 namespace { |
| 24 | 25 |
| 25 const char kInputSubsystem[] = "input"; | 26 const char kInputSubsystem[] = "input"; |
| 26 const char kUsbSubsystem[] = "usb"; | 27 const char kUsbSubsystem[] = "usb"; |
| 27 const char kUsbDeviceType[] = "usb_device"; | 28 const char kUsbDeviceType[] = "usb_device"; |
| 28 const float kMaxLinuxAxisValue = 32767.0; | 29 const float kMaxLinuxAxisValue = 32767.0; |
| 29 | 30 |
| 30 void CloseFileDescriptorIfValid(int fd) { | 31 void CloseFileDescriptorIfValid(int fd) { |
| 31 if (fd >= 0) | 32 if (fd >= 0) |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 namespace content { | 65 namespace content { |
| 65 | 66 |
| 66 using WebKit::WebGamepad; | 67 using WebKit::WebGamepad; |
| 67 using WebKit::WebGamepads; | 68 using WebKit::WebGamepads; |
| 68 | 69 |
| 69 GamepadPlatformDataFetcherLinux::GamepadPlatformDataFetcherLinux() { | 70 GamepadPlatformDataFetcherLinux::GamepadPlatformDataFetcherLinux() { |
| 70 for (size_t i = 0; i < arraysize(device_fds_); ++i) | 71 for (size_t i = 0; i < arraysize(device_fds_); ++i) |
| 71 device_fds_[i] = -1; | 72 device_fds_[i] = -1; |
| 72 memset(mappers_, 0, sizeof(mappers_)); | 73 memset(mappers_, 0, sizeof(mappers_)); |
| 73 | 74 |
| 74 udev_ = udev_new(); | 75 std::vector<UdevLinux::UdevMonitorFilter> filters; |
| 75 CHECK(udev_); | 76 filters.push_back( |
| 76 | 77 content::UdevLinux::UdevMonitorFilter(kInputSubsystem, NULL)); |
| 77 monitor_ = udev_monitor_new_from_netlink(udev_, "udev"); | 78 udev_.reset( |
| 78 CHECK(monitor_); | 79 new UdevLinux(filters, |
| 79 int ret = udev_monitor_filter_add_match_subsystem_devtype(monitor_, | 80 base::Bind(&GamepadPlatformDataFetcherLinux::RefreshDevice, |
| 80 kInputSubsystem, | 81 base::Unretained(this)))); |
| 81 NULL); | |
| 82 CHECK_EQ(0, ret); | |
| 83 ret = udev_monitor_enable_receiving(monitor_); | |
| 84 CHECK_EQ(0, ret); | |
| 85 monitor_fd_ = udev_monitor_get_fd(monitor_); | |
| 86 CHECK_GE(monitor_fd_, 0); | |
| 87 bool success = MessageLoopForIO::current()->WatchFileDescriptor(monitor_fd_, | |
| 88 true, MessageLoopForIO::WATCH_READ, &monitor_watcher_, this); | |
| 89 CHECK(success); | |
| 90 | 82 |
| 91 EnumerateDevices(); | 83 EnumerateDevices(); |
| 92 } | 84 } |
| 93 | 85 |
| 94 GamepadPlatformDataFetcherLinux::~GamepadPlatformDataFetcherLinux() { | 86 GamepadPlatformDataFetcherLinux::~GamepadPlatformDataFetcherLinux() { |
| 95 monitor_watcher_.StopWatchingFileDescriptor(); | |
| 96 udev_monitor_unref(monitor_); | |
| 97 udev_unref(udev_); | |
| 98 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) | 87 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) |
| 99 CloseFileDescriptorIfValid(device_fds_[i]); | 88 CloseFileDescriptorIfValid(device_fds_[i]); |
| 100 } | 89 } |
| 101 | 90 |
| 102 void GamepadPlatformDataFetcherLinux::GetGamepadData(WebGamepads* pads, bool) { | 91 void GamepadPlatformDataFetcherLinux::GetGamepadData(WebGamepads* pads, bool) { |
| 103 TRACE_EVENT0("GAMEPAD", "GetGamepadData"); | 92 TRACE_EVENT0("GAMEPAD", "GetGamepadData"); |
| 104 | 93 |
| 105 data_.length = WebGamepads::itemsLengthCap; | 94 data_.length = WebGamepads::itemsLengthCap; |
| 106 | 95 |
| 107 // Update our internal state. | 96 // Update our internal state. |
| 108 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) { | 97 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) { |
| 109 if (device_fds_[i] >= 0) { | 98 if (device_fds_[i] >= 0) { |
| 110 ReadDeviceData(i); | 99 ReadDeviceData(i); |
| 111 } | 100 } |
| 112 } | 101 } |
| 113 | 102 |
| 114 // Copy to the current state to the output buffer, using the mapping | 103 // Copy to the current state to the output buffer, using the mapping |
| 115 // function, if there is one available. | 104 // function, if there is one available. |
| 116 pads->length = data_.length; | 105 pads->length = data_.length; |
| 117 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) { | 106 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) { |
| 118 if (mappers_[i]) | 107 if (mappers_[i]) |
| 119 mappers_[i](data_.items[i], &pads->items[i]); | 108 mappers_[i](data_.items[i], &pads->items[i]); |
| 120 else | 109 else |
| 121 pads->items[i] = data_.items[i]; | 110 pads->items[i] = data_.items[i]; |
| 122 } | 111 } |
| 123 } | 112 } |
| 124 | 113 |
| 125 void GamepadPlatformDataFetcherLinux::OnFileCanReadWithoutBlocking(int fd) { | |
| 126 // Events occur when devices attached to the system are added, removed, or | |
| 127 // change state. udev_monitor_receive_device() will return a device object | |
| 128 // representing the device which changed and what type of change occured. | |
| 129 DCHECK_EQ(monitor_fd_, fd); | |
| 130 udev_device* dev = udev_monitor_receive_device(monitor_); | |
| 131 if (!dev) | |
| 132 return; | |
| 133 RefreshDevice(dev); | |
| 134 udev_device_unref(dev); | |
| 135 } | |
| 136 | |
| 137 void GamepadPlatformDataFetcherLinux::OnFileCanWriteWithoutBlocking(int fd) { | |
| 138 } | |
| 139 | |
| 140 // Used during enumeration, and monitor notifications. | 114 // Used during enumeration, and monitor notifications. |
| 141 void GamepadPlatformDataFetcherLinux::RefreshDevice(udev_device* dev) { | 115 void GamepadPlatformDataFetcherLinux::RefreshDevice(udev_device* dev) { |
| 142 int index; | 116 int index; |
| 143 std::string node_path; | 117 std::string node_path; |
| 144 if (IsGamepad(dev, &index, &node_path)) { | 118 if (IsGamepad(dev, &index, &node_path)) { |
| 145 int& device_fd = device_fds_[index]; | 119 int& device_fd = device_fds_[index]; |
| 146 WebGamepad& pad = data_.items[index]; | 120 WebGamepad& pad = data_.items[index]; |
| 147 GamepadStandardMappingFunction& mapper = mappers_[index]; | 121 GamepadStandardMappingFunction& mapper = mappers_[index]; |
| 148 | 122 |
| 149 CloseFileDescriptorIfValid(device_fd); | 123 CloseFileDescriptorIfValid(device_fd); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 TruncateUTF8ToByteSize(id, WebGamepad::idLengthCap - 1, &id); | 190 TruncateUTF8ToByteSize(id, WebGamepad::idLengthCap - 1, &id); |
| 217 string16 tmp16 = UTF8ToUTF16(id); | 191 string16 tmp16 = UTF8ToUTF16(id); |
| 218 memset(pad.id, 0, sizeof(pad.id)); | 192 memset(pad.id, 0, sizeof(pad.id)); |
| 219 tmp16.copy(pad.id, arraysize(pad.id) - 1); | 193 tmp16.copy(pad.id, arraysize(pad.id) - 1); |
| 220 | 194 |
| 221 pad.connected = true; | 195 pad.connected = true; |
| 222 } | 196 } |
| 223 } | 197 } |
| 224 | 198 |
| 225 void GamepadPlatformDataFetcherLinux::EnumerateDevices() { | 199 void GamepadPlatformDataFetcherLinux::EnumerateDevices() { |
| 226 udev_enumerate* enumerate = udev_enumerate_new(udev_); | 200 udev_enumerate* enumerate = udev_enumerate_new(udev_->udev_handle()); |
| 227 if (!enumerate) | 201 if (!enumerate) |
| 228 return; | 202 return; |
| 229 int ret = udev_enumerate_add_match_subsystem(enumerate, kInputSubsystem); | 203 int ret = udev_enumerate_add_match_subsystem(enumerate, kInputSubsystem); |
| 230 if (ret != 0) | 204 if (ret != 0) |
| 231 return; | 205 return; |
| 232 ret = udev_enumerate_scan_devices(enumerate); | 206 ret = udev_enumerate_scan_devices(enumerate); |
| 233 if (ret != 0) | 207 if (ret != 0) |
| 234 return; | 208 return; |
| 235 | 209 |
| 236 udev_list_entry* devices = udev_enumerate_get_list_entry(enumerate); | 210 udev_list_entry* devices = udev_enumerate_get_list_entry(enumerate); |
| 237 for (udev_list_entry* dev_list_entry = devices; | 211 for (udev_list_entry* dev_list_entry = devices; |
| 238 dev_list_entry != NULL; | 212 dev_list_entry != NULL; |
| 239 dev_list_entry = udev_list_entry_get_next(dev_list_entry)) { | 213 dev_list_entry = udev_list_entry_get_next(dev_list_entry)) { |
| 240 // Get the filename of the /sys entry for the device and create a | 214 // Get the filename of the /sys entry for the device and create a |
| 241 // udev_device object (dev) representing it | 215 // udev_device object (dev) representing it |
| 242 const char* path = udev_list_entry_get_name(dev_list_entry); | 216 const char* path = udev_list_entry_get_name(dev_list_entry); |
| 243 udev_device* dev = udev_device_new_from_syspath(udev_, path); | 217 udev_device* dev = udev_device_new_from_syspath(udev_->udev_handle(), path); |
| 244 if (!dev) | 218 if (!dev) |
| 245 continue; | 219 continue; |
| 246 RefreshDevice(dev); | 220 RefreshDevice(dev); |
| 247 udev_device_unref(dev); | 221 udev_device_unref(dev); |
| 248 } | 222 } |
| 249 // Free the enumerator object | 223 // Free the enumerator object |
| 250 udev_enumerate_unref(enumerate); | 224 udev_enumerate_unref(enumerate); |
| 251 } | 225 } |
| 252 | 226 |
| 253 void GamepadPlatformDataFetcherLinux::ReadDeviceData(size_t index) { | 227 void GamepadPlatformDataFetcherLinux::ReadDeviceData(size_t index) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 275 continue; | 249 continue; |
| 276 pad.buttons[item] = event.value ? 1.0 : 0.0; | 250 pad.buttons[item] = event.value ? 1.0 : 0.0; |
| 277 if (item >= pad.buttonsLength) | 251 if (item >= pad.buttonsLength) |
| 278 pad.buttonsLength = item + 1; | 252 pad.buttonsLength = item + 1; |
| 279 } | 253 } |
| 280 pad.timestamp = event.time; | 254 pad.timestamp = event.time; |
| 281 } | 255 } |
| 282 } | 256 } |
| 283 | 257 |
| 284 } // namespace content | 258 } // namespace content |
| OLD | NEW |