| 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 "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/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" | |
| 13 | 11 |
| 14 namespace content { | 12 namespace device { |
| 15 | 13 |
| 16 using namespace blink; | 14 using namespace blink; |
| 17 | 15 |
| 18 namespace { | 16 namespace { |
| 19 | 17 |
| 20 float NormalizeAxis(long value, long min, long max) { | 18 float NormalizeAxis(long value, long min, long max) { |
| 21 return (2.f * (value - min) / static_cast<float>(max - min)) - 1.f; | 19 return (2.f * (value - min) / static_cast<float>(max - min)) - 1.f; |
| 22 } | 20 } |
| 23 | 21 |
| 24 unsigned long GetBitmask(unsigned short bits) { | 22 unsigned long GetBitmask(unsigned short bits) { |
| 25 return (1 << bits) - 1; | 23 return (1 << bits) - 1; |
| 26 } | 24 } |
| 27 | 25 |
| 28 // From the HID Usage Tables specification. | 26 // From the HID Usage Tables specification. |
| 29 USHORT DeviceUsages[] = { | 27 USHORT DeviceUsages[] = { |
| 30 0x04, // Joysticks | 28 0x04, // Joysticks |
| 31 0x05, // Gamepads | 29 0x05, // Gamepads |
| 32 0x08, // Multi Axis | 30 0x08, // Multi Axis |
| 33 }; | 31 }; |
| 34 | 32 |
| 35 const uint32_t kAxisMinimumUsageNumber = 0x30; | 33 const uint32_t kAxisMinimumUsageNumber = 0x30; |
| 36 const uint32_t kGameControlsUsagePage = 0x05; | 34 const uint32_t kGameControlsUsagePage = 0x05; |
| 37 const uint32_t kButtonUsagePage = 0x09; | 35 const uint32_t kButtonUsagePage = 0x09; |
| 38 | 36 |
| 39 } // namespace | 37 } // namespace |
| 40 | 38 |
| 41 RawGamepadInfo::RawGamepadInfo() { | 39 RawGamepadInfo::RawGamepadInfo() {} |
| 42 } | |
| 43 | 40 |
| 44 RawGamepadInfo::~RawGamepadInfo() { | 41 RawGamepadInfo::~RawGamepadInfo() {} |
| 45 } | |
| 46 | 42 |
| 47 RawInputDataFetcher::RawInputDataFetcher() | 43 RawInputDataFetcher::RawInputDataFetcher() |
| 48 : hid_dll_(base::FilePath(FILE_PATH_LITERAL("hid.dll"))), | 44 : hid_dll_(base::FilePath(FILE_PATH_LITERAL("hid.dll"))), |
| 49 rawinput_available_(GetHidDllFunctions()), | 45 rawinput_available_(GetHidDllFunctions()), |
| 50 filter_xinput_(true), | 46 filter_xinput_(true), |
| 51 events_monitored_(false) { | 47 events_monitored_(false) {} |
| 52 } | |
| 53 | 48 |
| 54 RawInputDataFetcher::~RawInputDataFetcher() { | 49 RawInputDataFetcher::~RawInputDataFetcher() { |
| 55 ClearControllers(); | 50 ClearControllers(); |
| 56 DCHECK(!window_); | 51 DCHECK(!window_); |
| 57 DCHECK(!events_monitored_); | 52 DCHECK(!events_monitored_); |
| 58 } | 53 } |
| 59 | 54 |
| 60 void RawInputDataFetcher::WillDestroyCurrentMessageLoop() { | 55 void RawInputDataFetcher::WillDestroyCurrentMessageLoop() { |
| 61 StopMonitor(); | 56 StopMonitor(); |
| 62 } | 57 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 84 PLOG(ERROR) << "Failed to create the raw input window"; | 79 PLOG(ERROR) << "Failed to create the raw input window"; |
| 85 window_.reset(); | 80 window_.reset(); |
| 86 return; | 81 return; |
| 87 } | 82 } |
| 88 } | 83 } |
| 89 | 84 |
| 90 // Register to receive raw HID input. | 85 // Register to receive raw HID input. |
| 91 std::unique_ptr<RAWINPUTDEVICE[]> devices( | 86 std::unique_ptr<RAWINPUTDEVICE[]> devices( |
| 92 GetRawInputDevices(RIDEV_INPUTSINK)); | 87 GetRawInputDevices(RIDEV_INPUTSINK)); |
| 93 if (!RegisterRawInputDevices(devices.get(), arraysize(DeviceUsages), | 88 if (!RegisterRawInputDevices(devices.get(), arraysize(DeviceUsages), |
| 94 sizeof(RAWINPUTDEVICE))) { | 89 sizeof(RAWINPUTDEVICE))) { |
| 95 PLOG(ERROR) << "RegisterRawInputDevices() failed for RIDEV_INPUTSINK"; | 90 PLOG(ERROR) << "RegisterRawInputDevices() failed for RIDEV_INPUTSINK"; |
| 96 window_.reset(); | 91 window_.reset(); |
| 97 return; | 92 return; |
| 98 } | 93 } |
| 99 | 94 |
| 100 // Start observing message loop destruction if we start monitoring the first | 95 // Start observing message loop destruction if we start monitoring the first |
| 101 // event. | 96 // event. |
| 102 if (!events_monitored_) | 97 if (!events_monitored_) |
| 103 base::MessageLoop::current()->AddDestructionObserver(this); | 98 base::MessageLoop::current()->AddDestructionObserver(this); |
| 104 | 99 |
| 105 events_monitored_ = true; | 100 events_monitored_ = true; |
| 106 } | 101 } |
| 107 | 102 |
| 108 void RawInputDataFetcher::StopMonitor() { | 103 void RawInputDataFetcher::StopMonitor() { |
| 109 if (!rawinput_available_ || !events_monitored_) | 104 if (!rawinput_available_ || !events_monitored_) |
| 110 return; | 105 return; |
| 111 | 106 |
| 112 // Stop receiving raw input. | 107 // Stop receiving raw input. |
| 113 DCHECK(window_); | 108 DCHECK(window_); |
| 114 std::unique_ptr<RAWINPUTDEVICE[]> devices(GetRawInputDevices(RIDEV_REMOVE)); | 109 std::unique_ptr<RAWINPUTDEVICE[]> devices(GetRawInputDevices(RIDEV_REMOVE)); |
| 115 | 110 |
| 116 if (!RegisterRawInputDevices(devices.get(), arraysize(DeviceUsages), | 111 if (!RegisterRawInputDevices(devices.get(), arraysize(DeviceUsages), |
| 117 sizeof(RAWINPUTDEVICE))) { | 112 sizeof(RAWINPUTDEVICE))) { |
| 118 PLOG(INFO) << "RegisterRawInputDevices() failed for RIDEV_REMOVE"; | 113 PLOG(INFO) << "RegisterRawInputDevices() failed for RIDEV_REMOVE"; |
| 119 } | 114 } |
| 120 | 115 |
| 121 events_monitored_ = false; | 116 events_monitored_ = false; |
| 122 window_.reset(); | 117 window_.reset(); |
| 123 | 118 |
| 124 // Stop observing message loop destruction if no event is being monitored. | 119 // Stop observing message loop destruction if no event is being monitored. |
| 125 base::MessageLoop::current()->RemoveDestructionObserver(this); | 120 base::MessageLoop::current()->RemoveDestructionObserver(this); |
| 126 } | 121 } |
| 127 | 122 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 142 UINT result = GetRawInputDeviceList(NULL, &count, sizeof(RAWINPUTDEVICELIST)); | 137 UINT result = GetRawInputDeviceList(NULL, &count, sizeof(RAWINPUTDEVICELIST)); |
| 143 if (result == static_cast<UINT>(-1)) { | 138 if (result == static_cast<UINT>(-1)) { |
| 144 PLOG(ERROR) << "GetRawInputDeviceList() failed"; | 139 PLOG(ERROR) << "GetRawInputDeviceList() failed"; |
| 145 return valid_controllers; | 140 return valid_controllers; |
| 146 } | 141 } |
| 147 DCHECK_EQ(0u, result); | 142 DCHECK_EQ(0u, result); |
| 148 | 143 |
| 149 std::unique_ptr<RAWINPUTDEVICELIST[]> device_list( | 144 std::unique_ptr<RAWINPUTDEVICELIST[]> device_list( |
| 150 new RAWINPUTDEVICELIST[count]); | 145 new RAWINPUTDEVICELIST[count]); |
| 151 result = GetRawInputDeviceList(device_list.get(), &count, | 146 result = GetRawInputDeviceList(device_list.get(), &count, |
| 152 sizeof(RAWINPUTDEVICELIST)); | 147 sizeof(RAWINPUTDEVICELIST)); |
| 153 if (result == static_cast<UINT>(-1)) { | 148 if (result == static_cast<UINT>(-1)) { |
| 154 PLOG(ERROR) << "GetRawInputDeviceList() failed"; | 149 PLOG(ERROR) << "GetRawInputDeviceList() failed"; |
| 155 return valid_controllers; | 150 return valid_controllers; |
| 156 } | 151 } |
| 157 DCHECK_EQ(count, result); | 152 DCHECK_EQ(count, result); |
| 158 | 153 |
| 159 for (UINT i = 0; i < count; ++i) { | 154 for (UINT i = 0; i < count; ++i) { |
| 160 if (device_list[i].dwType == RIM_TYPEHID) { | 155 if (device_list[i].dwType == RIM_TYPEHID) { |
| 161 HANDLE device_handle = device_list[i].hDevice; | 156 HANDLE device_handle = device_list[i].hDevice; |
| 162 RawGamepadInfo* gamepad_info = ParseGamepadInfo(device_handle); | 157 RawGamepadInfo* gamepad_info = ParseGamepadInfo(device_handle); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 178 } | 173 } |
| 179 | 174 |
| 180 RawGamepadInfo* RawInputDataFetcher::ParseGamepadInfo(HANDLE hDevice) { | 175 RawGamepadInfo* RawInputDataFetcher::ParseGamepadInfo(HANDLE hDevice) { |
| 181 UINT size = 0; | 176 UINT size = 0; |
| 182 | 177 |
| 183 // Do we already have this device in the map? | 178 // Do we already have this device in the map? |
| 184 if (GetGamepadInfo(hDevice)) | 179 if (GetGamepadInfo(hDevice)) |
| 185 return NULL; | 180 return NULL; |
| 186 | 181 |
| 187 // Query basic device info. | 182 // Query basic device info. |
| 188 UINT result = GetRawInputDeviceInfo(hDevice, RIDI_DEVICEINFO, | 183 UINT result = GetRawInputDeviceInfo(hDevice, RIDI_DEVICEINFO, NULL, &size); |
| 189 NULL, &size); | |
| 190 if (result == static_cast<UINT>(-1)) { | 184 if (result == static_cast<UINT>(-1)) { |
| 191 PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; | 185 PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; |
| 192 return NULL; | 186 return NULL; |
| 193 } | 187 } |
| 194 DCHECK_EQ(0u, result); | 188 DCHECK_EQ(0u, result); |
| 195 | 189 |
| 196 std::unique_ptr<uint8_t[]> di_buffer(new uint8_t[size]); | 190 std::unique_ptr<uint8_t[]> di_buffer(new uint8_t[size]); |
| 197 RID_DEVICE_INFO* device_info = | 191 RID_DEVICE_INFO* device_info = |
| 198 reinterpret_cast<RID_DEVICE_INFO*>(di_buffer.get()); | 192 reinterpret_cast<RID_DEVICE_INFO*>(di_buffer.get()); |
| 199 result = GetRawInputDeviceInfo(hDevice, RIDI_DEVICEINFO, | 193 result = |
| 200 di_buffer.get(), &size); | 194 GetRawInputDeviceInfo(hDevice, RIDI_DEVICEINFO, di_buffer.get(), &size); |
| 201 if (result == static_cast<UINT>(-1)) { | 195 if (result == static_cast<UINT>(-1)) { |
| 202 PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; | 196 PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; |
| 203 return NULL; | 197 return NULL; |
| 204 } | 198 } |
| 205 DCHECK_EQ(size, result); | 199 DCHECK_EQ(size, result); |
| 206 | 200 |
| 207 // Make sure this device is of a type that we want to observe. | 201 // Make sure this device is of a type that we want to observe. |
| 208 bool valid_type = false; | 202 bool valid_type = false; |
| 209 for (USHORT device_usage : DeviceUsages) { | 203 for (USHORT device_usage : DeviceUsages) { |
| 210 if (device_info->hid.usUsage == device_usage) { | 204 if (device_info->hid.usUsage == device_usage) { |
| 211 valid_type = true; | 205 valid_type = true; |
| 212 break; | 206 break; |
| 213 } | 207 } |
| 214 } | 208 } |
| 215 | 209 |
| 216 if (!valid_type) | 210 if (!valid_type) |
| 217 return NULL; | 211 return NULL; |
| 218 | 212 |
| 219 std::unique_ptr<RawGamepadInfo> gamepad_info(new RawGamepadInfo); | 213 std::unique_ptr<RawGamepadInfo> gamepad_info(new RawGamepadInfo); |
| 220 gamepad_info->handle = hDevice; | 214 gamepad_info->handle = hDevice; |
| 221 gamepad_info->report_id = 0; | 215 gamepad_info->report_id = 0; |
| 222 gamepad_info->vendor_id = device_info->hid.dwVendorId; | 216 gamepad_info->vendor_id = device_info->hid.dwVendorId; |
| 223 gamepad_info->product_id = device_info->hid.dwProductId; | 217 gamepad_info->product_id = device_info->hid.dwProductId; |
| 224 gamepad_info->buttons_length = 0; | 218 gamepad_info->buttons_length = 0; |
| 225 ZeroMemory(gamepad_info->buttons, sizeof(gamepad_info->buttons)); | 219 ZeroMemory(gamepad_info->buttons, sizeof(gamepad_info->buttons)); |
| 226 gamepad_info->axes_length = 0; | 220 gamepad_info->axes_length = 0; |
| 227 ZeroMemory(gamepad_info->axes, sizeof(gamepad_info->axes)); | 221 ZeroMemory(gamepad_info->axes, sizeof(gamepad_info->axes)); |
| 228 | 222 |
| 229 // Query device identifier | 223 // Query device identifier |
| 230 result = GetRawInputDeviceInfo(hDevice, RIDI_DEVICENAME, | 224 result = GetRawInputDeviceInfo(hDevice, RIDI_DEVICENAME, NULL, &size); |
| 231 NULL, &size); | |
| 232 if (result == static_cast<UINT>(-1)) { | 225 if (result == static_cast<UINT>(-1)) { |
| 233 PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; | 226 PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; |
| 234 return NULL; | 227 return NULL; |
| 235 } | 228 } |
| 236 DCHECK_EQ(0u, result); | 229 DCHECK_EQ(0u, result); |
| 237 | 230 |
| 238 std::unique_ptr<wchar_t[]> name_buffer(new wchar_t[size]); | 231 std::unique_ptr<wchar_t[]> name_buffer(new wchar_t[size]); |
| 239 result = GetRawInputDeviceInfo(hDevice, RIDI_DEVICENAME, | 232 result = |
| 240 name_buffer.get(), &size); | 233 GetRawInputDeviceInfo(hDevice, RIDI_DEVICENAME, name_buffer.get(), &size); |
| 241 if (result == static_cast<UINT>(-1)) { | 234 if (result == static_cast<UINT>(-1)) { |
| 242 PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; | 235 PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; |
| 243 return NULL; | 236 return NULL; |
| 244 } | 237 } |
| 245 DCHECK_EQ(size, result); | 238 DCHECK_EQ(size, result); |
| 246 | 239 |
| 247 // The presence of "IG_" in the device name indicates that this is an XInput | 240 // The presence of "IG_" in the device name indicates that this is an XInput |
| 248 // Gamepad. Skip enumerating these devices and let the XInput path handle it. | 241 // Gamepad. Skip enumerating these devices and let the XInput path handle it. |
| 249 // http://msdn.microsoft.com/en-us/library/windows/desktop/ee417014.aspx | 242 // http://msdn.microsoft.com/en-us/library/windows/desktop/ee417014.aspx |
| 250 if (filter_xinput_ && wcsstr( name_buffer.get(), L"IG_" ) ) | 243 if (filter_xinput_ && wcsstr(name_buffer.get(), L"IG_")) |
| 251 return NULL; | 244 return NULL; |
| 252 | 245 |
| 253 // Get a friendly device name | 246 // Get a friendly device name |
| 254 BOOLEAN got_product_string = FALSE; | 247 BOOLEAN got_product_string = FALSE; |
| 255 HANDLE hid_handle = CreateFile(name_buffer.get(), GENERIC_READ|GENERIC_WRITE, | 248 HANDLE hid_handle = CreateFile( |
| 256 FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL); | 249 name_buffer.get(), GENERIC_READ | GENERIC_WRITE, |
| 250 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL); |
| 257 if (hid_handle) { | 251 if (hid_handle) { |
| 258 got_product_string = hidd_get_product_string_(hid_handle, gamepad_info->id, | 252 got_product_string = hidd_get_product_string_(hid_handle, gamepad_info->id, |
| 259 sizeof(gamepad_info->id)); | 253 sizeof(gamepad_info->id)); |
| 260 CloseHandle(hid_handle); | 254 CloseHandle(hid_handle); |
| 261 } | 255 } |
| 262 | 256 |
| 263 if (!got_product_string) | 257 if (!got_product_string) |
| 264 swprintf(gamepad_info->id, WebGamepad::idLengthCap, L"Unknown Gamepad"); | 258 swprintf(gamepad_info->id, WebGamepad::idLengthCap, L"Unknown Gamepad"); |
| 265 | 259 |
| 266 // Query device capabilities. | 260 // Query device capabilities. |
| 267 result = GetRawInputDeviceInfo(hDevice, RIDI_PREPARSEDDATA, | 261 result = GetRawInputDeviceInfo(hDevice, RIDI_PREPARSEDDATA, NULL, &size); |
| 268 NULL, &size); | |
| 269 if (result == static_cast<UINT>(-1)) { | 262 if (result == static_cast<UINT>(-1)) { |
| 270 PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; | 263 PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; |
| 271 return NULL; | 264 return NULL; |
| 272 } | 265 } |
| 273 DCHECK_EQ(0u, result); | 266 DCHECK_EQ(0u, result); |
| 274 | 267 |
| 275 gamepad_info->ppd_buffer.reset(new uint8_t[size]); | 268 gamepad_info->ppd_buffer.reset(new uint8_t[size]); |
| 276 gamepad_info->preparsed_data = | 269 gamepad_info->preparsed_data = |
| 277 reinterpret_cast<PHIDP_PREPARSED_DATA>(gamepad_info->ppd_buffer.get()); | 270 reinterpret_cast<PHIDP_PREPARSED_DATA>(gamepad_info->ppd_buffer.get()); |
| 278 result = GetRawInputDeviceInfo(hDevice, RIDI_PREPARSEDDATA, | 271 result = GetRawInputDeviceInfo(hDevice, RIDI_PREPARSEDDATA, |
| 279 gamepad_info->ppd_buffer.get(), &size); | 272 gamepad_info->ppd_buffer.get(), &size); |
| 280 if (result == static_cast<UINT>(-1)) { | 273 if (result == static_cast<UINT>(-1)) { |
| 281 PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; | 274 PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; |
| 282 return NULL; | 275 return NULL; |
| 283 } | 276 } |
| 284 DCHECK_EQ(size, result); | 277 DCHECK_EQ(size, result); |
| 285 | 278 |
| 286 HIDP_CAPS caps; | 279 HIDP_CAPS caps; |
| 287 NTSTATUS status = hidp_get_caps_(gamepad_info->preparsed_data, &caps); | 280 NTSTATUS status = hidp_get_caps_(gamepad_info->preparsed_data, &caps); |
| 288 DCHECK_EQ(HIDP_STATUS_SUCCESS, status); | 281 DCHECK_EQ(HIDP_STATUS_SUCCESS, status); |
| 289 | 282 |
| 290 // Query button information. | 283 // Query button information. |
| 291 USHORT count = caps.NumberInputButtonCaps; | 284 USHORT count = caps.NumberInputButtonCaps; |
| 292 if (count > 0) { | 285 if (count > 0) { |
| 293 std::unique_ptr<HIDP_BUTTON_CAPS[]> button_caps( | 286 std::unique_ptr<HIDP_BUTTON_CAPS[]> button_caps( |
| 294 new HIDP_BUTTON_CAPS[count]); | 287 new HIDP_BUTTON_CAPS[count]); |
| 295 status = hidp_get_button_caps_( | 288 status = hidp_get_button_caps_(HidP_Input, button_caps.get(), &count, |
| 296 HidP_Input, button_caps.get(), &count, gamepad_info->preparsed_data); | 289 gamepad_info->preparsed_data); |
| 297 DCHECK_EQ(HIDP_STATUS_SUCCESS, status); | 290 DCHECK_EQ(HIDP_STATUS_SUCCESS, status); |
| 298 | 291 |
| 299 for (uint32_t i = 0; i < count; ++i) { | 292 for (uint32_t i = 0; i < count; ++i) { |
| 300 if (button_caps[i].Range.UsageMin <= WebGamepad::buttonsLengthCap && | 293 if (button_caps[i].Range.UsageMin <= WebGamepad::buttonsLengthCap && |
| 301 button_caps[i].UsagePage == kButtonUsagePage) { | 294 button_caps[i].UsagePage == kButtonUsagePage) { |
| 302 uint32_t max_index = | 295 uint32_t max_index = |
| 303 std::min(WebGamepad::buttonsLengthCap, | 296 std::min(WebGamepad::buttonsLengthCap, |
| 304 static_cast<size_t>(button_caps[i].Range.UsageMax)); | 297 static_cast<size_t>(button_caps[i].Range.UsageMax)); |
| 305 gamepad_info->buttons_length = std::max( | 298 gamepad_info->buttons_length = |
| 306 gamepad_info->buttons_length, max_index); | 299 std::max(gamepad_info->buttons_length, max_index); |
| 307 } | 300 } |
| 308 } | 301 } |
| 309 } | 302 } |
| 310 | 303 |
| 311 // Query axis information. | 304 // Query axis information. |
| 312 count = caps.NumberInputValueCaps; | 305 count = caps.NumberInputValueCaps; |
| 313 std::unique_ptr<HIDP_VALUE_CAPS[]> axes_caps(new HIDP_VALUE_CAPS[count]); | 306 std::unique_ptr<HIDP_VALUE_CAPS[]> axes_caps(new HIDP_VALUE_CAPS[count]); |
| 314 status = hidp_get_value_caps_(HidP_Input, axes_caps.get(), &count, | 307 status = hidp_get_value_caps_(HidP_Input, axes_caps.get(), &count, |
| 315 gamepad_info->preparsed_data); | 308 gamepad_info->preparsed_data); |
| 316 | 309 |
| 317 bool mapped_all_axes = true; | 310 bool mapped_all_axes = true; |
| 318 | 311 |
| 319 for (UINT i = 0; i < count; i++) { | 312 for (UINT i = 0; i < count; i++) { |
| 320 uint32_t axis_index = axes_caps[i].Range.UsageMin - kAxisMinimumUsageNumber; | 313 uint32_t axis_index = axes_caps[i].Range.UsageMin - kAxisMinimumUsageNumber; |
| 321 if (axis_index < WebGamepad::axesLengthCap) { | 314 if (axis_index < WebGamepad::axesLengthCap) { |
| 322 gamepad_info->axes[axis_index].caps = axes_caps[i]; | 315 gamepad_info->axes[axis_index].caps = axes_caps[i]; |
| 323 gamepad_info->axes[axis_index].value = 0; | 316 gamepad_info->axes[axis_index].value = 0; |
| 324 gamepad_info->axes[axis_index].active = true; | 317 gamepad_info->axes[axis_index].active = true; |
| 325 gamepad_info->axes[axis_index].bitmask = GetBitmask(axes_caps[i].BitSize); | 318 gamepad_info->axes[axis_index].bitmask = GetBitmask(axes_caps[i].BitSize); |
| 326 gamepad_info->axes_length = | 319 gamepad_info->axes_length = |
| 327 std::max(gamepad_info->axes_length, axis_index + 1); | 320 std::max(gamepad_info->axes_length, axis_index + 1); |
| 328 } else { | 321 } else { |
| 329 mapped_all_axes = false; | 322 mapped_all_axes = false; |
| 330 } | 323 } |
| 331 } | 324 } |
| 332 | 325 |
| 333 if (!mapped_all_axes) { | 326 if (!mapped_all_axes) { |
| 334 // For axes who's usage puts them outside the standard axesLengthCap range. | 327 // For axes who's usage puts them outside the standard axesLengthCap range. |
| 335 uint32_t next_index = 0; | 328 uint32_t next_index = 0; |
| 336 for (UINT i = 0; i < count; i++) { | 329 for (UINT i = 0; i < count; i++) { |
| 337 uint32_t usage = axes_caps[i].Range.UsageMin - kAxisMinimumUsageNumber; | 330 uint32_t usage = axes_caps[i].Range.UsageMin - kAxisMinimumUsageNumber; |
| 338 if (usage >= WebGamepad::axesLengthCap && | 331 if (usage >= WebGamepad::axesLengthCap && |
| 339 axes_caps[i].UsagePage <= kGameControlsUsagePage) { | 332 axes_caps[i].UsagePage <= kGameControlsUsagePage) { |
| 340 | |
| 341 for (; next_index < WebGamepad::axesLengthCap; ++next_index) { | 333 for (; next_index < WebGamepad::axesLengthCap; ++next_index) { |
| 342 if (!gamepad_info->axes[next_index].active) | 334 if (!gamepad_info->axes[next_index].active) |
| 343 break; | 335 break; |
| 344 } | 336 } |
| 345 if (next_index < WebGamepad::axesLengthCap) { | 337 if (next_index < WebGamepad::axesLengthCap) { |
| 346 gamepad_info->axes[next_index].caps = axes_caps[i]; | 338 gamepad_info->axes[next_index].caps = axes_caps[i]; |
| 347 gamepad_info->axes[next_index].value = 0; | 339 gamepad_info->axes[next_index].value = 0; |
| 348 gamepad_info->axes[next_index].active = true; | 340 gamepad_info->axes[next_index].active = true; |
| 349 gamepad_info->axes[next_index].bitmask = GetBitmask( | 341 gamepad_info->axes[next_index].bitmask = |
| 350 axes_caps[i].BitSize); | 342 GetBitmask(axes_caps[i].BitSize); |
| 351 gamepad_info->axes_length = | 343 gamepad_info->axes_length = |
| 352 std::max(gamepad_info->axes_length, next_index + 1); | 344 std::max(gamepad_info->axes_length, next_index + 1); |
| 353 } | 345 } |
| 354 } | 346 } |
| 355 | 347 |
| 356 if (next_index >= WebGamepad::axesLengthCap) | 348 if (next_index >= WebGamepad::axesLengthCap) |
| 357 break; | 349 break; |
| 358 } | 350 } |
| 359 } | 351 } |
| 360 | 352 |
| 361 return gamepad_info.release(); | 353 return gamepad_info.release(); |
| 362 } | 354 } |
| 363 | 355 |
| 364 void RawInputDataFetcher::UpdateGamepad( | 356 void RawInputDataFetcher::UpdateGamepad(RAWINPUT* input, |
| 365 RAWINPUT* input, | 357 RawGamepadInfo* gamepad_info) { |
| 366 RawGamepadInfo* gamepad_info) { | |
| 367 NTSTATUS status; | 358 NTSTATUS status; |
| 368 | 359 |
| 369 gamepad_info->report_id++; | 360 gamepad_info->report_id++; |
| 370 | 361 |
| 371 // Query button state. | 362 // Query button state. |
| 372 if (gamepad_info->buttons_length) { | 363 if (gamepad_info->buttons_length) { |
| 373 // Clear the button state | 364 // Clear the button state |
| 374 ZeroMemory(gamepad_info->buttons, sizeof(gamepad_info->buttons)); | 365 ZeroMemory(gamepad_info->buttons, sizeof(gamepad_info->buttons)); |
| 375 ULONG buttons_length = 0; | 366 ULONG buttons_length = 0; |
| 376 | 367 |
| 377 hidp_get_usages_ex_(HidP_Input, | 368 hidp_get_usages_ex_(HidP_Input, 0, NULL, &buttons_length, |
| 378 0, | |
| 379 NULL, | |
| 380 &buttons_length, | |
| 381 gamepad_info->preparsed_data, | 369 gamepad_info->preparsed_data, |
| 382 reinterpret_cast<PCHAR>(input->data.hid.bRawData), | 370 reinterpret_cast<PCHAR>(input->data.hid.bRawData), |
| 383 input->data.hid.dwSizeHid); | 371 input->data.hid.dwSizeHid); |
| 384 | 372 |
| 385 std::unique_ptr<USAGE_AND_PAGE[]> usages( | 373 std::unique_ptr<USAGE_AND_PAGE[]> usages( |
| 386 new USAGE_AND_PAGE[buttons_length]); | 374 new USAGE_AND_PAGE[buttons_length]); |
| 387 status = | 375 status = |
| 388 hidp_get_usages_ex_(HidP_Input, | 376 hidp_get_usages_ex_(HidP_Input, 0, usages.get(), &buttons_length, |
| 389 0, | |
| 390 usages.get(), | |
| 391 &buttons_length, | |
| 392 gamepad_info->preparsed_data, | 377 gamepad_info->preparsed_data, |
| 393 reinterpret_cast<PCHAR>(input->data.hid.bRawData), | 378 reinterpret_cast<PCHAR>(input->data.hid.bRawData), |
| 394 input->data.hid.dwSizeHid); | 379 input->data.hid.dwSizeHid); |
| 395 | 380 |
| 396 if (status == HIDP_STATUS_SUCCESS) { | 381 if (status == HIDP_STATUS_SUCCESS) { |
| 397 // Set each reported button to true. | 382 // Set each reported button to true. |
| 398 for (uint32_t j = 0; j < buttons_length; j++) { | 383 for (uint32_t j = 0; j < buttons_length; j++) { |
| 399 int32_t button_index = usages[j].Usage - 1; | 384 int32_t button_index = usages[j].Usage - 1; |
| 400 if (usages[j].UsagePage == kButtonUsagePage && | 385 if (usages[j].UsagePage == kButtonUsagePage && button_index >= 0 && |
| 401 button_index >= 0 && | |
| 402 button_index < | 386 button_index < |
| 403 static_cast<int>(blink::WebGamepad::buttonsLengthCap)) { | 387 static_cast<int>(blink::WebGamepad::buttonsLengthCap)) { |
| 404 gamepad_info->buttons[button_index] = true; | 388 gamepad_info->buttons[button_index] = true; |
| 405 } | 389 } |
| 406 } | 390 } |
| 407 } | 391 } |
| 408 } | 392 } |
| 409 | 393 |
| 410 // Query axis state. | 394 // Query axis state. |
| 411 ULONG axis_value = 0; | 395 ULONG axis_value = 0; |
| 412 LONG scaled_axis_value = 0; | 396 LONG scaled_axis_value = 0; |
| 413 for (uint32_t i = 0; i < gamepad_info->axes_length; i++) { | 397 for (uint32_t i = 0; i < gamepad_info->axes_length; i++) { |
| 414 RawGamepadAxis* axis = &gamepad_info->axes[i]; | 398 RawGamepadAxis* axis = &gamepad_info->axes[i]; |
| 415 | 399 |
| 416 // If the min is < 0 we have to query the scaled value, otherwise we need | 400 // If the min is < 0 we have to query the scaled value, otherwise we need |
| 417 // the normal unscaled value. | 401 // the normal unscaled value. |
| 418 if (axis->caps.LogicalMin < 0) { | 402 if (axis->caps.LogicalMin < 0) { |
| 419 status = hidp_get_scaled_usage_value_(HidP_Input, axis->caps.UsagePage, 0, | 403 status = hidp_get_scaled_usage_value_( |
| 420 axis->caps.Range.UsageMin, &scaled_axis_value, | 404 HidP_Input, axis->caps.UsagePage, 0, axis->caps.Range.UsageMin, |
| 421 gamepad_info->preparsed_data, | 405 &scaled_axis_value, gamepad_info->preparsed_data, |
| 422 reinterpret_cast<PCHAR>(input->data.hid.bRawData), | 406 reinterpret_cast<PCHAR>(input->data.hid.bRawData), |
| 423 input->data.hid.dwSizeHid); | 407 input->data.hid.dwSizeHid); |
| 424 if (status == HIDP_STATUS_SUCCESS) { | 408 if (status == HIDP_STATUS_SUCCESS) { |
| 425 axis->value = NormalizeAxis(scaled_axis_value, | 409 axis->value = NormalizeAxis(scaled_axis_value, axis->caps.PhysicalMin, |
| 426 axis->caps.PhysicalMin, axis->caps.PhysicalMax); | 410 axis->caps.PhysicalMax); |
| 427 } | 411 } |
| 428 } else { | 412 } else { |
| 429 status = hidp_get_usage_value_(HidP_Input, axis->caps.UsagePage, 0, | 413 status = hidp_get_usage_value_( |
| 430 axis->caps.Range.UsageMin, &axis_value, | 414 HidP_Input, axis->caps.UsagePage, 0, axis->caps.Range.UsageMin, |
| 431 gamepad_info->preparsed_data, | 415 &axis_value, gamepad_info->preparsed_data, |
| 432 reinterpret_cast<PCHAR>(input->data.hid.bRawData), | 416 reinterpret_cast<PCHAR>(input->data.hid.bRawData), |
| 433 input->data.hid.dwSizeHid); | 417 input->data.hid.dwSizeHid); |
| 434 if (status == HIDP_STATUS_SUCCESS) { | 418 if (status == HIDP_STATUS_SUCCESS) { |
| 435 axis->value = NormalizeAxis(axis_value & axis->bitmask, | 419 axis->value = NormalizeAxis(axis_value & axis->bitmask, |
| 436 axis->caps.LogicalMin & axis->bitmask, | 420 axis->caps.LogicalMin & axis->bitmask, |
| 437 axis->caps.LogicalMax & axis->bitmask); | 421 axis->caps.LogicalMax & axis->bitmask); |
| 438 } | 422 } |
| 439 } | 423 } |
| 440 } | 424 } |
| 441 } | 425 } |
| 442 | 426 |
| 443 LRESULT RawInputDataFetcher::OnInput(HRAWINPUT input_handle) { | 427 LRESULT RawInputDataFetcher::OnInput(HRAWINPUT input_handle) { |
| 444 // Get the size of the input record. | 428 // Get the size of the input record. |
| 445 UINT size = 0; | 429 UINT size = 0; |
| 446 UINT result = GetRawInputData( | 430 UINT result = GetRawInputData(input_handle, RID_INPUT, NULL, &size, |
| 447 input_handle, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER)); | 431 sizeof(RAWINPUTHEADER)); |
| 448 if (result == static_cast<UINT>(-1)) { | 432 if (result == static_cast<UINT>(-1)) { |
| 449 PLOG(ERROR) << "GetRawInputData() failed"; | 433 PLOG(ERROR) << "GetRawInputData() failed"; |
| 450 return 0; | 434 return 0; |
| 451 } | 435 } |
| 452 DCHECK_EQ(0u, result); | 436 DCHECK_EQ(0u, result); |
| 453 | 437 |
| 454 // Retrieve the input record. | 438 // Retrieve the input record. |
| 455 std::unique_ptr<uint8_t[]> buffer(new uint8_t[size]); | 439 std::unique_ptr<uint8_t[]> buffer(new uint8_t[size]); |
| 456 RAWINPUT* input = reinterpret_cast<RAWINPUT*>(buffer.get()); | 440 RAWINPUT* input = reinterpret_cast<RAWINPUT*>(buffer.get()); |
| 457 result = GetRawInputData( | 441 result = GetRawInputData(input_handle, RID_INPUT, buffer.get(), &size, |
| 458 input_handle, RID_INPUT, buffer.get(), &size, sizeof(RAWINPUTHEADER)); | 442 sizeof(RAWINPUTHEADER)); |
| 459 if (result == static_cast<UINT>(-1)) { | 443 if (result == static_cast<UINT>(-1)) { |
| 460 PLOG(ERROR) << "GetRawInputData() failed"; | 444 PLOG(ERROR) << "GetRawInputData() failed"; |
| 461 return 0; | 445 return 0; |
| 462 } | 446 } |
| 463 DCHECK_EQ(size, result); | 447 DCHECK_EQ(size, result); |
| 464 | 448 |
| 465 // Notify the observer about events generated locally. | 449 // Notify the observer about events generated locally. |
| 466 if (input->header.dwType == RIM_TYPEHID && input->header.hDevice != NULL) { | 450 if (input->header.dwType == RIM_TYPEHID && input->header.hDevice != NULL) { |
| 467 RawGamepadInfo* gamepad = GetGamepadInfo(input->header.hDevice); | 451 RawGamepadInfo* gamepad = GetGamepadInfo(input->header.hDevice); |
| 468 if (gamepad) | 452 if (gamepad) |
| (...skipping 19 matching lines...) Expand all Loading... |
| 488 | 472 |
| 489 bool RawInputDataFetcher::GetHidDllFunctions() { | 473 bool RawInputDataFetcher::GetHidDllFunctions() { |
| 490 hidp_get_caps_ = NULL; | 474 hidp_get_caps_ = NULL; |
| 491 hidp_get_button_caps_ = NULL; | 475 hidp_get_button_caps_ = NULL; |
| 492 hidp_get_value_caps_ = NULL; | 476 hidp_get_value_caps_ = NULL; |
| 493 hidp_get_usages_ex_ = NULL; | 477 hidp_get_usages_ex_ = NULL; |
| 494 hidp_get_usage_value_ = NULL; | 478 hidp_get_usage_value_ = NULL; |
| 495 hidp_get_scaled_usage_value_ = NULL; | 479 hidp_get_scaled_usage_value_ = NULL; |
| 496 hidd_get_product_string_ = NULL; | 480 hidd_get_product_string_ = NULL; |
| 497 | 481 |
| 498 if (!hid_dll_.is_valid()) return false; | 482 if (!hid_dll_.is_valid()) |
| 483 return false; |
| 499 | 484 |
| 500 hidp_get_caps_ = reinterpret_cast<HidPGetCapsFunc>( | 485 hidp_get_caps_ = reinterpret_cast<HidPGetCapsFunc>( |
| 501 hid_dll_.GetFunctionPointer("HidP_GetCaps")); | 486 hid_dll_.GetFunctionPointer("HidP_GetCaps")); |
| 502 if (!hidp_get_caps_) | 487 if (!hidp_get_caps_) |
| 503 return false; | 488 return false; |
| 504 hidp_get_button_caps_ = reinterpret_cast<HidPGetButtonCapsFunc>( | 489 hidp_get_button_caps_ = reinterpret_cast<HidPGetButtonCapsFunc>( |
| 505 hid_dll_.GetFunctionPointer("HidP_GetButtonCaps")); | 490 hid_dll_.GetFunctionPointer("HidP_GetButtonCaps")); |
| 506 if (!hidp_get_button_caps_) | 491 if (!hidp_get_button_caps_) |
| 507 return false; | 492 return false; |
| 508 hidp_get_value_caps_ = reinterpret_cast<HidPGetValueCapsFunc>( | 493 hidp_get_value_caps_ = reinterpret_cast<HidPGetValueCapsFunc>( |
| (...skipping 13 matching lines...) Expand all Loading... |
| 522 if (!hidp_get_scaled_usage_value_) | 507 if (!hidp_get_scaled_usage_value_) |
| 523 return false; | 508 return false; |
| 524 hidd_get_product_string_ = reinterpret_cast<HidDGetStringFunc>( | 509 hidd_get_product_string_ = reinterpret_cast<HidDGetStringFunc>( |
| 525 hid_dll_.GetFunctionPointer("HidD_GetProductString")); | 510 hid_dll_.GetFunctionPointer("HidD_GetProductString")); |
| 526 if (!hidd_get_product_string_) | 511 if (!hidd_get_product_string_) |
| 527 return false; | 512 return false; |
| 528 | 513 |
| 529 return true; | 514 return true; |
| 530 } | 515 } |
| 531 | 516 |
| 532 } // namespace content | 517 } // namespace device |
| OLD | NEW |