76 lines
3.2 KiB
Bash
76 lines
3.2 KiB
Bash
#!/vendor/bin/sh
|
|
#
|
|
# wireless_reprobe.sh - re-probe wireless drivers once /vendor is mounted.
|
|
#
|
|
# Built-in wireless drivers probe during early kernel init, before /vendor
|
|
# (which holds all firmware; see the kernel's patched fw_path[]) is mounted.
|
|
# Their firmware requests fail fast with ENOENT and the kernel never retries,
|
|
# leaving the hardware driverless or degraded. Run from init at post-fs
|
|
# (i.e. after /vendor is mounted) via init.tart.wifi.rc, this script:
|
|
#
|
|
# 1. Force-rebinds known WiFi USB drivers, so a USB WiFi adapter that was
|
|
# plugged in at power-on (and whose firmware request failed on the
|
|
# missing /vendor mount) gets a second, working probe. Confirmed on
|
|
# hardware (2026-07-13) that mt76-family drivers do NOT fail probe() on
|
|
# a missing-firmware error -- they bind "successfully" and then loop
|
|
# forever retrying an MCU handshake that can never succeed, so a plain
|
|
# driverless-only reprobe (the previous version of this script) never
|
|
# touches them. Unbind+rebind is required regardless of bound state.
|
|
# 2. Rebinds the Broadcom Bluetooth serdev device, so hci_bcm reloads its
|
|
# .hcd patch firmware (e.g. brcm/BCM.hcd). Without the patch the
|
|
# controller runs with unpatched defaults, which cripples TX power/range.
|
|
# Confirmed on hardware: firmware build version goes 0000 -> 1000 after
|
|
# this rebind.
|
|
#
|
|
# Both operations are idempotent and safe to run more than once.
|
|
|
|
# List of built-in USB WiFi driver names from tart_defconfig (see
|
|
# CONFIG_WLAN_VENDOR_MEDIATEK/_REALTEK/_ATH/_RALINK/_ZYDAS/CONFIG_MWIFIEX).
|
|
WIFI_USB_DRIVERS="mt7601u mt76x0u mt76x2u mt7921u mt7925u \
|
|
rt2500usb rt73usb rt2800usb \
|
|
rtl8187 rtl8xxxu rtw_8822bu rtw_8822cu rtw_8723du rtw_8821cu \
|
|
ath9k_htc carl9170 ar5523 \
|
|
zd1211rw mwifiex_usb"
|
|
|
|
is_wifi_driver() {
|
|
for d in $WIFI_USB_DRIVERS; do
|
|
[ "$d" = "$1" ] && return 0
|
|
done
|
|
return 1
|
|
}
|
|
|
|
# USB: for interfaces already bound to a known WiFi driver, force an
|
|
# unbind+rebind (their probe "succeeded" despite the firmware failure, so a
|
|
# driverless-only reprobe never reaches them). For genuinely unbound
|
|
# interfaces, just ask the kernel to re-run driver matching. Two passes with
|
|
# a delay: a probe already in flight when /vendor finished mounting can still
|
|
# fail after the first pass runs; the second pass catches what it leaves
|
|
# behind.
|
|
reprobe_usb() {
|
|
for intf in /sys/bus/usb/devices/*:*; do
|
|
name="${intf##*/}"
|
|
if [ -e "$intf/driver" ]; then
|
|
drv="$(basename "$(readlink -f "$intf/driver")")"
|
|
if is_wifi_driver "$drv"; then
|
|
echo "$name" > "$intf/driver/unbind" 2>/dev/null
|
|
echo "$name" > /sys/bus/usb/drivers_probe 2>/dev/null
|
|
fi
|
|
else
|
|
echo "$name" > /sys/bus/usb/drivers_probe 2>/dev/null
|
|
fi
|
|
done
|
|
}
|
|
reprobe_usb
|
|
sleep 3
|
|
reprobe_usb
|
|
|
|
# 2. Bluetooth: unbind + re-probe serdev devices so the hci_bcm driver's
|
|
# firmware patch request runs again with /vendor/firmware available.
|
|
for dev in /sys/bus/serial/devices/*; do
|
|
[ -e "$dev/driver" ] || continue
|
|
name="${dev##*/}"
|
|
echo "$name" > "$dev/driver/unbind" 2>/dev/null
|
|
echo "$name" > /sys/bus/serial/drivers_probe 2>/dev/null
|
|
done
|
|
|
|
exit 0
|