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 |