| 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" |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 RAWINPUTDEVICE* RawInputDataFetcher::GetRawInputDevices(DWORD flags) { | 63 RAWINPUTDEVICE* RawInputDataFetcher::GetRawInputDevices(DWORD flags) { |
| 64 size_t usage_count = arraysize(DeviceUsages); | 64 size_t usage_count = arraysize(DeviceUsages); |
| 65 scoped_ptr<RAWINPUTDEVICE[]> devices(new RAWINPUTDEVICE[usage_count]); | 65 std::unique_ptr<RAWINPUTDEVICE[]> devices(new RAWINPUTDEVICE[usage_count]); |
| 66 for (size_t i = 0; i < usage_count; ++i) { | 66 for (size_t i = 0; i < usage_count; ++i) { |
| 67 devices[i].dwFlags = flags; | 67 devices[i].dwFlags = flags; |
| 68 devices[i].usUsagePage = 1; | 68 devices[i].usUsagePage = 1; |
| 69 devices[i].usUsage = DeviceUsages[i]; | 69 devices[i].usUsage = DeviceUsages[i]; |
| 70 devices[i].hwndTarget = (flags & RIDEV_REMOVE) ? 0 : window_->hwnd(); | 70 devices[i].hwndTarget = (flags & RIDEV_REMOVE) ? 0 : window_->hwnd(); |
| 71 } | 71 } |
| 72 return devices.release(); | 72 return devices.release(); |
| 73 } | 73 } |
| 74 | 74 |
| 75 void RawInputDataFetcher::StartMonitor() { | 75 void RawInputDataFetcher::StartMonitor() { |
| 76 if (!rawinput_available_ || events_monitored_) | 76 if (!rawinput_available_ || events_monitored_) |
| 77 return; | 77 return; |
| 78 | 78 |
| 79 if (!window_) { | 79 if (!window_) { |
| 80 window_.reset(new base::win::MessageWindow()); | 80 window_.reset(new base::win::MessageWindow()); |
| 81 if (!window_->Create(base::Bind(&RawInputDataFetcher::HandleMessage, | 81 if (!window_->Create(base::Bind(&RawInputDataFetcher::HandleMessage, |
| 82 base::Unretained(this)))) { | 82 base::Unretained(this)))) { |
| 83 PLOG(ERROR) << "Failed to create the raw input window"; | 83 PLOG(ERROR) << "Failed to create the raw input window"; |
| 84 window_.reset(); | 84 window_.reset(); |
| 85 return; | 85 return; |
| 86 } | 86 } |
| 87 } | 87 } |
| 88 | 88 |
| 89 // Register to receive raw HID input. | 89 // Register to receive raw HID input. |
| 90 scoped_ptr<RAWINPUTDEVICE[]> devices(GetRawInputDevices(RIDEV_INPUTSINK)); | 90 std::unique_ptr<RAWINPUTDEVICE[]> devices( |
| 91 GetRawInputDevices(RIDEV_INPUTSINK)); |
| 91 if (!RegisterRawInputDevices(devices.get(), arraysize(DeviceUsages), | 92 if (!RegisterRawInputDevices(devices.get(), arraysize(DeviceUsages), |
| 92 sizeof(RAWINPUTDEVICE))) { | 93 sizeof(RAWINPUTDEVICE))) { |
| 93 PLOG(ERROR) << "RegisterRawInputDevices() failed for RIDEV_INPUTSINK"; | 94 PLOG(ERROR) << "RegisterRawInputDevices() failed for RIDEV_INPUTSINK"; |
| 94 window_.reset(); | 95 window_.reset(); |
| 95 return; | 96 return; |
| 96 } | 97 } |
| 97 | 98 |
| 98 // Start observing message loop destruction if we start monitoring the first | 99 // Start observing message loop destruction if we start monitoring the first |
| 99 // event. | 100 // event. |
| 100 if (!events_monitored_) | 101 if (!events_monitored_) |
| 101 base::MessageLoop::current()->AddDestructionObserver(this); | 102 base::MessageLoop::current()->AddDestructionObserver(this); |
| 102 | 103 |
| 103 events_monitored_ = true; | 104 events_monitored_ = true; |
| 104 } | 105 } |
| 105 | 106 |
| 106 void RawInputDataFetcher::StopMonitor() { | 107 void RawInputDataFetcher::StopMonitor() { |
| 107 if (!rawinput_available_ || !events_monitored_) | 108 if (!rawinput_available_ || !events_monitored_) |
| 108 return; | 109 return; |
| 109 | 110 |
| 110 // Stop receiving raw input. | 111 // Stop receiving raw input. |
| 111 DCHECK(window_); | 112 DCHECK(window_); |
| 112 scoped_ptr<RAWINPUTDEVICE[]> devices(GetRawInputDevices(RIDEV_REMOVE)); | 113 std::unique_ptr<RAWINPUTDEVICE[]> devices(GetRawInputDevices(RIDEV_REMOVE)); |
| 113 | 114 |
| 114 if (!RegisterRawInputDevices(devices.get(), arraysize(DeviceUsages), | 115 if (!RegisterRawInputDevices(devices.get(), arraysize(DeviceUsages), |
| 115 sizeof(RAWINPUTDEVICE))) { | 116 sizeof(RAWINPUTDEVICE))) { |
| 116 PLOG(INFO) << "RegisterRawInputDevices() failed for RIDEV_REMOVE"; | 117 PLOG(INFO) << "RegisterRawInputDevices() failed for RIDEV_REMOVE"; |
| 117 } | 118 } |
| 118 | 119 |
| 119 events_monitored_ = false; | 120 events_monitored_ = false; |
| 120 window_.reset(); | 121 window_.reset(); |
| 121 | 122 |
| 122 // Stop observing message loop destruction if no event is being monitored. | 123 // Stop observing message loop destruction if no event is being monitored. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 137 ClearControllers(); | 138 ClearControllers(); |
| 138 | 139 |
| 139 UINT count = 0; | 140 UINT count = 0; |
| 140 UINT result = GetRawInputDeviceList(NULL, &count, sizeof(RAWINPUTDEVICELIST)); | 141 UINT result = GetRawInputDeviceList(NULL, &count, sizeof(RAWINPUTDEVICELIST)); |
| 141 if (result == static_cast<UINT>(-1)) { | 142 if (result == static_cast<UINT>(-1)) { |
| 142 PLOG(ERROR) << "GetRawInputDeviceList() failed"; | 143 PLOG(ERROR) << "GetRawInputDeviceList() failed"; |
| 143 return valid_controllers; | 144 return valid_controllers; |
| 144 } | 145 } |
| 145 DCHECK_EQ(0u, result); | 146 DCHECK_EQ(0u, result); |
| 146 | 147 |
| 147 scoped_ptr<RAWINPUTDEVICELIST[]> device_list(new RAWINPUTDEVICELIST[count]); | 148 std::unique_ptr<RAWINPUTDEVICELIST[]> device_list( |
| 149 new RAWINPUTDEVICELIST[count]); |
| 148 result = GetRawInputDeviceList(device_list.get(), &count, | 150 result = GetRawInputDeviceList(device_list.get(), &count, |
| 149 sizeof(RAWINPUTDEVICELIST)); | 151 sizeof(RAWINPUTDEVICELIST)); |
| 150 if (result == static_cast<UINT>(-1)) { | 152 if (result == static_cast<UINT>(-1)) { |
| 151 PLOG(ERROR) << "GetRawInputDeviceList() failed"; | 153 PLOG(ERROR) << "GetRawInputDeviceList() failed"; |
| 152 return valid_controllers; | 154 return valid_controllers; |
| 153 } | 155 } |
| 154 DCHECK_EQ(count, result); | 156 DCHECK_EQ(count, result); |
| 155 | 157 |
| 156 for (UINT i = 0; i < count; ++i) { | 158 for (UINT i = 0; i < count; ++i) { |
| 157 if (device_list[i].dwType == RIM_TYPEHID) { | 159 if (device_list[i].dwType == RIM_TYPEHID) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 183 | 185 |
| 184 // Query basic device info. | 186 // Query basic device info. |
| 185 UINT result = GetRawInputDeviceInfo(hDevice, RIDI_DEVICEINFO, | 187 UINT result = GetRawInputDeviceInfo(hDevice, RIDI_DEVICEINFO, |
| 186 NULL, &size); | 188 NULL, &size); |
| 187 if (result == static_cast<UINT>(-1)) { | 189 if (result == static_cast<UINT>(-1)) { |
| 188 PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; | 190 PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; |
| 189 return NULL; | 191 return NULL; |
| 190 } | 192 } |
| 191 DCHECK_EQ(0u, result); | 193 DCHECK_EQ(0u, result); |
| 192 | 194 |
| 193 scoped_ptr<uint8_t[]> di_buffer(new uint8_t[size]); | 195 std::unique_ptr<uint8_t[]> di_buffer(new uint8_t[size]); |
| 194 RID_DEVICE_INFO* device_info = | 196 RID_DEVICE_INFO* device_info = |
| 195 reinterpret_cast<RID_DEVICE_INFO*>(di_buffer.get()); | 197 reinterpret_cast<RID_DEVICE_INFO*>(di_buffer.get()); |
| 196 result = GetRawInputDeviceInfo(hDevice, RIDI_DEVICEINFO, | 198 result = GetRawInputDeviceInfo(hDevice, RIDI_DEVICEINFO, |
| 197 di_buffer.get(), &size); | 199 di_buffer.get(), &size); |
| 198 if (result == static_cast<UINT>(-1)) { | 200 if (result == static_cast<UINT>(-1)) { |
| 199 PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; | 201 PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; |
| 200 return NULL; | 202 return NULL; |
| 201 } | 203 } |
| 202 DCHECK_EQ(size, result); | 204 DCHECK_EQ(size, result); |
| 203 | 205 |
| 204 // Make sure this device is of a type that we want to observe. | 206 // Make sure this device is of a type that we want to observe. |
| 205 bool valid_type = false; | 207 bool valid_type = false; |
| 206 for (USHORT device_usage : DeviceUsages) { | 208 for (USHORT device_usage : DeviceUsages) { |
| 207 if (device_info->hid.usUsage == device_usage) { | 209 if (device_info->hid.usUsage == device_usage) { |
| 208 valid_type = true; | 210 valid_type = true; |
| 209 break; | 211 break; |
| 210 } | 212 } |
| 211 } | 213 } |
| 212 | 214 |
| 213 if (!valid_type) | 215 if (!valid_type) |
| 214 return NULL; | 216 return NULL; |
| 215 | 217 |
| 216 scoped_ptr<RawGamepadInfo> gamepad_info(new RawGamepadInfo); | 218 std::unique_ptr<RawGamepadInfo> gamepad_info(new RawGamepadInfo); |
| 217 gamepad_info->handle = hDevice; | 219 gamepad_info->handle = hDevice; |
| 218 gamepad_info->report_id = 0; | 220 gamepad_info->report_id = 0; |
| 219 gamepad_info->vendor_id = device_info->hid.dwVendorId; | 221 gamepad_info->vendor_id = device_info->hid.dwVendorId; |
| 220 gamepad_info->product_id = device_info->hid.dwProductId; | 222 gamepad_info->product_id = device_info->hid.dwProductId; |
| 221 gamepad_info->buttons_length = 0; | 223 gamepad_info->buttons_length = 0; |
| 222 ZeroMemory(gamepad_info->buttons, sizeof(gamepad_info->buttons)); | 224 ZeroMemory(gamepad_info->buttons, sizeof(gamepad_info->buttons)); |
| 223 gamepad_info->axes_length = 0; | 225 gamepad_info->axes_length = 0; |
| 224 ZeroMemory(gamepad_info->axes, sizeof(gamepad_info->axes)); | 226 ZeroMemory(gamepad_info->axes, sizeof(gamepad_info->axes)); |
| 225 | 227 |
| 226 // Query device identifier | 228 // Query device identifier |
| 227 result = GetRawInputDeviceInfo(hDevice, RIDI_DEVICENAME, | 229 result = GetRawInputDeviceInfo(hDevice, RIDI_DEVICENAME, |
| 228 NULL, &size); | 230 NULL, &size); |
| 229 if (result == static_cast<UINT>(-1)) { | 231 if (result == static_cast<UINT>(-1)) { |
| 230 PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; | 232 PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; |
| 231 return NULL; | 233 return NULL; |
| 232 } | 234 } |
| 233 DCHECK_EQ(0u, result); | 235 DCHECK_EQ(0u, result); |
| 234 | 236 |
| 235 scoped_ptr<wchar_t[]> name_buffer(new wchar_t[size]); | 237 std::unique_ptr<wchar_t[]> name_buffer(new wchar_t[size]); |
| 236 result = GetRawInputDeviceInfo(hDevice, RIDI_DEVICENAME, | 238 result = GetRawInputDeviceInfo(hDevice, RIDI_DEVICENAME, |
| 237 name_buffer.get(), &size); | 239 name_buffer.get(), &size); |
| 238 if (result == static_cast<UINT>(-1)) { | 240 if (result == static_cast<UINT>(-1)) { |
| 239 PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; | 241 PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; |
| 240 return NULL; | 242 return NULL; |
| 241 } | 243 } |
| 242 DCHECK_EQ(size, result); | 244 DCHECK_EQ(size, result); |
| 243 | 245 |
| 244 // The presence of "IG_" in the device name indicates that this is an XInput | 246 // The presence of "IG_" in the device name indicates that this is an XInput |
| 245 // Gamepad. Skip enumerating these devices and let the XInput path handle it. | 247 // Gamepad. Skip enumerating these devices and let the XInput path handle it. |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 280 } | 282 } |
| 281 DCHECK_EQ(size, result); | 283 DCHECK_EQ(size, result); |
| 282 | 284 |
| 283 HIDP_CAPS caps; | 285 HIDP_CAPS caps; |
| 284 NTSTATUS status = hidp_get_caps_(gamepad_info->preparsed_data, &caps); | 286 NTSTATUS status = hidp_get_caps_(gamepad_info->preparsed_data, &caps); |
| 285 DCHECK_EQ(HIDP_STATUS_SUCCESS, status); | 287 DCHECK_EQ(HIDP_STATUS_SUCCESS, status); |
| 286 | 288 |
| 287 // Query button information. | 289 // Query button information. |
| 288 USHORT count = caps.NumberInputButtonCaps; | 290 USHORT count = caps.NumberInputButtonCaps; |
| 289 if (count > 0) { | 291 if (count > 0) { |
| 290 scoped_ptr<HIDP_BUTTON_CAPS[]> button_caps(new HIDP_BUTTON_CAPS[count]); | 292 std::unique_ptr<HIDP_BUTTON_CAPS[]> button_caps( |
| 293 new HIDP_BUTTON_CAPS[count]); |
| 291 status = hidp_get_button_caps_( | 294 status = hidp_get_button_caps_( |
| 292 HidP_Input, button_caps.get(), &count, gamepad_info->preparsed_data); | 295 HidP_Input, button_caps.get(), &count, gamepad_info->preparsed_data); |
| 293 DCHECK_EQ(HIDP_STATUS_SUCCESS, status); | 296 DCHECK_EQ(HIDP_STATUS_SUCCESS, status); |
| 294 | 297 |
| 295 for (uint32_t i = 0; i < count; ++i) { | 298 for (uint32_t i = 0; i < count; ++i) { |
| 296 if (button_caps[i].Range.UsageMin <= WebGamepad::buttonsLengthCap) { | 299 if (button_caps[i].Range.UsageMin <= WebGamepad::buttonsLengthCap) { |
| 297 uint32_t max_index = | 300 uint32_t max_index = |
| 298 std::min(WebGamepad::buttonsLengthCap, | 301 std::min(WebGamepad::buttonsLengthCap, |
| 299 static_cast<size_t>(button_caps[i].Range.UsageMax)); | 302 static_cast<size_t>(button_caps[i].Range.UsageMax)); |
| 300 gamepad_info->buttons_length = std::max( | 303 gamepad_info->buttons_length = std::max( |
| 301 gamepad_info->buttons_length, max_index); | 304 gamepad_info->buttons_length, max_index); |
| 302 } | 305 } |
| 303 } | 306 } |
| 304 } | 307 } |
| 305 | 308 |
| 306 // Query axis information. | 309 // Query axis information. |
| 307 count = caps.NumberInputValueCaps; | 310 count = caps.NumberInputValueCaps; |
| 308 scoped_ptr<HIDP_VALUE_CAPS[]> axes_caps(new HIDP_VALUE_CAPS[count]); | 311 std::unique_ptr<HIDP_VALUE_CAPS[]> axes_caps(new HIDP_VALUE_CAPS[count]); |
| 309 status = hidp_get_value_caps_(HidP_Input, axes_caps.get(), &count, | 312 status = hidp_get_value_caps_(HidP_Input, axes_caps.get(), &count, |
| 310 gamepad_info->preparsed_data); | 313 gamepad_info->preparsed_data); |
| 311 | 314 |
| 312 bool mapped_all_axes = true; | 315 bool mapped_all_axes = true; |
| 313 | 316 |
| 314 for (UINT i = 0; i < count; i++) { | 317 for (UINT i = 0; i < count; i++) { |
| 315 uint32_t axis_index = axes_caps[i].Range.UsageMin - kAxisMinimumUsageNumber; | 318 uint32_t axis_index = axes_caps[i].Range.UsageMin - kAxisMinimumUsageNumber; |
| 316 if (axis_index < WebGamepad::axesLengthCap) { | 319 if (axis_index < WebGamepad::axesLengthCap) { |
| 317 gamepad_info->axes[axis_index].caps = axes_caps[i]; | 320 gamepad_info->axes[axis_index].caps = axes_caps[i]; |
| 318 gamepad_info->axes[axis_index].value = 0; | 321 gamepad_info->axes[axis_index].value = 0; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 370 ULONG buttons_length = 0; | 373 ULONG buttons_length = 0; |
| 371 | 374 |
| 372 hidp_get_usages_ex_(HidP_Input, | 375 hidp_get_usages_ex_(HidP_Input, |
| 373 0, | 376 0, |
| 374 NULL, | 377 NULL, |
| 375 &buttons_length, | 378 &buttons_length, |
| 376 gamepad_info->preparsed_data, | 379 gamepad_info->preparsed_data, |
| 377 reinterpret_cast<PCHAR>(input->data.hid.bRawData), | 380 reinterpret_cast<PCHAR>(input->data.hid.bRawData), |
| 378 input->data.hid.dwSizeHid); | 381 input->data.hid.dwSizeHid); |
| 379 | 382 |
| 380 scoped_ptr<USAGE_AND_PAGE[]> usages(new USAGE_AND_PAGE[buttons_length]); | 383 std::unique_ptr<USAGE_AND_PAGE[]> usages( |
| 384 new USAGE_AND_PAGE[buttons_length]); |
| 381 status = | 385 status = |
| 382 hidp_get_usages_ex_(HidP_Input, | 386 hidp_get_usages_ex_(HidP_Input, |
| 383 0, | 387 0, |
| 384 usages.get(), | 388 usages.get(), |
| 385 &buttons_length, | 389 &buttons_length, |
| 386 gamepad_info->preparsed_data, | 390 gamepad_info->preparsed_data, |
| 387 reinterpret_cast<PCHAR>(input->data.hid.bRawData), | 391 reinterpret_cast<PCHAR>(input->data.hid.bRawData), |
| 388 input->data.hid.dwSizeHid); | 392 input->data.hid.dwSizeHid); |
| 389 | 393 |
| 390 if (status == HIDP_STATUS_SUCCESS) { | 394 if (status == HIDP_STATUS_SUCCESS) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 438 UINT size = 0; | 442 UINT size = 0; |
| 439 UINT result = GetRawInputData( | 443 UINT result = GetRawInputData( |
| 440 input_handle, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER)); | 444 input_handle, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER)); |
| 441 if (result == static_cast<UINT>(-1)) { | 445 if (result == static_cast<UINT>(-1)) { |
| 442 PLOG(ERROR) << "GetRawInputData() failed"; | 446 PLOG(ERROR) << "GetRawInputData() failed"; |
| 443 return 0; | 447 return 0; |
| 444 } | 448 } |
| 445 DCHECK_EQ(0u, result); | 449 DCHECK_EQ(0u, result); |
| 446 | 450 |
| 447 // Retrieve the input record. | 451 // Retrieve the input record. |
| 448 scoped_ptr<uint8_t[]> buffer(new uint8_t[size]); | 452 std::unique_ptr<uint8_t[]> buffer(new uint8_t[size]); |
| 449 RAWINPUT* input = reinterpret_cast<RAWINPUT*>(buffer.get()); | 453 RAWINPUT* input = reinterpret_cast<RAWINPUT*>(buffer.get()); |
| 450 result = GetRawInputData( | 454 result = GetRawInputData( |
| 451 input_handle, RID_INPUT, buffer.get(), &size, sizeof(RAWINPUTHEADER)); | 455 input_handle, RID_INPUT, buffer.get(), &size, sizeof(RAWINPUTHEADER)); |
| 452 if (result == static_cast<UINT>(-1)) { | 456 if (result == static_cast<UINT>(-1)) { |
| 453 PLOG(ERROR) << "GetRawInputData() failed"; | 457 PLOG(ERROR) << "GetRawInputData() failed"; |
| 454 return 0; | 458 return 0; |
| 455 } | 459 } |
| 456 DCHECK_EQ(size, result); | 460 DCHECK_EQ(size, result); |
| 457 | 461 |
| 458 // Notify the observer about events generated locally. | 462 // Notify the observer about events generated locally. |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 516 return false; | 520 return false; |
| 517 hidd_get_product_string_ = reinterpret_cast<HidDGetStringFunc>( | 521 hidd_get_product_string_ = reinterpret_cast<HidDGetStringFunc>( |
| 518 hid_dll_.GetFunctionPointer("HidD_GetProductString")); | 522 hid_dll_.GetFunctionPointer("HidD_GetProductString")); |
| 519 if (!hidd_get_product_string_) | 523 if (!hidd_get_product_string_) |
| 520 return false; | 524 return false; |
| 521 | 525 |
| 522 return true; | 526 return true; |
| 523 } | 527 } |
| 524 | 528 |
| 525 } // namespace content | 529 } // namespace content |
| OLD | NEW |