PHY_DIR="/sys/class/ieee80211"
+cli_device_status_phy() {
+ local phy="${1}"
+ assert phy_exists "${phy}"
+
+ local address="$(phy_get_address "${phy}")"
+ cli_print_fmt1 1 "Address" "${address}"
+
+ # Show kernel module
+ local driver="$(phy_get_driver "${phy}")"
+ if isset driver; then
+ cli_print_fmt1 1 "Driver" "${driver}"
+ fi
+
+ cli_space
+
+ local devices="$(phy_get_devices "${phy}")"
+ if isset devices; then
+ cli_headline 2 "Soft interfaces"
+
+ local device
+ for device in ${devices}; do
+ cli_print 2 "* %s" "${device}"
+ done
+ cli_space
+ fi
+
+ cli_headline 2 "Features"
+
+ cli_print_fmt1 2 "Automatic Channel Selection" \
+ "$(phy_supports_acs "${phy}" && print "Supported" || print "Not Supported")"
+ cli_print_fmt1 2 "DFS" \
+ "$(phy_supports_dfs "${phy}" && print "Supported" || print "Not Supported")"
+
+ cli_space
+
+ return ${EXIT_OK}
+}
+
phy_dir() {
local phy=${1}
print "$(<${path})"
}
+phy_get_driver() {
+ local phy="${1}"
+ assert isset phy
+
+ get_driver_from_path "$(phy_dir "${phy}")/device/driver/module"
+}
+
phy_get_devices() {
local phy="${1}"
assert isset phy
fi
done
}
+
+phy_list_leds() {
+ local phy="${1}"
+
+ # Check if the PHY exists
+ assert phy_exists "${phy}"
+
+ local led
+ for led in $(list_directory /sys/class/leds); do
+ # Get basename of the LED
+ led=${led%*/}
+
+ if [[ ${led} =~ ${phy}(:.*)?$ ]]; then
+ print "${led}"
+ fi
+ done
+}
+
+# This function tries to automatically configure LEDs to
+# something useful
+phy_leds_autoconf() {
+ local phy="${1}"
+ assert isset phy
+
+ local led
+ for led in $(phy_list_leds "${phy}"); do
+ # Skip some types of LEDs
+ case "${led}" in
+ # Pretty much everything we tested from Ralink
+ # locked up the kernel after a couple of seconds
+ rt*)
+ continue
+ ;;
+ esac
+
+ # We try to set the LED into tpt mode (flashing on activity),
+ # but will fallback to tx mode if that isn't supported
+ local trigger
+ for trigger in "${phy}tpt" "${phy}tx"; do
+ if led_set_trigger "${led}" "${trigger}"; then
+ break
+ fi
+ done
+ done
+
+ return ${EXIT_OK}
+}
+
+phy_supports_channel() {
+ local phy="${1}"
+ assert isset phy
+
+ local channel="${2}"
+ assert isinteger channel
+
+ local _channel _frequency _dfs _max_tx_power
+ while read -r _channel _frequency _dfs _max_tx_power; do
+ if [ "${channel}" = "${_channel}" ]; then
+ return ${EXIT_TRUE}
+ fi
+ done <<< "$(network-phy-list-channels "${phy}")"
+
+ return ${EXIT_FALSE}
+}
+
+phy_list_ciphers() {
+ local phy="${1}"
+ assert isset phy
+
+ network-phy-list-ciphers "${phy}"
+}
+
+phy_supports_cipher() {
+ local phy="${1}"
+ assert isset phy
+
+ local cipher="${2}"
+ assert isset cipher
+
+ list_match "${cipher}" $(phy_list_ciphers "${phy}")
+}
+
+__phy_list_ht_capabilities() {
+ local phy="${1}"
+ assert isset phy
+
+ local capabilities="$(network-phy-list-ht-caps "${phy}")"
+
+ print "${capabilities//[\[\]]/ }"
+}
+
+phy_supports_ht_capability() {
+ local phy="${1}"
+ assert isset phy
+
+ local capability="${2}"
+ assert isset capability
+
+ list_match "${capability}" $(__phy_list_ht_capabilities "${phy}")
+}
+
+# Returns TRUE if the PHY supports ACS
+phy_supports_acs() {
+ local phy="${1}"
+ assert isset phy
+
+ local driver="$(phy_get_driver "${phy}")"
+ if ! isset driver; then
+ return ${EXIT_ERROR}
+ fi
+
+ # This is basically a whilelist of drivers which support this
+ # There is no better detection
+ case "${driver}" in
+ ath10k_*|ath9k|ath5k)
+ return ${EXIT_TRUE}
+ ;;
+ *)
+ return ${EXIT_FALSE}
+ ;;
+ esac
+}
+
+# Returns TRUE if the PHY supports DFS
+phy_supports_dfs() {
+ local phy="${1}"
+ assert isset phy
+
+ local driver="$(phy_get_driver "${phy}")"
+ if ! isset driver; then
+ return ${EXIT_ERROR}
+ fi
+
+ # This is basically a whilelist of drivers which support this
+ # There is no better detection
+ case "${driver}" in
+ ath10k_*|ath9k|ath5k)
+ return ${EXIT_TRUE}
+ ;;
+ *)
+ return ${EXIT_FALSE}
+ ;;
+ esac
+}