#!/bin/sh

if [ "$roku_dev_mode" = 'dev=1' ] && [ -f /nvram/p2p-functions ]
then
    echo
    echo "=== WIFI with /nvram/p2p-functions"
    source /nvram/p2p-functions
fi

PLATFORM=`roku_platform`
[ -f /tmp/wlan-module ] && MODULE=`cat /tmp/wlan-module`

P2PCTRL=/tmp/wpa_ctrl
P2PPID=/tmp/p2p_pid
P2PDIR=/nvram/ozmo
P2P_FIFO=/tmp/p2papp_log.fifo
P2P_FREQ_INFO=/tmp/p2p-default-freq

# Assume P2P should be enabled, unless parent script said otherwise
P2P_CAPABLE=${P2P_CAPABLE-true}
if [ "$PLATFORM" == "glaze" ] || [ "$PLATFORM" == "smiley" ] || [ "$PLATFORM" == "galveston" ]; then
P2P_CAPABLE=false
fi

HAS_5G=true
if [ "$PLATFORM" == "gilbert" ] || [ "$PLATFORM" == "gilbert4k" ] || [ "$PLATFORM" == "nemo" ]; then
    HAS_5G=false
fi
#Default to channel 36 or 11 for remote control
P2P_FREQ=5180
[ "$HAS_5G" = false ] && P2P_FREQ=2462
[ ! -f $P2P_FREQ_INFO ] && echo $P2P_FREQ > $P2P_FREQ_INFO

. /lib/wlan/networking-functions

setup_esn() {
    if [ -z "$ESN_ESN" ]; then
        ESN_CACHED_FILE="/tmp/esn_cached"
        if [ ! -f "$ESN_CACHED_FILE" ]; then
            esn -a > "$ESN_CACHED_FILE"
        fi
        # puts ESN_ESN, ESN_MODELNUM, ESN_DEVNAME, etc into environment
        eval $(cat $ESN_CACHED_FILE)
    fi
}

setup_p2p() {
    # Generate unique Wifi-direct SSID and passphrase
    mkdir -p $P2PDIR
    if [ ! -f $P2PDIR/passphrase ]; then
        #head -c 64 /dev/urandom | hexdump -v -e '1/1 "%02x"' | cut -c1-16 > $P2PDIR/passphrase
        head -c 64 /dev/urandom | hexdump -v -e '1/1 "%d"' | cut -c1-8 > $P2PDIR/passphrase
    fi
    if [ ! -f $P2PDIR/ssid ]; then
        setup_esn
        SSID="DIRECT-roku-${ESN_ESN:9:3}"
        SSID=${SSID}-$(head -c 16 /dev/urandom | hexdump -v -e '1/1 "%02X"' | cut -c1-6)
        echo $SSID > $P2PDIR/ssid
    fi
}

wait_p2p_supplicant() {                                                             
    local TIMEOUT                                                                    
                                                                                     
    # Arg: interface name                                                            
    TIMEOUT=100                                                                      
    while ! wpa_cli -p/tmp/wpa_ctrl -i $1 ping 2>/dev/null | grep PONG >/dev/null; do
        echo "Supplicant: waiting for $1..."                      
        [ $TIMEOUT = "0" ] && return 1                            
        let TIMEOUT=$TIMEOUT-1                                   
        usleep 100000                                            
    done                                                        
    return 0                                                    
}

