[haiku-commits] haiku: hrev51945 - src/add-ons/kernel/bus_managers/ps2

  • From: Adrien Destugues <pulkomandy@xxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 17 May 2018 02:18:22 -0400 (EDT)

hrev51945 adds 2 changesets to branch 'master'
old head: b08627f310bb2e80bca50176e7a758182384735a
new head: 79cb8f02d9310dae0c347e6730414f7eacb4abd6
overview: 
https://git.haiku-os.org/haiku/log/?qt=range&q=79cb8f02d931+%5Eb08627f310bb

----------------------------------------------------------------------------

258b7d4a8b25: ps2_synaptics: support Lenovo use of extra buttons
  
  On some Thinkpads, the extra buttons are used for the trackpoint, so
  they should be reported as "main" buttons, not extended ones. An
  (undocumented) information query was added to the firmware to report
  when this is the case, however it is not advertised as supported by the
  firmware itself by the usual mechanism.
  
  What we do is (just as the Linux driver) detect that the tocuhpad has a
  PS/2 passthrough (likely used to daisy-chain a trackpoint on the same
  PS/2 port) and also advertises extra buttons (an unlikely case, it is
  already uncommon to even get a middle button these days...) and assume
  that the information query is available then.
  
  When the query is available and reports the quirk, the extended buttons
  are reported as 0, 1, 2 (left, right, middle), instead of extra buttons
  the userland would have no idea what to do with.
  
  Change-Id: Iad5a9e140b6e49c298dcc901f4e331a4a847d7b2

79cb8f02d931: PS/2 synaptics: minimal clickpad support
  
  Handled as a 1-button mouse. We didn't really support this since the old
  Macintosh ADB mouses, so let's see if that code aged well!
  
  Change-Id: Ibed2423023e821ae4ce608f0ddbc5ac32bfbd8f7

                             [ Adrien Destugues <pulkomandy@xxxxxxxxxxxxx> ]

----------------------------------------------------------------------------

2 files changed, 104 insertions(+), 46 deletions(-)
.../kernel/bus_managers/ps2/ps2_synaptics.cpp    | 147 +++++++++++++------
.../kernel/bus_managers/ps2/ps2_synaptics.h      |   3 +

############################################################################

Commit:      258b7d4a8b2572c6d0cb83abbda29245fb5f97c4
URL:         https://git.haiku-os.org/haiku/commit/?id=258b7d4a8b25
Author:      Adrien Destugues <pulkomandy@xxxxxxxxxxxxx>
Date:        Thu May 10 17:52:28 2018 UTC
Committer:   Adrien Destugues <pulkomandy@xxxxxxxxx>
Commit-Date: Thu May 17 06:18:19 2018 UTC

ps2_synaptics: support Lenovo use of extra buttons

On some Thinkpads, the extra buttons are used for the trackpoint, so
they should be reported as "main" buttons, not extended ones. An
(undocumented) information query was added to the firmware to report
when this is the case, however it is not advertised as supported by the
firmware itself by the usual mechanism.

What we do is (just as the Linux driver) detect that the tocuhpad has a
PS/2 passthrough (likely used to daisy-chain a trackpoint on the same
PS/2 port) and also advertises extra buttons (an unlikely case, it is
already uncommon to even get a middle button these days...) and assume
that the information query is available then.

When the query is available and reports the quirk, the extended buttons
are reported as 0, 1, 2 (left, right, middle), instead of extra buttons
the userland would have no idea what to do with.

Change-Id: Iad5a9e140b6e49c298dcc901f4e331a4a847d7b2

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.cpp 
b/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.cpp
index b7fb39dbf4..ccd997f340 100644
--- a/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.cpp
+++ b/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.cpp
@@ -29,6 +29,21 @@
 #define REAL_MAX_PRESSURE              100
 #define MAX_PRESSURE                   200
 
+enum {
+       kIdentify = 0x00,
+       kReadModes = 0x01,
+       kReadCapabilities = 0x02,
+       kReadModelId = 0x03,
+       kReadSerialNumberPrefix = 0x06,
+       kReadSerialModelSuffix = 0x07,
+       kReadResolutions = 0x08,
+       kExtendedModelId = 0x09,
+       kContinuedCapabilities = 0x0C,
+       kMaximumCoordinates = 0x0D,
+       kDeluxeLedInfo = 0x0E,
+       kMinimumCoordinates = 0x0F,
+       kTrackpointQuirk = 0x10
+};
 
 static hardware_specs gHardwareSpecs;
 
@@ -83,6 +98,26 @@ set_touchpad_mode(ps2_dev *dev, uint8 mode)
 }
 
 
