Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save gtxaspec/757db86fe86169a5f006764b500a6182 to your computer and use it in GitHub Desktop.

Select an option

Save gtxaspec/757db86fe86169a5f006764b500a6182 to your computer and use it in GitHub Desktop.
Thingino 802.11AC USB Adapter Driver Script
#!/bin/sh
LOGTAG="8821_run.sh"
# Global variables
RTL_IFACE=""
WORK_DIR=""
# ---------------------------------------------------------------------------
# Supported USB WiFi adapters
#
# Different Realtek chipsets need different, incompatible kernel modules, so
# each adapter profile carries its own download URL, hash, on-disk filename,
# and lsmod module name. At runtime we look at which VID:PID is actually
# plugged in and load the matching driver. To support another chipset, add
# a new block below and list its profile name in ADAPTER_PROFILES.
# ---------------------------------------------------------------------------
# --- RTL8812A/RTL8821A family (e.g. TP-Link Archer T2U Nano, 2357:011e) ---
# Source: https://github.com/svpcom/rtl8812au @ 47d89ba3d8114e2854112e0a1349e0ef89b43760
# Patches: thingino-firmware/package/wifi-rtl8812au/0002-ioctl_cfg80211_fix.patch
# thingino-firmware/package/wifi-rtl8812au/0003-wifi_regd_fix.patch
# (both needed to build against this camera's 3.10.14 kernel headers;
# without them the build fails on NL80211_CHAN_WIDTH_5/10 and an
# old-kernel #if/#else bug in wifi_regd.c)
# Build: Makefile defaults already set CONFIG_RTL8812A=y CONFIG_RTL8821A=y -
# leave them as-is, that combo is what produces the "88XXau" naming.
# Cross-compile against the matching camera kernel tree/toolchain
# (e.g. docker-worker/workspace/output-stable/<camera_target>/{host/bin,build/linux-*}):
# make -j$(nproc) CONFIG_PLATFORM_I386_PC=n ARCH=mips \
# CROSS_COMPILE=<toolchain>/mipsel-linux- KSRC=<kernel_build_dir> \
# KVER=<uname -r on target, e.g. 3.10.14__isvp_swan_1.0__> \
# USER_EXTRA_CFLAGS="-DCONFIG_LITTLE_ENDIAN -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT"
# Output is 88XXau_wfb.ko - rename to 88XXau.ko before hashing/uploading.
RTL8812_VID="2357"
RTL8812_PID="011e"
RTL8812_DRIVER_FILE="88XXau.ko"
RTL8812_DRIVER_URL="https://<<URL>>/88XXau.ko"
RTL8812_DRIVER_HASH="c9f8589bb8f6e8239c39d1c85a2b3feef971a720b53aa5164263287ab414ff80" # <-- Update with actual SHA256 hash
RTL8812_MODULE_NAME="88XXau"
# --- RTL8822B family (e.g. TP-Link Archer T3U Nano, 2357:012e) ---
# Source: https://github.com/RinCat/RTL88x2BU-Linux-Driver @ ad889cc324baf2f13724e3d7b6e880804d3adae7
# Patches: none needed - builds clean against this camera's 3.10.14 kernel as-is.
# Build: Makefile default already sets CONFIG_RTL8822B=y, no override needed.
# Same cross-compile setup as the RTL8812 profile above:
# make -j$(nproc) CONFIG_PLATFORM_I386_PC=n ARCH=mips \
# CROSS_COMPILE=<toolchain>/mipsel-linux- KSRC=<kernel_build_dir> \
# KVER=<uname -r on target, e.g. 3.10.14__isvp_swan_1.0__> \
# USER_EXTRA_CFLAGS="-DCONFIG_LITTLE_ENDIAN -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT"
# Output is already named 88x2bu.ko - no rename needed.
# NOTE: Do NOT use the svpcom/rtl8812au driver for this chip even though its
# USB ID table lists 2357:012e - direct chip-register readout confirms
# this is genuine RTL8822B silicon, and the au driver pushes the wrong
# firmware to it (manifests as USB write timeouts during firmware
# download, easy to mistake for a power/hardware problem).
RTL8822B_VID="2357"
RTL8822B_PID="012e"
RTL8822B_DRIVER_FILE="88x2bu.ko"
RTL8822B_DRIVER_URL="https://<<URL>>/88x2bu.ko"
RTL8822B_DRIVER_HASH="bcc53df7285d1db0e65ce8dbad99f8f162df762929d783f4eefd05991f33f10a" # <-- Update with actual SHA256 hash
RTL8822B_MODULE_NAME="88x2bu"
ADAPTER_PROFILES="RTL8812 RTL8822B"
# Selected at runtime by detect_adapter_profile()
SELECTED_PROFILE=""
SELECTED_VID=""
SELECTED_PID=""
SELECTED_DRIVER_FILE=""
SELECTED_DRIVER_URL=""
SELECTED_DRIVER_HASH=""
SELECTED_MODULE_NAME=""
# ---------------------------------------------------------------------------
# Connection watchdog settings
#
# Once the USB WiFi interface is up, we keep checking that it can actually
# reach its gateway (not just that it's "associated"). If it can't:
# - the first MAX_LIGHT_RECOVERY_ATTEMPTS failures trigger a lightweight
# recovery (restart wpa_supplicant + renew DHCP)
# - if connectivity is still down after REBOOT_AFTER_FAILS consecutive
# checks, we reboot as a last resort.
#
# We deliberately do NOT rmmod/reload the kernel module as a recovery step:
# we've seen that specific operation wedge the USB bus on this hardware
# badly enough to require a physical unplug/replug to recover, which an
# unattended watchdog can't do. A full reboot resets the USB controller far
# more reliably than a software-only unbind/rmmod does.
# ---------------------------------------------------------------------------
CHECK_INTERVAL=60 # seconds between connectivity checks
MAX_LIGHT_RECOVERY_ATTEMPTS=3 # consecutive failures that trigger wpa_supplicant/DHCP restart
REBOOT_AFTER_FAILS=15 # consecutive failed checks (~15 min) before rebooting
log() {
echo "[$LOGTAG] $*"
if [ -n "$WORK_DIR" ]; then
echo "[$LOGTAG] $*" >> "$WORK_DIR/8821_run.log"
fi
}
detect_adapter_profile() {
# Scan attached USB devices for a VID:PID we have a driver profile for.
# Sets SELECTED_* globals and returns 0 on match, 1 if nothing matched.
local vid pid profile devdir profile_vid profile_pid
for devdir in /sys/bus/usb/devices/*/; do
[ -f "${devdir}idVendor" ] && [ -f "${devdir}idProduct" ] || continue
vid=$(cat "${devdir}idVendor" 2>/dev/null)
pid=$(cat "${devdir}idProduct" 2>/dev/null)
[ -z "$vid" ] && continue
for profile in $ADAPTER_PROFILES; do
eval "profile_vid=\$${profile}_VID"
eval "profile_pid=\$${profile}_PID"
if [ "$vid" = "$profile_vid" ] && [ "$pid" = "$profile_pid" ]; then
SELECTED_PROFILE="$profile"
SELECTED_VID="$vid"
SELECTED_PID="$pid"
eval "SELECTED_DRIVER_FILE=\$${profile}_DRIVER_FILE"
eval "SELECTED_DRIVER_URL=\$${profile}_DRIVER_URL"
eval "SELECTED_DRIVER_HASH=\$${profile}_DRIVER_HASH"
eval "SELECTED_MODULE_NAME=\$${profile}_MODULE_NAME"
return 0
fi
done
done
return 1
}
wait_for_adapter_profile() {
log "Waiting for a supported USB WiFi adapter..."
for i in $(seq 1 30); do
if detect_adapter_profile; then
log "Detected $SELECTED_PROFILE adapter ($SELECTED_VID:$SELECTED_PID - driver: $SELECTED_DRIVER_FILE)"
return 0
fi
sleep 1
done
log "No supported USB WiFi adapter found after 30s"
return 1
}
load_module() {
if lsmod | grep -q "^$SELECTED_MODULE_NAME"; then
log "$SELECTED_PROFILE module ($SELECTED_MODULE_NAME) already loaded."
else
log "Loading $SELECTED_PROFILE driver ($SELECTED_DRIVER_FILE)..."
insmod "$WORK_DIR/$SELECTED_DRIVER_FILE" || { log "Failed to load $SELECTED_DRIVER_FILE from $WORK_DIR"; exit 1; }
fi
}
# Add a quiet version for use in loops
detect_sdio_wifi_interfaces_quiet() {
# Find wlan interfaces that correspond to SDIO devices (quiet version)
local sdio_interfaces=""
# Get all wlan interfaces
local all_wlan_ifaces=$(ip link | awk '$0 ~ /^[0-9]+:/ && $2 ~ /^wlan/ {gsub(":", "", $2); print $2}')
# Check each wlan interface to see if it's SDIO-based
for iface in $all_wlan_ifaces; do
# Check if interface has a corresponding device
if [ -d "/sys/class/net/$iface/device" ]; then
# Method 1: Check for SDIO device ID (from your lssdio output: Device ID: 0xf179)
if [ -f "/sys/class/net/$iface/device/device" ]; then
local device_id=$(cat "/sys/class/net/$iface/device/device" 2>/dev/null)
if [ "$device_id" = "0xf179" ]; then
sdio_interfaces="$sdio_interfaces $iface"
continue
fi
fi
# Method 2: Check device path for SDIO/MMC indicators
local device_path=$(readlink -f "/sys/class/net/$iface/device" 2>/dev/null)
if [ -n "$device_path" ] && (echo "$device_path" | grep -q "mmc\|sdio"); then
sdio_interfaces="$sdio_interfaces $iface"
continue
fi
# Method 3: Check for wireless subsystem and absence of USB indicators
if [ -d "/sys/class/net/$iface/wireless" ] || [ -d "/sys/class/net/$iface/phy80211" ]; then
# It's a wireless interface, check if it's NOT USB
if ! echo "$device_path" | grep -q "usb"; then
# Check if modalias indicates SDIO
local modalias=""
if [ -f "/sys/class/net/$iface/device/modalias" ]; then
modalias=$(cat "/sys/class/net/$iface/device/modalias" 2>/dev/null)
fi
if echo "$modalias" | grep -q "sdio"; then
sdio_interfaces="$sdio_interfaces $iface"
fi
fi
fi
fi
done
echo "$sdio_interfaces" | xargs
}
wait_for_onboard_wlan() {
log "Waiting for all onboard wlan interfaces to be available..."
for i in $(seq 1 100); do
ONBOARD_IFACES=$(detect_sdio_wifi_interfaces_quiet)
# Debug: log what we found every 10 iterations
if [ $((i % 10)) -eq 1 ]; then
log "Iteration $i: Found onboard interfaces: '$ONBOARD_IFACES'"
fi
if [ -z "$ONBOARD_IFACES" ]; then
sleep 1
continue
fi
ALL_PRESENT=true
for IFACE in $ONBOARD_IFACES; do
if ! ip link show "$IFACE" > /dev/null 2>&1; then
ALL_PRESENT=false
break
fi
done
if $ALL_PRESENT; then
log "All onboard wlan interfaces are available: $ONBOARD_IFACES"
return 0
fi
sleep 1
done
log "Timeout waiting for onboard wlan interfaces."
exit 1
}
detect_usb_wifi_interfaces() {
# Find wlan interfaces that correspond to USB devices
local usb_interfaces=""
# Get all wlan interfaces
local all_wlan_ifaces=$(ip link | awk '$0 ~ /^[0-9]+:/ && $2 ~ /^wlan/ {gsub(":", "", $2); print $2}')
# Check each wlan interface to see if it's USB-based
for iface in $all_wlan_ifaces; do
# Check if interface has a corresponding USB device path
if [ -d "/sys/class/net/$iface/device" ]; then
# Follow the device symlink to see if it points to a USB device
local device_path=$(readlink -f "/sys/class/net/$iface/device" 2>/dev/null)
if echo "$device_path" | grep -q "usb"; then
usb_interfaces="$usb_interfaces $iface"
log "Detected USB WiFi interface: $iface" >&2
fi
fi
done
echo "$usb_interfaces" | xargs
}
manage_prudynt_service() {
local action="$1" # "start" or "stop"
if [ "$action" = "start" ]; then
log "Starting prudynt service..."
service start prudynt || log "Warning: Failed to start prudynt service"
elif [ "$action" = "stop" ]; then
log "Stopping prudynt service..."
service stop prudynt || log "Warning: Failed to stop prudynt service"
else
log "Invalid action for prudynt service: $action"
return 1
fi
}
stop_wlan0() {
log "Bringing down wlan0..."
fw_setenv wlanap_enabled false
# Release DHCP lease before stopping interface
release_dhcp_lease "wlan0"
# kill wpa_supplicant for wlan0
for PID in $(pgrep -f "wpa_supplicant.*-i.*wlan0"); do
log "Killing wpa_supplicant for wlan0 (PID $PID)..."
kill "$PID" || log "Failed to kill wpa_supplicant for wlan0"
done
# Finally bring down the interface
ip link set wlan0 down || log "Failed to bring down wlan0 (may already be down)"
}
find_rtl_iface() {
# Find USB WiFi interfaces (should be the Realtek adapter)
local usb_ifaces=$(detect_usb_wifi_interfaces)
if [ -n "$usb_ifaces" ]; then
RTL_IFACE=$(echo "$usb_ifaces" | awk '{print $1}') # Take first USB WiFi interface
log "Detected Realtek interface: $RTL_IFACE"
else
log "Could not find USB WiFi interface (Realtek adapter)"
exit 1
fi
}
cleanup_rtl_services() {
# Release DHCP lease for Realtek interface if active
release_dhcp_lease "$RTL_IFACE"
# Kill any old wpa_supplicant for Realtek interface
for PID in $(pgrep -f "wpa_supplicant.*-i.*$RTL_IFACE"); do
log "Killing old wpa_supplicant (PID $PID) for $RTL_IFACE"
kill $PID
done
# Extra: kill any duplicate udhcpc for $RTL_IFACE not tracked by pidfile
for PID in $(pgrep -f "udhcpc.*-i.*$RTL_IFACE"); do
log "Killing extra udhcpc (PID $PID) for $RTL_IFACE"
kill $PID
done
}
start_rtl_wlan8821() {
log "Waiting for Realtek interface..."
for i in $(seq 1 10); do
find_rtl_iface
if [ -n "$RTL_IFACE" ]; then
break
fi
sleep 1
done
if [ -z "$RTL_IFACE" ]; then
log "Could not find Realtek USB interface"
exit 1
fi
cleanup_rtl_services
log "Bringing up $RTL_IFACE..."
ip link set "$RTL_IFACE" up || { log "Failed to bring up $RTL_IFACE"; exit 1; }
log "Starting wpa_supplicant for $RTL_IFACE..."
wpa_supplicant -i "$RTL_IFACE" -c /etc/wpa_supplicant.conf -B || { log "Failed to start wpa_supplicant"; exit 1; }
sleep 5
BASE_HOSTNAME="$(hostname)"
wlan8821_HOSTNAME="${BASE_HOSTNAME}"
log "Using DHCP hostname: $wlan8821_HOSTNAME"
udhcpc -x hostname:$wlan8821_HOSTNAME -S -T1 -t15 -R -b -O search -O 100 -O 101 -O 160 -p /var/run/udhcpc."$RTL_IFACE".pid -i "$RTL_IFACE" || { log "DHCP failed for $RTL_IFACE"; exit 1; }
# Check if the Realtek interface got an IP address
IP_ADDR=$(ip -4 addr show "$RTL_IFACE" | awk '/inet / {print $2}' | cut -d/ -f1)
if [ -n "$IP_ADDR" ]; then
log "$RTL_IFACE got IP $IP_ADDR, stopping wlan0."
stop_wlan0
# Start prudynt service when USB WiFi is active and has IP
manage_prudynt_service "start"
log "$RTL_IFACE setup complete."
monitor_connection
else
log "$RTL_IFACE did not get an IP address, keeping wlan0 up."
log "$RTL_IFACE setup complete."
fi
}
release_dhcp_lease() {
local interface="$1"
if [ -z "$interface" ]; then
log "No interface specified for DHCP release"
return 1
fi
local pidfile="/var/run/udhcpc.$interface.pid"
if [ -f "$pidfile" ]; then
log "Releasing DHCP lease for $interface..."
# Send DHCPRELEASE with timeout to prevent hanging
timeout 5 udhcpc -R -i "$interface" 2>/dev/null || log "DHCP release timed out or failed for $interface"
PID=$(cat "$pidfile")
log "Stopping udhcpc for $interface (PID $PID)..."
kill "$PID" || log "Failed to kill udhcpc for $interface"
rm -f "$pidfile"
# Kill any lingering DHCP release processes for this interface
for release_pid in $(pgrep -f "udhcpc.*-R.*-i.*$interface"); do
log "Killing lingering DHCP release process (PID $release_pid) for $interface"
kill "$release_pid" 2>/dev/null || true
done
else
log "No DHCP client pidfile found for $interface"
fi
}
check_connectivity() {
# Returns 0 if $RTL_IFACE has an IP and can reach its gateway, 1 otherwise
local gw
if ! ip link show "$RTL_IFACE" >/dev/null 2>&1; then
return 1
fi
if ! ip -4 addr show "$RTL_IFACE" | grep -q "inet "; then
return 1
fi
gw=$(ip route show dev "$RTL_IFACE" | awk '/^default/ {print $3; exit}')
if [ -z "$gw" ]; then
return 1
fi
ping -c 2 -W 3 -I "$RTL_IFACE" "$gw" >/dev/null 2>&1
}
monitor_connection() {
local fail_count=0
local light_recovery_attempts=0
log "Starting connection watchdog for $RTL_IFACE (check every ${CHECK_INTERVAL}s)"
while true; do
sleep "$CHECK_INTERVAL"
if check_connectivity; then
if [ "$fail_count" -gt 0 ]; then
log "Connectivity restored for $RTL_IFACE after $fail_count failed check(s)"
fi
fail_count=0
light_recovery_attempts=0
continue
fi
fail_count=$((fail_count + 1))
log "Connectivity check failed for $RTL_IFACE ($fail_count/$REBOOT_AFTER_FAILS)"
if [ "$fail_count" -ge "$REBOOT_AFTER_FAILS" ]; then
log "Connectivity not restored after $fail_count checks (~$((fail_count * CHECK_INTERVAL / 60)) min) - rebooting"
sync
reboot
exit 0
fi
if [ "$light_recovery_attempts" -lt "$MAX_LIGHT_RECOVERY_ATTEMPTS" ]; then
light_recovery_attempts=$((light_recovery_attempts + 1))
log "Attempting lightweight recovery for $RTL_IFACE (attempt $light_recovery_attempts)"
for PID in $(pgrep -f "wpa_supplicant.*-i.*$RTL_IFACE"); do
kill "$PID" 2>/dev/null
done
release_dhcp_lease "$RTL_IFACE"
wpa_supplicant -i "$RTL_IFACE" -c /etc/wpa_supplicant.conf -B || log "Failed to restart wpa_supplicant during recovery"
sleep 5
udhcpc -x hostname:"$(hostname)" -S -T1 -t15 -R -b -O search -O 100 -O 101 -O 160 -p /var/run/udhcpc."$RTL_IFACE".pid -i "$RTL_IFACE" || log "DHCP renewal failed during recovery"
else
log "Lightweight recovery exhausted ($light_recovery_attempts attempts); waiting for reboot threshold"
fi
done
}
determine_working_directory() {
local sd_path="/mnt/mmcblk0p1"
local tmp_path="/tmp/8821_workdir"
# Check if SD card path exists and is mounted
if [ -d "$sd_path" ] && mountpoint -q "$sd_path" 2>/dev/null; then
# Check if it's actually an mmcblk device (SD card)
local device=$(df "$sd_path" | tail -n1 | awk '{print $1}')
if echo "$device" | grep -q "mmcblk"; then
# Check available space (in KB, convert 64MB to KB = 65536)
local available_kb=$(df "$sd_path" | tail -n1 | awk '{print $4}')
if [ "$available_kb" -gt 65536 ]; then
log "Using SD card working directory: $sd_path" >&2
echo "$sd_path"
return 0
else
log "SD card has insufficient space ($available_kb KB < 64MB)" >&2
fi
else
log "Path $sd_path is not an SD card device" >&2
fi
else
log "SD card path $sd_path not available" >&2
fi
# Fallback to /tmp directory
if [ ! -d "$tmp_path" ]; then
mkdir -p "$tmp_path" || { log "Failed to create $tmp_path" >&2; echo "/tmp"; return 1; }
log "Created working directory: $tmp_path" >&2
fi
log "Using temporary working directory: $tmp_path" >&2
echo "$tmp_path"
return 0
}
fetch_driver_file() {
local driver_file="$WORK_DIR/$SELECTED_DRIVER_FILE"
local temp_file="$WORK_DIR/$SELECTED_DRIVER_FILE.tmp"
if [ -z "$WORK_DIR" ]; then
log "No working directory set for driver fetch" >&2
return 1
fi
if [ -z "$SELECTED_DRIVER_URL" ]; then
log "No driver URL configured for $SELECTED_PROFILE" >&2
return 1
fi
log "Downloading $SELECTED_PROFILE driver from $SELECTED_DRIVER_URL..." >&2
# Try different download tools
if command -v wget >/dev/null 2>&1; then
wget -q -O "$temp_file" "$SELECTED_DRIVER_URL" || {
log "Failed to download driver with wget" >&2
rm -f "$temp_file"
return 1
}
elif command -v curl >/dev/null 2>&1; then
curl -s -o "$temp_file" "$SELECTED_DRIVER_URL" || {
log "Failed to download driver with curl" >&2
rm -f "$temp_file"
return 1
}
else
log "No download tool available (wget or curl)" >&2
return 1
fi
# Move temp file to final location
mv "$temp_file" "$driver_file" || {
log "Failed to move downloaded driver to final location" >&2
rm -f "$temp_file"
return 1
}
log "Driver file successfully downloaded: $driver_file" >&2
return 0
}
validate_driver_hash() {
local driver_file="$WORK_DIR/$SELECTED_DRIVER_FILE"
if [ -z "$SELECTED_DRIVER_HASH" ]; then
log "Warning: No driver hash configured for $SELECTED_PROFILE, skipping validation" >&2
return 0
fi
if ! command -v sha256sum >/dev/null 2>&1; then
log "Warning: sha256sum not available, skipping hash validation" >&2
return 0
fi
if [ ! -f "$driver_file" ]; then
log "Driver file does not exist for hash validation" >&2
return 1
fi
local file_hash=$(sha256sum "$driver_file" | cut -d' ' -f1)
if [ "$file_hash" != "$SELECTED_DRIVER_HASH" ]; then
log "Driver hash mismatch. Expected: $SELECTED_DRIVER_HASH, Got: $file_hash" >&2
return 1
fi
log "Driver hash validated successfully" >&2
return 0
}
ensure_driver_file() {
local driver_file="$WORK_DIR/$SELECTED_DRIVER_FILE"
local max_attempts=2
local attempt=1
while [ $attempt -le $max_attempts ]; do
# Ensure file exists
if ! check_driver_file; then
log "Driver file missing (attempt $attempt), downloading..." >&2
fetch_driver_file || {
log "Download failed on attempt $attempt" >&2
attempt=$((attempt + 1))
continue
}
else
log "Driver file exists (attempt $attempt)" >&2
fi
# Validate hash
if validate_driver_hash; then
log "Driver file ready and validated" >&2
return 0
else
log "Hash validation failed on attempt $attempt" >&2
if [ $attempt -lt $max_attempts ]; then
log "Removing invalid file and retrying..." >&2
rm -f "$driver_file"
fi
fi
attempt=$((attempt + 1))
done
log "Failed to ensure valid driver file after $max_attempts attempts" >&2
return 1
}
check_driver_file() {
local driver_file="$WORK_DIR/$SELECTED_DRIVER_FILE"
if [ -z "$WORK_DIR" ]; then
log "No working directory set for driver check"
return 1
fi
if [ -f "$driver_file" ]; then
log "Driver file found: $driver_file"
return 0
else
log "Driver file not found: $driver_file"
return 1
fi
}
install_to_bin() {
local script_path="$0"
local script_name="8821_run.sh"
local bin_path="/bin/$script_name"
# Check if we're already running from /bin
if [ "$script_path" = "$bin_path" ] || [ "$(readlink -f "$script_path")" = "$bin_path" ]; then
log "Script is already running from /bin, skipping installation"
# Still need to ensure boot entry exists
add_to_boot
return $?
fi
log "Installing script to /bin..."
# Check if script path is valid
if [ ! -f "$script_path" ]; then
log "Error: Cannot find current script at $script_path"
return 1
fi
# Copy script to /bin
cp "$script_path" "$bin_path" || {
log "Failed to copy script to $bin_path"
return 1
}
# Make it executable
chmod +x "$bin_path" || {
log "Failed to make $bin_path executable"
return 1
}
log "Script successfully installed to $bin_path"
# Also create the boot entry
add_to_boot || {
log "Warning: Failed to add script to boot process"
return 1
}
return 0
}
remove_old_boot_entries() {
local service_name="S398821wifi"
local service_path="/etc/init.d/$service_name"
if [ -f "$service_path" ]; then
log "Removing old boot entry $service_name..."
rm -f "$service_path" || log "Failed to remove old boot entry $service_name"
else
log "No old boot entry $service_name found, skipping removal"
fi
}
add_to_boot() {
remove_old_boot_entries
local service_name="S998821wifi"
local service_path="/etc/init.d/$service_name"
local script_path="/bin/8821_run.sh"
log "Adding script to boot process..."
# Check if script exists in /bin (should be installed already)
if [ ! -f "$script_path" ]; then
log "Error: Script not found at $script_path - run install_to_bin first"
return 1
fi
# Check if init script already exists and is up to date
if [ -f "$service_path" ]; then
if grep -q "$script_path" "$service_path" 2>/dev/null; then
log "Boot service already configured"
return 0
else
log "Updating existing boot service"
fi
else
log "Creating new boot service"
fi
# Create the init script
cat > "$service_path" << 'EOF'
#!/bin/sh
DESC="8821 WiFi USB Adapter Service"
DAEMON="/bin/8821_run.sh"
case "$1" in
start)
echo "Starting $DESC"
if [ -x "$DAEMON" ]; then
$DAEMON --sync
else
echo "Error: $DAEMON not found or not executable"
exit 1
fi
;;
stop)
echo "Stopping $DESC"
# Kill any running instances
pkill -f "8821_run.sh" || true
;;
restart)
$0 stop
sleep 2
$0 start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
;;
esac
exit 0
EOF
# Make it executable
chmod +x "$service_path" || {
log "Failed to make service executable"
return 1
}
log "Boot service installed as $service_name"
return 0
}
main() {
install_to_bin
manage_prudynt_service "stop"
WORK_DIR=$(determine_working_directory)
wait_for_adapter_profile || { log "No supported USB WiFi adapter attached, aborting"; exit 1; }
ensure_driver_file || { log "Failed to ensure driver file availability"; exit 1; }
wait_for_onboard_wlan
load_module
start_rtl_wlan8821
}
if [ "$1" = "--sync" ]; then
main
else
main &
fi
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment