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