diff --git a/device.mk b/device.mk index 39068f1..b3d2e9c 100644 --- a/device.mk +++ b/device.mk @@ -287,7 +287,8 @@ PRODUCT_PACKAGES += \ com.android.hardware.wifi.hostapd.opi5 \ com.android.hardware.wifi.supplicant.opi5 \ libwpa_client \ - wificond + wificond \ + wireless_reprobe.sh PRODUCT_COPY_FILES += \ frameworks/native/data/etc/android.hardware.wifi.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.wifi.xml diff --git a/sepolicy/file_contexts b/sepolicy/file_contexts index 97e520a..2d1b627 100644 --- a/sepolicy/file_contexts +++ b/sepolicy/file_contexts @@ -49,4 +49,6 @@ /dev/block/by-name/boot u:object_r:boot_block_device:s0 #V4L2 -/vendor/bin/hw/android\.hardware\.media\.c2@1\.2-service-v4l2(.*)? u:object_r:mediacodec_exec:s0 \ No newline at end of file +/vendor/bin/hw/android\.hardware\.media\.c2@1\.2-service-v4l2(.*)? u:object_r:mediacodec_exec:s0 +# WiFi +/vendor/bin/wireless_reprobe\.sh u:object_r:wireless_reprobe_exec:s0 diff --git a/sepolicy/wireless_reprobe.te b/sepolicy/wireless_reprobe.te new file mode 100644 index 0000000..c5e8da0 --- /dev/null +++ b/sepolicy/wireless_reprobe.te @@ -0,0 +1,16 @@ +# Domain for wireless_reprobe.sh: re-probes wireless drivers via sysfs after +# /vendor is mounted (see wifi/wireless_reprobe.sh). Runs once from init at +# post-fs as a oneshot service. +type wireless_reprobe, domain; +type wireless_reprobe_exec, exec_type, vendor_file_type, file_type; + +init_daemon_domain(wireless_reprobe) + +# Execute the vendor shell and toybox for the script interpreter +allow wireless_reprobe vendor_shell_exec:file rx_file_perms; +allow wireless_reprobe vendor_toolbox_exec:file rx_file_perms; + +# Walk /sys/bus/{usb,serial}/devices and write to drivers_probe/unbind +allow wireless_reprobe sysfs:dir r_dir_perms; +allow wireless_reprobe sysfs:file rw_file_perms; +allow wireless_reprobe sysfs:lnk_file read; diff --git a/wifi/Android.bp b/wifi/Android.bp index 2ac32dc..ea626f0 100644 --- a/wifi/Android.bp +++ b/wifi/Android.bp @@ -3,6 +3,15 @@ // // SPDX-License-Identifier: Apache-2.0 +// Re-probes wireless drivers after /vendor mounts so firmware-dependent +// probes that failed during early kernel init get a working second chance. +sh_binary { + name: "wireless_reprobe.sh", + src: "wireless_reprobe.sh", + vendor: true, + init_rc: ["init.tart.wifi.rc"], +} + prebuilt_etc { name: "android.hardware.wifi.hostapd-service.rc", src: "android.hardware.wifi.hostapd-service.rc", diff --git a/wifi/init.tart.wifi.rc b/wifi/init.tart.wifi.rc new file mode 100644 index 0000000..ecd20f0 --- /dev/null +++ b/wifi/init.tart.wifi.rc @@ -0,0 +1,11 @@ +# Re-probe wireless drivers whose early firmware requests failed because +# /vendor was not yet mounted. See wireless_reprobe.sh for details. +service wireless_reprobe /vendor/bin/wireless_reprobe.sh + class core + user root + group root + oneshot + disabled + +on post-fs + start wireless_reprobe diff --git a/wifi/wireless_reprobe.sh b/wifi/wireless_reprobe.sh new file mode 100644 index 0000000..d825ae1 --- /dev/null +++ b/wifi/wireless_reprobe.sh @@ -0,0 +1,38 @@ +#!/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. Re-probes every driverless USB interface, so a USB WiFi adapter that +# was plugged in at power-on (and whose driver probe failed on the +# missing firmware) gets a second probe that can now load firmware. +# 2. Rebinds the Broadcom Bluetooth serdev device, so hci_bcm reloads its +# .hcd patch firmware (e.g. brcm/SYN43711A0.hcd). Without the patch the +# controller runs with unpatched defaults, which cripples TX power/range. +# +# Both operations are idempotent and safe: already-bound USB interfaces are +# skipped, and the BT rebind simply re-registers hci0 before the Bluetooth +# stack starts. + +# 1. USB: ask the kernel to re-run driver matching for unbound interfaces +# (directories like 1-1:1.0 without a "driver" symlink). +for intf in /sys/bus/usb/devices/*:*; do + [ -e "$intf/driver" ] && continue + echo "${intf##*/}" > /sys/bus/usb/drivers_probe 2>/dev/null +done + +# 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