+static status_t
+get_information_query(ps2_dev *dev, uint8 extendedQueries, uint8 query,
+       uint8 val[3])
+{
+       if (query == kTrackpointQuirk) {
+               // Special case: this information query is not reported in the
+               // "extended queries", but is still supported when the touchpad 
has
+               // a pass-through port.
+               if (!sTouchpadInfo.capPassThrough)
+                       return B_NOT_SUPPORTED;
+       } else if (query > extendedQueries + 8)
+               return B_NOT_SUPPORTED;
+
+       status_t error = send_touchpad_arg(dev, query);
+       if (error != B_OK)
+               return error;
+       return ps2_dev_command(dev, 0xE9, NULL, 0, val, 3);
+}
+
+
 static status_t
 get_synaptics_movment(synaptics_cookie *cookie, mouse_movement *movement)
 {
@@ -128,35 +163,31 @@ get_synaptics_movment(synaptics_cookie *cookie, 
mouse_movement *movement)
                if (sTouchpadInfo.capMiddleButton || 
sTouchpadInfo.capFourButtons)
                        event.buttons |= ((event_buffer[0] ^ event_buffer[3]) & 
0x01) << 2;
 
-               if (sTouchpadInfo.nExtendedButtons > 0
-                               && ((event_buffer[0] ^ event_buffer[3]) & 0x02) 
!= 0) {
-                       int nextButton = 2;
-                       if (sTouchpadInfo.capMiddleButton)
-                               nextButton = 3;
-                       if (sTouchpadInfo.capFourButtons)
-                               nextButton = 4;
-
-                       // The touchpad supports extended buttons and one of 
them is
-                       // currently being pressed. They replace the lowest 
bits of X and Y.
-                       int button = 0;
-                       bool pressed;
-                       while (button < sTouchpadInfo.nExtendedButtons) {
-                               // Odd buttons are in the X byte
-                               pressed = event_buffer[4] >> (button / 2) & 0x1;
-
-                               if (pressed)
-                                       event.buttons |= 1 << (button + 
nextButton);
-
-                               button++;
-
-                               // Even buttons are in the Y byte
-                               pressed = event_buffer[5] >> (button / 2) & 0x1;
-
-                               if (pressed)
-                                       event.buttons |= 1 << (button + 
nextButton);
-
-                               button++;
+               if (sTouchpadInfo.nExtendedButtons > 0)
+               {
+                       if (((event_buffer[0] ^ event_buffer[3]) & 0x02) != 0) {
+                               // This packet includes extended buttons state. 
The state is
+                               // only reported once when one of the buttons 
is pressed or
+                               // released, so we must keep track of the 
buttons state.
+
+                               // The values replace the lowest bits of the X 
and Y coordinates
+                               // in the packet, we need to extract them from 
there.
+
+                               bool pressed;
+                               for (int button = 0; button < 
sTouchpadInfo.nExtendedButtons;
+                                               button++) {
+                                       // Even buttons are in the X byte
+                                       pressed = event_buffer[4 + button % 2] 

button / 2 & 0x1;
+                                       if (pressed) {
+                                               
sTouchpadInfo.extendedButtonsState |= 1 << button;
+                                       } else {
+                                               
sTouchpadInfo.extendedButtonsState &= ~(1 << button);
+                                       }
+                               }
                        }
+
+                       event.buttons |= sTouchpadInfo.extendedButtonsState
+                               << sTouchpadInfo.firstExtendedButton;
                }
        } else {
                bool finger = event_buffer[0] >> 5 & 1;
@@ -190,9 +221,9 @@ static void
 query_capability(ps2_dev *dev)
 {
        uint8 val[3];
-       uint8 nExtendedQueries;
-       send_touchpad_arg(dev, 0x02);
-       ps2_dev_command(dev, 0xE9, NULL, 0, val, 3);
+       uint8 nExtendedQueries = 0;
+
+       get_information_query(dev, nExtendedQueries, kReadCapabilities, val);
 
        TRACE("SYNAPTICS: extended mode %2x\n", val[0] >> 7 & 1);
        sTouchpadInfo.capExtended = val[0] >> 7 & 1;
@@ -212,17 +243,37 @@ query_capability(ps2_dev *dev)
        TRACE("SYNAPTICS: pass through %2x\n", val[2] >> 7 & 1);
        sTouchpadInfo.capPassThrough = val[2] >> 7 & 1;
 
-       if (nExtendedQueries >= 1) {
-               // This touchpad supports the "extended model ID" command, and 
can
-               // report extra buttons.
-               send_touchpad_arg(dev, 0x09);
-               ps2_dev_command(dev, 0xE9, NULL, 0, val, 3);
-
-               TRACE("SYNAPTICS: extended buttons %2x\n", val[1] >> 4 & 15);
-               sTouchpadInfo.nExtendedButtons = val[1] >> 4 & 15;
-       } else {
+       if (get_information_query(dev, nExtendedQueries, kExtendedModelId, val)
+                       != B_OK) {
+               // "Extended Model ID" is not supported, so there cannot be 
extra
+               // buttons.
                sTouchpadInfo.nExtendedButtons = 0;
+               sTouchpadInfo.firstExtendedButton = 0;
+               return;
        }
+
+       TRACE("SYNAPTICS: extended buttons %2x\n", val[1] >> 4 & 15);
+       sTouchpadInfo.nExtendedButtons = val[1] >> 4 & 15;
+       sTouchpadInfo.extendedButtonsState = 0;
+
+       if (sTouchpadInfo.capMiddleButton)
+               sTouchpadInfo.firstExtendedButton = 3;
+       else
+               sTouchpadInfo.firstExtendedButton = 2;
+
+       // Capability 0x10 is not documented in the Synaptics Touchpad 
interfacing
+       // guide (at least the versions I could find), but we got the 
information
+       // from Linux patches: https://lkml.org/lkml/2015/2/6/621
+       if (get_information_query(dev, nExtendedQueries, kTrackpointQuirk, val)
+                       != B_OK)
+               return;
+
+       // Workaround for Thinkpad use of the extended buttons: they are
+       // used as buttons for the trackpoint, so they should be reported
+       // as buttons 0, 1, 2 rather than 3, 4, 5.
+       TRACE("SYNAPTICS: alternate buttons %2x\n", val[0] >> 0 & 1);
+       if (val[0] >> 0 & 1)
+               sTouchpadInfo.firstExtendedButton = 0;
 }
 
 
@@ -337,12 +388,7 @@ probe_synaptics(ps2_dev *dev)
 
        // Request "Identify touchpad"
        // The touchpad will delay this, until it's ready and calibrated.
-       status = send_touchpad_arg(dev, 0x00);
-       if (status != B_OK)
-               return status;
-
-       // "Status request" (executes "Identify touchpad")
-       status = ps2_dev_command(dev, 0xE9, NULL, 0, val, 3);
+       status = get_information_query(dev, 0, kIdentify, val);
        if (status != B_OK)
                return status;
 
diff --git a/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.h 
b/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.h
index 751d15bd8f..a4dc0dbb8c 100644
--- a/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.h
+++ b/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.h
@@ -51,6 +51,8 @@ typedef struct {
        bool capPassThrough;
 
        uint8 nExtendedButtons;
+       uint8 firstExtendedButton;
+       uint8 extendedButtonsState;
 } touchpad_info;
 
 

############################################################################

Revision:    hrev51945
Commit:      79cb8f02d9310dae0c347e6730414f7eacb4abd6
URL:         https://git.haiku-os.org/haiku/commit/?id=79cb8f02d931
Author:      Adrien Destugues <pulkomandy@xxxxxxxxxxxxx>
Date:        Sun May 13 08:42:20 2018 UTC
Committer:   Adrien Destugues <pulkomandy@xxxxxxxxx>
Commit-Date: Thu May 17 06:18:19 2018 UTC

PS/2 synaptics: minimal clickpad support

Handled as a 1-button mouse. We didn't really support this since the old
Macintosh ADB mouses, so let's see if that code aged well!

Change-Id: Ibed2423023e821ae4ce608f0ddbc5ac32bfbd8f7

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.cpp 
b/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.cpp
index ccd997f340..ac5e758b5d 100644
--- a/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.cpp
+++ b/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.cpp
@@ -160,6 +160,11 @@ get_synaptics_movment(synaptics_cookie *cookie, 
mouse_movement *movement)
                event.wValue = wValue;
                event.gesture = false;
 
+               // Clickpad pretends that all clicks on the touchpad are middle 
clicks.
+               // Pass them to userspace as left clicks instead.
+               if (sTouchpadInfo.capClickPad)
+                       event.buttons |= ((event_buffer[0] ^ event_buffer[3]) & 
0x01);
+
                if (sTouchpadInfo.capMiddleButton || 
sTouchpadInfo.capFourButtons)
                        event.buttons |= ((event_buffer[0] ^ event_buffer[3]) & 
0x01) << 2;
 
@@ -249,9 +254,13 @@ query_capability(ps2_dev *dev)
                // buttons.
                sTouchpadInfo.nExtendedButtons = 0;
                sTouchpadInfo.firstExtendedButton = 0;
+               sTouchpadInfo.capClickPad = false;
                return;
        }
 
+       sTouchpadInfo.capClickPad = (val[0] >> 5 & 1) | (val[1] >> 0 & 1);
+       TRACE("SYNAPTICS: clickpad %x\n", sTouchpadInfo.capClickPad);
+
        TRACE("SYNAPTICS: extended buttons %2x\n", val[1] >> 4 & 15);
        sTouchpadInfo.nExtendedButtons = val[1] >> 4 & 15;
        sTouchpadInfo.extendedButtonsState = 0;
diff --git a/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.h 
b/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.h
index a4dc0dbb8c..544624c8ff 100644
--- a/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.h
+++ b/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.h
@@ -49,6 +49,7 @@ typedef struct {
        bool capMultiFinger;
        bool capPalmDetection;
        bool capPassThrough;
+       bool capClickPad;
 
        uint8 nExtendedButtons;
        uint8 firstExtendedButton;


Other related posts:

  • » [haiku-commits] haiku: hrev51945 - src/add-ons/kernel/bus_managers/ps2 - Adrien Destugues