@@ -63,6 +63,7 @@ struct ps_led_info {
6363 int max_brightness ;
6464 enum led_brightness (* brightness_get )(struct led_classdev * cdev );
6565 int (* brightness_set )(struct led_classdev * cdev , enum led_brightness );
66+ int (* blink_set )(struct led_classdev * led , unsigned long * on , unsigned long * off );
6667};
6768
6869/* Seed values for DualShock4 / DualSense CRC32 for different report types. */
@@ -319,6 +320,7 @@ struct dualsense_output_report {
319320#define DS4_ACC_RANGE (4*DS_ACC_RES_PER_G)
320321#define DS4_GYRO_RES_PER_DEG_S 1024
321322#define DS4_GYRO_RANGE (2048*DS_GYRO_RES_PER_DEG_S)
323+ #define DS4_LIGHTBAR_MAX_BLINK 255 /* 255 centiseconds */
322324#define DS4_TOUCHPAD_WIDTH 1920
323325#define DS4_TOUCHPAD_HEIGHT 942
324326
@@ -343,10 +345,13 @@ struct dualshock4 {
343345
344346 /* Lightbar leds */
345347 bool update_lightbar ;
348+ bool update_lightbar_blink ;
346349 bool lightbar_enabled ; /* For use by global LED control. */
347350 uint8_t lightbar_red ;
348351 uint8_t lightbar_green ;
349352 uint8_t lightbar_blue ;
353+ uint8_t lightbar_blink_on ; /* In increments of 10ms. */
354+ uint8_t lightbar_blink_off ; /* In increments of 10ms. */
350355 struct led_classdev lightbar_leds [4 ];
351356
352357 struct work_struct output_worker ;
@@ -724,6 +729,7 @@ static int ps_led_register(struct ps_device *ps_dev, struct led_classdev *led,
724729 led -> flags = LED_CORE_SUSPENDRESUME ;
725730 led -> brightness_get = led_info -> brightness_get ;
726731 led -> brightness_set_blocking = led_info -> brightness_set ;
732+ led -> blink_set = led_info -> blink_set ;
727733
728734 ret = devm_led_classdev_register (& ps_dev -> hdev -> dev , led );
729735 if (ret ) {
@@ -1783,6 +1789,37 @@ static enum led_brightness dualshock4_led_get_brightness(struct led_classdev *le
17831789 return -1 ;
17841790}
17851791
1792+ static int dualshock4_led_set_blink (struct led_classdev * led , unsigned long * delay_on ,
1793+ unsigned long * delay_off )
1794+ {
1795+ struct hid_device * hdev = to_hid_device (led -> dev -> parent );
1796+ struct dualshock4 * ds4 = hid_get_drvdata (hdev );
1797+ unsigned long flags ;
1798+
1799+ spin_lock_irqsave (& ds4 -> base .lock , flags );
1800+
1801+ if (!* delay_on && !* delay_off ) {
1802+ /* Default to 1 Hz (50 centiseconds on, 50 centiseconds off). */
1803+ ds4 -> lightbar_blink_on = 50 ;
1804+ ds4 -> lightbar_blink_off = 50 ;
1805+ } else {
1806+ /* Blink delays in centiseconds. */
1807+ ds4 -> lightbar_blink_on = min_t (unsigned long , * delay_on /10 , DS4_LIGHTBAR_MAX_BLINK );
1808+ ds4 -> lightbar_blink_off = min_t (unsigned long , * delay_off /10 , DS4_LIGHTBAR_MAX_BLINK );
1809+ }
1810+
1811+ ds4 -> update_lightbar_blink = true;
1812+
1813+ spin_unlock_irqrestore (& ds4 -> base .lock , flags );
1814+
1815+ dualshock4_schedule_work (ds4 );
1816+
1817+ * delay_on = ds4 -> lightbar_blink_on ;
1818+ * delay_off = ds4 -> lightbar_blink_off ;
1819+
1820+ return 0 ;
1821+ }
1822+
17861823static int dualshock4_led_set_brightness (struct led_classdev * led , enum led_brightness value )
17871824{
17881825 struct hid_device * hdev = to_hid_device (led -> dev -> parent );
@@ -1866,6 +1903,13 @@ static void dualshock4_output_worker(struct work_struct *work)
18661903 ds4 -> update_lightbar = false;
18671904 }
18681905
1906+ if (ds4 -> update_lightbar_blink ) {
1907+ common -> valid_flag0 |= DS4_OUTPUT_VALID_FLAG0_LED_BLINK ;
1908+ common -> lightbar_blink_on = ds4 -> lightbar_blink_on ;
1909+ common -> lightbar_blink_off = ds4 -> lightbar_blink_off ;
1910+ ds4 -> update_lightbar_blink = false;
1911+ }
1912+
18691913 spin_unlock_irqrestore (& ds4 -> base .lock , flags );
18701914
18711915 hid_hw_output_report (ds4 -> base .hdev , report .data , report .len );
@@ -2124,7 +2168,8 @@ static struct ps_device *dualshock4_create(struct hid_device *hdev)
21242168 { NULL , "red" , 255 , dualshock4_led_get_brightness , dualshock4_led_set_brightness },
21252169 { NULL , "green" , 255 , dualshock4_led_get_brightness , dualshock4_led_set_brightness },
21262170 { NULL , "blue" , 255 , dualshock4_led_get_brightness , dualshock4_led_set_brightness },
2127- { NULL , "global" , 1 , dualshock4_led_get_brightness , dualshock4_led_set_brightness },
2171+ { NULL , "global" , 1 , dualshock4_led_get_brightness , dualshock4_led_set_brightness ,
2172+ dualshock4_led_set_blink },
21282173 };
21292174
21302175 ds4 = devm_kzalloc (& hdev -> dev , sizeof (* ds4 ), GFP_KERNEL );
0 commit comments