Title: [211220] trunk/Source/WebCore
Revision
211220
Author
beid...@apple.com
Date
2017-01-26 11:21:39 -0800 (Thu, 26 Jan 2017)

Log Message

Gamepad support shows wrong values for PS4 controllers (D-pad is missing).
<rdar://problem/29578619> and https://bugs.webkit.org/show_bug.cgi?id=165588

Reviewed by Alex Christensen.

No new tests (Currently unable to test HID backend directly)

DPads report their HID type as "a button", but their HID usage is "Hatswitch".
This patch adds a new element type that maps a "hatswitch" value to 4 additional buttons.

* platform/gamepad/mac/HIDGamepad.cpp:
(WebCore::HIDGamepad::initElements):
(WebCore::HIDGamepad::initElementsFromArray):
(WebCore::HIDGamepad::maybeAddButton):
(WebCore::HIDGamepad::maybeAddDPad):
(WebCore::HIDGamepad::maybeAddAxis):
(WebCore::fillInButtonValues):
(WebCore::HIDGamepad::valueChanged):

* platform/gamepad/mac/HIDGamepad.h:
(WebCore::HIDGamepadElement::isDPad):
(WebCore::HIDGamepadDPad::HIDGamepadDPad):
(WebCore::HIDGamepadDPad::normalizedValue):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (211219 => 211220)


--- trunk/Source/WebCore/ChangeLog	2017-01-26 18:55:34 UTC (rev 211219)
+++ trunk/Source/WebCore/ChangeLog	2017-01-26 19:21:39 UTC (rev 211220)
@@ -1,3 +1,29 @@
+2017-01-26  Brady Eidson  <beid...@apple.com>
+
+        Gamepad support shows wrong values for PS4 controllers (D-pad is missing).
+        <rdar://problem/29578619> and https://bugs.webkit.org/show_bug.cgi?id=165588
+
+        Reviewed by Alex Christensen.
+
+        No new tests (Currently unable to test HID backend directly)
+
+        DPads report their HID type as "a button", but their HID usage is "Hatswitch".
+        This patch adds a new element type that maps a "hatswitch" value to 4 additional buttons.
+        
+        * platform/gamepad/mac/HIDGamepad.cpp:
+        (WebCore::HIDGamepad::initElements):
+        (WebCore::HIDGamepad::initElementsFromArray):
+        (WebCore::HIDGamepad::maybeAddButton):
+        (WebCore::HIDGamepad::maybeAddDPad):
+        (WebCore::HIDGamepad::maybeAddAxis):
+        (WebCore::fillInButtonValues):
+        (WebCore::HIDGamepad::valueChanged):
+
+        * platform/gamepad/mac/HIDGamepad.h:
+        (WebCore::HIDGamepadElement::isDPad):
+        (WebCore::HIDGamepadDPad::HIDGamepadDPad):
+        (WebCore::HIDGamepadDPad::normalizedValue):
+
 2017-01-26  Antoine Quint  <grao...@apple.com>
 
         [Modern Media Controls] Hiding controls, changing their width and showing them again shows an incorrect layout

Modified: trunk/Source/WebCore/platform/gamepad/mac/HIDGamepad.cpp (211219 => 211220)


--- trunk/Source/WebCore/platform/gamepad/mac/HIDGamepad.cpp	2017-01-26 18:55:34 UTC (rev 211219)
+++ trunk/Source/WebCore/platform/gamepad/mac/HIDGamepad.cpp	2017-01-26 19:21:39 UTC (rev 211220)
@@ -79,13 +79,16 @@
     });
 
     m_axisValues.resize(m_axes.size());
-    m_buttonValues.resize(m_buttons.size());
+    m_buttonValues.resize(m_buttons.size() + (m_dPads.size() * 4));
 
     for (auto& button : m_buttons)
-        getCurrentValueForElement(*button);
+        getCurrentValueForElement(button.get());
 
+    for (auto& dPad : m_dPads)
+        getCurrentValueForElement(dPad.get());
+
     for (auto& axis : m_axes)
-        getCurrentValueForElement(*axis);
+        getCurrentValueForElement(axis.get());
 }
 
 void HIDGamepad::initElementsFromArray(CFArrayRef elements)
