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 "device/gamepad/raw_input_data_fetcher_win.h" | 5 #include "device/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/strings/stringprintf.h" |
10 #include "base/trace_event/trace_event.h" | 11 #include "base/trace_event/trace_event.h" |
11 | 12 |
12 namespace device { | 13 namespace device { |
13 | 14 |
14 using namespace blink; | 15 using namespace blink; |
15 | 16 |
16 namespace { | 17 namespace { |
17 | 18 |
18 float NormalizeAxis(long value, long min, long max) { | 19 float NormalizeAxis(long value, long min, long max) { |
19 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 14 matching lines...) Expand all Loading... |
34 const uint32_t kGameControlsUsagePage = 0x05; | 35 const uint32_t kGameControlsUsagePage = 0x05; |
35 const uint32_t kButtonUsagePage = 0x09; | 36 const uint32_t kButtonUsagePage = 0x09; |
36 | 37 |
37 } // namespace | 38 } // namespace |
38 | 39 |
39 RawGamepadInfo::RawGamepadInfo() {} | 40 RawGamepadInfo::RawGamepadInfo() {} |
40 | 41 |
41 RawGamepadInfo::~RawGamepadInfo() {} | 42 RawGamepadInfo::~RawGamepadInfo() {} |
42 | 43 |
43 RawInputDataFetcher::RawInputDataFetcher() | 44 RawInputDataFetcher::RawInputDataFetcher() |
44 : hid_dll_(base::FilePath(FILE_PATH_LITERAL("hid.dll"))), | 45 : rawinput_available_(false), |
45 rawinput_available_(GetHidDllFunctions()), | |
46 filter_xinput_(true), | 46 filter_xinput_(true), |
47 events_monitored_(false) {} | 47 events_monitored_(false), |
| 48 last_source_id_(0), |
| 49 last_enumeration_id_(0) {} |
48 | 50 |
49 RawInputDataFetcher::~RawInputDataFetcher() { | 51 RawInputDataFetcher::~RawInputDataFetcher() { |
50 ClearControllers(); | 52 ClearControllers(); |
51 DCHECK(!window_); | 53 DCHECK(!window_); |
52 DCHECK(!events_monitored_); | 54 DCHECK(!events_monitored_); |
53 } | 55 } |
54 | 56 |
| 57 GamepadSource RawInputDataFetcher::source() { |
| 58 return Factory::static_source(); |
| 59 } |
| 60 |
55 void RawInputDataFetcher::WillDestroyCurrentMessageLoop() { | 61 void RawInputDataFetcher::WillDestroyCurrentMessageLoop() { |
56 StopMonitor(); | 62 StopMonitor(); |
57 } | 63 } |
58 | 64 |
| 65 void RawInputDataFetcher::OnAddedToProvider() { |
| 66 hid_dll_.Reset(base::LoadNativeLibrary( |
| 67 base::FilePath(FILE_PATH_LITERAL("hid.dll")), nullptr)); |
| 68 rawinput_available_ = GetHidDllFunctions(); |
| 69 } |
| 70 |
59 RAWINPUTDEVICE* RawInputDataFetcher::GetRawInputDevices(DWORD flags) { | 71 RAWINPUTDEVICE* RawInputDataFetcher::GetRawInputDevices(DWORD flags) { |
60 size_t usage_count = arraysize(DeviceUsages); | 72 size_t usage_count = arraysize(DeviceUsages); |
61 std::unique_ptr<RAWINPUTDEVICE[]> devices(new RAWINPUTDEVICE[usage_count]); | 73 std::unique_ptr<RAWINPUTDEVICE[]> devices(new RAWINPUTDEVICE[usage_count]); |
62 for (size_t i = 0; i < usage_count; ++i) { | 74 for (size_t i = 0; i < usage_count; ++i) { |
63 devices[i].dwFlags = flags; | 75 devices[i].dwFlags = flags; |
64 devices[i].usUsagePage = 1; | 76 devices[i].usUsagePage = 1; |
65 devices[i].usUsage = DeviceUsages[i]; | 77 devices[i].usUsage = DeviceUsages[i]; |
66 devices[i].hwndTarget = (flags & RIDEV_REMOVE) ? 0 : window_->hwnd(); | 78 devices[i].hwndTarget = (flags & RIDEV_REMOVE) ? 0 : window_->hwnd(); |
67 } | 79 } |
68 return devices.release(); | 80 return devices.release(); |
69 } | 81 } |
70 | 82 |
| 83 void RawInputDataFetcher::PauseHint(bool pause) { |
| 84 if (pause) |
| 85 StopMonitor(); |
| 86 else |
| 87 StartMonitor(); |
| 88 } |
| 89 |
71 void RawInputDataFetcher::StartMonitor() { | 90 void RawInputDataFetcher::StartMonitor() { |
72 if (!rawinput_available_ || events_monitored_) | 91 if (!rawinput_available_ || events_monitored_) |
73 return; | 92 return; |
74 | 93 |
75 if (!window_) { | 94 if (!window_) { |
76 window_.reset(new base::win::MessageWindow()); | 95 window_.reset(new base::win::MessageWindow()); |
77 if (!window_->Create(base::Bind(&RawInputDataFetcher::HandleMessage, | 96 if (!window_->Create(base::Bind(&RawInputDataFetcher::HandleMessage, |
78 base::Unretained(this)))) { | 97 base::Unretained(this)))) { |
79 PLOG(ERROR) << "Failed to create the raw input window"; | 98 PLOG(ERROR) << "Failed to create the raw input window"; |
80 window_.reset(); | 99 window_.reset(); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 } | 140 } |
122 | 141 |
123 void RawInputDataFetcher::ClearControllers() { | 142 void RawInputDataFetcher::ClearControllers() { |
124 while (!controllers_.empty()) { | 143 while (!controllers_.empty()) { |
125 RawGamepadInfo* gamepad_info = controllers_.begin()->second; | 144 RawGamepadInfo* gamepad_info = controllers_.begin()->second; |
126 controllers_.erase(gamepad_info->handle); | 145 controllers_.erase(gamepad_info->handle); |
127 delete gamepad_info; | 146 delete gamepad_info; |
128 } | 147 } |
129 } | 148 } |
130 | 149 |
131 std::vector<RawGamepadInfo*> RawInputDataFetcher::EnumerateDevices() { | 150 void RawInputDataFetcher::GetGamepadData(bool devices_changed_hint) { |
132 std::vector<RawGamepadInfo*> valid_controllers; | 151 if (!rawinput_available_) |
| 152 return; |
133 | 153 |
134 ClearControllers(); | 154 if (devices_changed_hint) |
| 155 EnumerateDevices(); |
| 156 |
| 157 for (const auto& controller : controllers_) { |
| 158 RawGamepadInfo* gamepad = controller.second; |
| 159 PadState* state = GetPadState(gamepad->source_id); |
| 160 if (!state) |
| 161 continue; |
| 162 |
| 163 WebGamepad& pad = state->data; |
| 164 |
| 165 pad.timestamp = gamepad->report_id; |
| 166 pad.buttonsLength = gamepad->buttons_length; |
| 167 pad.axesLength = gamepad->axes_length; |
| 168 |
| 169 for (unsigned int i = 0; i < pad.buttonsLength; i++) { |
| 170 pad.buttons[i].pressed = gamepad->buttons[i]; |
| 171 pad.buttons[i].value = gamepad->buttons[i] ? 1.0 : 0.0; |
| 172 } |
| 173 |
| 174 for (unsigned int i = 0; i < pad.axesLength; i++) |
| 175 pad.axes[i] = gamepad->axes[i].value; |
| 176 } |
| 177 } |
| 178 |
| 179 void RawInputDataFetcher::EnumerateDevices() { |
| 180 last_enumeration_id_++; |
135 | 181 |
136 UINT count = 0; | 182 UINT count = 0; |
137 UINT result = GetRawInputDeviceList(NULL, &count, sizeof(RAWINPUTDEVICELIST)); | 183 UINT result = GetRawInputDeviceList(NULL, &count, sizeof(RAWINPUTDEVICELIST)); |
138 if (result == static_cast<UINT>(-1)) { | 184 if (result == static_cast<UINT>(-1)) { |
139 PLOG(ERROR) << "GetRawInputDeviceList() failed"; | 185 PLOG(ERROR) << "GetRawInputDeviceList() failed"; |
140 return valid_controllers; | 186 return; |
141 } | 187 } |
142 DCHECK_EQ(0u, result); | 188 DCHECK_EQ(0u, result); |
143 | 189 |
144 std::unique_ptr<RAWINPUTDEVICELIST[]> device_list( | 190 std::unique_ptr<RAWINPUTDEVICELIST[]> device_list( |
145 new RAWINPUTDEVICELIST[count]); | 191 new RAWINPUTDEVICELIST[count]); |
146 result = GetRawInputDeviceList(device_list.get(), &count, | 192 result = GetRawInputDeviceList(device_list.get(), &count, |
147 sizeof(RAWINPUTDEVICELIST)); | 193 sizeof(RAWINPUTDEVICELIST)); |
148 if (result == static_cast<UINT>(-1)) { | 194 if (result == static_cast<UINT>(-1)) { |
149 PLOG(ERROR) << "GetRawInputDeviceList() failed"; | 195 PLOG(ERROR) << "GetRawInputDeviceList() failed"; |
150 return valid_controllers; | 196 return; |
151 } | 197 } |
152 DCHECK_EQ(count, result); | 198 DCHECK_EQ(count, result); |
153 | 199 |
154 for (UINT i = 0; i < count; ++i) { | 200 for (UINT i = 0; i < count; ++i) { |
155 if (device_list[i].dwType == RIM_TYPEHID) { | 201 if (device_list[i].dwType == RIM_TYPEHID) { |
156 HANDLE device_handle = device_list[i].hDevice; | 202 HANDLE device_handle = device_list[i].hDevice; |
157 RawGamepadInfo* gamepad_info = ParseGamepadInfo(device_handle); | 203 ControllerMap::iterator controller = controllers_.find(device_handle); |
158 if (gamepad_info) { | 204 |
159 controllers_[device_handle] = gamepad_info; | 205 RawGamepadInfo* gamepad; |
160 valid_controllers.push_back(gamepad_info); | 206 if (controller != controllers_.end()) { |
| 207 gamepad = controller->second; |
| 208 } else { |
| 209 gamepad = ParseGamepadInfo(device_handle); |
| 210 if (!gamepad) |
| 211 continue; |
| 212 |
| 213 PadState* state = GetPadState(gamepad->source_id); |
| 214 if (!state) |
| 215 continue; // No slot available for this gamepad. |
| 216 |
| 217 controllers_[device_handle] = gamepad; |
| 218 |
| 219 WebGamepad& pad = state->data; |
| 220 pad.connected = true; |
| 221 |
| 222 std::string vendor = base::StringPrintf("%04x", gamepad->vendor_id); |
| 223 std::string product = base::StringPrintf("%04x", gamepad->product_id); |
| 224 state->mapper = GetGamepadStandardMappingFunction(vendor, product); |
| 225 state->axis_mask = 0; |
| 226 state->button_mask = 0; |
| 227 |
| 228 swprintf(pad.id, WebGamepad::idLengthCap, |
| 229 L"%ls (%lsVendor: %04x Product: %04x)", gamepad->id, |
| 230 state->mapper ? L"STANDARD GAMEPAD " : L"", gamepad->vendor_id, |
| 231 gamepad->product_id); |
| 232 |
| 233 if (state->mapper) |
| 234 swprintf(pad.mapping, WebGamepad::mappingLengthCap, L"standard"); |
| 235 else |
| 236 pad.mapping[0] = 0; |
161 } | 237 } |
| 238 |
| 239 gamepad->enumeration_id = last_enumeration_id_; |
162 } | 240 } |
163 } | 241 } |
164 return valid_controllers; | |
165 } | |
166 | 242 |
167 RawGamepadInfo* RawInputDataFetcher::GetGamepadInfo(HANDLE handle) { | 243 // Clear out old controllers that weren't part of this enumeration pass. |
168 std::map<HANDLE, RawGamepadInfo*>::iterator it = controllers_.find(handle); | 244 for (const auto& controller : controllers_) { |
169 if (it != controllers_.end()) | 245 RawGamepadInfo* gamepad = controller.second; |
170 return it->second; | 246 if (gamepad->enumeration_id != last_enumeration_id_) { |
171 | 247 controllers_.erase(gamepad->handle); |
172 return NULL; | 248 delete gamepad; |
| 249 } |
| 250 } |
173 } | 251 } |
174 | 252 |
175 RawGamepadInfo* RawInputDataFetcher::ParseGamepadInfo(HANDLE hDevice) { | 253 RawGamepadInfo* RawInputDataFetcher::ParseGamepadInfo(HANDLE hDevice) { |
176 UINT size = 0; | 254 UINT size = 0; |
177 | 255 |
178 // Do we already have this device in the map? | |
179 if (GetGamepadInfo(hDevice)) | |
180 return NULL; | |
181 | |
182 // Query basic device info. | 256 // Query basic device info. |
183 UINT result = GetRawInputDeviceInfo(hDevice, RIDI_DEVICEINFO, NULL, &size); | 257 UINT result = GetRawInputDeviceInfo(hDevice, RIDI_DEVICEINFO, NULL, &size); |
184 if (result == static_cast<UINT>(-1)) { | 258 if (result == static_cast<UINT>(-1)) { |
185 PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; | 259 PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; |
186 return NULL; | 260 return NULL; |
187 } | 261 } |
188 DCHECK_EQ(0u, result); | 262 DCHECK_EQ(0u, result); |
189 | 263 |
190 std::unique_ptr<uint8_t[]> di_buffer(new uint8_t[size]); | 264 std::unique_ptr<uint8_t[]> di_buffer(new uint8_t[size]); |
191 RID_DEVICE_INFO* device_info = | 265 RID_DEVICE_INFO* device_info = |
192 reinterpret_cast<RID_DEVICE_INFO*>(di_buffer.get()); | 266 reinterpret_cast<RID_DEVICE_INFO*>(di_buffer.get()); |
193 result = | 267 result = |
194 GetRawInputDeviceInfo(hDevice, RIDI_DEVICEINFO, di_buffer.get(), &size); | 268 GetRawInputDeviceInfo(hDevice, RIDI_DEVICEINFO, di_buffer.get(), &size); |
195 if (result == static_cast<UINT>(-1)) { | 269 if (result == static_cast<UINT>(-1)) { |
196 PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; | 270 PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; |
197 return NULL; | 271 return NULL; |
198 } | 272 } |
199 DCHECK_EQ(size, result); | 273 DCHECK_EQ(size, result); |
200 | 274 |
201 // Make sure this device is of a type that we want to observe. | 275 // Make sure this device is of a type that we want to observe. |
202 bool valid_type = false; | 276 bool valid_type = false; |
203 for (USHORT device_usage : DeviceUsages) { | 277 for (USHORT device_usage : DeviceUsages) { |
204 if (device_info->hid.usUsage == device_usage) { | 278 if (device_info->hid.usUsage == device_usage) { |
205 valid_type = true; | 279 valid_type = true; |
206 break; | 280 break; |
207 } | 281 } |
208 } | 282 } |
209 | 283 |
| 284 // This is terrible, but the Oculus Rift seems to think it's a gamepad. |
| 285 // Filter out any Oculus devices. (We'll handle Oculus Touch elsewhere.) |
| 286 if (device_info->hid.dwVendorId == 0x2833) { |
| 287 valid_type = false; |
| 288 } |
| 289 |
210 if (!valid_type) | 290 if (!valid_type) |
211 return NULL; | 291 return NULL; |
212 | 292 |
213 std::unique_ptr<RawGamepadInfo> gamepad_info(new RawGamepadInfo); | 293 std::unique_ptr<RawGamepadInfo> gamepad_info(new RawGamepadInfo); |
| 294 gamepad_info->source_id = ++last_source_id_; |
214 gamepad_info->handle = hDevice; | 295 gamepad_info->handle = hDevice; |
215 gamepad_info->report_id = 0; | 296 gamepad_info->report_id = 0; |
216 gamepad_info->vendor_id = device_info->hid.dwVendorId; | 297 gamepad_info->vendor_id = device_info->hid.dwVendorId; |
217 gamepad_info->product_id = device_info->hid.dwProductId; | 298 gamepad_info->product_id = device_info->hid.dwProductId; |
218 gamepad_info->buttons_length = 0; | 299 gamepad_info->buttons_length = 0; |
219 ZeroMemory(gamepad_info->buttons, sizeof(gamepad_info->buttons)); | 300 ZeroMemory(gamepad_info->buttons, sizeof(gamepad_info->buttons)); |
220 gamepad_info->axes_length = 0; | 301 gamepad_info->axes_length = 0; |
221 ZeroMemory(gamepad_info->axes, sizeof(gamepad_info->axes)); | 302 ZeroMemory(gamepad_info->axes, sizeof(gamepad_info->axes)); |
222 | 303 |
223 // Query device identifier | 304 // Query device identifier |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
343 gamepad_info->axes_length = | 424 gamepad_info->axes_length = |
344 std::max(gamepad_info->axes_length, next_index + 1); | 425 std::max(gamepad_info->axes_length, next_index + 1); |
345 } | 426 } |
346 } | 427 } |
347 | 428 |
348 if (next_index >= WebGamepad::axesLengthCap) | 429 if (next_index >= WebGamepad::axesLengthCap) |
349 break; | 430 break; |
350 } | 431 } |
351 } | 432 } |
352 | 433 |
| 434 // Sometimes devices show up with no buttons or axes. Don't return these. |
| 435 if (gamepad_info->buttons_length == 0 && gamepad_info->axes_length == 0) |
| 436 return nullptr; |
| 437 |
353 return gamepad_info.release(); | 438 return gamepad_info.release(); |
354 } | 439 } |
355 | 440 |
356 void RawInputDataFetcher::UpdateGamepad(RAWINPUT* input, | 441 void RawInputDataFetcher::UpdateGamepad(RAWINPUT* input, |
357 RawGamepadInfo* gamepad_info) { | 442 RawGamepadInfo* gamepad_info) { |
358 NTSTATUS status; | 443 NTSTATUS status; |
359 | 444 |
360 gamepad_info->report_id++; | 445 gamepad_info->report_id++; |
361 | 446 |
362 // Query button state. | 447 // Query button state. |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
441 result = GetRawInputData(input_handle, RID_INPUT, buffer.get(), &size, | 526 result = GetRawInputData(input_handle, RID_INPUT, buffer.get(), &size, |
442 sizeof(RAWINPUTHEADER)); | 527 sizeof(RAWINPUTHEADER)); |
443 if (result == static_cast<UINT>(-1)) { | 528 if (result == static_cast<UINT>(-1)) { |
444 PLOG(ERROR) << "GetRawInputData() failed"; | 529 PLOG(ERROR) << "GetRawInputData() failed"; |
445 return 0; | 530 return 0; |
446 } | 531 } |
447 DCHECK_EQ(size, result); | 532 DCHECK_EQ(size, result); |
448 | 533 |
449 // Notify the observer about events generated locally. | 534 // Notify the observer about events generated locally. |
450 if (input->header.dwType == RIM_TYPEHID && input->header.hDevice != NULL) { | 535 if (input->header.dwType == RIM_TYPEHID && input->header.hDevice != NULL) { |
451 RawGamepadInfo* gamepad = GetGamepadInfo(input->header.hDevice); | 536 ControllerMap::iterator it = controllers_.find(input->header.hDevice); |
452 if (gamepad) | 537 if (it != controllers_.end()) |
453 UpdateGamepad(input, gamepad); | 538 UpdateGamepad(input, it->second); |
454 } | 539 } |
455 | 540 |
456 return DefRawInputProc(&input, 1, sizeof(RAWINPUTHEADER)); | 541 return DefRawInputProc(&input, 1, sizeof(RAWINPUTHEADER)); |
457 } | 542 } |
458 | 543 |
459 bool RawInputDataFetcher::HandleMessage(UINT message, | 544 bool RawInputDataFetcher::HandleMessage(UINT message, |
460 WPARAM wparam, | 545 WPARAM wparam, |
461 LPARAM lparam, | 546 LPARAM lparam, |
462 LRESULT* result) { | 547 LRESULT* result) { |
463 switch (message) { | 548 switch (message) { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
508 return false; | 593 return false; |
509 hidd_get_product_string_ = reinterpret_cast<HidDGetStringFunc>( | 594 hidd_get_product_string_ = reinterpret_cast<HidDGetStringFunc>( |
510 hid_dll_.GetFunctionPointer("HidD_GetProductString")); | 595 hid_dll_.GetFunctionPointer("HidD_GetProductString")); |
511 if (!hidd_get_product_string_) | 596 if (!hidd_get_product_string_) |
512 return false; | 597 return false; |
513 | 598 |
514 return true; | 599 return true; |
515 } | 600 } |
516 | 601 |
517 } // namespace device | 602 } // namespace device |
OLD | NEW |