Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(753)

Side by Side Diff: device/gamepad/gamepad_platform_data_fetcher_linux.cc

Issue 2129003002: Refactored gamepad polling to support dynamic sources (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed unit test issue and Mac XBoxDataFetcher constructor Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "device/gamepad/gamepad_platform_data_fetcher_linux.h" 5 #include "device/gamepad/gamepad_platform_data_fetcher_linux.h"
6 6
7 #include <fcntl.h> 7 #include <fcntl.h>
8 #include <linux/joystick.h> 8 #include <linux/joystick.h>
9 #include <string.h> 9 #include <string.h>
10 #include <sys/stat.h> 10 #include <sys/stat.h>
11 #include <sys/types.h> 11 #include <sys/types.h>
12 #include <unistd.h> 12 #include <unistd.h>
13 13
14 #include "base/macros.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/posix/eintr_wrapper.h" 14 #include "base/posix/eintr_wrapper.h"
17 #include "base/strings/string_number_conversions.h" 15 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/string_util.h" 16 #include "base/strings/string_util.h"
19 #include "base/strings/stringprintf.h" 17 #include "base/strings/stringprintf.h"
20 #include "base/strings/utf_string_conversions.h" 18 #include "base/strings/utf_string_conversions.h"
21 #include "base/trace_event/trace_event.h" 19 #include "base/trace_event/trace_event.h"
22 #include "device/udev_linux/scoped_udev.h" 20 #include "device/udev_linux/scoped_udev.h"
23 #include "device/udev_linux/udev_linux.h" 21 #include "device/udev_linux/udev_linux.h"
24 22
25 namespace { 23 namespace {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 } 61 }
64 62
65 } // namespace 63 } // namespace
66 64
67 namespace device { 65 namespace device {
68 66
69 using blink::WebGamepad; 67 using blink::WebGamepad;
70 using blink::WebGamepads; 68 using blink::WebGamepads;
71 69
72 GamepadPlatformDataFetcherLinux::GamepadPlatformDataFetcherLinux() { 70 GamepadPlatformDataFetcherLinux::GamepadPlatformDataFetcherLinux() {
73 for (size_t i = 0; i < arraysize(pad_state_); ++i) { 71 for (size_t i = 0; i < arraysize(device_fd_); ++i) {
74 device_fd_[i] = -1; 72 device_fd_[i] = -1;
75 pad_state_[i].mapper = 0;
76 pad_state_[i].axis_mask = 0;
77 pad_state_[i].button_mask = 0;
78 } 73 }
74 }
79 75
76 GamepadPlatformDataFetcherLinux::~GamepadPlatformDataFetcherLinux() {
77 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i)
78 CloseFileDescriptorIfValid(device_fd_[i]);
79 }
80
81 GamepadSource GamepadPlatformDataFetcherLinux::source() {
82 return Factory::static_source();
83 }
84
85 void GamepadPlatformDataFetcherLinux::OnAddedToProvider() {
80 std::vector<UdevLinux::UdevMonitorFilter> filters; 86 std::vector<UdevLinux::UdevMonitorFilter> filters;
81 filters.push_back(UdevLinux::UdevMonitorFilter(kInputSubsystem, NULL)); 87 filters.push_back(UdevLinux::UdevMonitorFilter(kInputSubsystem, NULL));
82 udev_.reset(new UdevLinux( 88 udev_.reset(new UdevLinux(
83 filters, base::Bind(&GamepadPlatformDataFetcherLinux::RefreshDevice, 89 filters, base::Bind(&GamepadPlatformDataFetcherLinux::RefreshDevice,
84 base::Unretained(this)))); 90 base::Unretained(this))));
85 91
86 EnumerateDevices(); 92 EnumerateDevices();
87 } 93 }
88 94
89 GamepadPlatformDataFetcherLinux::~GamepadPlatformDataFetcherLinux() { 95 void GamepadPlatformDataFetcherLinux::GetGamepadData(bool) {
90 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i)
91 CloseFileDescriptorIfValid(device_fd_[i]);
92 }
93
94 void GamepadPlatformDataFetcherLinux::GetGamepadData(WebGamepads* pads, bool) {
95 TRACE_EVENT0("GAMEPAD", "GetGamepadData"); 96 TRACE_EVENT0("GAMEPAD", "GetGamepadData");
96 97
97 // Update our internal state. 98 // Update our internal state.
98 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) { 99 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) {
99 if (device_fd_[i] >= 0) { 100 if (device_fd_[i] >= 0) {
100 ReadDeviceData(i); 101 ReadDeviceData(i);
101 } 102 }
102 } 103 }
103
104 pads->length = WebGamepads::itemsLengthCap;
105 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) {
106 MapAndSanitizeGamepadData(&pad_state_[i], &pads->items[i]);
107 }
108 } 104 }
109 105
110 // Used during enumeration, and monitor notifications. 106 // Used during enumeration, and monitor notifications.
111 void GamepadPlatformDataFetcherLinux::RefreshDevice(udev_device* dev) { 107 void GamepadPlatformDataFetcherLinux::RefreshDevice(udev_device* dev) {
112 int index; 108 int index;
113 std::string node_path; 109 std::string node_path;
114 if (IsGamepad(dev, &index, &node_path)) { 110 if (IsGamepad(dev, &index, &node_path)) {
115 int& device_fd = device_fd_[index]; 111 int& device_fd = device_fd_[index];
116 WebGamepad& pad = pad_state_[index].data;
117 GamepadStandardMappingFunction& mapper = pad_state_[index].mapper;
118 112
119 CloseFileDescriptorIfValid(device_fd); 113 CloseFileDescriptorIfValid(device_fd);
120 114
121 // The device pointed to by dev contains information about the logical 115 // The device pointed to by dev contains information about the logical
122 // joystick device. In order to get the information about the physical 116 // joystick device. In order to get the information about the physical
123 // hardware, get the parent device that is also in the "input" subsystem. 117 // hardware, get the parent device that is also in the "input" subsystem.
124 // This function should just walk up the tree one level. 118 // This function should just walk up the tree one level.
125 dev = udev_device_get_parent_with_subsystem_devtype(dev, kInputSubsystem, 119 dev = udev_device_get_parent_with_subsystem_devtype(dev, kInputSubsystem,
126 NULL); 120 NULL);
127 if (!dev) { 121 if (!dev) {
128 // Unable to get device information, don't use this device. 122 // Unable to get device information, don't use this device.
129 device_fd = -1; 123 device_fd = -1;
130 pad.connected = false;
131 return; 124 return;
132 } 125 }
133 126
134 device_fd = HANDLE_EINTR(open(node_path.c_str(), O_RDONLY | O_NONBLOCK)); 127 device_fd = HANDLE_EINTR(open(node_path.c_str(), O_RDONLY | O_NONBLOCK));
135 if (device_fd < 0) { 128 if (device_fd < 0) {
136 // Unable to open device, don't use. 129 // Unable to open device, don't use.
137 pad.connected = false;
138 return; 130 return;
139 } 131 }
140 132
133 PadState* state = GetPadState(index);
134 if (!state) {
135 // No slot available for device, don't use.
136 CloseFileDescriptorIfValid(device_fd);
137 device_fd = -1;
138 return;
139 }
140
141 WebGamepad& pad = state->data;
142 GamepadStandardMappingFunction& mapper = state->mapper;
143
141 const char* vendor_id = udev_device_get_sysattr_value(dev, "id/vendor"); 144 const char* vendor_id = udev_device_get_sysattr_value(dev, "id/vendor");
142 const char* product_id = udev_device_get_sysattr_value(dev, "id/product"); 145 const char* product_id = udev_device_get_sysattr_value(dev, "id/product");
143 mapper = GetGamepadStandardMappingFunction(vendor_id, product_id); 146 mapper = GetGamepadStandardMappingFunction(vendor_id, product_id);
144 147
145 // Driver returns utf-8 strings here, so combine in utf-8 first and 148 // Driver returns utf-8 strings here, so combine in utf-8 first and
146 // convert to WebUChar later once we've picked an id string. 149 // convert to WebUChar later once we've picked an id string.
147 const char* name = udev_device_get_sysattr_value(dev, "name"); 150 const char* name = udev_device_get_sysattr_value(dev, "name");
148 std::string name_string(name); 151 std::string name_string(name);
149 152
150 // In many cases the information the input subsystem contains isn't 153 // In many cases the information the input subsystem contains isn't
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 std::string mapping = "standard"; 190 std::string mapping = "standard";
188 base::TruncateUTF8ToByteSize(mapping, WebGamepad::mappingLengthCap - 1, 191 base::TruncateUTF8ToByteSize(mapping, WebGamepad::mappingLengthCap - 1,
189 &mapping); 192 &mapping);
190 tmp16 = base::UTF8ToUTF16(mapping); 193 tmp16 = base::UTF8ToUTF16(mapping);
191 memset(pad.mapping, 0, sizeof(pad.mapping)); 194 memset(pad.mapping, 0, sizeof(pad.mapping));
192 tmp16.copy(pad.mapping, arraysize(pad.mapping) - 1); 195 tmp16.copy(pad.mapping, arraysize(pad.mapping) - 1);
193 } else { 196 } else {
194 pad.mapping[0] = 0; 197 pad.mapping[0] = 0;
195 } 198 }
196 199
197 pad_state_[index].axis_mask = 0;
198 pad_state_[index].button_mask = 0;
199
200 pad.connected = true; 200 pad.connected = true;
201 } 201 }
202 } 202 }
203 203
204 void GamepadPlatformDataFetcherLinux::EnumerateDevices() { 204 void GamepadPlatformDataFetcherLinux::EnumerateDevices() {
205 ScopedUdevEnumeratePtr enumerate(udev_enumerate_new(udev_->udev_handle())); 205 ScopedUdevEnumeratePtr enumerate(udev_enumerate_new(udev_->udev_handle()));
206 if (!enumerate) 206 if (!enumerate)
207 return; 207 return;
208 int ret = 208 int ret =
209 udev_enumerate_add_match_subsystem(enumerate.get(), kInputSubsystem); 209 udev_enumerate_add_match_subsystem(enumerate.get(), kInputSubsystem);
(...skipping 17 matching lines...) Expand all
227 } 227 }
228 } 228 }
229 229
230 void GamepadPlatformDataFetcherLinux::ReadDeviceData(size_t index) { 230 void GamepadPlatformDataFetcherLinux::ReadDeviceData(size_t index) {
231 // Linker does not like CHECK_LT(index, WebGamepads::itemsLengthCap). =/ 231 // Linker does not like CHECK_LT(index, WebGamepads::itemsLengthCap). =/
232 if (index >= WebGamepads::itemsLengthCap) { 232 if (index >= WebGamepads::itemsLengthCap) {
233 CHECK(false); 233 CHECK(false);
234 return; 234 return;
235 } 235 }
236 236
237 const int& fd = device_fd_[index]; 237 PadState* state = GetPadState(index);
238 WebGamepad& pad = pad_state_[index].data; 238 if (!state)
239 return;
240
241 int fd = device_fd_[index];
239 DCHECK_GE(fd, 0); 242 DCHECK_GE(fd, 0);
240 243
244 WebGamepad& pad = state->data;
245
241 js_event event; 246 js_event event;
242 while (HANDLE_EINTR(read(fd, &event, sizeof(struct js_event))) > 0) { 247 while (HANDLE_EINTR(read(fd, &event, sizeof(struct js_event))) > 0) {
243 size_t item = event.number; 248 size_t item = event.number;
244 if (event.type & JS_EVENT_AXIS) { 249 if (event.type & JS_EVENT_AXIS) {
245 if (item >= WebGamepad::axesLengthCap) 250 if (item >= WebGamepad::axesLengthCap)
246 continue; 251 continue;
247 252
248 pad.axes[item] = event.value / kMaxLinuxAxisValue; 253 pad.axes[item] = event.value / kMaxLinuxAxisValue;
249 254
250 if (item >= pad.axesLength) 255 if (item >= pad.axesLength)
251 pad.axesLength = item + 1; 256 pad.axesLength = item + 1;
252 } else if (event.type & JS_EVENT_BUTTON) { 257 } else if (event.type & JS_EVENT_BUTTON) {
253 if (item >= WebGamepad::buttonsLengthCap) 258 if (item >= WebGamepad::buttonsLengthCap)
254 continue; 259 continue;
255 260
256 pad.buttons[item].pressed = event.value; 261 pad.buttons[item].pressed = event.value;
257 pad.buttons[item].value = event.value ? 1.0 : 0.0; 262 pad.buttons[item].value = event.value ? 1.0 : 0.0;
258 263
259 if (item >= pad.buttonsLength) 264 if (item >= pad.buttonsLength)
260 pad.buttonsLength = item + 1; 265 pad.buttonsLength = item + 1;
261 } 266 }
262 pad.timestamp = event.time; 267 pad.timestamp = event.time;
263 } 268 }
264 } 269 }
265 270
266 } // namespace device 271 } // namespace device
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698