329 lines
7.3 KiB
Bash

#!/bin/sh
. /lib/netifd/netifd-wireless.sh
. /lib/netifd/quantenna.sh
init_wireless_driver "$@"
# primarily to allow RPC API call debugging
quantenna_call() {
logger "Calling qcsapi_sockrpc" $*
qcsapi_sockrpc $*
}
quantenna_rfenable() {
local enable=$1
# compat: fw v36 req "wifi0" arg, v37 (and later?) does not
case "$(quantenna_api_ver)" in
v36)
quantenna_call rfenable $(quantenna_primaryif) $enable
;;
*)
quantenna_call rfenable $enable
;;
esac
}
quantenna_rfstatus() {
# compat: fw v36 req "wifi0" arg, v37 (and later?) does not
case "$(quantenna_api_ver)" in
v36)
quantenna_call rfstatus $(quantenna_primaryif)
;;
*)
quantenna_call rfstatus
;;
esac
}
# mostly harmless if already done
quantenna_ready() {
[ -n "$(quantenna_ifprefix)" ] || return 1
[ "$(quantenna_call startprod)" = "complete" ] || return 1
[ "$(quantenna_call is_startprod_done)" = "1" ] || return 1
[ "$(quantenna_rfstatus)" = "On" ] || [ "$(quantenna_rfenable 1)" = "complete" ] || return 1
return 0
}
quantenna_set_security_mode() {
local ifname=$1
[ "$(quantenna_call apply_security_config $ifname)" = "complete" ] || return 1
return 0
}
quantenna_set_ssid_hidden() {
local ifname=$1
local hidden=${2:-0}
local enable=1
[ $hidden -gt 0 ] && enable=0
[ "$(quantenna_call set_option $ifname SSID_broadcast $enable)" = "complete" ] || return 1
return 0
}
quantenna_interface_enable() {
local ifname=$1
local enable=${2:-0}
local updown=down
[ $enable -gt 0 ] && updown=up
ip link set $ifname $updown
[ "$(quantenna_call enable_interface $ifname $enable)" = "complete" ] || return 1
return 0
}
_ifname2vid() {
echo "$((${1#$(quantenna_ifprefix)}+10))"
}
quantenna_interface_add() {
local ifname="$1"
local type="$2"
local phy="$3"
local vid=$(_ifname2vid $ifname)
# maximum number of devs is 8
[ $vid -lt 18 ] || return
case "$type" in
ap)
[ "$ifname" = "$(quantenna_primaryif)" ] || [ "$(quantenna_call wifi_create_bss $ifname)" = "complete" ] || echo "failed to create $ifname"
quantenna_set_security_mode $ifname || return 1
[ "$(quantenna_call set_pmf $ifname 0)" = "complete" ] || return 1
;;
*)
echo "$ifname: unsupported interface type '$type'"
return
;;
esac
# host local vlan dev
ip link add link $phy name $ifname type vlan id $vid
# bind quantenna vif to vlan
[ "$(quantenna_call vlan_config $ifname enable $vid)" = "complete" ] || return 1
[ "$(quantenna_call vlan_config $ifname bind $vid)" = "complete" ] || return 1
# disable interface until configured
quantenna_interface_enable $ifname 0
}
quantenna_interface_del() {
local ifname="$1"
local type="$2"
local vid=$(_ifname2vid $ifname)
quantenna_call vlan_config $ifname unbind $vid
quantenna_call vlan_config $ifname disable $vid
quantenna_interface_enable $ifname 0
case "$type" in
ap)
[ "$ifname" = "$(quantenna_primaryif)" ] || quantenna_call wifi_remove_bss $ifname
;;
*)
echo "$ifname: unsupported interface type '$type'"
return
;;
esac
ip link del $ifname
}
quantenna_set_ssid() {
local ifname=$1
local ssid=$2
quantenna_call set_SSID $ifname $ssid
}
quantenna_set_macaddr() {
local ifname=$1
local mac=$2
quantenna_call set_macaddr $ifname "$mac"
}
quantenna_set_encr() {
local ifname=$1
local encr=$2
quantenna_call set_WPA_encryption_modes $ifname "$encr"
}
quantenna_set_auth() {
local ifname=$1
local auth=$2
quantenna_call set_WPA_authentication_mode $ifname "$auth"
}
quantenna_set_key() {
local ifname=$1
local key=$2
quantenna_call set_passphrase $ifname 0 "$key"
}
quantenna_set_beacon() {
local ifname=$1
local type=$2
quantenna_call set_beacon $ifname "$type"
}
# This will not work with hairpin_mode enabled
quantenna_fixup_vif() {
echo "quantenna_fixup_vif: $(json_dump)"
json_select data
json_get_vars ifname
json_select ..
[ -r "/sys/class/net/$ifname/brport/hairpin_mode" ] && echo 0 > "/sys/class/net/$ifname/brport/hairpin_mode"
}
quantenna_setup_vif() {
local name="$1"
echo "quantenna_setup_vif: $(json_dump)"
json_select config
json_get_vars mode ssid macaddr enable key hidden
json_select ..
# FIXME - mac addresses for VAPs will be auto-generated by Quantenna firmware - we need only managed the first one...
# [ -n "$macaddr" ] || {
# macaddr="$(mac80211_generate_mac $phy)"
# macidx="$(($macidx + 1))"
# }
if_idx=$((${if_idx:--1} + 1))
local ifname="$(quantenna_ifprefix)${if_idx}"
set_default enable 1
json_add_object data
json_add_string ifname "$ifname"
json_close_object
json_select config
wireless_vif_parse_encryption
json_select ..
quantenna_interface_add "$ifname" "$mode" "$phy" || return
quantenna_set_ssid_hidden $ifname "$hidden"
case "$auth_type" in
none)
quantenna_set_beacon $ifname Basic
;;
psk)
quantenna_set_auth $ifname PSKAuthentication
;;
*)
echo "unsupported auth_type: $auth_type"
;;
esac
case "$wpa_cipher" in
"TKIP")
quantenna_set_beacon $ifname WPA
quantenna_set_encr $ifname TKIPEncryption
;;
"CCMP")
quantenna_set_beacon $ifname 11i
quantenna_set_encr $ifname AESEncryption
;;
"CCMP TKIP")
quantenna_set_beacon $ifname WPAand11i
quantenna_set_encr $ifname TKIPandAESEncryption
;;
*)
;;
esac
[ -n "$key" ] && quantenna_set_key $ifname "$key"
quantenna_set_ssid $ifname "$ssid"
[ -n "$macaddr" ] && quantenna_set_macaddr $ifname "$macaddr"
quantenna_interface_enable $ifname $enable
wireless_add_vif "$name" "$ifname"
}
quantenna_cleanup_vif() {
local name="$1"
echo "quantenna_cleanup_vif ($name): $(json_dump)"
json_select config
json_get_vars mode
json_select ..
json_select data
json_get_vars ifname
json_select ..
quantenna_interface_del $ifname $mode
}
# will be evaled after _wdev_common_device_config(), which adds
# config_add_string channel hwmode htmode noscan
drv_quantenna_init_device_config() {
config_add_string phy
config_add_int beacon_int
echo "drv_quantenna_init_device_config"
}
# will be evaled after _wdev_common_iface_config(), which adds
# config_add_string mode ssid encryption 'key:wpakey'
drv_quantenna_init_iface_config() {
config_add_boolean enable hidden
echo "drv_quantenna_init_iface_config"
}
drv_quantenna_setup() {
json_select config
echo "drv_quantenna_setup: $(json_dump)"
json_get_vars phy channel htmode beacon_int
json_select ..
[ "$(quantenna_device)" = "$phy" ] || {
echo "Could not find PHY for device '$1'"
wireless_set_retry 0
return 1
}
quantenna_ready || {
echo "Failed to connect to Quantenna module"
wireless_set_retry 1
return 1
}
quantenna_call set_channel $(quantenna_primaryif) $channel
case "$htmode" in
VHT20|HT20)
quantenna_call set_bw $(quantenna_primaryif) 20
;;
HT40*|VHT40)
quantenna_call set_bw $(quantenna_primaryif) 40
;;
VHT80)
quantenna_call set_bw $(quantenna_primaryif) 80
;;
*)
quantenna_call set_bw $(quantenna_primaryif) 40
;;
esac
[ -n "beacon_int" ] && quantenna_call set_beacon_interval $(quantenna_primaryif) $beacon_int
# FIMXE: support all modes: ap, sta, adhoc, wds, monitor, mesh
for_each_interface "ap" quantenna_setup_vif
wireless_set_up
for_each_interface "ap" quantenna_fixup_vif
}
drv_quantenna_teardown() {
echo "$drv_quantenna_teardown: $(json_dump)"
for_each_interface "ap" quantenna_cleanup_vif
quantenna_rfenable 0
}
add_driver quantenna