init_p2p() {
    [ "$P2P_CAPABLE" = false ] && return
    [ -f /nvram/p2p-disable ] && touch /tmp/wifi-no-p2p

    echo realtek > /tmp/p2p-wlan-driver
    echo $P2PINTF > /tmp/p2p-interface-name
    echo $MODULE > /tmp/p2p-module

    # Get MAC used by Wifi remote for magic packet wake-up (WOWL):                 
    iw $STAINTF info | grep addr | cut -d" " -f2 >/tmp/wifimac 

    if ps ax | grep wpa_supplicant | grep $P2PINTF >/dev/null; then
        echo "=== Wifi: P2P supplicant already running"
        return 0
    fi

    echo "=== Wifi: starting P2P supplicant"

    setup_p2p
    read SSID < $P2PDIR/ssid
    ID=${SSID:7:32}
    read PASSPHRASE < $P2PDIR/passphrase

    # Configure P2P Supplicant:
    SUPP_CONF=/etc/p2p-supp.conf
    [ -f /nvram/p2p-supp.conf ] && SUPP_CONF=/nvram/p2p-supp.conf
    CONF=/tmp/p2p-supp.conf
    cp -f $SUPP_CONF $CONF

    echo "ap_isolate=1" >> $CONF
    
    echo "network={" >> $CONF
    echo "    ssid=\"DIRECT-$ID\"" >> $CONF
    echo "    wpa_psk_file=\"/nvram/p2p-psk-file\"" >> $CONF
    echo "    psk=\"$PASSPHRASE\"" >> $CONF
    echo "    disabled=2" >> $CONF
    echo "    mode=3" >> $CONF
    echo "}" >> $CONF

    unset P2PDBG
    [ -f /nvram/p2p-debug ] && P2PDBG="-ddKtf /dev/kmsg"
    # Note: -B daemon option not working
    ARGS="-i$P2PINTF -Dnl80211 -c $CONF $P2PDBG"
    echo "--- P2P wpa_supplicant $ARGS"
    # Open up the FIFO in read/write mode so that it doesn't block and hold
    # up wpa_supplicant from starting
    exec 3<>$P2P_FIFO
    wpa_supplicant $ARGS | tee /dev/console >&3 &
    echo $! > $P2PPID

    if wait_p2p_supplicant $P2PINTF; then
        chown -R app /tmp/wpa_ctrl
    else
        echo "=== Wifi: P2P supplicant failed to start !!!"
        return 2
    fi

    wpa_cli -p $P2PCTRL -i$P2PINTF p2p_set per_sta_psk 1

    init_udhcpd $P2PINTF

    LAST_P2P_FREQ=$(sed -n 's/.*LastP2pFreqMHz=\(.*\)/\1/p' /nvram/system.conf)

    if [ ! -z ${LAST_P2P_FREQ} ]; then
    	P2P_FREQ=${LAST_P2P_FREQ}
        if [ "$HAS_5G" = false ] && [ ${LAST_P2P_FREQ} -gt 2484 ]; then
            echo "Invalid P2P freq $P2P_FREQ on 2G only device, set to 2462"
            P2P_FREQ=2462
        fi
        echo "Using last P2P channel $P2P_FREQ"
    fi

    if [ -d $P2PCTRL ]; then
        MANUFACTURER=Roku
        setup_esn
        wpa_cli -p $P2PCTRL -i$P2PINTF set manufacturer "$MANUFACTURER"
        wpa_cli -p $P2PCTRL -i$P2PINTF set model_name "$ESN_MODELNAME"
        wpa_cli -p $P2PCTRL -i$P2PINTF set model_number "$ESN_MODELNUM"
        wpa_cli -p $P2PCTRL -i$P2PINTF set device_name "$ESN_DEVNAME"
        echo $ESN_DEVNAME > /tmp/dev_name.txt

        # Proceed only if P2P is enabled
        [ -f /tmp/wifi-no-p2p ] && return 0
        grep "NoP2P=true" /nvram/system.conf && return 0

        if [ -f /nvram/system.conf ]; then
            grep "Miracast/Enabled=true" /nvram/system.conf && init_wfd && return 0
        else
            echo "=== Wifi: use default config after factory reset"
            init_wfd && return 0
        fi
        # If init_wfd failed, we still need P2P for the remote:
        wpa_cli -p $P2PCTRL -i$P2PINTF p2p_group_add persistent=0 freq=$P2P_FREQ
        return 0
    fi

    echo "=== Wifi: P2P supplicant did not start !!!"
    return 2
}

kill_p2p() {
    [ "$P2P_CAPABLE" = false ] && return
    echo "=== Wifi: kill P2P supplicant"

    echo "=== Wifi: kill udhcpd"
    killall -q -9 udhcpd
    [ ! -x $P2PCTRL/$P2PINTF ] && return 0
    wpa_cli -p$P2PCTRL -i$P2PINTF p2p_group_remove $P2PINTF
    sleep 1
    wpa_cli -p$P2PCTRL -i$P2PINTF terminate
    # It can take several seconds to tear-down and deauth clients
    # If suspend happens before complete, chip won't enter WOWL state
    TIMEOUT=10
    while ! grep $P2PINTF /proc/net/rtl$MODULE/$P2PINTF/adapters_status | grep STA; do
        sleep 1
        echo "!!! Wifi: waiting for P2P termination ($TIMEOUT)"
        let TIMEOUT=TIMEOUT-1
        [ $TIMEOUT -le 0 ] && return 1
    done
    find /tmp -type f -maxdepth 1 -name "p2papp*" ! -name "$P2P_FIFO" -exec rm -f {} \;
    return 0
}

