@@ -273,6 +273,11 @@ enum {
273273 TRACKPAD_GESTURE_KEYBOARD ,
274274};
275275
276+ /* Pad identifiers for the deck */
277+ #define STEAM_PAD_LEFT 0
278+ #define STEAM_PAD_RIGHT 1
279+ #define STEAM_PAD_BOTH 2
280+
276281/* Other random constants */
277282#define STEAM_SERIAL_LEN 0x15
278283
@@ -291,6 +296,9 @@ struct steam_device {
291296 struct power_supply __rcu * battery ;
292297 u8 battery_charge ;
293298 u16 voltage ;
299+ struct delayed_work mode_switch ;
300+ bool did_mode_switch ;
301+ bool gamepad_mode ;
294302 struct work_struct rumble_work ;
295303 u16 rumble_left ;
296304 u16 rumble_right ;
@@ -460,6 +468,37 @@ static inline int steam_request_conn_status(struct steam_device *steam)
460468 return ret ;
461469}
462470
471+ /*
472+ * Send a haptic pulse to the trackpads
473+ * Duration and interval are measured in microseconds, count is the number
474+ * of pulses to send for duration time with interval microseconds between them
475+ * and gain is measured in decibels, ranging from -24 to +6
476+ */
477+ static inline int steam_haptic_pulse (struct steam_device * steam , u8 pad ,
478+ u16 duration , u16 interval , u16 count , u8 gain )
479+ {
480+ int ret ;
481+ u8 report [10 ] = {ID_TRIGGER_HAPTIC_PULSE , 8 };
482+
483+ /* Left and right are swapped on this report for legacy reasons */
484+ if (pad < STEAM_PAD_BOTH )
485+ pad ^= 1 ;
486+
487+ report [2 ] = pad ;
488+ report [3 ] = duration & 0xFF ;
489+ report [4 ] = duration >> 8 ;
490+ report [5 ] = interval & 0xFF ;
491+ report [6 ] = interval >> 8 ;
492+ report [7 ] = count & 0xFF ;
493+ report [8 ] = count >> 8 ;
494+ report [9 ] = gain ;
495+
496+ mutex_lock (& steam -> report_mutex );
497+ ret = steam_send_report (steam , report , sizeof (report ));
498+ mutex_unlock (& steam -> report_mutex );
499+ return ret ;
500+ }
501+
463502static inline int steam_haptic_rumble (struct steam_device * steam ,
464503 u16 intensity , u16 left_speed , u16 right_speed ,
465504 u8 left_gain , u8 right_gain )
@@ -505,6 +544,9 @@ static int steam_play_effect(struct input_dev *dev, void *data,
505544
506545static void steam_set_lizard_mode (struct steam_device * steam , bool enable )
507546{
547+ if (steam -> gamepad_mode )
548+ enable = false;
549+
508550 if (enable ) {
509551 mutex_lock (& steam -> report_mutex );
510552 /* enable esc, enter, cursors */
@@ -542,11 +584,18 @@ static int steam_input_open(struct input_dev *dev)
542584 unsigned long flags ;
543585 bool set_lizard_mode ;
544586
545- spin_lock_irqsave (& steam -> lock , flags );
546- set_lizard_mode = !steam -> client_opened && lizard_mode ;
547- spin_unlock_irqrestore (& steam -> lock , flags );
548- if (set_lizard_mode )
549- steam_set_lizard_mode (steam , false);
587+ /*
588+ * Disabling lizard mode automatically is only done on the Steam
589+ * Controller. On the Steam Deck, this is toggled manually by holding
590+ * the options button instead, handled by steam_mode_switch_cb.
591+ */
592+ if (!(steam -> quirks & STEAM_QUIRK_DECK )) {
593+ spin_lock_irqsave (& steam -> lock , flags );
594+ set_lizard_mode = !steam -> client_opened && lizard_mode ;
595+ spin_unlock_irqrestore (& steam -> lock , flags );
596+ if (set_lizard_mode )
597+ steam_set_lizard_mode (steam , false);
598+ }
550599
551600 return 0 ;
552601}
@@ -557,11 +606,13 @@ static void steam_input_close(struct input_dev *dev)
557606 unsigned long flags ;
558607 bool set_lizard_mode ;
559608
560- spin_lock_irqsave (& steam -> lock , flags );
561- set_lizard_mode = !steam -> client_opened && lizard_mode ;
562- spin_unlock_irqrestore (& steam -> lock , flags );
563- if (set_lizard_mode )
564- steam_set_lizard_mode (steam , true);
609+ if (!(steam -> quirks & STEAM_QUIRK_DECK )) {
610+ spin_lock_irqsave (& steam -> lock , flags );
611+ set_lizard_mode = !steam -> client_opened && lizard_mode ;
612+ spin_unlock_irqrestore (& steam -> lock , flags );
613+ if (set_lizard_mode )
614+ steam_set_lizard_mode (steam , true);
615+ }
565616}
566617
567618static enum power_supply_property steam_battery_props [] = {
@@ -886,6 +937,34 @@ static void steam_work_connect_cb(struct work_struct *work)
886937 }
887938}
888939
940+ static void steam_mode_switch_cb (struct work_struct * work )
941+ {
942+ struct steam_device * steam = container_of (to_delayed_work (work ),
943+ struct steam_device , mode_switch );
944+ unsigned long flags ;
945+ bool client_opened ;
946+ steam -> gamepad_mode = !steam -> gamepad_mode ;
947+ if (!lizard_mode )
948+ return ;
949+
950+ if (steam -> gamepad_mode )
951+ steam_set_lizard_mode (steam , false);
952+ else {
953+ spin_lock_irqsave (& steam -> lock , flags );
954+ client_opened = steam -> client_opened ;
955+ spin_unlock_irqrestore (& steam -> lock , flags );
956+ if (!client_opened )
957+ steam_set_lizard_mode (steam , lizard_mode );
958+ }
959+
960+ steam_haptic_pulse (steam , STEAM_PAD_RIGHT , 0x190 , 0 , 1 , 0 );
961+ if (steam -> gamepad_mode ) {
962+ steam_haptic_pulse (steam , STEAM_PAD_LEFT , 0x14D , 0x14D , 0x2D , 0 );
963+ } else {
964+ steam_haptic_pulse (steam , STEAM_PAD_LEFT , 0x1F4 , 0x1F4 , 0x1E , 0 );
965+ }
966+ }
967+
889968static bool steam_is_valve_interface (struct hid_device * hdev )
890969{
891970 struct hid_report_enum * rep_enum ;
@@ -1040,6 +1119,7 @@ static int steam_probe(struct hid_device *hdev,
10401119 mutex_init (& steam -> report_mutex );
10411120 steam -> quirks = id -> driver_data ;
10421121 INIT_WORK (& steam -> work_connect , steam_work_connect_cb );
1122+ INIT_DELAYED_WORK (& steam -> mode_switch , steam_mode_switch_cb );
10431123 INIT_LIST_HEAD (& steam -> list );
10441124 INIT_WORK (& steam -> rumble_work , steam_haptic_rumble_cb );
10451125
@@ -1097,6 +1177,7 @@ static int steam_probe(struct hid_device *hdev,
10971177hid_hw_open_fail :
10981178hid_hw_start_fail :
10991179 cancel_work_sync (& steam -> work_connect );
1180+ cancel_delayed_work_sync (& steam -> mode_switch );
11001181 cancel_work_sync (& steam -> rumble_work );
11011182steam_alloc_fail :
11021183 hid_err (hdev , "%s: failed with error %d\n" ,
@@ -1113,6 +1194,7 @@ static void steam_remove(struct hid_device *hdev)
11131194 return ;
11141195 }
11151196
1197+ cancel_delayed_work_sync (& steam -> mode_switch );
11161198 cancel_work_sync (& steam -> work_connect );
11171199 hid_destroy_device (steam -> client_hdev );
11181200 steam -> client_hdev = NULL ;
@@ -1398,6 +1480,17 @@ static void steam_do_deck_input_event(struct steam_device *steam,
13981480 b13 = data [13 ];
13991481 b14 = data [14 ];
14001482
1483+ if (!(b9 & BIT (6 )) && steam -> did_mode_switch ) {
1484+ steam -> did_mode_switch = false;
1485+ cancel_delayed_work_sync (& steam -> mode_switch );
1486+ } else if (!steam -> client_opened && (b9 & BIT (6 )) && !steam -> did_mode_switch ) {
1487+ steam -> did_mode_switch = true;
1488+ schedule_delayed_work (& steam -> mode_switch , 45 * HZ / 100 );
1489+ }
1490+
1491+ if (!steam -> gamepad_mode )
1492+ return ;
1493+
14011494 lpad_touched = b10 & BIT (3 );
14021495 rpad_touched = b10 & BIT (4 );
14031496
0 commit comments