Skip to content

Commit 82d93f6

Browse files
Roderick ColenbranderJiri Kosina
authored andcommitted
HID: playstation: support DualShock4 lightbar blink.
Support lightbar blink through LEDs framework. Signed-off-by: Roderick Colenbrander <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent 4521109 commit 82d93f6

File tree

1 file changed

+46
-1
lines changed

1 file changed

+46
-1
lines changed

drivers/hid/hid-playstation.c

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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+
17861823
static 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

Comments
 (0)