init_wfd() {
    grep "NoP2P=true" /nvram/system.conf && return 0
    grep "Miracast/Enabled=false" /nvram/system.conf && return 1

    if [ -d $P2PCTRL ]; then
        echo "=== Wifi: starting WFD"
        ! init_udhcpd $P2PINTF && return 2

        # Change permission for miracast pseudo terminal
        chmod 666 /dev/ptmx
        chmod -R o+rwx /tmp/wpa_ctrl
        touch /var/log/miracast.log
        chmod o+rw /var/log/miracast.log

        wpa_cli -p $P2PCTRL -i$P2PINTF set wifi_display 1
        wpa_cli -p $P2PCTRL -i$P2PINTF wfd_subelem_set 0 000601111c440032

        if [ ! $1 ]; then
            wpa_cli -p $P2PCTRL -i$P2PINTF p2p_group_add persistent=0 freq=$P2P_FREQ
        else
            wpa_cli -p $P2PCTRL p2p_group_remove $P2PINTF
            sleep 1
            wpa_cli -p $P2PCTRL -i$P2PINTF p2p_group_add persistent=0 freq=$P2P_FREQ
        fi
        return 0
    fi

    echo "=== Wifi: Miracast failed to start !!!"
    return 2
}

kill_wfd() {
    echo "=== Wifi: kill WFD"

    if [ ! $1 ]; then
        : # If called by kill_p2p, only kill udhcpd
        echo "kill_wfd: leaving udhcpd up..."
    else
        [ ! -d $P2PCTRL ] && return 0

        wpa_cli -p $P2PCTRL p2p_group_remove $P2PINTF
        sleep 1
        wpa_cli -p $P2PCTRL -i$P2PINTF set wifi_display 0
        wpa_cli -p $P2PCTRL -i$P2PINTF p2p_group_add persistent=0 freq=$P2P_FREQ
    fi
    return 0
}

init_ozmo() {
    [ "$P2P_CAPABLE" = false ] && return
    lsmod | grep ozwpan &>/dev/null && return
    echo "=== Wifi: init Ozmo wireless PAN"
    TIMER=0
    until ifconfig $P2PINTF &> /dev/null
    do
        [ $TIMER -ge 20 ] && break
        let TIMER=$TIMER+1
        echo "Ozmo: waiting for $P2PINTF ..."
        sleep 1
    done
    insmod /lib/modules/ozwpan.ko g_net_dev=$P2PINTF
    return 0
}

kill_ozmo() {
    [ "$P2P_CAPABLE" = false ] && return
    echo "=== Wifi: kill Ozmo wireless PAN"
    lsmod | grep ozwpan &>/dev/null && rmmod ozwpan
}

update_dev_name() {
    [ "$P2P_CAPABLE" = false ] && return
    if [ -f /tmp/dev_name.txt ] ; then
        read DEVNAME_1 < /tmp/dev_name.txt
    fi
    DEVNAME_2=`esn -n`

    if [ "$DEVNAME_1" != "$DEVNAME_2" ]; then
        if [ -d $P2PCTRL ]; then
            wpa_cli -p $P2PCTRL -i$P2PINTF set device_name "$DEVNAME_2"
            echo $DEVNAME_2 > /tmp/dev_name.txt

            [ -f /nvram/system.conf ] && grep "NoP2P=true" /nvram/system.conf && return 1
            wpa_cli -p $P2PCTRL p2p_group_remove $P2PINTF
            sleep 1
            wpa_cli -p $P2PCTRL -i$P2PINTF p2p_group_add persistent=0 freq=$P2P_FREQ
        fi
    fi
}

init_fifos() {
    echo "=== Wifi: init_fifos"
    [ -p $P2P_FIFO ] && return
    mkfifo -m 0666 $P2P_FIFO
}
