ps5_vibration_tester files
wget https://git.christianimmanuel.de/games/ps5_vibration_tester/archive/ps5_vibration_tester.tar.gzmain.c raw
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/input.h>
#include <string.h>
#include <errno.h>
void play_rumble(int fd, __u16 strong, __u16 weak, int duration_ms) {
struct ff_effect effect;
memset(&effect, 0, sizeof(effect));
effect.type = FF_RUMBLE;
effect.id = -1;
effect.u.rumble.strong_magnitude = strong;
effect.u.rumble.weak_magnitude = weak;
effect.replay.length = duration_ms;
effect.replay.delay = 0;
if (ioctl(fd, EVIOCSFF, &effect) < 0) {
perror("Error uploading effect");
return;
}
struct input_event play;
memset(&play, 0, sizeof(play));
play.type = EV_FF;
play.code = effect.id;
play.value = 1;
if (write(fd, &play, sizeof(play)) < 0) {
perror("Error playing effect");
return;
}
usleep(duration_ms * 1000);
play.value = 0;
write(fd, &play, sizeof(play));
}
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "Usage: %s /dev/input/eventX\n", argv[0]);
return 1;
}
const char *device = argv[1];
int fd = open(device, O_RDWR);
if (fd < 0) {
perror("Failed to open device");
return 1;
}
printf("Select motor to test (left, right, both, auto):[auto] ");
char motor[16];
if (!fgets(motor, sizeof(motor), stdin)) {
fprintf(stderr, "Input error\n");
close(fd);
return 1;
}
motor[strcspn(motor, "\n")] = 0; // remove newline
if (strcmp(motor, "auto") == 0 || motor[0] == '\0') {
printf("Auto test: left motor 100%%, pause, right motor 100%%\n");
printf("Testing Left!\n");
play_rumble(fd, 0, 0xFFFF, 1000);
play_rumble(fd, 0, 0xFFFF, 1000);
play_rumble(fd, 0, 0xFFFF, 1000);
printf("Pause!\n");
usleep(1500 * 1000); // 1.5s pause
printf("Testing Right!\n");
play_rumble(fd, 0xFFFF, 0, 1000);
play_rumble(fd, 0xFFFF, 0, 1000);
play_rumble(fd, 0xFFFF, 0, 1000);
close(fd);
return 0;
}
printf("Enter strength (0-100): ");
int strength_percent = 0;
if (scanf("%d", &strength_percent) != 1 || strength_percent < 0 || strength_percent > 100) {
fprintf(stderr, "Invalid strength\n");
close(fd);
return 1;
}
__u16 strong_magnitude = 0;
__u16 weak_magnitude = 0;
if (strcmp(motor, "left") == 0) {
weak_magnitude = strength_percent * 0xFFFF / 100;
} else if (strcmp(motor, "right") == 0) {
strong_magnitude = strength_percent * 0xFFFF / 100;
} else if (strcmp(motor, "both") == 0) {
strong_magnitude = weak_magnitude = strength_percent * 0xFFFF / 100;
} else {
fprintf(stderr, "Invalid motor selection\n");
close(fd);
return 1;
}
struct ff_effect effect;
memset(&effect, 0, sizeof(effect));
effect.type = FF_RUMBLE;
effect.id = -1;
effect.u.rumble.strong_magnitude = strong_magnitude;
effect.u.rumble.weak_magnitude = weak_magnitude;
effect.replay.length = 2000; // 2 seconds
effect.replay.delay = 0;
if (ioctl(fd, EVIOCSFF, &effect) < 0) {
perror("Error uploading effect");
close(fd);
return 1;
}
struct input_event play;
memset(&play, 0, sizeof(play));
play.type = EV_FF;
play.code = effect.id;
play.value = 1;
if (write(fd, &play, sizeof(play)) < 0) {
perror("Error playing effect");
close(fd);
return 1;
}
printf("Rumble started for 2 seconds\n");
sleep(2);
play.value = 0;
write(fd, &play, sizeof(play));
close(fd);
return 0;
}