#!/bin/bash
# autoconfig.sh
# search and map pci gpu deviced to xorg modules

set -eu

DEST_XORG_CONF="$1"

[ -n "$DEST_XORG_CONF" ] || exit 2

pci_line="$(lspci -nnm | grep -F '[0300]' | head -1)" || exit 1
PCI_ADDR="$(echo "$pci_line" | awk '{print $1}')"

pci_line_raw="$(lspci -nm -s "$PCI_ADDR"  | head -1)" || exit 1

PCI_VENDOR_ID="$(echo "$pci_line_raw" | awk -F'"' '{print $4}')"
PCI_DEVICE_ID="$(echo "$pci_line_raw" | awk -F'"' '{print $6}')"

RAW_BUS="$(echo "$pci_line_raw" | awk '{print $1}')"

case "$RAW_BUS" in
    *:*:*.*)
        PCI_DOMAIN="$(echo "$RAW_BUS" | awk -F'[:.]' '{print $1}')"
        PCI_BUS="$(echo "$RAW_BUS"    | awk -F'[:.]' '{print $2}')"
        PCI_DEV="$(echo "$RAW_BUS"    | awk -F'[:.]' '{print $3}')"
        PCI_FUNC="$(echo "$RAW_BUS"   | awk -F'[:.]' '{print $4}')"
        ;;
    *:*.*)
        PCI_DOMAIN="0000"
        PCI_BUS="$(echo "$RAW_BUS"    | awk -F'[:.]' '{print $1}')"
        PCI_DEV="$(echo "$RAW_BUS"    | awk -F'[:.]' '{print $2}')"
        PCI_FUNC="$(echo "$RAW_BUS"   | awk -F'[:.]' '{print $3}')"
        ;;
    *)
        echo "ERROR: invalid PCI address format: $RAW_BUS" >&2
        exit 2
        ;;
esac

if [ "$PCI_DOMAIN" = "0000" ]; then
    XORG_BUSID="PCI:$((16#$PCI_BUS)):$((16#$PCI_DEV)):$PCI_FUNC"
else
    XORG_BUSID=""
    echo "WARNING: non-zero PCI domain detected, skipping BusID on old Xorg"
fi

logger -t retrodebian-xorg-autoconfig "GPU detected !"
logger -t retrodebian-xorg-autoconfig "  Line    : $pci_line"
logger -t retrodebian-xorg-autoconfig "  Address : $PCI_ADDR"
logger -t retrodebian-xorg-autoconfig "  Vendor  : $PCI_VENDOR_ID"
logger -t retrodebian-xorg-autoconfig "  Device  : $PCI_DEVICE_ID"
logger -t retrodebian-xorg-autoconfig "  RawBus  : $RAW_BUS"
logger -t retrodebian-xorg-autoconfig "  Domain   : $PCI_DOMAIN"
logger -t retrodebian-xorg-autoconfig "  Bus   : $PCI_BUS"
logger -t retrodebian-xorg-autoconfig "  Dev   : $PCI_DEV"
logger -t retrodebian-xorg-autoconfig "  Func   : $PCI_FUNC"
logger -t retrodebian-xorg-autoconfig "  XorgBusID   : $XORG_BUSID"




ROOT_DIR="/opt/retrodebian/xorg"
XORG_FILE_BASENAME="xorg.conf"
TEMPLATE_XORG_FILE="${XORG_FILE_BASENAME}.template"
TMP_XORG_FILE_PATH="$(mktemp)"

cp "${ROOT_DIR}/${TEMPLATE_XORG_FILE}" "${TMP_XORG_FILE_PATH}"

MATCHED=0

for module in "${ROOT_DIR}/video-detect.d/"*.sh; do
    [ -f "$module" ] || continue

    logger -t retrodebian-xorg-autoconfig "Trying module: $module"

    if PCI_ADDR="$PCI_ADDR" \
       PCI_VENDOR_ID="$PCI_VENDOR_ID" \
       PCI_DEVICE_ID="$PCI_DEVICE_ID" \
       XORG_BUSID="$XORG_BUSID" \
       "$module" "${TMP_XORG_FILE_PATH}"
    then
        logger -t retrodebian-xorg-autoconfig "Matched module: $module"
        MATCHED=1
        break
    else
        rc=$?
        if [ "$rc" -ne 1 ]; then
            logger -p daemon.err -t retrodebian-xorg-autoconfig "ERROR: module failed: $module"
        fi
    fi
done

if [ -n "$XORG_BUSID" ]; then
    sed -i -e "s|{DeviceBusID}|$XORG_BUSID|g" "${TMP_XORG_FILE_PATH}" || exit 2
else
    sed -i \
        -e '/^[[:space:]]*BusID[[:space:]]*"{DeviceBusID}"[[:space:]]*$/d' \
        "${TMP_XORG_FILE_PATH}" || exit 2
fi

[ "$MATCHED" -eq 1 ] || exit 2

MATCHED=0

for module in "${ROOT_DIR}/mouse-detect.d/"*.sh; do
    [ -f "$module" ] || continue

    logger -t retrodebian-xorg-autoconfig "Trying module: $module"

    if "$module" "${TMP_XORG_FILE_PATH}"
    then
        logger -t retrodebian-xorg-autoconfig "Matched module: $module"
        MATCHED=1
        break
    else
        rc=$?
        if [ "$rc" -ne 1 ]; then
            logger -p daemon.err -t retrodebian-xorg-autoconfig "ERROR: module failed: $module"
        fi
    fi
done

[ "$MATCHED" -eq 1 ] || exit 2

cp -f "${TMP_XORG_FILE_PATH}" "$DEST_XORG_CONF"
rm -f "${TMP_XORG_FILE_PATH}"

exit 0