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

Side by Side Diff: content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc

Issue 1586663006: Refactoring gamepad polling to support dynamically added sources (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 11 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 "content/browser/gamepad/gamepad_platform_data_fetcher_linux.h" 5 #include "content/browser/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 "content/browser/udev_linux.h" 20 #include "content/browser/udev_linux.h"
23 #include "device/udev_linux/scoped_udev.h" 21 #include "device/udev_linux/scoped_udev.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 content { 65 namespace content {
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 void GamepadPlatformDataFetcherLinux::OnAddedToProvider() {
80 std::vector<UdevLinux::UdevMonitorFilter> filters; 82 std::vector<UdevLinux::UdevMonitorFilter> filters;
81 filters.push_back(UdevLinux::UdevMonitorFilter(kInputSubsystem, NULL)); 83 filters.push_back(UdevLinux::UdevMonitorFilter(kInputSubsystem, NULL));
82 udev_.reset( 84 udev_.reset(
83 new UdevLinux(filters, 85 new UdevLinux(filters,
84 base::Bind(&GamepadPlatformDataFetcherLinux::RefreshDevice, 86 base::Bind(&GamepadPlatformDataFetcherLinux::RefreshDevice,
85 base::Unretained(this)))); 87 base::Unretained(this))));
86 88
87 EnumerateDevices(); 89 EnumerateDevices();
88 } 90 }
89 91
90 GamepadPlatformDataFetcherLinux::~GamepadPlatformDataFetcherLinux() { 92 void GamepadPlatformDataFetcherLinux::GetGamepadData(bool) {
91 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i)
92 CloseFileDescriptorIfValid(device_fd_[i]);
93 }
94
95 void GamepadPlatformDataFetcherLinux::GetGamepadData(WebGamepads* pads, bool) {
96 TRACE_EVENT0("GAMEPAD", "GetGamepadData"); 93 TRACE_EVENT0("GAMEPAD", "GetGamepadData");
97 94
98 // Update our internal state. 95 // Update our internal state.
99 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) { 96 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) {
100 if (device_fd_[i] >= 0) { 97 if (device_fd_[i] >= 0) {
101 ReadDeviceData(i); 98 ReadDeviceData(i);
102 } 99 }
103 } 100 }
104
105 pads->length = WebGamepads::itemsLengthCap;
106 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) {
107 MapAndSanitizeGamepadData(&pad_state_[i], &pads->items[i]);
108 }
109 } 101 }
110 102
111 // Used during enumeration, and monitor notifications. 103 // Used during enumeration, and monitor notifications.
112 void GamepadPlatformDataFetcherLinux::RefreshDevice(udev_device* dev) { 104 void GamepadPlatformDataFetcherLinux::RefreshDevice(udev_device* dev) {
113 int index; 105 int index;
114 std::string node_path; 106 std::string node_path;
115 if (IsGamepad(dev, &index, &node_path)) { 107 if (IsGamepad(dev, &index, &node_path)) {
116 int& device_fd = device_fd_[index]; 108 int& device_fd = device_fd_[index];
117 WebGamepad& pad = pad_state_[index].data;
118 GamepadStandardMappingFunction& mapper = pad_state_[index].mapper;
119 109
120 CloseFileDescriptorIfValid(device_fd); 110 CloseFileDescriptorIfValid(device_fd);
121 111
122 // The device pointed to by dev contains information about the logical 112 // The device pointed to by dev contains information about the logical
123 // joystick device. In order to get the information about the physical 113 // joystick device. In order to get the information about the physical
124 // hardware, get the parent device that is also in the "input" subsystem. 114 // hardware, get the parent device that is also in the "input" subsystem.
125 // This function should just walk up the tree one level. 115 // This function should just walk up the tree one level.
126 dev = device::udev_device_get_parent_with_subsystem_devtype( 116 dev = device::udev_device_get_parent_with_subsystem_devtype(
127 dev, kInputSubsystem, NULL); 117 dev, kInputSubsystem, NULL);
128 if (!dev) { 118 if (!dev) {
129 // Unable to get device information, don't use this device. 119 // Unable to get device information, don't use this device.
130 device_fd = -1; 120 device_fd = -1;
131 pad.connected = false;
132 return; 121 return;
133 } 122 }
134 123
135 device_fd = HANDLE_EINTR(open(node_path.c_str(), O_RDONLY | O_NONBLOCK)); 124 device_fd = HANDLE_EINTR(open(node_path.c_str(), O_RDONLY | O_NONBLOCK));
136 if (device_fd < 0) { 125 if (device_fd < 0) {
137 // Unable to open device, don't use. 126 // Unable to open device, don't use.
138 pad.connected = false;
139 return; 127 return;
140 } 128 }
141 129
130 PadState* state = provider()->GetPadState(GAMEPAD_SOURCE_LINUX_UDEV, index);
131 if (!state) {
132 // No slot available for device, don't use.
133 CloseFileDescriptorIfValid(device_fd);
134 device_fd = -1;
135 return;
136 }
137
138 WebGamepad& pad = state->data;
139 GamepadStandardMappingFunction& mapper = state->mapper;
140
142 const char* vendor_id = 141 const char* vendor_id =
143 device::udev_device_get_sysattr_value(dev, "id/vendor"); 142 device::udev_device_get_sysattr_value(dev, "id/vendor");
144 const char* product_id = 143 const char* product_id =
145 device::udev_device_get_sysattr_value(dev, "id/product"); 144 device::udev_device_get_sysattr_value(dev, "id/product");
146 mapper = GetGamepadStandardMappingFunction(vendor_id, product_id); 145 mapper = GetGamepadStandardMappingFunction(vendor_id, product_id);
147 146
148 // Driver returns utf-8 strings here, so combine in utf-8 first and 147 // Driver returns utf-8 strings here, so combine in utf-8 first and
149 // convert to WebUChar later once we've picked an id string. 148 // convert to WebUChar later once we've picked an id string.
150 const char* name = device::udev_device_get_sysattr_value(dev, "name"); 149 const char* name = device::udev_device_get_sysattr_value(dev, "name");
151 std::string name_string(name); 150 std::string name_string(name);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 std::string mapping = "standard"; 192 std::string mapping = "standard";
194 base::TruncateUTF8ToByteSize( 193 base::TruncateUTF8ToByteSize(
195 mapping, WebGamepad::mappingLengthCap - 1, &mapping); 194 mapping, WebGamepad::mappingLengthCap - 1, &mapping);
196 tmp16 = base::UTF8ToUTF16(mapping); 195 tmp16 = base::UTF8ToUTF16(mapping);
197 memset(pad.mapping, 0, sizeof(pad.mapping)); 196 memset(pad.mapping, 0, sizeof(pad.mapping));
198 tmp16.copy(pad.mapping, arraysize(pad.mapping) - 1); 197 tmp16.copy(pad.mapping, arraysize(pad.mapping) - 1);
199 } else { 198 } else {
200 pad.mapping[0] = 0; 199 pad.mapping[0] = 0;
201 } 200 }
202 201
203 pad_state_[index].axis_mask = 0;
204 pad_state_[index].button_mask = 0;
205
206 pad.connected = true; 202 pad.connected = true;
207 } 203 }
208 } 204 }
209 205
210 void GamepadPlatformDataFetcherLinux::EnumerateDevices() { 206 void GamepadPlatformDataFetcherLinux::EnumerateDevices() {
211 device::ScopedUdevEnumeratePtr enumerate( 207 device::ScopedUdevEnumeratePtr enumerate(
212 device::udev_enumerate_new(udev_->udev_handle())); 208 device::udev_enumerate_new(udev_->udev_handle()));
213 if (!enumerate) 209 if (!enumerate)
214 return; 210 return;
215 int ret = device::udev_enumerate_add_match_subsystem(enumerate.get(), 211 int ret = device::udev_enumerate_add_match_subsystem(enumerate.get(),
(...skipping 19 matching lines...) Expand all
235 } 231 }
236 } 232 }
237 233
238 void GamepadPlatformDataFetcherLinux::ReadDeviceData(size_t index) { 234 void GamepadPlatformDataFetcherLinux::ReadDeviceData(size_t index) {
239 // Linker does not like CHECK_LT(index, WebGamepads::itemsLengthCap). =/ 235 // Linker does not like CHECK_LT(index, WebGamepads::itemsLengthCap). =/
240 if (index >= WebGamepads::itemsLengthCap) { 236 if (index >= WebGamepads::itemsLengthCap) {
241 CHECK(false); 237 CHECK(false);
242 return; 238 return;
243 } 239 }
244 240
245 const int& fd = device_fd_[index]; 241 PadState* state = provider()->GetPadState(GAMEPAD_SOURCE_LINUX_UDEV, index);
246 WebGamepad& pad = pad_state_[index].data; 242 if (!state)
243 return;
244
245 int fd = device_fd_[index];
247 DCHECK_GE(fd, 0); 246 DCHECK_GE(fd, 0);
248 247
248 WebGamepad& pad = state->data;
249
249 js_event event; 250 js_event event;
250 while (HANDLE_EINTR(read(fd, &event, sizeof(struct js_event))) > 0) { 251 while (HANDLE_EINTR(read(fd, &event, sizeof(struct js_event))) > 0) {
251 size_t item = event.number; 252 size_t item = event.number;
252 if (event.type & JS_EVENT_AXIS) { 253 if (event.type & JS_EVENT_AXIS) {
253 if (item >= WebGamepad::axesLengthCap) 254 if (item >= WebGamepad::axesLengthCap)
254 continue; 255 continue;
255 256
256 pad.axes[item] = event.value / kMaxLinuxAxisValue; 257 pad.axes[item] = event.value / kMaxLinuxAxisValue;
257 258
258 if (item >= pad.axesLength) 259 if (item >= pad.axesLength)
259 pad.axesLength = item + 1; 260 pad.axesLength = item + 1;
260 } else if (event.type & JS_EVENT_BUTTON) { 261 } else if (event.type & JS_EVENT_BUTTON) {
261 if (item >= WebGamepad::buttonsLengthCap) 262 if (item >= WebGamepad::buttonsLengthCap)
262 continue; 263 continue;
263 264
264 pad.buttons[item].pressed = event.value; 265 pad.buttons[item].pressed = event.value;
265 pad.buttons[item].value = event.value ? 1.0 : 0.0; 266 pad.buttons[item].value = event.value ? 1.0 : 0.0;
266 267
267 if (item >= pad.buttonsLength) 268 if (item >= pad.buttonsLength)
268 pad.buttonsLength = item + 1; 269 pad.buttonsLength = item + 1;
269 } 270 }
270 pad.timestamp = event.time; 271 pad.timestamp = event.time;
271 } 272 }
272 } 273 }
273 274
274 } // namespace content 275 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698