https://github.com/linuxhw/hw-probe, what it does it run and has to upload it to there website - https://linux-hardware.org/ to get a report on the drivers status of our linux pc.
Sample report - https://linux-hardware.org/?probe=0c82de2288
I have made a script to show the hardware report as html without uploading using YAD,
Yad also shows the driver details and help use to locate the driver file. You can also launch the HTML report from yad.
the script uses Appimage of hwprobe and yad.
I am uploading a module for this with all the scripts and desktop files.
https://www.mediafire.com/file/9vtjxfny ... 5.xzm/file
Hope this helps somebody. All modifications are welcome to make this better
Launch script
Code: Select all
#!/usr/bin/env bash
#
# Launcher script to run hardware probe as root and YAD viewer as normal user.
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
echo "=========================================="
echo " Starting Hardware Probe Data Collection "
echo "=========================================="
echo "Requesting authentication..."
echo
# 1. Run probe script as root via pkexec (Single Password Prompt)
if pkexec "$SCRIPT_DIR/HwProbe_offline.sh"; then
echo
echo "Data collection complete! Launching YAD..."
# 2. Launch YAD completely detached from this terminal session
nohup "$SCRIPT_DIR/hwprobe-yad" >/dev/null 2>&1 &
# 3. Small pause then exit terminal
sleep 0.5
exit 0
else
echo
echo "Authentication failed or cancelled."
read -rp "Press Enter to close..."
exit 1
fiCode: Select all
#!/usr/bin/env bash
#
# Generates an offline HTML hardware report matching linux-hardware.org
# with syntax-highlighted log pages and deep kernel module path resolution.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SCRIPT_PATH="${SCRIPT_DIR}/$(basename "${BASH_SOURCE[0]}")"
OUTPUT_DIR="${SCRIPT_DIR}/hw_probe_local"
REPORT_FILE="${SCRIPT_DIR}/hardware_report.html"
LOGS_HTML_DIR="${SCRIPT_DIR}/logs_html"
if [ "$EUID" -ne 0 ]; then
echo "Notice: Root privileges required. Escalating with sudo..."
exec sudo "$SCRIPT_PATH" "$@"
fi
HW_PROBE_BIN=""
APPIMAGE_PATH=$(find "$SCRIPT_DIR" -maxdepth 1 -type f -name "hw-probe-*.AppImage" | head -n1 || true)
if [ -x "/usr/bin/hw-probe" ]; then
HW_PROBE_BIN="/usr/bin/hw-probe"
elif [ -n "$APPIMAGE_PATH" ] && [ -f "$APPIMAGE_PATH" ]; then
chmod +x "$APPIMAGE_PATH" 2>/dev/null || true
HW_PROBE_BIN="$APPIMAGE_PATH"
else
echo "Error: Neither system hw-probe nor any hw-probe-*.AppImage was found in ${SCRIPT_DIR}!"
exit 1
fi
echo "==> Using binary: ${HW_PROBE_BIN}"
echo "==> Gathering local hardware probe logs..."
rm -rf "$OUTPUT_DIR" "$LOGS_HTML_DIR"
mkdir -p "$OUTPUT_DIR" "$LOGS_HTML_DIR"
"$HW_PROBE_BIN" -all -save "$OUTPUT_DIR" > /dev/null 2>&1 || true
# Extract hw.info tarballs recursively if created
find "$OUTPUT_DIR" -type f \( -name "*.txz" -o -name "*.tar.gz" -o -name "*.tgz" \) | while read -r archive; do
tar -xf "$archive" -C "$OUTPUT_DIR" 2>/dev/null || true
done
# Locate target log files
HW_INFO_DIR=$(find "$OUTPUT_DIR" -type d -name "hw.info" | head -n1 || true)
if [ -z "$HW_INFO_DIR" ]; then
HW_INFO_DIR="$OUTPUT_DIR"
fi
# System Metadata Retrieval
HOSTNAME_VAL=$(cat "$HW_INFO_DIR/hostname" 2>/dev/null || hostname)
OS_VAL=$(cat "$HW_INFO_DIR/os" 2>/dev/null || echo "Linux")
ARCH_VAL=$(uname -m 2>/dev/null || echo "x86_64")
KERNEL_VAL=$(cat "$HW_INFO_DIR/kernel" 2>/dev/null || uname -r)
VENDOR_VAL=$(cat "$HW_INFO_DIR/sys_vendor" 2>/dev/null || cat "$HW_INFO_DIR/dmi/sys_vendor" 2>/dev/null || echo "Generic")
MODEL_VAL=$(cat "$HW_INFO_DIR/product_name" 2>/dev/null || cat "$HW_INFO_DIR/dmi/product_name" 2>/dev/null || echo "System")
YEAR_VAL=$(cat "$HW_INFO_DIR/product_year" 2>/dev/null || echo "N/A")
HWID_VAL=$(cat "$HW_INFO_DIR/probe.id" 2>/dev/null || echo "Offline")
TYPE_VAL=$(cat "$HW_INFO_DIR/chassis_type" 2>/dev/null || echo "Desktop/Laptop")
DE_VAL=$(cat "$HW_INFO_DIR/desktop" 2>/dev/null || echo "${DESKTOP_SESSION:-${XDG_CURRENT_DESKTOP:-Unknown}}")
# Log Categorization
get_log_category() {
local fname
fname=$(echo "$1" | tr '[:upper:]' '[:lower:]')
case "$fname" in
*hwinfo*|*devices*|*lspci*|*lsusb*|*lshw*|*lscpu*|*lsblk*|*lsscsi*|*dmidecode*|*dmi*|*pci*|*usb*|*cpu*|*bios*|*edid*|*input*)
echo "Hardware & Devices" ;;
*nmcli*|*iwconfig*|*ifconfig*|*ip*|*route*|*net*|*wpa*|*fstab*|*mount*|*smartctl*|*hdparm*|*disk*|*nvme*)
echo "Network & Storage" ;;
*dmesg*|*uname*|*uptime*|*modules*|*lsmod*|*sysctl*|*cmdline*|*hostname*|*os*|*kernel*|*systemd*)
echo "System & Kernel" ;;
*xorg*|*wayland*|*glxinfo*|*vulkan*|*drm*|*display*|*gpu*)
echo "Graphics & Display" ;;
*alsa*|*sound*|*audio*|*pulse*|*pipewire*|*amixer*|*aplay*)
echo "Audio & Sound" ;;
*)
echo "Other Logs" ;;
esac
}
# Deep Driver Module Resolution
resolve_driver_path() {
local drv="$1"
if [ -z "$drv" ] || [ "$drv" = "-" ]; then
echo "-"
return
fi
local mod_path=""
mod_path=$(modinfo -n "$drv" 2>/dev/null || true)
if [ -n "$mod_path" ] && [[ "$mod_path" != "(builtin)" ]] && [ -f "$mod_path" ]; then
echo "$mod_path"
return
fi
mod_path=$(modprobe --show-depends "$drv" 2>/dev/null | awk '/insmod/ {print $2}' | tail -n1 || true)
if [ -n "$mod_path" ] && [ -f "$mod_path" ]; then
echo "$mod_path"
return
fi
local kver
kver=$(uname -r)
mod_path=$(find "/lib/modules/$kver" -type f \( -name "${drv}.ko" -o -name "${drv}.ko.xz" -o -name "${drv}.ko.zst" -o -name "${drv}.ko.gz" \) 2>/dev/null | head -n1 || true)
if [ -n "$mod_path" ]; then
echo "$mod_path"
return
fi
if [ -d "/sys/module/$drv" ]; then
echo "/sys/module/$drv"
return
fi
echo "builtin / $drv"
}
echo "==> Rendering separate HTML pages for logs..."
find "$HW_INFO_DIR" -type f ! -name "*.txz" ! -name "*.gz" | sort | while read -r logfile; do
REL_PATH="${logfile#$HW_INFO_DIR/}"
SAFE_NAME=$(echo "$REL_PATH" | tr '/' '_').html
TARGET_HTML="${LOGS_HTML_DIR}/${SAFE_NAME}"
if file "$logfile" | grep -q "text"; then
HIGHLIGHTED_LOG=$(sed 's/&/\&/g; s/</\</g; s/>/\>/g' "$logfile" | awk '
{
gsub(/(Intel|AMD|NVIDIA|Realtek|Broadcom|Qualcomm|Samsung|Lenovo|Dell|HP|Asus|Acer|Gigabyte|MSI|Crucial|Kingston|Western Digital|Seagate|Logitech|Apple|Atheros)/, "<span class=\"hl-vendor\">&</span>")
gsub(/(driver|Driver|module|Module|kernel|Kernel|sysfs|pci|usb|i2c|nvme|ahci|snd_[a-z0-9_]+|iwlwifi|ath9k|amdgpu|i915|nouveau|nvidia)[ :=]/, "<span class=\"hl-driver\">&</span>")
gsub(/([0-9]+(\.[0-9]+)?\s*(GHz|MHz|GiB|MiB|KiB|GB|MB|KB|TB|%|Core|Cores|Threads|bits|bit))/, "<span class=\"hl-val\">&</span>")
gsub(/([0-9a-fA-F]{4}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}\.[0-9]|[0-9a-fA-F]{4}:[0-9a-fA-F]{4})/, "<span class=\"hl-id\">&</span>")
gsub(/(\/dev\/|\/sys\/|\/lib\/|\/etc\/|\/proc\/)[a-zA-Z0-9_\/\.\-]+/, "<span class=\"hl-path\">&</span>")
print $0
}')
cat <<EOF > "$TARGET_HTML"
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Log: ${REL_PATH}</title>
<style>
body { background: #18191a; color: #e4e6eb; font-family: monospace; font-size: 15px; padding: 25px; line-height: 1.5; }
h2 { color: #4599df; font-family: sans-serif; font-size: 1.5em; }
a { color: #61afef; text-decoration: none; font-family: sans-serif; font-size: 1.1em; font-weight: bold; }
a:hover { text-decoration: underline; }
pre { background: #242526; padding: 18px; border-radius: 6px; overflow-x: auto; border: 1px solid #3a3b3c; font-size: 0.95em; color: #e4e6eb; line-height: 1.5; }
.hl-vendor { color: #e5c07b; font-weight: bold; }
.hl-driver { color: #ce9178; font-weight: bold; }
.hl-val { color: #98c379; font-weight: bold; }
.hl-id { color: #e06c75; font-weight: bold; }
.hl-path { color: #61afef; }
</style>
</head>
<body>
<p><a href="../hardware_report.html">← Back to Main Report</a></p>
<h2>Log File: ${REL_PATH}</h2>
<pre>${HIGHLIGHTED_LOG}</pre>
</body>
</html>
EOF
fi
done
echo "==> Rendering primary hardware report..."
cat <<EOF > "$REPORT_FILE"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hardware Probe - ${HOSTNAME_VAL}</title>
<style>
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: #18191a; color: #e4e6eb; margin: 0; padding: 25px; font-size: 15px; }
h2 { font-size: 1.4em; color: #ffffff; margin-top: 30px; margin-bottom: 15px; }
h3.cat-title { color: #4599df; font-size: 1.2em; border-bottom: 1px solid #3a3b3c; padding-bottom: 6px; margin-top: 20px; margin-bottom: 12px; }
.sys-card { background: #242526; padding: 20px; border-radius: 8px; margin-bottom: 25px; border: 1px solid #3a3b3c; }
.sys-title { font-size: 1.3em; font-weight: bold; color: #4599df; margin-bottom: 15px; }
.sys-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px; font-size: 1em; }
.sys-item { background: #1c1e21; padding: 10px 14px; border-radius: 6px; border: 1px solid #3a3b3c; }
.sys-label { color: #b0b3b8; font-weight: bold; }
.sys-val { color: #ffffff; font-weight: 500; }
table.hw-table { width: 100%; border-collapse: collapse; background: #242526; border-radius: 8px; overflow: hidden; border: 1px solid #3a3b3c; margin-bottom: 30px; }
table.hw-table th { background: #1c1e21; color: #4599df; text-align: left; padding: 12px 14px; font-size: 0.95em; text-transform: uppercase; border-bottom: 2px solid #3a3b3c; }
table.hw-table td { padding: 11px 14px; border-bottom: 1px solid #3a3b3c; font-size: 0.95em; line-height: 1.4; }
table.hw-table tr:hover { background: #3a3b3c; }
.bus-id { font-family: monospace; color: #61afef; font-weight: bold; font-size: 1.05em; }
.vendor { font-weight: bold; color: #ffffff; }
.driver { font-family: monospace; color: #ce9178; font-size: 0.95em; }
.drv-path { font-family: monospace; color: #98c379; font-size: 0.85em; word-break: break-all; }
.status-works { background: #1b4721; color: #4caf50; padding: 3px 8px; border-radius: 4px; font-size: 0.88em; font-weight: bold; }
.status-detected { background: #4a2c00; color: #ff9800; padding: 3px 8px; border-radius: 4px; font-size: 0.88em; font-weight: bold; }
.status-nodriver { background: #4a0000; color: #f44336; padding: 3px 8px; border-radius: 4px; font-size: 0.88em; font-weight: bold; }
.logs-container { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 15px; }
.log-link { background: #242526; border: 1px solid #3a3b3c; padding: 8px 14px; border-radius: 5px; color: #61afef; text-decoration: none; font-size: 0.98em; font-family: monospace; font-weight: bold; }
.log-link:hover { background: #3a3b3c; color: #ffffff; }
</style>
</head>
<body>
<div class="sys-card">
<div class="sys-title">System Overview</div>
<div class="sys-grid">
<div class="sys-item"><span class="sys-label">System:</span> <span class="sys-val">${OS_VAL}</span></div>
<div class="sys-item"><span class="sys-label">Arch:</span> <span class="sys-val">${ARCH_VAL}</span></div>
<div class="sys-item"><span class="sys-label">Kernel:</span> <span class="sys-val">${KERNEL_VAL}</span></div>
<div class="sys-item"><span class="sys-label">Vendor:</span> <span class="sys-val">${VENDOR_VAL}</span></div>
<div class="sys-item"><span class="sys-label">Model:</span> <span class="sys-val">${MODEL_VAL}</span></div>
<div class="sys-item"><span class="sys-label">Year:</span> <span class="sys-val">${YEAR_VAL}</span></div>
<div class="sys-item"><span class="sys-label">HWid:</span> <span class="sys-val">${HWID_VAL}</span></div>
<div class="sys-item"><span class="sys-label">Type:</span> <span class="sys-val">${TYPE_VAL}</span></div>
<div class="sys-item"><span class="sys-label">DE:</span> <span class="sys-val">${DE_VAL}</span></div>
</div>
</div>
<h2>Devices Table</h2>
<table class="hw-table">
<thead>
<tr>
<th>BUS ID/Class</th>
<th>Status</th>
<th>Type</th>
<th>Driver</th>
<th>Vendor</th>
<th>Device</th>
<th>Driver Module (.ko) Path</th>
</tr>
</thead>
<tbody>
EOF
DEVICES_FILE=$(find "$OUTPUT_DIR" -type f -name "devices" 2>/dev/null | head -n1 || true)
if [ -n "$DEVICES_FILE" ] && [ -s "$DEVICES_FILE" ]; then
while IFS=';' read -r bus_id_class vendor_id status_val type_val driver_val vendor_val device_val company_val rest || [ -n "$bus_id_class" ]; do
[[ "$bus_id_class" =~ ^# ]] && continue
[ -z "$bus_id_class" ] && continue
status_val=${status_val:-detected}
type_val=${type_val:--}
driver_val=${driver_val:--}
vendor_val=${vendor_val:--}
device_val=${device_val:--}
if [ "$status_val" = "works" ]; then
st_html="<span class=\"status-works\">works</span>"
elif [ "$status_val" = "detected" ]; then
st_html="<span class=\"status-detected\">detected</span>"
else
st_html="<span class=\"status-nodriver\">${status_val}</span>"
fi
drv_path=$(resolve_driver_path "$driver_val")
cat <<TR >> "$REPORT_FILE"
<tr>
<td class="bus-id">${bus_id_class}</td>
<td>${st_html}</td>
<td>${type_val}</td>
<td class="driver">${driver_val}</td>
<td class="vendor">${vendor_val}</td>
<td>${device_val}</td>
<td class="drv-path">${drv_path}</td>
</tr>
TR
done < "$DEVICES_FILE"
fi
cat <<EOF >> "$REPORT_FILE"
</tbody>
</table>
<h2>Hardware Probe Logs</h2>
EOF
CATEGORIES=("Audio & Sound" "Graphics & Display" "Hardware & Devices" "Network & Storage" "System & Kernel" "Other Logs")
for cat_name in "${CATEGORIES[@]}"; do
FOUND_LOGS=()
while IFS= read -r html_page; do
[ -z "$html_page" ] && continue
REL_NAME=$(basename "$html_page")
DISPLAY_NAME=$(echo "$REL_NAME" | sed 's/\.html$//; s/_/\//g')
LOG_CAT=$(get_log_category "$DISPLAY_NAME")
if [ "$LOG_CAT" = "$cat_name" ]; then
FOUND_LOGS+=("<a class=\"log-link\" href=\"logs_html/${REL_NAME}\" target=\"_blank\">${DISPLAY_NAME}</a>")
fi
done < <(find "$LOGS_HTML_DIR" -name "*.html" | sort)
if [ ${#FOUND_LOGS[@]} -gt 0 ]; then
echo " <h3 class=\"cat-title\">${cat_name}</h3>" >> "$REPORT_FILE"
echo " <div class=\"logs-container\">" >> "$REPORT_FILE"
for log_btn in "${FOUND_LOGS[@]}"; do
echo " ${log_btn}" >> "$REPORT_FILE"
done
echo " </div>" >> "$REPORT_FILE"
fi
done
cat <<EOF >> "$REPORT_FILE"
</body>
</html>
EOF
# Hand file ownership back to the user who invoked pkexec/sudo
if [ -n "${PKEXEC_UID:-}" ]; then
REAL_USER=$(id -nu "$PKEXEC_UID")
REAL_GROUP=$(id -ng "$PKEXEC_UID")
chown -R "$REAL_USER:$REAL_GROUP" "$OUTPUT_DIR"
elif [ -n "${SUDO_USER:-}" ]; then
chown -R "$SUDO_USER:$SUDO_USER" "$OUTPUT_DIR"
fi
echo "==> Report successfully generated at: ${REPORT_FILE}"Code: Select all
#!/usr/bin/env bash
#
# YAD GUI Viewer with Inline Positional Column Action Handlers
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
OUTPUT_DIR="${SCRIPT_DIR}/hw_probe_local"
if [ ! -d "$OUTPUT_DIR" ]; then
echo "Error: Directory ${OUTPUT_DIR} does not exist. Run Hw-Probe_offline.sh first."
exit 1
fi
HW_INFO_DIR=$(find "$OUTPUT_DIR" -type d -name "hw.info" | head -n1 || true)
[ -z "$HW_INFO_DIR" ] && HW_INFO_DIR="$OUTPUT_DIR"
OS_VAL=$(cat "$HW_INFO_DIR/os" 2>/dev/null || echo "Linux")
ARCH_VAL=$(uname -m 2>/dev/null || echo "x86_64")
KERNEL_VAL=$(cat "$HW_INFO_DIR/kernel" 2>/dev/null || uname -r)
VENDOR_VAL=$(cat "$HW_INFO_DIR/sys_vendor" 2>/dev/null || cat "$HW_INFO_DIR/dmi/sys_vendor" 2>/dev/null || echo "Generic")
MODEL_VAL=$(cat "$HW_INFO_DIR/product_name" 2>/dev/null || cat "$HW_INFO_DIR/dmi/product_name" 2>/dev/null || echo "System")
YEAR_VAL=$(cat "$HW_INFO_DIR/product_year" 2>/dev/null || echo "N/A")
HWID_VAL=$(cat "$HW_INFO_DIR/probe.id" 2>/dev/null || echo "Offline")
TYPE_VAL=$(cat "$HW_INFO_DIR/chassis_type" 2>/dev/null || echo "Desktop/Laptop")
DE_VAL=$(cat "$HW_INFO_DIR/desktop" 2>/dev/null || echo "${DESKTOP_SESSION:-${XDG_CURRENT_DESKTOP:-Unknown}}")
# XML Escaping for Pango
xml_escape() {
sed 's/&/\&/g; s/</\</g; s/>/\>/g; s/"/\"/g; s/'\''/\'/g' <<< "$1"
}
# Log Categorization
get_log_category() {
local fname
fname=$(echo "$1" | tr '[:upper:]' '[:lower:]')
case "$fname" in
*hwinfo*|*devices*|*lspci*|*lsusb*|*lshw*|*lscpu*|*lsblk*|*lsscsi*|*dmidecode*|*dmi*|*pci*|*usb*|*cpu*|*bios*|*edid*|*input*)
echo "Hardware & Devices" ;;
*nmcli*|*iwconfig*|*ifconfig*|*ip*|*route*|*net*|*wpa*|*fstab*|*mount*|*smartctl*|*hdparm*|*disk*|*nvme*)
echo "Network & Storage" ;;
*dmesg*|*uname*|*uptime*|*modules*|*lsmod*|*sysctl*|*cmdline*|*hostname*|*os*|*kernel*|*systemd*)
echo "System & Kernel" ;;
*xorg*|*wayland*|*glxinfo*|*vulkan*|*drm*|*display*|*gpu*)
echo "Graphics & Display" ;;
*alsa*|*sound*|*audio*|*pulse*|*pipewire*|*amixer*|*aplay*)
echo "Audio & Sound" ;;
*)
echo "Other Logs" ;;
esac
}
# Driver Module Path Resolver
resolve_driver_path() {
local drv="$1"
if [ -z "$drv" ] || [ "$drv" = "-" ]; then
echo "-"
return
fi
local mod_path=""
mod_path=$(modinfo -n "$drv" 2>/dev/null || true)
if [ -n "$mod_path" ] && [[ "$mod_path" != "(builtin)" ]] && [ -f "$mod_path" ]; then
echo "$mod_path"
return
fi
mod_path=$(modprobe --show-depends "$drv" 2>/dev/null | awk '/insmod/ {print $2}' | tail -n1 || true)
if [ -n "$mod_path" ] && [ -f "$mod_path" ]; then
echo "$mod_path"
return
fi
local kver
kver=$(uname -r)
mod_path=$(find "/lib/modules/$kver" -type f \( -name "${drv}.ko" -o -name "${drv}.ko.xz" -o -name "${drv}.ko.zst" -o -name "${drv}.ko.gz" \) 2>/dev/null | head -n1 || true)
if [ -n "$mod_path" ]; then
echo "$mod_path"
return
fi
if [ -d "/sys/module/$drv" ]; then
echo "/sys/module/$drv"
return
fi
echo "builtin / $drv"
}
GRID_DATA=$(mktemp)
LOG_TEMP=$(mktemp)
LOG_DATA=$(mktemp)
trap 'rm -f "$GRID_DATA" "$LOG_TEMP" "$LOG_DATA"' EXIT
DEVICES_FILE=$(find "$OUTPUT_DIR" -type f -name "devices" | head -n 1 || true)
# Process Devices
if [ -n "$DEVICES_FILE" ] && [ -f "$DEVICES_FILE" ]; then
while IFS=';' read -r bus_id_class vendor_id status_val type_val driver_val vendor_val device_val company_val rest || [ -n "$bus_id_class" ]; do
[[ "$bus_id_class" =~ ^# ]] && continue
[ -z "$bus_id_class" ] && continue
status_val=${status_val:-detected}
type_val=${type_val:--}
driver_val=${driver_val:--}
vendor_val=${vendor_val:--}
device_val=${device_val:--}
bus_esc=$(xml_escape "$bus_id_class")
type_esc=$(xml_escape "$type_val")
driver_esc=$(xml_escape "$driver_val")
vendor_esc=$(xml_escape "$vendor_val")
device_esc=$(xml_escape "$device_val")
bus_id="<span foreground=\"#61afef\" font_family=\"monospace\"><b>${bus_esc}</b></span>"
if [ "$status_val" = "works" ]; then
st="<span foreground=\"#4caf50\"><b>works</b></span>"
elif [ "$status_val" = "detected" ]; then
st="<span foreground=\"#ff9800\"><b>detected</b></span>"
else
st="<span foreground=\"#f44336\"><b>$(xml_escape "$status_val")</b></span>"
fi
drv_f="<span foreground=\"#ce9178\" font_family=\"monospace\">${driver_esc}</span>"
v_f="<span foreground=\"#ffffff\"><b>${vendor_esc}</b></span>"
drv_path=$(resolve_driver_path "$driver_val")
path_esc=$(xml_escape "$drv_path")
path_f="<span foreground=\"#98c379\" font_family=\"monospace\">${path_esc}</span>"
printf "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n" "$bus_id" "$st" "$type_esc" "$drv_f" "$v_f" "$device_esc" "$path_f" "$drv_path" >> "$GRID_DATA"
done < "$DEVICES_FILE"
fi
# Process Logs
find "$HW_INFO_DIR" -type f ! -name "*.txz" ! -name "*.gz" | while read -r f; do
if file "$f" | grep -q "text"; then
REL_NAME="${f#$HW_INFO_DIR/}"
CAT=$(get_log_category "$REL_NAME")
printf "%s|%s|%s\n" "$CAT" "$REL_NAME" "$f" >> "$LOG_TEMP"
fi
done
sort -t'|' -k1,1 -k2,2 "$LOG_TEMP" | while IFS='|' read -r CAT REL_NAME f; do
CAT_ESC=$(xml_escape "$CAT")
REL_ESC=$(xml_escape "$REL_NAME")
CAT_FMT="<span foreground=\"#4599df\"><b>${CAT_ESC}</b></span>"
LOG_FMT="<span foreground=\"#61afef\" font_family=\"monospace\"><b>${REL_ESC}</b></span>"
printf "%s\n%s\n%s\n" "$CAT_FMT" "$LOG_FMT" "$f" >> "$LOG_DATA"
done
KEY=$RANDOM
# Tab 1: System Info
yad --plug=$KEY --tabnum=1 --form \
--field="System:":RO "$OS_VAL" \
--field="Arch:":RO "$ARCH_VAL" \
--field="Kernel:":RO "$KERNEL_VAL" \
--field="Vendor:":RO "$VENDOR_VAL" \
--field="Model:":RO "$MODEL_VAL" \
--field="Year:":RO "$YEAR_VAL" \
--field="HWid:":RO "$HWID_VAL" \
--field="Type:":RO "$TYPE_VAL" \
--field="DE:":RO "$DE_VAL" --columns=3 &
# Tab 2: Devices Table (Checks nemo first, falls back to xdg-open/thunar)
yad --plug=$KEY --tabnum=2 --list \
--markup \
--column="BUS ID/Class" \
--column="Status" \
--column="Type" \
--column="Driver" \
--column="Vendor" \
--column="Device" \
--column="Driver Path (.ko)" \
--column="Raw Path":HD \
--dclick-action='bash -c '\''
target="${8#builtin / }"
if [ -f "$target" ]; then target=$(dirname "$target"); fi
if [ -d "$target" ]; then
nemo "$target" 2>/dev/null || xdg-open "$target" 2>/dev/null || thunar "$target" 2>/dev/null || pcmanfm "$target" 2>/dev/null
fi
'\'' _ %s' \
--grid-lines=both < "$GRID_DATA" &
# Tab 3: Sorted Categorized Logs ($3 maps to 3rd column: Full File Path)
yad --plug=$KEY --tabnum=3 --list \
--markup \
--column="Category" \
--column="Log File" \
--column="Full Path":HD \
--dclick-action='bash -c '\''
file="$3"
if [ -f "$file" ]; then
yad --text-info --title="Log View: $(basename "$file")" --filename="$file" --width=1000 --height=680 --fontname="Monospace 11" --button="Close:0"
fi
'\'' _ %s' \
--grid-lines=both < "$LOG_DATA" &
# Master Notebook Window
yad --notebook --key=$KEY \
--tab="System Overview" \
--tab="Devices Table" \
--tab="Logs" \
--title="Offline Hardware Probe - ${VENDOR_VAL} ${MODEL_VAL}" \
--width=1200 --height=720 \
--button="Open HTML Report:bash -c 'xdg-open \"${SCRIPT_DIR}/hardware_report.html\"'" \
--button="Close:0"