@@ -104,8 +107,12 @@
 
         IOHIDElementType type = IOHIDElementGetType(element);
 
-        if ((type == kIOHIDElementTypeInput_Misc || type == kIOHIDElementTypeInput_Button) && maybeAddButton(element))
-            continue;
+        if ((type == kIOHIDElementTypeInput_Misc || type == kIOHIDElementTypeInput_Button)) {
+            if (maybeAddButton(element))
+                continue;
+            if (maybeAddDPad(element))
+                continue;
+        }
 
         if ((type == kIOHIDElementTypeInput_Misc || type == kIOHIDElementTypeInput_Axis) && maybeAddAxis(element))
             continue;
@@ -128,14 +135,35 @@
     CFIndex min = IOHIDElementGetLogicalMin(element);
     CFIndex max = IOHIDElementGetLogicalMax(element);
 
-    m_buttons.append(std::make_unique<HIDGamepadButton>(usage, min, max, element));
+    m_buttons.append(makeUniqueRef<HIDGamepadButton>(usage, min, max, element));
 
     IOHIDElementCookie cookie = IOHIDElementGetCookie(element);
-    m_elementMap.set(cookie, m_buttons.last().get());
+    m_elementMap.set(cookie, &m_buttons.last().get());
 
     return true;
 }
 
+bool HIDGamepad::maybeAddDPad(IOHIDElementRef element)
+{
+    uint32_t usagePage = IOHIDElementGetUsagePage(element);
+    if (usagePage != kHIDPage_GenericDesktop)
+        return false;
+
+    uint32_t usage = IOHIDElementGetUsage(element);
+    if (!usage || usage != kHIDUsage_GD_Hatswitch)
+        return false;
+
+    CFIndex min = IOHIDElementGetLogicalMin(element);
+    CFIndex max = IOHIDElementGetLogicalMax(element);
+
+    m_dPads.append(makeUniqueRef<HIDGamepadDPad>(min, max, element));
+
+    IOHIDElementCookie cookie = IOHIDElementGetCookie(element);
+    m_elementMap.set(cookie, &m_dPads.last().get());
+
+    return true;
+}
+
 bool HIDGamepad::maybeAddAxis(IOHIDElementRef element)
 {
     uint32_t usagePage = IOHIDElementGetUsagePage(element);
@@ -150,14 +178,46 @@
     CFIndex min = IOHIDElementGetPhysicalMin(element);
     CFIndex max = IOHIDElementGetPhysicalMax(element);
 
-    m_axes.append(std::make_unique<HIDGamepadAxis>(min, max, element));
+    m_axes.append(makeUniqueRef<HIDGamepadAxis>(min, max, element));
 
     IOHIDElementCookie cookie = IOHIDElementGetCookie(element);
-    m_elementMap.set(cookie, m_axes.last().get());
+    m_elementMap.set(cookie, &m_axes.last().get());
 
     return true;
 }
 
