#!/usr/bin/perl
# Copyright 2026 SUSE LLC
# SPDX-License-Identifier: GPL-2.0-or-later

=head1 NAME

openterface-input - os-autoinst GENERAL_HW_INPUT_CMD for the Openterface Mini-KVM

=head1 SYNOPSIS

    openterface-input [--port /dev/ttyUSB0] [--baud 115200]
                      [--width 1920] [--height 1080] [--device /dev/video0]

Reads input events on stdin, one per line, in the protocol spoken by
os-autoinst's consoles::video_stream (see os-autoinst doc/backend_vars.md,
GENERAL_HW_INPUT_CMD):

    mouse_move <x> <y>     move pointer to framebuffer pixel coordinates
    mouse_button <mask>    press/release buttons (bit 0 left, 1 right, 2 middle)
    <key-combo>            anything else, e.g. "a", "ret", "ctrl-alt-f2"

Each processed event is confirmed with a line C<ok> on stdout.

Pixel coordinates are scaled into the CH9329's fixed 0..4095 absolute space
using the capture resolution, autodetected from the Openterface video device
unless --width/--height are given. Pass options via GENERAL_HW_INPUT_ARGS.

=cut

use strict;
use warnings;
use Getopt::Long;
use Openterface::Serial;
use Openterface::Keymap;
use Openterface::Video;

my %opt;
GetOptions(\%opt, 'port=s', 'baud=i', 'width=i', 'height=i', 'device=s', 'help')
  or die "Usage: $0 [--port DEV] [--baud N] [--width N] [--height N] [--device VIDEODEV]\n";
if ($opt{help}) { exec 'perldoc', $0 }

my ($width, $height) = ($opt{width}, $opt{height});
($width, $height) = Openterface::Video::resolution($opt{device})
  unless $width && $height;

my $kvm = Openterface::Serial->new(
    ($opt{port} ? (port => $opt{port}) : ()),
    ($opt{baud} ? (baud => $opt{baud}) : ()),
);

STDOUT->autoflush(1);

sub scale ($$) {
    my ($value, $range) = @_;
    my $scaled = int($value * Openterface::Serial::ABS_RANGE / $range);
    $scaled = 0 if $scaled < 0;
    $scaled = Openterface::Serial::ABS_RANGE - 1 if $scaled >= Openterface::Serial::ABS_RANGE;
    return $scaled;
}

while (defined(my $line = <STDIN>)) {
    chomp $line;
    next unless length $line;
    my $ok = eval {
        if ($line =~ /^mouse_move\s+(-?\d+)\s+(-?\d+)$/) {
            $kvm->mouse_move_abs(scale($1, $width), scale($2, $height));
        }
        elsif ($line =~ /^mouse_button\s+(\d+)$/) {
            $kvm->mouse_button($1 & 0x07);
        }
        else {
            $kvm->key_tap(Openterface::Keymap::parse_combo($line));
        }
        1;
    };
    if ($ok) {
        print "ok\n";
    }
    else {
        my $error = $@ // 'unknown error';
        chomp $error;
        print "error: $error\n";
    }
}
