Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
dualsensectl
build.sh
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ Linux tool for controlling Sony PlayStation 5 DualSense controller.
info Get the controller firmware info
lightbar STATE Enable (on) or disable (off) lightbar
lightbar RED GREEN BLUE [BRIGHTNESS] Set lightbar color and brightness (0-255)
lightbar rainbow enable Enable lightbar rainbow mode
lightbar rainbow disable Disable lightbar rainbow mode
led-brightness NUMBER Set player and microphone LED dimming (0-2)
player-leds NUMBER [instant] Set player LEDs (1-7) or disabled (0)
microphone STATE Enable (on) or disable (off) microphone
Expand Down
62 changes: 62 additions & 0 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
#include <poll.h>
#include <sys/wait.h>

#include <time.h>
#include <math.h>

#include <hidapi/hidapi.h>
#include <libudev.h>

Expand Down Expand Up @@ -578,6 +581,56 @@ static int command_lightbar3(struct dualsense *ds, uint8_t red, uint8_t green, u
return 0;
}

static int command_lightbar_rainbow_enable(struct dualsense *ds)
{
struct dualsense_output_report rp;
uint8_t rbuf[DS_OUTPUT_REPORT_BT_SIZE];
dualsense_init_output_report(ds, &rp, rbuf);

pid_t pid = fork();

if (pid == -1) {
perror("fork failed :(");
exit(1);
} else if (pid == 0) {
FILE *fp = fopen("child.pid", "w");
if (fp) {
fprintf(fp, "%d", getpid());
fclose(fp);
}
struct timespec req = {
.tv_sec = 0,
.tv_nsec = 200000000,
};
struct timespec rem;
double timer = 0;
while (true) {
rp.common->valid_flag1 = DS_OUTPUT_VALID_FLAG1_LIGHTBAR_CONTROL_ENABLE;
rp.common->lightbar_red = 128 + (uint8_t)(128 * sin(3 * timer));
rp.common->lightbar_green = 128 + (uint8_t)(128 * cos(5 * timer));
rp.common->lightbar_blue = 128 + (uint8_t)(128 * sin(10 * timer));
nanosleep(&req, &rem);
dualsense_send_output_report(ds, &rp);
timer += 0.03;
}
exit(0);
}
return 0;
}

static int command_lightbar_rainbow_disable()
{
FILE *fp = fopen("child.pid", "r");
if (fp) {
pid_t pid;
fscanf(fp, "%d", &pid);
kill(pid, SIGTERM);
fclose(fp);
}

return 0;
}

static int command_led_brightness(struct dualsense *ds, uint8_t number)
{
if (number > 2) {
Expand Down Expand Up @@ -1335,6 +1388,15 @@ int main(int argc, char *argv[])
} else if (argc == 5 || argc == 6) {
uint8_t brightness = argc == 6 ? atoi_x(argv[5]) : 255;
return command_lightbar3(&ds, atoi_x(argv[2]), atoi_x(argv[3]), atoi_x(argv[4]), brightness);
} else if (argc == 4) {
if (!strcmp(argv[3], "enable")) {
return command_lightbar_rainbow_enable(&ds);
} else if (!strcmp(argv[3], "disable")) {
return command_lightbar_rainbow_disable();
} else {
fprintf(stderr, "Invalid arguments\n");
return 2;
}
} else {
fprintf(stderr, "Invalid arguments\n");
return 2;
Expand Down
5 changes: 4 additions & 1 deletion meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@ add_project_arguments(
udev = dependency('libudev')
hidapi_hidraw = dependency('hidapi-hidraw')

cc = meson.get_compiler('c')
m_dep = cc.find_library('m', required : false)

executable(
'dualsensectl',
['main.c'],
dependencies: [udev, hidapi_hidraw],
dependencies: [udev, hidapi_hidraw, m_dep],
install: true,
)