#!/bin/bash
SOURCE="$0"
source /usr/lib/elive-tools/functions
EL_REPORTS="1"
el_make_environment
. gettext.sh
TEXTDOMAIN="elive-tools"
export TEXTDOMAIN



# include sbin in our PATH since its needed sometimes, and there's nothing wrong by using it!
if [[ "$PATH" != *"/usr/sbin"* ]] ; then
    # needed for: iwconfig
    export PATH="${PATH}:/usr/local/sbin:/usr/sbin:/sbin"
fi

extra_fixes(){
    if dmidecode -s system-manufacturer | grep -qsi "LENOVO" ; then
        # https://wiki.archlinux.org/index.php/Talk:Broadcom_wireless
        if [[ "$( dmidecode -s system-version )" = *"G580"* ]] ; then
            cat > "/etc/modprobe.d/10_wl.conf" <<EOF
blacklist brcmsmac
blacklist bcma
softdep wl pre: lib80211_crypt_tkip lib80211_crypt_ccmp lib80211_crypt_wep
EOF
        fi

        # https://wiki.archlinux.org/index.php/Talk:Broadcom_wireless
        if [[ "$( dmidecode -s system-version )" = *"Twist"* ]] ; then
            cat > "/etc/modprobe.d/10_b43.conf" <<EOF
options b43 pio=0 qos=0
EOF
        fi
    fi
}

try_and_configure(){

    # note: wl must be the first one (broadcom-sta-dkms)
    #modules_list="wl b43 b43legacy brcm80211"
    modules_list="wl b43 b43legacy brcm80211 b44 bcma brcmsmac brcmfmac ssb rndis_wlan tg3"

    # remove every b43 module
    for j in $( seq 5 )
    do
        for i in $modules_list
        do
            rmmod "$i" 2>/dev/null || true
        done
    done

    # TODO: do we require to unblock rfkill?
    # Try drivers
    for driver in $modules_list
    do
        if ! modprobe "$driver" 2>/dev/null ; then
            el_debug "failed attempt to use driver: ${driver}"
            rmmod "$driver" 2>/dev/null || true
            continue
        fi

        el_debug "trying with driver $driver ..."

        # unblock rfkill
        rfkill unblock all 2>/dev/null || true

        # up to 5 seconds
        for j in $( seq 10 )
        do
            wifi_dev="$( LC_ALL=C iwconfig 2>&1 | grep -F IEEE | awk '{print $1}' | grep "[[:alpha:]]" | tail -1 )"
            if [[ -n "$wifi_dev" ]] ; then
                el_debug "possible good driver: $driver"

                for dev in $( LC_ALL=C iwconfig 2>&1 | grep -F IEEE | awk '{print $1}' | grep "[[:alpha:]]" | tr '\n' ' ' )
                do
                    [[ -z "$dev" ]] && continue
                    for j in $( seq 8 )
                    do
                        if LC_ALL=C iwlist $dev scan 1>/dev/null 2>&1 ; then
                            driver_good="$driver"
                            wifi_dev="$dev"
                            break 4
                        fi

                        LC_ALL=C sleep 0.5
                    done
                done
            fi

            LC_ALL=C  sleep 0.5
        done

        # do not conflict, remove
        rmmod "$driver" 2>/dev/null || true
    done

    # valid driver! hooorray
    if [[ -n "$wifi_dev" ]] ; then
        el_debug "Wireless interface found '$wifi_dev' using driver '$driver_good' "
        # delete previous conf
        if ! [[ -s /etc/modprobe.d/broadcom-sta-dkms.conf ]] ; then
            el_debug "/etc/modprobe.d/broadcom-sta-dkms.conf doesnt exist, ignoring..."
        fi
        rm -f /etc/modprobe.d/broadcom-sta-dkms.conf


        case "$driver_good" in
            b43)
                echo -e "# blacklisting modules by Elive to make broadcom b43 devices working\n# Contact thanatermesis@gmail.com if this list should be improved for your type of driver" >> /etc/modprobe.d/broadcom-sta-dkms.conf
                echo -e "blacklist wl" >> /etc/modprobe.d/broadcom-sta-dkms.conf
                echo -e "blacklist b43legacy" >> /etc/modprobe.d/broadcom-sta-dkms.conf
                ;;
            b43legacy)
                echo -e "# blacklisting modules by Elive to make broadcom b43 devices working\n# Contact thanatermesis@gmail.com if this list should be improved for your type of driver" >> /etc/modprobe.d/broadcom-sta-dkms.conf
                echo -e "blacklist wl" >> /etc/modprobe.d/broadcom-sta-dkms.conf
                echo -e "blacklist b43" >> /etc/modprobe.d/broadcom-sta-dkms.conf
                ;;
            wl)
                echo -e "# blacklisting modules by Elive to make broadcom b43 devices working\n# Contact thanatermesis@gmail.com if this list should be improved for your type of driver" >> /etc/modprobe.d/broadcom-sta-dkms.conf
                echo -e "blacklist b43" >> /etc/modprobe.d/broadcom-sta-dkms.conf
                echo -e "blacklist b43legacy" >> /etc/modprobe.d/broadcom-sta-dkms.conf
                echo -e "blacklist b44" >> /etc/modprobe.d/broadcom-sta-dkms.conf
                echo -e "blacklist bcma" >> /etc/modprobe.d/broadcom-sta-dkms.conf
                echo -e "blacklist brcm80211" >> /etc/modprobe.d/broadcom-sta-dkms.conf
                echo -e "blacklist brcmsmac" >> /etc/modprobe.d/broadcom-sta-dkms.conf
                echo -e "blacklist ssb" >> /etc/modprobe.d/broadcom-sta-dkms.conf
                ;;
        esac

        if ! grep -qsE "^${driver_good}$" /etc/modules ; then
            echo -e "# broadcom b43 wifi by elive\n$driver_good" >> /etc/modules
        fi

        is_wifi_working=1
        service network-manager restart 1>/dev/null 2>&1 || true
    fi
}


