| 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 |