Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(98)

Side by Side Diff: content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm

Issue 1939613003: Fix broken normalization of some HID axes on OSX (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/browser/gamepad/gamepad_platform_data_fetcher_mac.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/gamepad_platform_data_fetcher_mac.h" 5 #include "content/browser/gamepad/gamepad_platform_data_fetcher_mac.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 #include <string.h> 8 #include <string.h>
9 9
10 #include "base/mac/foundation_util.h" 10 #include "base/mac/foundation_util.h"
(...skipping 27 matching lines...) Expand all
38 base::mac::CFToNSCast(CFSTR(kIOHIDDeviceUsagePageKey)), 38 base::mac::CFToNSCast(CFSTR(kIOHIDDeviceUsagePageKey)),
39 [NSNumber numberWithUnsignedInt:usage], 39 [NSNumber numberWithUnsignedInt:usage],
40 base::mac::CFToNSCast(CFSTR(kIOHIDDeviceUsageKey)), 40 base::mac::CFToNSCast(CFSTR(kIOHIDDeviceUsageKey)),
41 nil]; 41 nil];
42 } 42 }
43 43
44 float NormalizeAxis(CFIndex value, CFIndex min, CFIndex max) { 44 float NormalizeAxis(CFIndex value, CFIndex min, CFIndex max) {
45 return (2.f * (value - min) / static_cast<float>(max - min)) - 1.f; 45 return (2.f * (value - min) / static_cast<float>(max - min)) - 1.f;
46 } 46 }
47 47
48 float NormalizeUInt8Axis(uint8_t value, uint8_t min, uint8_t max) {
49 return (2.f * (value - min) / static_cast<float>(max - min)) - 1.f;
50 }
51
52 float NormalizeUInt16Axis(uint16_t value, uint16_t min, uint16_t max) {
53 return (2.f * (value - min) / static_cast<float>(max - min)) - 1.f;
54 }
55
56 float NormalizeUInt32Axis(uint32_t value, uint32_t min, uint32_t max) {
57 return (2.f * (value - min) / static_cast<float>(max - min)) - 1.f;
58 }
59
48 // http://www.usb.org/developers/hidpage 60 // http://www.usb.org/developers/hidpage
49 const uint32_t kGenericDesktopUsagePage = 0x01; 61 const uint32_t kGenericDesktopUsagePage = 0x01;
50 const uint32_t kGameControlsUsagePage = 0x05; 62 const uint32_t kGameControlsUsagePage = 0x05;
51 const uint32_t kButtonUsagePage = 0x09; 63 const uint32_t kButtonUsagePage = 0x09;
52 const uint32_t kJoystickUsageNumber = 0x04; 64 const uint32_t kJoystickUsageNumber = 0x04;
53 const uint32_t kGameUsageNumber = 0x05; 65 const uint32_t kGameUsageNumber = 0x05;
54 const uint32_t kMultiAxisUsageNumber = 0x08; 66 const uint32_t kMultiAxisUsageNumber = 0x08;
55 const uint32_t kAxisMinimumUsageNumber = 0x30; 67 const uint32_t kAxisMinimumUsageNumber = 0x30;
56 68
57 } // namespace 69 } // namespace
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 usage_page == kButtonUsagePage) { 210 usage_page == kButtonUsagePage) {
199 uint32_t button_index = usage - 1; 211 uint32_t button_index = usage - 1;
200 if (button_index < WebGamepad::buttonsLengthCap) { 212 if (button_index < WebGamepad::buttonsLengthCap) {
201 associated.hid.button_elements[button_index] = element; 213 associated.hid.button_elements[button_index] = element;
202 pad.buttonsLength = std::max(pad.buttonsLength, button_index + 1); 214 pad.buttonsLength = std::max(pad.buttonsLength, button_index + 1);
203 } 215 }
204 } 216 }
205 else if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Misc) { 217 else if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Misc) {
206 uint32_t axis_index = usage - kAxisMinimumUsageNumber; 218 uint32_t axis_index = usage - kAxisMinimumUsageNumber;
207 if (axis_index < WebGamepad::axesLengthCap) { 219 if (axis_index < WebGamepad::axesLengthCap) {
208 associated.hid.axis_minimums[axis_index] =
209 IOHIDElementGetLogicalMin(element);
210 associated.hid.axis_maximums[axis_index] =
211 IOHIDElementGetLogicalMax(element);
212 associated.hid.axis_elements[axis_index] = element; 220 associated.hid.axis_elements[axis_index] = element;
213 pad.axesLength = std::max(pad.axesLength, axis_index + 1); 221 pad.axesLength = std::max(pad.axesLength, axis_index + 1);
214 } else { 222 } else {
215 mapped_all_axes = false; 223 mapped_all_axes = false;
216 } 224 }
217 } 225 }
218 } 226 }
219 227
220 if (!mapped_all_axes) { 228 if (!mapped_all_axes) {
221 // For axes who's usage puts them outside the standard axesLengthCap range. 229 // For axes who's usage puts them outside the standard axesLengthCap range.
222 uint32_t next_index = 0; 230 uint32_t next_index = 0;
223 for (id elem in elements) { 231 for (id elem in elements) {
224 IOHIDElementRef element = reinterpret_cast<IOHIDElementRef>(elem); 232 IOHIDElementRef element = reinterpret_cast<IOHIDElementRef>(elem);
225 if (!CheckCollection(element)) 233 if (!CheckCollection(element))
226 continue; 234 continue;
227 235
228 uint32_t usage_page = IOHIDElementGetUsagePage(element); 236 uint32_t usage_page = IOHIDElementGetUsagePage(element);
229 uint32_t usage = IOHIDElementGetUsage(element); 237 uint32_t usage = IOHIDElementGetUsage(element);
230 if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Misc && 238 if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Misc &&
231 usage - kAxisMinimumUsageNumber >= WebGamepad::axesLengthCap && 239 usage - kAxisMinimumUsageNumber >= WebGamepad::axesLengthCap &&
232 usage_page <= kGameControlsUsagePage) { 240 usage_page <= kGameControlsUsagePage) {
233 for (; next_index < WebGamepad::axesLengthCap; ++next_index) { 241 for (; next_index < WebGamepad::axesLengthCap; ++next_index) {
234 if (associated.hid.axis_elements[next_index] == NULL) 242 if (associated.hid.axis_elements[next_index] == NULL)
235 break; 243 break;
236 } 244 }
237 if (next_index < WebGamepad::axesLengthCap) { 245 if (next_index < WebGamepad::axesLengthCap) {
238 associated.hid.axis_minimums[next_index] =
239 IOHIDElementGetLogicalMin(element);
240 associated.hid.axis_maximums[next_index] =
241 IOHIDElementGetLogicalMax(element);
242 associated.hid.axis_elements[next_index] = element; 246 associated.hid.axis_elements[next_index] = element;
243 pad.axesLength = std::max(pad.axesLength, next_index + 1); 247 pad.axesLength = std::max(pad.axesLength, next_index + 1);
244 } 248 }
245 } 249 }
246 250
247 if (next_index >= WebGamepad::axesLengthCap) 251 if (next_index >= WebGamepad::axesLengthCap)
248 break; 252 break;
249 } 253 }
250 } 254 }
251 255
256 for (uint32_t axis_index = 0; axis_index < pad.axesLength; ++axis_index) {
257 IOHIDElementRef element = associated.hid.axis_elements[axis_index];
258 if (element != NULL) {
259 CFIndex axis_min = IOHIDElementGetLogicalMin(element);
260 CFIndex axis_max = IOHIDElementGetLogicalMax(element);
261
262 // Some HID axes report a logical range of -1 to 0 signed, which must be
263 // interpreted as 0 to -1 unsigned for correct normalization behavior.
264 if (axis_min == -1 && axis_max == 0) {
265 axis_max = -1;
266 axis_min = 0;
267 }
268
269 associated.hid.axis_minimums[axis_index] = axis_min;
270 associated.hid.axis_maximums[axis_index] = axis_max;
271 associated.hid.axis_report_sizes[axis_index] =
272 IOHIDElementGetReportSize(element);
273 }
274 }
275
252 return (pad.axesLength > 0 || pad.buttonsLength > 0); 276 return (pad.axesLength > 0 || pad.buttonsLength > 0);
253 } 277 }
254 278
255 size_t GamepadPlatformDataFetcherMac::GetEmptySlot() { 279 size_t GamepadPlatformDataFetcherMac::GetEmptySlot() {
256 // Find a free slot for this device. 280 // Find a free slot for this device.
257 for (size_t slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) { 281 for (size_t slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) {
258 if (!pad_state_[slot].data.connected) 282 if (!pad_state_[slot].data.connected)
259 return slot; 283 return slot;
260 } 284 }
261 return WebGamepads::itemsLengthCap; 285 return WebGamepads::itemsLengthCap;
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
409 pad.buttons[i].pressed = IOHIDValueGetIntegerValue(value); 433 pad.buttons[i].pressed = IOHIDValueGetIntegerValue(value);
410 pad.buttons[i].value = pad.buttons[i].pressed ? 1.f : 0.f; 434 pad.buttons[i].value = pad.buttons[i].pressed ? 1.f : 0.f;
411 pad.timestamp = std::max(pad.timestamp, IOHIDValueGetTimeStamp(value)); 435 pad.timestamp = std::max(pad.timestamp, IOHIDValueGetTimeStamp(value));
412 return; 436 return;
413 } 437 }
414 } 438 }
415 439
416 // Find and fill in the associated axis event, if any. 440 // Find and fill in the associated axis event, if any.
417 for (size_t i = 0; i < pad.axesLength; ++i) { 441 for (size_t i = 0; i < pad.axesLength; ++i) {
418 if (associated.hid.axis_elements[i] == element) { 442 if (associated.hid.axis_elements[i] == element) {
419 pad.axes[i] = NormalizeAxis(IOHIDValueGetIntegerValue(value), 443 CFIndex axis_min = associated.hid.axis_minimums[i];
420 associated.hid.axis_minimums[i], 444 CFIndex axis_max = associated.hid.axis_maximums[i];
421 associated.hid.axis_maximums[i]); 445 CFIndex axis_value = IOHIDValueGetIntegerValue(value);
446
447 if (axis_min > axis_max) {
448 // We'll need to interpret this axis as unsigned during normalization.
449 switch (associated.hid.axis_report_sizes[i]) {
450 case 8:
451 pad.axes[i] = NormalizeUInt8Axis(axis_value, axis_min, axis_max);
452 break;
453 case 16:
454 pad.axes[i] = NormalizeUInt16Axis(axis_value, axis_min, axis_max);
455 break;
456 case 32:
457 pad.axes[i] = NormalizeUInt32Axis(axis_value, axis_min, axis_max);
458 break;
459 }
460 } else {
461 pad.axes[i] = NormalizeAxis(axis_value, axis_min, axis_max);
462 }
463
422 pad.timestamp = std::max(pad.timestamp, IOHIDValueGetTimeStamp(value)); 464 pad.timestamp = std::max(pad.timestamp, IOHIDValueGetTimeStamp(value));
423 return; 465 return;
424 } 466 }
425 } 467 }
426 } 468 }
427 469
428 void GamepadPlatformDataFetcherMac::XboxDeviceAdd(XboxController* device) { 470 void GamepadPlatformDataFetcherMac::XboxDeviceAdd(XboxController* device) {
429 if (!enabled_) 471 if (!enabled_)
430 return; 472 return;
431 473
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
524 pads->length = 0; 566 pads->length = 0;
525 return; 567 return;
526 } 568 }
527 569
528 pads->length = WebGamepads::itemsLengthCap; 570 pads->length = WebGamepads::itemsLengthCap;
529 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) 571 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i)
530 MapAndSanitizeGamepadData(&pad_state_[i], &pads->items[i]); 572 MapAndSanitizeGamepadData(&pad_state_[i], &pads->items[i]);
531 } 573 }
532 574
533 } // namespace content 575 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/gamepad/gamepad_platform_data_fetcher_mac.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698