#!/bin/bash
# install.sh: Driver Installation and Port Mapping Script
# Date: 2026-01-23
# Purpose: Unbind conflicting drivers, install xr17v35x, and map TTY nodes.

EXAR_VID=13a8

# 1. Identify PCIe devices and current active drivers
# Get PCIe domain/bus/device/function (DBDF) numbers
PCIe_unbind=($(lspci -Dkn | grep "$EXAR_VID" | awk '{print $1}'))
# Identify which driver is currently controlling these devices
Orig_driver=($(lspci -Dkn | grep -A 3 "$EXAR_VID" | grep "in use" | awk '{print $5}'))

# 2. Pre-installation checks
if [ -f xr17v35x.ko ]; then
    :
else
    echo "Error: xr17v35x.ko not found. Please run 'make' first."
    exit 1
fi

# Check if the driver is already loaded
if lsmod | grep -q xr17v35x; then
    echo "Info: Driver already installed."
    exit 0
fi

# 3. Unbind devices from generic drivers (e.g., 8250_pci)
# This is necessary to allow xr17v35x to take control of the hardware.
for ((index=0; index<${#PCIe_unbind[@]}; index++)); do
    CURRENT_DRIVER=${Orig_driver[$index]}
    if [ -n "$CURRENT_DRIVER" ]; then
        echo "Unbinding ${PCIe_unbind[$index]} from $CURRENT_DRIVER..."
        echo -n "${PCIe_unbind[$index]}" > "/sys/bus/pci/drivers/$CURRENT_DRIVER/unbind" 2>/dev/null
    fi
done

# 4. Insert the xr17v35x kernel module
insmod xr17v35x.ko
if [ $? -eq 0 ]; then
    echo "Success: Install driver OK!"
    # IMPORTANT: Wait for sysfs to populate the new TTY nodes
    sleep 1
else
    echo "Error: Failed to install driver!"
    exit 1
fi

# 5. Scan and list mapping from PCI hardware to TTY device nodes
echo "---------------------------------------"
for ((index=0; index<${#PCIe_unbind[@]}; index++)); do
    ADDR=${PCIe_unbind[$index]}
    
    # Retrieve Subsystem IDs via lspci
    SVID_SDID=$(lspci -Dkn -s "$ADDR" | grep -A 1 "$ADDR" | grep Subsystem | awk '{print $2}')
    
    # Identify board model and port count based on Subsystem IDs
    PORT=0
    case "$SVID_SDID" in
        1441:0080 ) echo -n "PCIe-S112 mode 232, "; PORT=1;;
        1440:0080 ) echo -n "PCIe-S142 mode 485, "; PORT=1;;
        1441:0091 ) echo -n "PCIe-S114 mode 232, "; PORT=3;;
        1440:0091 ) echo -n "PCIe-S144 mode 485, "; PORT=3;;
        1441:00a0 ) echo -n "PCIe-S118 mode 232, "; PORT=7;;
        1440:00a0 ) echo -n "PCIe-S148 mode 485, "; PORT=7;;
        * ) echo -n "Unknown Device ($SVID_SDID), "; PORT=0;;
    esac

    # Robust detection: Search /sys/class/tty for nodes linked to this PCI address.
    # This works even with nested sysfs structures in newer kernels (6.x+).
    TTY_NODE=$(ls -l /sys/class/tty/ttyXR* 2>/dev/null | grep "$ADDR" | awk -F'/' '{print $NF}' | head -n 1)

    if [ -n "$TTY_NODE" ]; then
        # Extract the base number from the node name (e.g., "ttyXR12" -> "12")
        BASE_NUM=$(echo "$TTY_NODE" | sed 's/[^0-9]*//g')
        END_NUM=$((BASE_NUM + PORT))
        echo "tty$TTY_NODE to ttyXR$END_NUM"
    else
        echo "Error: Could not find ttyXR nodes for hardware at $ADDR"
    fi
done
echo "---------------------------------------"
