#!/bin/bash
# usb-driver-map.sh
# Show connected USB devices and which kernel modules/drivers support them.

set -eu

SYSUSB=/sys/bus/usb/devices

for dev in "$SYSUSB"/*; do
  [ -d "$dev" ] || continue
  [ -f "$dev/idVendor" ] || continue
  [ -f "$dev/idProduct" ] || continue

  vendor=$(cat "$dev/idVendor" 2>/dev/null || echo "?")
  product=$(cat "$dev/idProduct" 2>/dev/null || echo "?")
  mfr=$(cat "$dev/manufacturer" 2>/dev/null || echo "")
  prod=$(cat "$dev/product" 2>/dev/null || echo "")
  serial=$(cat "$dev/serial" 2>/dev/null || echo "")
  busdev=$(basename "$dev")

  echo "============================================================"
  echo "USB device: $busdev"
  echo "VID:PID    : $vendor:$product"
  [ -n "$mfr" ] && echo "Maker      : $mfr"
  [ -n "$prod" ] && echo "Product    : $prod"
  [ -n "$serial" ] && echo "Serial     : $serial"

  if [ -L "$dev/driver" ]; then
    driver=$(basename "$(readlink "$dev/driver")")
    echo "USB driver : $driver"
  else
    echo "USB driver : (none bound at device level)"
  fi

  echo
  echo "Interfaces:"
  found_if=0
  for ifc in "$SYSUSB"/"${busdev}":*; do
    [ -d "$ifc" ] || continue
    found_if=1
    ifname=$(basename "$ifc")

    cls=$(cat "$ifc/bInterfaceClass" 2>/dev/null || echo "")
    sub=$(cat "$ifc/bInterfaceSubClass" 2>/dev/null || echo "")
    proto=$(cat "$ifc/bInterfaceProtocol" 2>/dev/null || echo "")

    printf "  %s\n" "$ifname"
    [ -n "$cls" ] && printf "    class/sub/proto : %s/%s/%s\n" "$cls" "$sub" "$proto"

    if [ -L "$ifc/driver" ]; then
      ifdrv=$(basename "$(readlink "$ifc/driver")")
      printf "    bound driver    : %s\n" "$ifdrv"

      modpath="/sys/bus/usb/drivers/$ifdrv/module"
      if [ -L "$modpath" ]; then
        mod=$(basename "$(readlink "$modpath")")
        printf "    kernel module   : %s\n" "$mod"
      else
        printf "    kernel module   : built into kernel or unknown\n"
      fi
    else
      printf "    bound driver    : (none)\n"
    fi
  done

  [ "$found_if" -eq 0 ] && echo "  (no interface directories found)"
  echo
done

