summaryrefslogtreecommitdiffstats
path: root/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm')
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm105
1 files changed, 86 insertions, 19 deletions
diff --git a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm
index 69d0c63e31d..fc457cdfb55 100644
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm
+++ b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm
@@ -21,6 +21,13 @@ namespace content {
namespace {
+void CopyNSStringAsUTF16LittleEndian(
+ NSString* src, blink::WebUChar* dest, size_t dest_len) {
+ NSData* as16 = [src dataUsingEncoding:NSUTF16LittleEndianStringEncoding];
+ memset(dest, 0, dest_len);
+ [as16 getBytes:dest length:dest_len - sizeof(blink::WebUChar)];
+}
+
NSDictionary* DeviceMatching(uint32_t usage_page, uint32_t usage) {
return [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithUnsignedInt:usage_page],
@@ -36,6 +43,7 @@ float NormalizeAxis(CFIndex value, CFIndex min, CFIndex max) {
// http://www.usb.org/developers/hidpage
const uint32_t kGenericDesktopUsagePage = 0x01;
+const uint32_t kGameControlsUsagePage = 0x05;
const uint32_t kButtonUsagePage = 0x09;
const uint32_t kJoystickUsageNumber = 0x04;
const uint32_t kGameUsageNumber = 0x05;
@@ -159,12 +167,14 @@ void GamepadPlatformDataFetcherMac::AddButtonsAndAxes(NSArray* elements,
memset(pad.axes, 0, sizeof(pad.axes));
memset(pad.buttons, 0, sizeof(pad.buttons));
+ bool mapped_all_axes = true;
+
for (id elem in elements) {
IOHIDElementRef element = reinterpret_cast<IOHIDElementRef>(elem);
- uint32_t usagePage = IOHIDElementGetUsagePage(element);
+ uint32_t usage_page = IOHIDElementGetUsagePage(element);
uint32_t usage = IOHIDElementGetUsage(element);
if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Button &&
- usagePage == kButtonUsagePage) {
+ usage_page == kButtonUsagePage) {
uint32_t button_index = usage - 1;
if (button_index < WebGamepad::buttonsLengthCap) {
associated.hid.button_elements[button_index] = element;
@@ -180,9 +190,40 @@ void GamepadPlatformDataFetcherMac::AddButtonsAndAxes(NSArray* elements,
IOHIDElementGetLogicalMax(element);
associated.hid.axis_elements[axis_index] = element;
pad.axesLength = std::max(pad.axesLength, axis_index + 1);
+ } else {
+ mapped_all_axes = false;
}
}
}
+
+ if (!mapped_all_axes) {
+ // For axes who's usage puts them outside the standard axesLengthCap range.
+ uint32_t next_index = 0;
+ for (id elem in elements) {
+ IOHIDElementRef element = reinterpret_cast<IOHIDElementRef>(elem);
+ uint32_t usage_page = IOHIDElementGetUsagePage(element);
+ uint32_t usage = IOHIDElementGetUsage(element);
+ if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Misc &&
+ usage - kAxisMinimumUsageNumber >= WebGamepad::axesLengthCap &&
+ usage_page <= kGameControlsUsagePage) {
+ for (; next_index < WebGamepad::axesLengthCap; ++next_index) {
+ if (associated.hid.axis_elements[next_index] == NULL)
+ break;
+ }
+ if (next_index < WebGamepad::axesLengthCap) {
+ associated.hid.axis_minimums[next_index] =
+ IOHIDElementGetLogicalMin(element);
+ associated.hid.axis_maximums[next_index] =
+ IOHIDElementGetLogicalMax(element);
+ associated.hid.axis_elements[next_index] = element;
+ pad.axesLength = std::max(pad.axesLength, next_index + 1);
+ }
+ }
+
+ if (next_index >= WebGamepad::axesLengthCap)
+ break;
+ }
+ }
}
size_t GamepadPlatformDataFetcherMac::GetEmptySlot() {
@@ -261,12 +302,19 @@ void GamepadPlatformDataFetcherMac::DeviceAdd(IOHIDDeviceRef device) {
associated_[slot].hid.mapper ? "STANDARD GAMEPAD " : "",
vendor_int,
product_int];
- NSData* as16 = [ident dataUsingEncoding:NSUTF16LittleEndianStringEncoding];
-
- const size_t kOutputLengthBytes = sizeof(data_.items[slot].id);
- memset(&data_.items[slot].id, 0, kOutputLengthBytes);
- [as16 getBytes:data_.items[slot].id
- length:kOutputLengthBytes - sizeof(blink::WebUChar)];
+ CopyNSStringAsUTF16LittleEndian(
+ ident,
+ data_.items[slot].id,
+ sizeof(data_.items[slot].id));
+
+ if (associated_[slot].hid.mapper) {
+ CopyNSStringAsUTF16LittleEndian(
+ @"standard",
+ data_.items[slot].mapping,
+ sizeof(data_.items[slot].mapping));
+ } else {
+ data_.items[slot].mapping[0] = 0;
+ }
base::ScopedCFTypeRef<CFArrayRef> elements(
IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone));
@@ -317,10 +365,18 @@ void GamepadPlatformDataFetcherMac::ValueChanged(IOHIDValueRef value) {
WebGamepad& pad = data_.items[slot];
AssociatedData& associated = associated_[slot];
+ uint32_t value_length = IOHIDValueGetLength(value);
+ if (value_length > 4) {
+ // Workaround for bizarre issue with PS3 controllers that try to return
+ // massive (30+ byte) values and crash IOHIDValueGetIntegerValue
+ return;
+ }
+
// Find and fill in the associated button event, if any.
for (size_t i = 0; i < pad.buttonsLength; ++i) {
if (associated.hid.button_elements[i] == element) {
- pad.buttons[i] = IOHIDValueGetIntegerValue(value) ? 1.f : 0.f;
+ pad.buttons[i].pressed = IOHIDValueGetIntegerValue(value);
+ pad.buttons[i].value = pad.buttons[i].pressed ? 1.f : 0.f;
pad.timestamp = std::max(pad.timestamp, IOHIDValueGetTimeStamp(value));
return;
}
@@ -353,13 +409,20 @@ void GamepadPlatformDataFetcherMac::XboxDeviceAdd(XboxController* device) {
NSString* ident =
[NSString stringWithFormat:
- @"Xbox 360 Controller (STANDARD GAMEPAD Vendor: %04x Product: %04x)",
+ @"%@ (STANDARD GAMEPAD Vendor: %04x Product: %04x)",
+ device->GetControllerType() == XboxController::XBOX_360_CONTROLLER
+ ? @"Xbox 360 Controller"
+ : @"Xbox One Controller",
device->GetProductId(), device->GetVendorId()];
- NSData* as16 = [ident dataUsingEncoding:NSUTF16StringEncoding];
- const size_t kOutputLengthBytes = sizeof(data_.items[slot].id);
- memset(&data_.items[slot].id, 0, kOutputLengthBytes);
- [as16 getBytes:data_.items[slot].id
- length:kOutputLengthBytes - sizeof(blink::WebUChar)];
+ CopyNSStringAsUTF16LittleEndian(
+ ident,
+ data_.items[slot].id,
+ sizeof(data_.items[slot].id));
+
+ CopyNSStringAsUTF16LittleEndian(
+ @"standard",
+ data_.items[slot].mapping,
+ sizeof(data_.items[slot].mapping));
associated_[slot].is_xbox = true;
associated_[slot].xbox.device = device;
@@ -406,12 +469,16 @@ void GamepadPlatformDataFetcherMac::XboxValueChanged(
WebGamepad& pad = data_.items[slot];
for (size_t i = 0; i < 6; i++) {
- pad.buttons[i] = data.buttons[i] ? 1.0f : 0.0f;
+ pad.buttons[i].pressed = data.buttons[i];
+ pad.buttons[i].value = data.buttons[i] ? 1.0f : 0.0f;
}
- pad.buttons[6] = data.triggers[0];
- pad.buttons[7] = data.triggers[1];
+ pad.buttons[6].pressed = data.triggers[0] > kDefaultButtonPressedThreshold;
+ pad.buttons[6].value = data.triggers[0];
+ pad.buttons[7].pressed = data.triggers[1] > kDefaultButtonPressedThreshold;
+ pad.buttons[7].value = data.triggers[1];
for (size_t i = 8; i < 17; i++) {
- pad.buttons[i] = data.buttons[i - 2] ? 1.0f : 0.0f;
+ pad.buttons[i].pressed = data.buttons[i - 2];
+ pad.buttons[i].value = data.buttons[i - 2] ? 1.0f : 0.0f;
}
for (size_t i = 0; i < arraysize(data.axes); i++) {
pad.axes[i] = data.axes[i];