| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |