#!/bin/sh
# tlp-func-rf - Radio Device Checks and PM Functions
#
# Copyright (c) 2023 Thomas Koch <linrunner at gmx.net> and others.
# SPDX-License-Identifier: GPL-2.0-or-later

# Needs: tlp-func-base

# ----------------------------------------------------------------------------
# Constants

readonly IW=iw

readonly BLUETOOTHD=/sys/class/bluetooth

# ----------------------------------------------------------------------------
# Functions

# --- Wifi Device Checks

get_wifi_ifaces () { # get all wifi devices -- retval: $_wifaces
    local wi wiu
    _wifaces=""

    for wiu in "$NETD"/*/uevent; do
        if grep -q -s 'DEVTYPE=wlan' "$wiu" ; then
            wi=${wiu%/uevent}; wi=${wi##*/}
            _wifaces="$_wifaces $wi"
        fi
    done

    _wifaces="${_wifaces# }"
    return 0
}

get_wifi_driver () { # get driver associated with interface
                     # $1: iface; retval: $_wifidrv
    local drvl

    _wifidrv=""
    if [ -d "$NETD/$1" ]; then
        drvl=$(readlink "$NETD/$1/device/driver")
        # shellcheck disable=SC2034
        [ -n "$drvl" ] && _wifidrv=${drvl##*/}
    fi

    return 0
}

wireless_in_use () { # check if wifi or wwan device is in use -- $1: iface
    if [ -f "$NETD/$1/carrier" ]; then
        if [ "$(read_sysf "$NETD/$1/carrier")" = "1" ]; then
            return 0
        fi
    fi
    return 1
}

any_wifi_in_use () { # check if any wifi device is in use
    local iface

    get_wifi_ifaces
    for iface in $_wifaces; do
        wireless_in_use "$iface" && return 0
    done

    return 1
}

# --- Wifi Power Management

set_wifi_power_mode () { # set wifi power save mode -- $1: 0=ac mode, 1=battery mode
    local pwr iface

    if [ "$1" = "1" ]; then
        pwr=${WIFI_PWR_ON_BAT:-}
    else
        pwr=${WIFI_PWR_ON_AC:-}
    fi

    # check values, translate obsolete syntax
    case "$pwr" in
        off|on)      ;;
        0|1|N)       pwr="off" ;;
        2|3|4|5|6|Y) pwr="on"  ;;
        *)           pwr=""    ;; # invalid input --> unconfigured
    esac

    if [ -z "$pwr" ]; then
        # do nothing if unconfigured
        echo_debug "pm" "set_wifi_power_mode($1).not_configured"
        return 0
    fi

    get_wifi_ifaces
    if [ -z "$_wifaces" ]; then
        echo_debug "pm" "set_wifi_power_mode($1).no_ifaces"
        return 0
    fi

    for iface in $_wifaces; do
        if [ -n "$iface" ]; then
            if  cmd_exists $IW; then
                $IW dev "$iface" set power_save "$pwr" > /dev/null 2>&1
                echo_debug "pm" "set_wifi_power_mode($1, $iface).iw: $pwr; rc=$?"
            else
                # iw not iwconfig installed
                echo_debug "pm" "set_wifi_power_mode($1, $iface).no_iw"
                return 1
            fi
        fi
    done

    return 0
}

# --- WWAN Device Checks

get_wwan_ifaces () { # get all wwan devices -- retval: $_wanifaces
    local wi wiu
    _wanifaces=""

    for wiu in "$NETD"/*/uevent; do
        if grep -q -s 'DEVTYPE=wwan' "$wiu" ; then
            wi=${wiu%/uevent}; wi=${wi##*/}
            _wanifaces="$_wanifaces $wi"
        fi
    done

    _wanifaces="${_wanifaces# }"
    return 0
}

any_wwan_in_use () { # check if any wwan device is in use
    local iface

    get_wwan_ifaces
    for iface in $_wanifaces; do
        wireless_in_use "$iface" && return 0
    done

    return 1
}

get_wwan_driver () { # get driver associated with interface
                     # $1: iface; retval: $_wwandrv
    local drvl

    _wwandrv=""
    if [ -d "$NETD/$1" ]; then
        drvl=$(readlink "$NETD/$1/device/driver")
        # shellcheck disable=SC2034
        [ -n "$drvl" ] && _wwandrv=${drvl##*/}
    fi

    return 0
}

# --- Bluetooth Device Checks

get_bluetooth_ifaces () { # get all bluetooth interfaces -- retval: $_bifaces
    # enumerate symlinks only
    _bifaces="$(for i in "$BLUETOOTHD"/*; do [ -h "$i" ] && echo "${i##/*/}"; done | grep -v ':')"
    return 0
}

get_bluetooth_driver () { # get driver associated with interface -- $1: iface; retval: $_btdrv
    local drvl

    # shellcheck disable=SC2034
    _btdrv=""
    if [ -d "$BLUETOOTHD/$1" ]; then
        drvl=$(readlink "$BLUETOOTHD/$1/device/driver")
        # shellcheck disable=SC2034
        [ -n "$drvl" ] && _btdrv=${drvl##*/}
    fi

    return 0
}

bluetooth_in_use () { # check if bluetooth interface is in use -- $1: iface
    local uev

    # when devices are connected to an interface its sysdir is populated with
    # subdevices like <iface>:<number> where the uevent file contains a line
    # "DEVTYPE=link"
    for uev in "$BLUETOOTHD/$1/$1":*/uevent; do
        grep -q -s 'DEVTYPE=link' "$uev" && return 0
    done

    return 1
}

any_bluetooth_in_use () { # check if any bluetooth interface is in use
    local i

    get_bluetooth_ifaces
    for i in $_bifaces; do
        bluetooth_in_use "$i" && return 0
    done

    return 1
}
