Nimbin2git.christianimmanuel.de / Games / ps5_vibration_tester / main.c

ps5_vibration_tester files

last change 2026-09-04 (2 hours ago)

wget https://git.christianimmanuel.de/games/ps5_vibration_tester/archive/ps5_vibration_tester.tar.gz
main.c 3.6 KB · 137 lines 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;
}