main(){
    # pre {{{
    #local  driver_good modules_list wifi_dev
    el_config_get
    # }}}

    # detect if we have a Broadcom 43* type wifi
    if [[ "$( lspci -nn -d "14e4:" | wc -l )" -gt 0 ]] || grep -Fqs "simulate=b43" /proc/cmdline ; then

        # not a wifi device:
        if lspci -nn -d "14e4:" | grep -qsE "(Ethernet|100Base)" ; then
            exit 0
        fi

        # get device name
        el_debug "BCM43 Broadcom Wireless device detected"

        wifi_dev="$( LC_ALL=C iwconfig 2>&1 | grep -F IEEE | awk '{print $1}' | grep "[[:alpha:]]" | tail -1 )"

        # check again..
        if [[ -z "$wifi_dev" ]] ; then
            sleep 1
            wifi_dev="$( LC_ALL=C iwconfig 2>&1 | grep -F IEEE | awk '{print $1}' | grep "[[:alpha:]]" | tail -1 )"
        fi

        # check if we can scan
        if [[ -n "$wifi_dev" ]] ; then
            if ! LC_ALL=C iwlist $wifi_dev scan 1>/dev/null 2>&1 ; then
                unset wifi_dev
            fi
        fi

        # wifi not working correctly? let's try with other modules:
        if [[ -n "$wifi_dev" ]] ; then
            el_debug "wifi seems to be correctly working, nothing more to do"
        else

            try_and_configure

            # hack: extracting firmwares, files included probably in built-time of the iso
            if ! ((is_wifi_working)) ; then

                # try to remove first some conflicting modules: https://wiki.archlinux.org/index.php/Talk:Broadcom_wireless
                rmmod "acer_wmi" 2>/dev/null || true
                rmmod "dell_wmi" 2>/dev/null || true
                rmmod "cfg80211" 2>/dev/null || true

                mv /lib/firmware/b43 /tmp/ 2>/dev/null || true
                mv /lib/firmware/b43legacy /tmp/ 2>/dev/null || true
                mkdir -p /lib/firmware/b43

                for i in /var/cache/firmwares/b43/*
                do
                    [[ -s "$i" ]] || continue
                    b43-fwcutter -w /lib/firmware "$i" || true
                done

                # configure again
                try_and_configure

                # try again with extra fixes
                if ! ((is_wifi_working)) ; then
                    extra_fixes
                    try_and_configure
                fi

                # cleanups
                if ! ((is_wifi_working)) ; then
                    rm -rf /lib/firmware/b43 /lib/firmware/b43legacy
                    mv /tmp/b43 /lib/firmware/ 2>/dev/null || true
                    mv /tmp/b43legacy /lib/firmware/ 2>/dev/null || true
                fi
            fi


            if ! ((is_wifi_working)) ; then
                el_error "B43 device not installed correctly: $( lspci -nn -d "14e4:" )\n$(dmesg | grep -iE "(broadcom|b43|firmware)" | tail -n 10)"

                if [[ -n "$DISPLAY" ]] ; then
                    if ! ((conf_is_user_reported_install_failed)) ; then
                        zenity --error --text="$( eval_gettext "Elive couldn't install the B43 drivers for your WiFi card. These drivers can be tricky; if you manage to get them working, report any necessary changes to Elive, which will work for  you next time and also will benefit everyone as well." )\n\nWiFi Model: $(lspci -nn -d "14e4:" | sed -e 's|^.*BCM|BCM|g' | awk '{print $1}' )"
                        conf_is_user_reported_install_failed=1
                        el_config_save "conf_is_user_reported_install_failed"
                    fi

                fi
            fi
        fi
    else
        el_debug "no b43 devices found, ignoring..."
    fi

}

#
#  MAIN
#
main "$@"

# vim: set foldmethod=marker :
