ps2: Add proper touchscreen command handling
authorAndreas Sandberg <andreas.sandberg@arm.com>
Mon, 9 Apr 2018 22:24:31 +0000 (22:24 +0000)
committerAndreas Sandberg <andreas.sandberg@arm.com>
Tue, 17 Apr 2018 11:19:44 +0000 (11:19 +0000)
The touchscreen model used ad-hoc mechanisms to enable/disable the
device. Use standard PS/2 commands to activate/deactivate the
device. Add proper TouchKit command handling.

Change-Id: I0c5a2e2b47639f36ab3ee07e3e559f11afa54b9d
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/9768
Reviewed-by: Gabe Black <gabeblack@google.com>
src/dev/ps2/touchkit.cc
src/dev/ps2/touchkit.hh

index fd81c5758b549f7028390c5303ebada56d5be882..819b06c5da0a46c5547cc8ce79c2ba0a91bbfccf 100644 (file)
@@ -54,7 +54,7 @@ const uint8_t PS2TouchKit::ID[] = {0x00};
 PS2TouchKit::PS2TouchKit(const PS2TouchKitParams *p)
     : PS2Device(p),
       vnc(p->vnc),
-      driverInitialized(false)
+      enabled(false), touchKitEnabled(false)
 {
     if (vnc)
         vnc->setMouse(this);
@@ -65,7 +65,8 @@ PS2TouchKit::serialize(CheckpointOut &cp) const
 {
     PS2Device::serialize(cp);
 
-    SERIALIZE_SCALAR(driverInitialized);
+    SERIALIZE_SCALAR(enabled);
+    SERIALIZE_SCALAR(touchKitEnabled);
 }
 
 void
@@ -73,7 +74,8 @@ PS2TouchKit::unserialize(CheckpointIn &cp)
 {
     PS2Device::unserialize(cp);
 
-    UNSERIALIZE_SCALAR(driverInitialized);
+    UNSERIALIZE_SCALAR(enabled);
+    UNSERIALIZE_SCALAR(touchKitEnabled);
 }
 
 bool
@@ -81,6 +83,9 @@ PS2TouchKit::recv(const std::vector<uint8_t> &data)
 {
     switch (data[0]) {
       case Ps2::Ps2Reset:
+        DPRINTF(PS2, "Resetting device.\n");
+        enabled = false;
+        touchKitEnabled = false;
         sendAck();
         send(Ps2::SelfTestPass);
         return true;
@@ -107,9 +112,24 @@ PS2TouchKit::recv(const std::vector<uint8_t> &data)
 
       case Ps2::SetScaling1_1:
       case Ps2::SetScaling1_2:
+        sendAck();
+        return true;
+
       case Ps2::Disable:
+        DPRINTF(PS2, "Disabling device.\n");
+        enabled = false;
+        sendAck();
+        return true;
+
       case Ps2::Enable:
+        DPRINTF(PS2, "Enabling device.\n");
+        enabled = true;
+        sendAck();
+        return true;
+
       case Ps2::SetDefaults:
+        DPRINTF(PS2, "Setting defaults and disabling device.\n");
+        enabled = false;
         sendAck();
         return true;
 
@@ -121,25 +141,53 @@ PS2TouchKit::recv(const std::vector<uint8_t> &data)
         return true;
 
       case Ps2::TouchKitId:
-        sendAck();
-        if (data.size() == 1) {
-            send(Ps2::TouchKitId);
-            send(1);
-            send('A');
-
-            return false;
-        } else if (data.size() == 3) {
-            driverInitialized = true;
-            return true;
-        } else {
-            return false;
-        }
+        return recvTouchKit(data);
+
+      default:
+        panic("Unknown byte received: %#x\n", data[0]);
+    }
+}
+
+bool
+PS2TouchKit::recvTouchKit(const std::vector<uint8_t> &data)
+{
+    // Ack all incoming bytes
+    sendAck();
+
+    // Packet format is: 0x0A SIZE CMD DATA
+    assert(data[0] == Ps2::TouchKitId);
+    if (data.size() < 3 || data.size() - 2 < data[1])
+        return false;
+
+    const uint8_t len = data[1];
+    const uint8_t cmd = data[2];
+
+    // We have received at least one TouchKit diagnostic
+    // command. Enabled TouchKit reports.
+    touchKitEnabled = true;
+
+
+    switch (cmd) {
+      case TouchKitActive:
+        warn_if(len != 1, "Unexpected activate packet length: %u\n", len);
+        sendTouchKit('A');
+        return true;
 
       default:
-        panic("Unknown byte received: %d\n", data[0]);
+        panic("Unimplemented touchscreen command: %#x\n", cmd);
     }
 }
 
+void
+PS2TouchKit::sendTouchKit(const uint8_t *data, size_t size)
+{
+    send(Ps2::TouchKitId);
+    send(size);
+    for (int i = 0; i < size; ++i)
+        send(data[i]);
+}
+
+
 void
 PS2TouchKit::mouseAt(uint16_t x, uint16_t y, uint8_t buttons)
 {
@@ -147,7 +195,7 @@ PS2TouchKit::mouseAt(uint16_t x, uint16_t y, uint8_t buttons)
     // it anything. Similarly we can get vnc mouse events orders of magnitude
     // faster than m5 can process them. Only queue up two sets mouse movements
     // and don't add more until those are processed.
-    if (!driverInitialized || sendPending() > 10)
+    if (!enabled || !touchKitEnabled || sendPending() > 10)
         return;
 
     // Convert screen coordinates to touchpad coordinates
index fa1bc52a4517299dc6bd20341e7382ec539ab68f..dc98a78fac73e93a96aad6d42a31606d7a80dbe1 100644 (file)
@@ -50,6 +50,12 @@ class PS2TouchKit : public PS2Device, public VncMouse
   protected:
     static const uint8_t ID[];
 
+    enum TKCommands {
+        TouchKitActive = 'A',
+        TouchKitFWRev = 'D',
+        TouchKitCtrlType = 'E',
+    };
+
   public:
     PS2TouchKit(const PS2TouchKitParams *p);
 
@@ -63,14 +69,21 @@ class PS2TouchKit : public PS2Device, public VncMouse
     void mouseAt(uint16_t x, uint16_t y, uint8_t buttons) override;
 
   protected:
+    bool recvTouchKit(const std::vector<uint8_t> &data);
+    void sendTouchKit(const uint8_t *data, size_t size);
+    void sendTouchKit(uint8_t data) { sendTouchKit(&data, 1); }
+
     /** The vnc server we're connected to (if any) */
     VncInput *const vnc;
 
+    /** Is the device enabled? */
+    bool enabled;
+
     /**
-     * Has the driver been initialized in TouchKit mode? The model
-     * suppresses touch event generation until this is true.
+     * Has the driver enabled TouchKit mode?  The model suppresses
+     * touch event generation until this is true.
      */
-    bool driverInitialized;
+    bool touchKitEnabled;
 };
 
 #endif // __DEV_PS2_TOUCHKIT_HH__