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

Side by Side Diff: content/browser/gamepad/raw_input_data_fetcher_win.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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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/raw_input_data_fetcher_win.h" 5 #include "content/browser/gamepad/raw_input_data_fetcher_win.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include "base/macros.h" 9 #include "base/macros.h"
10 #include "base/trace_event/trace_event.h" 10 #include "base/trace_event/trace_event.h"
11 #include "content/common/gamepad_hardware_buffer.h"
12 #include "content/common/gamepad_messages.h" 11 #include "content/common/gamepad_messages.h"
13 12
14 namespace content { 13 namespace content {
15 14
16 using namespace blink; 15 using namespace blink;
17 16
18 namespace { 17 namespace {
19 18
20 float NormalizeAxis(long value, long min, long max) { 19 float NormalizeAxis(long value, long min, long max) {
21 return (2.f * (value - min) / static_cast<float>(max - min)) - 1.f; 20 return (2.f * (value - min) / static_cast<float>(max - min)) - 1.f;
(...skipping 15 matching lines...) Expand all
37 36
38 } // namespace 37 } // namespace
39 38
40 RawGamepadInfo::RawGamepadInfo() { 39 RawGamepadInfo::RawGamepadInfo() {
41 } 40 }
42 41
43 RawGamepadInfo::~RawGamepadInfo() { 42 RawGamepadInfo::~RawGamepadInfo() {
44 } 43 }
45 44
46 RawInputDataFetcher::RawInputDataFetcher() 45 RawInputDataFetcher::RawInputDataFetcher()
47 : hid_dll_(base::FilePath(FILE_PATH_LITERAL("hid.dll"))), 46 : rawinput_available_(false),
48 rawinput_available_(GetHidDllFunctions()),
49 filter_xinput_(true), 47 filter_xinput_(true),
50 events_monitored_(false) { 48 events_monitored_(false),
49 last_source_id_(0),
50 last_enumeration_id_(0) {
51 } 51 }
52 52
53 RawInputDataFetcher::~RawInputDataFetcher() { 53 RawInputDataFetcher::~RawInputDataFetcher() {
54 ClearControllers(); 54 ClearControllers();
55 DCHECK(!window_); 55 DCHECK(!window_);
56 DCHECK(!events_monitored_); 56 DCHECK(!events_monitored_);
57 } 57 }
58 58
59 void RawInputDataFetcher::WillDestroyCurrentMessageLoop() { 59 void RawInputDataFetcher::WillDestroyCurrentMessageLoop() {
60 StopMonitor(); 60 StopMonitor();
61 } 61 }
62 62
63 void RawInputDataFetcher::OnAddedToProvider() {
64 hid_dll_.Reset(base::LoadNativeLibrary(
65 base::FilePath(FILE_PATH_LITERAL("hid.dll")), nullptr));
66 rawinput_available_ = GetHidDllFunctions();
67 }
68
63 RAWINPUTDEVICE* RawInputDataFetcher::GetRawInputDevices(DWORD flags) { 69 RAWINPUTDEVICE* RawInputDataFetcher::GetRawInputDevices(DWORD flags) {
64 size_t usage_count = arraysize(DeviceUsages); 70 size_t usage_count = arraysize(DeviceUsages);
65 scoped_ptr<RAWINPUTDEVICE[]> devices(new RAWINPUTDEVICE[usage_count]); 71 scoped_ptr<RAWINPUTDEVICE[]> devices(new RAWINPUTDEVICE[usage_count]);
66 for (size_t i = 0; i < usage_count; ++i) { 72 for (size_t i = 0; i < usage_count; ++i) {
67 devices[i].dwFlags = flags; 73 devices[i].dwFlags = flags;
68 devices[i].usUsagePage = 1; 74 devices[i].usUsagePage = 1;
69 devices[i].usUsage = DeviceUsages[i]; 75 devices[i].usUsage = DeviceUsages[i];
70 devices[i].hwndTarget = (flags & RIDEV_REMOVE) ? 0 : window_->hwnd(); 76 devices[i].hwndTarget = (flags & RIDEV_REMOVE) ? 0 : window_->hwnd();
71 } 77 }
72 return devices.release(); 78 return devices.release();
73 } 79 }
74 80
81 void RawInputDataFetcher::PauseHint(bool pause) {
82 if (pause)
83 StopMonitor();
84 else
85 StartMonitor();
86 }
87
75 void RawInputDataFetcher::StartMonitor() { 88 void RawInputDataFetcher::StartMonitor() {
76 if (!rawinput_available_ || events_monitored_) 89 if (!rawinput_available_ || events_monitored_)
77 return; 90 return;
78 91
79 if (!window_) { 92 if (!window_) {
80 window_.reset(new base::win::MessageWindow()); 93 window_.reset(new base::win::MessageWindow());
81 if (!window_->Create(base::Bind(&RawInputDataFetcher::HandleMessage, 94 if (!window_->Create(base::Bind(&RawInputDataFetcher::HandleMessage,
82 base::Unretained(this)))) { 95 base::Unretained(this)))) {
83 PLOG(ERROR) << "Failed to create the raw input window"; 96 PLOG(ERROR) << "Failed to create the raw input window";
84 window_.reset(); 97 window_.reset();
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 } 137 }
125 138
126 void RawInputDataFetcher::ClearControllers() { 139 void RawInputDataFetcher::ClearControllers() {
127 while (!controllers_.empty()) { 140 while (!controllers_.empty()) {
128 RawGamepadInfo* gamepad_info = controllers_.begin()->second; 141 RawGamepadInfo* gamepad_info = controllers_.begin()->second;
129 controllers_.erase(gamepad_info->handle); 142 controllers_.erase(gamepad_info->handle);
130 delete gamepad_info; 143 delete gamepad_info;
131 } 144 }
132 } 145 }
133 146
134 std::vector<RawGamepadInfo*> RawInputDataFetcher::EnumerateDevices() { 147 void RawInputDataFetcher::GetGamepadData(bool devices_changed_hint) {
135 std::vector<RawGamepadInfo*> valid_controllers; 148 if (!rawinput_available_)
149 return;
136 150
137 ClearControllers(); 151 if (devices_changed_hint)
152 EnumerateDevices();
153
154 for (const auto& controller : controllers_) {
155 RawGamepadInfo* gamepad = controller.second;
156 PadState* state = provider()->GetPadState(GAMEPAD_SOURCE_WIN_RAW,
157 gamepad->source_id);
158 if (!state)
159 continue;
160
161 WebGamepad& pad = state->data;
162
163 pad.timestamp = gamepad->report_id;
164 pad.buttonsLength = gamepad->buttons_length;
165 pad.axesLength = gamepad->axes_length;
166
167 for (unsigned int i = 0; i < pad.buttonsLength; i++) {
168 pad.buttons[i].pressed = gamepad->buttons[i];
169 pad.buttons[i].value = gamepad->buttons[i] ? 1.0 : 0.0;
170 }
171
172 for (unsigned int i = 0; i < pad.axesLength; i++)
173 pad.axes[i] = gamepad->axes[i].value;
174 }
175 }
176
177 void RawInputDataFetcher::EnumerateDevices() {
178 last_enumeration_id_++;
138 179
139 UINT count = 0; 180 UINT count = 0;
140 UINT result = GetRawInputDeviceList(NULL, &count, sizeof(RAWINPUTDEVICELIST)); 181 UINT result = GetRawInputDeviceList(NULL, &count, sizeof(RAWINPUTDEVICELIST));
141 if (result == static_cast<UINT>(-1)) { 182 if (result == static_cast<UINT>(-1)) {
142 PLOG(ERROR) << "GetRawInputDeviceList() failed"; 183 PLOG(ERROR) << "GetRawInputDeviceList() failed";
143 return valid_controllers; 184 return;
144 } 185 }
145 DCHECK_EQ(0u, result); 186 DCHECK_EQ(0u, result);
146 187
147 scoped_ptr<RAWINPUTDEVICELIST[]> device_list(new RAWINPUTDEVICELIST[count]); 188 scoped_ptr<RAWINPUTDEVICELIST[]> device_list(new RAWINPUTDEVICELIST[count]);
148 result = GetRawInputDeviceList(device_list.get(), &count, 189 result = GetRawInputDeviceList(device_list.get(), &count,
149 sizeof(RAWINPUTDEVICELIST)); 190 sizeof(RAWINPUTDEVICELIST));
150 if (result == static_cast<UINT>(-1)) { 191 if (result == static_cast<UINT>(-1)) {
151 PLOG(ERROR) << "GetRawInputDeviceList() failed"; 192 PLOG(ERROR) << "GetRawInputDeviceList() failed";
152 return valid_controllers; 193 return;
153 } 194 }
154 DCHECK_EQ(count, result); 195 DCHECK_EQ(count, result);
155 196
156 for (UINT i = 0; i < count; ++i) { 197 for (UINT i = 0; i < count; ++i) {
157 if (device_list[i].dwType == RIM_TYPEHID) { 198 if (device_list[i].dwType == RIM_TYPEHID) {
158 HANDLE device_handle = device_list[i].hDevice; 199 HANDLE device_handle = device_list[i].hDevice;
159 RawGamepadInfo* gamepad_info = ParseGamepadInfo(device_handle); 200 ControllerMap::iterator controller = controllers_.find(device_handle);
160 if (gamepad_info) { 201
161 controllers_[device_handle] = gamepad_info; 202 RawGamepadInfo* gamepad;
162 valid_controllers.push_back(gamepad_info); 203 if (controller != controllers_.end()) {
204 gamepad = controller->second;
205 } else {
206 gamepad = ParseGamepadInfo(device_handle);
207 if (!gamepad)
208 continue;
209
210 PadState* state = provider()->GetPadState(GAMEPAD_SOURCE_WIN_RAW,
211 gamepad->source_id);
212 if (!state)
213 continue; // No slot available for this gamepad.
214
215 controllers_[device_handle] = gamepad;
216
217 WebGamepad& pad = state->data;
218 pad.connected = true;
219
220 std::string vendor = base::StringPrintf("%04x", gamepad->vendor_id);
221 std::string product = base::StringPrintf("%04x", gamepad->product_id);
222 state->mapper = GetGamepadStandardMappingFunction(vendor, product);
223 state->axis_mask = 0;
224 state->button_mask = 0;
225
226 swprintf(pad.id, WebGamepad::idLengthCap,
227 L"%ls (%lsVendor: %04x Product: %04x)",
228 gamepad->id, state->mapper ? L"STANDARD GAMEPAD " : L"",
229 gamepad->vendor_id, gamepad->product_id);
230
231 if (state->mapper)
232 swprintf(pad.mapping, WebGamepad::mappingLengthCap, L"standard");
233 else
234 pad.mapping[0] = 0;
163 } 235 }
236
237 gamepad->enumeration_id = last_enumeration_id_;
164 } 238 }
165 } 239 }
166 return valid_controllers;
167 }
168 240
169 RawGamepadInfo* RawInputDataFetcher::GetGamepadInfo(HANDLE handle) { 241 // Clear out old controllers that weren't part of this enumeration pass.
170 std::map<HANDLE, RawGamepadInfo*>::iterator it = controllers_.find(handle); 242 for (const auto& controller : controllers_) {
171 if (it != controllers_.end()) 243 RawGamepadInfo* gamepad = controller.second;
172 return it->second; 244 if (gamepad->enumeration_id != last_enumeration_id_) {
245 controllers_.erase(gamepad->handle);
246 delete gamepad;
247 }
248 }
173 249
174 return NULL; 250 return;
175 } 251 }
176 252
177 RawGamepadInfo* RawInputDataFetcher::ParseGamepadInfo(HANDLE hDevice) { 253 RawGamepadInfo* RawInputDataFetcher::ParseGamepadInfo(HANDLE hDevice) {
178 UINT size = 0; 254 UINT size = 0;
179 255
180 // Do we already have this device in the map?
181 if (GetGamepadInfo(hDevice))
182 return NULL;
183
184 // Query basic device info. 256 // Query basic device info.
185 UINT result = GetRawInputDeviceInfo(hDevice, RIDI_DEVICEINFO, 257 UINT result = GetRawInputDeviceInfo(hDevice, RIDI_DEVICEINFO,
186 NULL, &size); 258 NULL, &size);
187 if (result == static_cast<UINT>(-1)) { 259 if (result == static_cast<UINT>(-1)) {
188 PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; 260 PLOG(ERROR) << "GetRawInputDeviceInfo() failed";
189 return NULL; 261 return NULL;
190 } 262 }
191 DCHECK_EQ(0u, result); 263 DCHECK_EQ(0u, result);
192 264
193 scoped_ptr<uint8_t[]> di_buffer(new uint8_t[size]); 265 scoped_ptr<uint8_t[]> di_buffer(new uint8_t[size]);
(...skipping 13 matching lines...) Expand all
207 if (device_info->hid.usUsage == device_usage) { 279 if (device_info->hid.usUsage == device_usage) {
208 valid_type = true; 280 valid_type = true;
209 break; 281 break;
210 } 282 }
211 } 283 }
212 284
213 if (!valid_type) 285 if (!valid_type)
214 return NULL; 286 return NULL;
215 287
216 scoped_ptr<RawGamepadInfo> gamepad_info(new RawGamepadInfo); 288 scoped_ptr<RawGamepadInfo> gamepad_info(new RawGamepadInfo);
289 gamepad_info->source_id = ++last_source_id_;
scottmg 2016/01/18 22:54:52 Initialize enumeration_id here maybe? I can't tell
bajones 2016/01/20 22:49:32 I don't think it can be, but it also doesn't hurt
217 gamepad_info->handle = hDevice; 290 gamepad_info->handle = hDevice;
218 gamepad_info->report_id = 0; 291 gamepad_info->report_id = 0;
219 gamepad_info->vendor_id = device_info->hid.dwVendorId; 292 gamepad_info->vendor_id = device_info->hid.dwVendorId;
220 gamepad_info->product_id = device_info->hid.dwProductId; 293 gamepad_info->product_id = device_info->hid.dwProductId;
221 gamepad_info->buttons_length = 0; 294 gamepad_info->buttons_length = 0;
222 ZeroMemory(gamepad_info->buttons, sizeof(gamepad_info->buttons)); 295 ZeroMemory(gamepad_info->buttons, sizeof(gamepad_info->buttons));
223 gamepad_info->axes_length = 0; 296 gamepad_info->axes_length = 0;
224 ZeroMemory(gamepad_info->axes, sizeof(gamepad_info->axes)); 297 ZeroMemory(gamepad_info->axes, sizeof(gamepad_info->axes));
225 298
226 // Query device identifier 299 // Query device identifier
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 gamepad_info->axes_length = 419 gamepad_info->axes_length =
347 std::max(gamepad_info->axes_length, next_index + 1); 420 std::max(gamepad_info->axes_length, next_index + 1);
348 } 421 }
349 } 422 }
350 423
351 if (next_index >= WebGamepad::axesLengthCap) 424 if (next_index >= WebGamepad::axesLengthCap)
352 break; 425 break;
353 } 426 }
354 } 427 }
355 428
429 // Sometimes devices show up with no buttons or axes. Don't return these.
430 if (gamepad_info->buttons_length == 0 && gamepad_info->axes_length == 0)
431 return nullptr;
432
356 return gamepad_info.release(); 433 return gamepad_info.release();
357 } 434 }
358 435
359 void RawInputDataFetcher::UpdateGamepad( 436 void RawInputDataFetcher::UpdateGamepad(
360 RAWINPUT* input, 437 RAWINPUT* input,
361 RawGamepadInfo* gamepad_info) { 438 RawGamepadInfo* gamepad_info) {
362 NTSTATUS status; 439 NTSTATUS status;
363 440
364 gamepad_info->report_id++; 441 gamepad_info->report_id++;
365 442
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 result = GetRawInputData( 527 result = GetRawInputData(
451 input_handle, RID_INPUT, buffer.get(), &size, sizeof(RAWINPUTHEADER)); 528 input_handle, RID_INPUT, buffer.get(), &size, sizeof(RAWINPUTHEADER));
452 if (result == static_cast<UINT>(-1)) { 529 if (result == static_cast<UINT>(-1)) {
453 PLOG(ERROR) << "GetRawInputData() failed"; 530 PLOG(ERROR) << "GetRawInputData() failed";
454 return 0; 531 return 0;
455 } 532 }
456 DCHECK_EQ(size, result); 533 DCHECK_EQ(size, result);
457 534
458 // Notify the observer about events generated locally. 535 // Notify the observer about events generated locally.
459 if (input->header.dwType == RIM_TYPEHID && input->header.hDevice != NULL) { 536 if (input->header.dwType == RIM_TYPEHID && input->header.hDevice != NULL) {
460 RawGamepadInfo* gamepad = GetGamepadInfo(input->header.hDevice); 537 ControllerMap::iterator it = controllers_.find(input->header.hDevice);
461 if (gamepad) 538 if (it != controllers_.end())
462 UpdateGamepad(input, gamepad); 539 UpdateGamepad(input, it->second);
463 } 540 }
464 541
465 return DefRawInputProc(&input, 1, sizeof(RAWINPUTHEADER)); 542 return DefRawInputProc(&input, 1, sizeof(RAWINPUTHEADER));
466 } 543 }
467 544
468 bool RawInputDataFetcher::HandleMessage(UINT message, 545 bool RawInputDataFetcher::HandleMessage(UINT message,
469 WPARAM wparam, 546 WPARAM wparam,
470 LPARAM lparam, 547 LPARAM lparam,
471 LRESULT* result) { 548 LRESULT* result) {
472 switch (message) { 549 switch (message) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
516 return false; 593 return false;
517 hidd_get_product_string_ = reinterpret_cast<HidDGetStringFunc>( 594 hidd_get_product_string_ = reinterpret_cast<HidDGetStringFunc>(
518 hid_dll_.GetFunctionPointer("HidD_GetProductString")); 595 hid_dll_.GetFunctionPointer("HidD_GetProductString"));
519 if (!hidd_get_product_string_) 596 if (!hidd_get_product_string_)
520 return false; 597 return false;
521 598
522 return true; 599 return true;
523 } 600 }
524 601
525 } // namespace content 602 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698