TRACKPAD_GESTURE_KEYBOARD,
 };
 
+/* Pad identifiers for the deck */
+#define STEAM_PAD_LEFT 0
+#define STEAM_PAD_RIGHT 1
+#define STEAM_PAD_BOTH 2
+
 /* Other random constants */
 #define STEAM_SERIAL_LEN 0x15
 
        struct power_supply __rcu *battery;
        u8 battery_charge;
        u16 voltage;
+       struct delayed_work mode_switch;
+       bool did_mode_switch;
+       bool gamepad_mode;
        struct work_struct rumble_work;
        u16 rumble_left;
        u16 rumble_right;
        return ret;
 }
 
+/*
+ * Send a haptic pulse to the trackpads
+ * Duration and interval are measured in microseconds, count is the number
+ * of pulses to send for duration time with interval microseconds between them
+ * and gain is measured in decibels, ranging from -24 to +6
+ */
+static inline int steam_haptic_pulse(struct steam_device *steam, u8 pad,
+                               u16 duration, u16 interval, u16 count, u8 gain)
+{
+       int ret;
+       u8 report[10] = {ID_TRIGGER_HAPTIC_PULSE, 8};
+
+       /* Left and right are swapped on this report for legacy reasons */
+       if (pad < STEAM_PAD_BOTH)
+               pad ^= 1;
+
+       report[2] = pad;
+       report[3] = duration & 0xFF;
+       report[4] = duration >> 8;
+       report[5] = interval & 0xFF;
+       report[6] = interval >> 8;
+       report[7] = count & 0xFF;
+       report[8] = count >> 8;
+       report[9] = gain;
+
+       mutex_lock(&steam->report_mutex);
+       ret = steam_send_report(steam, report, sizeof(report));
+       mutex_unlock(&steam->report_mutex);
+       return ret;
+}
+
 static inline int steam_haptic_rumble(struct steam_device *steam,
                                u16 intensity, u16 left_speed, u16 right_speed,
                                u8 left_gain, u8 right_gain)
 
 static void steam_set_lizard_mode(struct steam_device *steam, bool enable)
 {
+       if (steam->gamepad_mode)
+               enable = false;
+
        if (enable) {
                mutex_lock(&steam->report_mutex);
                /* enable esc, enter, cursors */
        unsigned long flags;
        bool set_lizard_mode;
 
-       spin_lock_irqsave(&steam->lock, flags);
-       set_lizard_mode = !steam->client_opened && lizard_mode;
-       spin_unlock_irqrestore(&steam->lock, flags);
-       if (set_lizard_mode)
-               steam_set_lizard_mode(steam, false);
+       /*
+        * Disabling lizard mode automatically is only done on the Steam
+        * Controller. On the Steam Deck, this is toggled manually by holding
+        * the options button instead, handled by steam_mode_switch_cb.
+        */
+       if (!(steam->quirks & STEAM_QUIRK_DECK)) {
+               spin_lock_irqsave(&steam->lock, flags);
+               set_lizard_mode = !steam->client_opened && lizard_mode;
+               spin_unlock_irqrestore(&steam->lock, flags);
+               if (set_lizard_mode)
+                       steam_set_lizard_mode(steam, false);
+       }
 
        return 0;
 }
        unsigned long flags;
        bool set_lizard_mode;
 
-       spin_lock_irqsave(&steam->lock, flags);
-       set_lizard_mode = !steam->client_opened && lizard_mode;
-       spin_unlock_irqrestore(&steam->lock, flags);
-       if (set_lizard_mode)
-               steam_set_lizard_mode(steam, true);
+       if (!(steam->quirks & STEAM_QUIRK_DECK)) {
+               spin_lock_irqsave(&steam->lock, flags);
+               set_lizard_mode = !steam->client_opened && lizard_mode;
+               spin_unlock_irqrestore(&steam->lock, flags);
+               if (set_lizard_mode)
+                       steam_set_lizard_mode(steam, true);
+       }
 }
 
 static enum power_supply_property steam_battery_props[] = {
        }
 }
 
+static void steam_mode_switch_cb(struct work_struct *work)
+{
+       struct steam_device *steam = container_of(to_delayed_work(work),
+                                                       struct steam_device, mode_switch);
+       unsigned long flags;
+       bool client_opened;
+       steam->gamepad_mode = !steam->gamepad_mode;
+       if (!lizard_mode)
+               return;
+
+       if (steam->gamepad_mode)
+               steam_set_lizard_mode(steam, false);
+       else {
+               spin_lock_irqsave(&steam->lock, flags);
+               client_opened = steam->client_opened;
+               spin_unlock_irqrestore(&steam->lock, flags);
+               if (!client_opened)
+                       steam_set_lizard_mode(steam, lizard_mode);
+       }
+
+       steam_haptic_pulse(steam, STEAM_PAD_RIGHT, 0x190, 0, 1, 0);
+       if (steam->gamepad_mode) {
+               steam_haptic_pulse(steam, STEAM_PAD_LEFT, 0x14D, 0x14D, 0x2D, 0);
+       } else {
+               steam_haptic_pulse(steam, STEAM_PAD_LEFT, 0x1F4, 0x1F4, 0x1E, 0);
+       }
+}
+
 static bool steam_is_valve_interface(struct hid_device *hdev)
 {
        struct hid_report_enum *rep_enum;
        mutex_init(&steam->report_mutex);
        steam->quirks = id->driver_data;
        INIT_WORK(&steam->work_connect, steam_work_connect_cb);
+       INIT_DELAYED_WORK(&steam->mode_switch, steam_mode_switch_cb);
        INIT_LIST_HEAD(&steam->list);
        INIT_WORK(&steam->rumble_work, steam_haptic_rumble_cb);
 
 hid_hw_open_fail:
 hid_hw_start_fail:
        cancel_work_sync(&steam->work_connect);
+       cancel_delayed_work_sync(&steam->mode_switch);
        cancel_work_sync(&steam->rumble_work);
 steam_alloc_fail:
        hid_err(hdev, "%s: failed with error %d\n",
                return;
        }
 
+       cancel_delayed_work_sync(&steam->mode_switch);
        cancel_work_sync(&steam->work_connect);
        hid_destroy_device(steam->client_hdev);
        steam->client_hdev = NULL;
        b13 = data[13];
        b14 = data[14];
 
+       if (!(b9 & BIT(6)) && steam->did_mode_switch) {
+               steam->did_mode_switch = false;
+               cancel_delayed_work_sync(&steam->mode_switch);
+       } else if (!steam->client_opened && (b9 & BIT(6)) && !steam->did_mode_switch) {
+               steam->did_mode_switch = true;
+               schedule_delayed_work(&steam->mode_switch, 45 * HZ / 100);
+       }
+
+       if (!steam->gamepad_mode)
+               return;
+
        lpad_touched = b10 & BIT(3);
        rpad_touched = b10 & BIT(4);