#!/bin/sh
# Rebind Exar XR21 from in-kernel xr / xr_serial or cdc_acm → cdc_xr_usb_serial (POG422 fork).
#
# Usage: sudo pog422_rebind_xr21.sh

XR_VENDOR="04e2"
XR_USB_DRIVER="cdc_xr_usb_serial"

# udev may fire before xr finishes binding; optional 1s wait when hotplugging.
if [ "${POG422_REBIND_DELAY:-0}" = "1" ]; then
  sleep 1
fi

is_xr_product() {
  case "$1" in
    1420|1421|1422|1424|1410|1411|1412|1414|1400|1401|1402|1403) return 0 ;;
    *) return 1 ;;
  esac
}

driver_name_from_iface() {
  _iface=$1
  [ -L "${_iface}/driver" ] || return 1
  _path=$(readlink -f "${_iface}/driver") || return 1
  _leaf=$(basename "$_path")
  # .../drivers/xr_serial/2-1.4:1.0 → xr_serial
  # .../drivers/xr_serial           → xr_serial (not "drivers")
  case "$_leaf" in
    *:*) basename "$(dirname "$_path")" ;;
    *) echo "$_leaf" ;;
  esac
}

unbind_iface_from_driver() {
  _iface_id=$1
  _driver=$2
  if [ -e "/sys/bus/usb-serial/drivers/${_driver}/unbind" ]; then
    echo "$_iface_id" > "/sys/bus/usb-serial/drivers/${_driver}/unbind"
    return $?
  fi
  if [ -e "/sys/bus/usb/drivers/${_driver}/unbind" ]; then
    echo "$_iface_id" > "/sys/bus/usb/drivers/${_driver}/unbind"
    return $?
  fi
  return 1
}

if [ "$(id -u)" -ne 0 ]; then
  echo "pog422_rebind: run with sudo" >&2
  exit 1
fi

modprobe xr_usb_serial_common 2>/dev/null || true

if [ ! -d "/sys/bus/usb/drivers/${XR_USB_DRIVER}" ]; then
  echo "pog422_rebind: FATAL: ${XR_USB_DRIVER} not registered — run install_pi.sh first" >&2
  exit 1
fi

rebound=0

for usb_dev in /sys/bus/usb/devices/*-*; do
  [ -f "${usb_dev}/idVendor" ] || continue
  [ -f "${usb_dev}/idProduct" ] || continue
  vendor=$(cat "${usb_dev}/idVendor")
  product=$(cat "${usb_dev}/idProduct")
  [ "$vendor" = "$XR_VENDOR" ] || continue
  is_xr_product "$product" || continue

  base=$(basename "$usb_dev")
  echo "pog422_rebind: Exar hat ${base} (${vendor}:${product})"

  for iface in /sys/bus/usb/devices/"${base}":*; do
    [ -e "$iface" ] || continue
    iface_id=$(basename "$iface")
    stock_driver=$(driver_name_from_iface "$iface") || continue
    [ "$stock_driver" = "$XR_USB_DRIVER" ] && continue
    [ "$stock_driver" = "drivers" ] && continue

    echo "pog422_rebind: unbind ${iface_id} from ${stock_driver}"
    if ! unbind_iface_from_driver "$iface_id" "$stock_driver"; then
      echo "  WARN: unbind failed (driver=${stock_driver})" >&2
      continue
    fi

    echo "pog422_rebind: bind ${iface_id} to ${XR_USB_DRIVER}"
    if ! echo "$iface_id" > "/sys/bus/usb/drivers/${XR_USB_DRIVER}/bind" 2>/dev/null; then
      echo "  WARN: bind failed" >&2
      continue
    fi
    rebound=$((rebound + 1))
  done
done

if [ "$rebound" -gt 0 ]; then
  echo "pog422_rebind: rebound ${rebound} interface(s)"
  ls /dev/ttyXRUSB* 2>/dev/null || echo "  (waiting for tty nodes…)"
  exit 0
fi

bound_xr=0
for _ in /sys/bus/usb/drivers/${XR_USB_DRIVER}/*:*; do
  [ -e "$_" ] || continue
  bound_xr=$((bound_xr + 1))
done

if [ "$bound_xr" -gt 0 ]; then
  echo "pog422_rebind: already on ${XR_USB_DRIVER} (${bound_xr} interface(s))"
  ls /dev/ttyXRUSB* 2>/dev/null || true
  exit 0
fi

echo "pog422_rebind: no bound Exar interfaces found to rebind"
echo "  lsusb | grep -i 04e2"
echo "  ls -l /sys/bus/usb/devices/*-*:*  (look for 04e2:1422)"
if [ -d /sys/bus/usb-serial/drivers ]; then
  echo "  usb-serial drivers: $(ls /sys/bus/usb-serial/drivers 2>/dev/null | tr '\n' ' ')"
fi
exit 1