+static void fillInButtonValues(int value, double& button0, double& button1, double& button2, double& button3)
+{
+    // Standard DPads have 8 possible position values, moving around a circle:
+    // 0 - Up
+    // 1 - Up + right
+    // 2 - Right
+    // 3 - Down + right
+    // 4 - Down
+    // 5 - Down + left
+    // 6 - Left
+    // 7 - Up and Left
+    // These 8 positions are mapped on to 4 button positions:
+    // 0 - Up
+    // 1 - Down
+    // 2 - Left
+    // 3 - Right
+
+    if (value < 0 || value > 7) {
+        // Handle an invalid input value that we don't know how to interpret.
+        button0 = 0.0;
+        button1 = 0.0;
+        button2 = 0.0;
+        button3 = 0.0;
+        return;
+    }
+
+    button0 = value < 2 || value == 7 ? 1.0 : 0.0;
+    button1 = value > 2 && value < 6 ? 1.0 : 0.0;
+    button2 = value > 4 ? 1.0 : 0.0;
+    button3 = value > 0 && value < 4 ? 1.0 : 0.0;
+}
+
 HIDInputType HIDGamepad::valueChanged(IOHIDValueRef value)
 {
     IOHIDElementCookie cookie = IOHIDElementGetCookie(IOHIDValueGetElement(value));
@@ -171,14 +231,31 @@
 
     if (element->isButton()) {
         for (unsigned i = 0; i < m_buttons.size(); ++i) {
-            if (m_buttons[i].get() == element)
+            if (&m_buttons[i].get() == element) {
                 m_buttonValues[i] = element->normalizedValue();
+                break;
+            }
         }
     } else if (element->isAxis()) {
         for (unsigned i = 0; i < m_axes.size(); ++i) {
-            if (m_axes[i].get() == element)
+            if (&m_axes[i].get() == element) {
                 m_axisValues[i] = element->normalizedValue();
+                break;
+            }
         }
+    } else if (element->isDPad()) {
+        int intValue = IOHIDValueGetIntegerValue(value) - element->min;
+        for (unsigned i = 0; i < m_dPads.size(); ++i) {
+            if (&m_dPads[i].get() != element)
+                continue;
+
+            // Each DPad represents 4 button values which are tacked on to the end of the values from non-DPad buttons.
+            unsigned firstButtonValue = m_buttons.size() + i * 4;
+
+            ASSERT(m_buttonValues.size() > firstButtonValue + 3);
+
+            fillInButtonValues(intValue, m_buttonValues[firstButtonValue], m_buttonValues[firstButtonValue + 1], m_buttonValues[firstButtonValue + 2], m_buttonValues[firstButtonValue + 3]);
+        }
     } else
         ASSERT_NOT_REACHED();
 

Modified: trunk/Source/WebCore/platform/gamepad/mac/HIDGamepad.h (211219 => 211220)


--- trunk/Source/WebCore/platform/gamepad/mac/HIDGamepad.h	2017-01-26 18:55:34 UTC (rev 211219)
+++ trunk/Source/WebCore/platform/gamepad/mac/HIDGamepad.h	2017-01-26 19:21:39 UTC (rev 211220)
@@ -31,6 +31,7 @@
 #include <IOKit/hid/IOHIDDevice.h>
 #include <wtf/HashMap.h>
 #include <wtf/RetainPtr.h>
+#include <wtf/UniqueRef.h>
 
 namespace WebCore {
 
@@ -54,6 +55,7 @@
 
     virtual bool isButton() const { return false; }
     virtual bool isAxis() const { return false; }
+    virtual bool isDPad() const { return false; }
 
     virtual double normalizedValue() = 0;
 };
@@ -67,7 +69,7 @@
 
     uint32_t priority;
 
-    bool isButton() const override { return true; }
+    bool isButton() const final { return true; }
 
     // Buttons normalize to the range (0.0) - (1.0)
     double normalizedValue() override
@@ -82,7 +84,7 @@
     {
     }
 
-    bool isAxis() const override { return true; }
+    bool isAxis() const final { return true; }
 
     // Axes normalize to the range (-1.0) - (1.0)
     double normalizedValue() override
@@ -91,6 +93,17 @@
     }
 };
 
+struct HIDGamepadDPad : HIDGamepadElement {
+    HIDGamepadDPad(double min, double max, IOHIDElementRef element)
+        : HIDGamepadElement(min, max, element)
+    {
+    }
+
+    bool isDPad() const final { return true; }
+
+    virtual double normalizedValue() { RELEASE_ASSERT_NOT_REACHED(); }
+};
+
 enum class HIDInputType {
     ButtonPress,
     NotAButtonPress,
@@ -112,6 +125,7 @@
     void initElementsFromArray(CFArrayRef);
 
     bool maybeAddButton(IOHIDElementRef);
+    bool maybeAddDPad(IOHIDElementRef);
     bool maybeAddAxis(IOHIDElementRef);
 
     void getCurrentValueForElement(const HIDGamepadElement&);
@@ -120,8 +134,9 @@
 
     HashMap<IOHIDElementCookie, HIDGamepadElement*> m_elementMap;
 
-    Vector<std::unique_ptr<HIDGamepadButton>> m_buttons;
-    Vector<std::unique_ptr<HIDGamepadAxis>> m_axes;
+    Vector<UniqueRef<HIDGamepadButton>> m_buttons;
+    Vector<UniqueRef<HIDGamepadAxis>> m_axes;
+    Vector<UniqueRef<HIDGamepadDPad>> m_dPads;
     Vector<double> m_buttonValues;
     Vector<double> m_axisValues;
 };
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to