OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |