#!/bin/bash

INTERACTIVE=True
ASK_TO_REBOOT=0
CONFIG=/boot/config.txt
CMDLINE=/proc/cmdline

USER=${SUDO_USER:-$(who -m | awk '{ print $1 }')}
if [ -z "$USER" ] && [ -n "$HOME" ]; then
  USER=$(getent passwd | awk -F: "\$6 == \"$HOME\" {print \$1}")
fi
if [ -z "$USER" ] || [ "$USER" = "root" ]; then
  USER=$(getent passwd | awk -F: '$3 == "1000" {print $1}')
fi

SYSFS_BOARDID_PATH="/sys/class/socinfo/board_id"
SYSFS_SOCNAME_PATH="/sys/class/socinfo/soc_name"
SYSFS_SOMNAME_PATH="/sys/class/socinfo/som_name"

get_rdk_type_string() {
  local soc_name=""
  local board_id=""
  local rdk_type="unknown"

  if [ -f "${SYSFS_SOCNAME_PATH}" ]; then
    soc_name=$(cat "${SYSFS_SOCNAME_PATH}" 2>/dev/null | tr -d '[:space:]')
  elif [ -f "${SYSFS_SOMNAME_PATH}" ]; then
    soc_name=$(cat "${SYSFS_SOMNAME_PATH}" 2>/dev/null | tr -d '[:space:]')
  fi
  soc_name=${soc_name:-""}

  if [ -f "${SYSFS_BOARDID_PATH}" ]; then
    board_id=$(cat "${SYSFS_BOARDID_PATH}" 2>/dev/null | tr -d '[:space:]')
  fi
  board_id=${board_id:-""}

  if echo "$soc_name" | grep -qi "x5"; then
    local prefix=""
    local version_num="0"
    
    if [[ "$board_id" == 30* ]]; then
      prefix="x5_rdk"
      version_num=$(echo "$board_id" | grep -o "30[0-9]" | grep -o "[0-9]$" || echo "0")
    elif [[ "$board_id" == 50* ]]; then
      prefix="x5_md"
      version_num=$(echo "$board_id" | grep -o "50[0-9]" | grep -o "[0-9]$" || echo "0")
    fi

    if [ -n "$prefix" ]; then
      rdk_type="${prefix}_v${version_num}"
    else
      rdk_type="x5_unknown"
    fi

  elif [[ "$soc_name" =~ ^[568b]$ ]]; then
    case "$soc_name" in
      "5") rdk_type="x3_rdk_v1"   ;; 
      "6") rdk_type="x3_rdk_v1_2" ;;  
      "8") rdk_type="x3_rdk_v2"   ;;
      "b") rdk_type="x3_md_v1"    ;;
    esac
  fi

  echo "$rdk_type"
}

is_rdkmd() {
  board_type_string=$(get_rdk_type_string)

  if [[ "$board_type_string" == *md* ]]; then
    return 0
  else
    return 1
  fi
}

is_installed() {
  if [ "$(dpkg -l "$1" 2> /dev/null | tail -n 1 | cut -d ' ' -f 1)" != "ii" ]; then
    return 1
  else
    return 0
  fi
}

calc_wt_size() {
  # NOTE: it's tempting to redirect stderr to /dev/null, so supress error
  # output from tput. However in this case, tput detects neither stdout or
  # stderr is a tty and so only gives default 80, 24 values
  WT_HEIGHT=18
  WT_WIDTH=$(tput cols)

  if [ -z "$WT_WIDTH" ] || [ "$WT_WIDTH" -lt 60 ]; then
    WT_WIDTH=80
  fi
  if [ "$WT_WIDTH" -gt 178 ]; then
    WT_WIDTH=120
  fi
  WT_MENU_HEIGHT=$((WT_HEIGHT - 7))
}

do_about() {
  whiptail --msgbox "\
This tool provides a straightforward way of doing initial
configuration of the RDK. Although it can be run
at any time, some of the options may have difficulties if
you have heavily customised your installation.\
" 20 70 1
  return 0
}

do_change_pass() {
  whiptail --msgbox "You will now be asked to enter a new password for the $USER user" 20 60 1
  passwd $USER &&
  whiptail --msgbox "Password changed successfully" 20 60 1
}

set_config_var() {
  lua - "$1" "$2" "$3" <<EOF > "$3.bak"
local key=assert(arg[1])
local value=assert(arg[2])
local fn=assert(arg[3])
local file=assert(io.open(fn))
local made_change=false
for line in file:lines() do
  if line:match("^#?%s*"..key.."=.*$") then
    line=key.."="..value
    made_change=true
  end
  print(line)
end

if not made_change then
  print(key.."="..value)
end
EOF
mv "$3.bak" "$3"
}

clear_config_var() {
  lua - "$1" "$2" <<EOF > "$2.bak"
local key=assert(arg[1])
local fn=assert(arg[2])
local file=assert(io.open(fn))
for line in file:lines() do
  if line:match("^%s*"..key.."=.*$") then
    line="#"..line
  end
  print(line)
end
EOF
mv "$2.bak" "$2"
}

get_config_var() {
  lua - "$1" "$2" <<EOF
local key=assert(arg[1])
local fn=assert(arg[2])
local file=assert(io.open(fn))
local found=false
for line in file:lines() do
  local val = line:match("^%s*"..key.."=(.*)$")
  if (val ~= nil) then
    print(val)
    found=true
    break
  end
end
if not found then
   print(0)
end
EOF
}

is_uname_current() {
  test -d "/lib/modules/$(uname -r)"
}

do_change_locale() {
  if [ "$INTERACTIVE" = True ]; then
    dpkg-reconfigure locales
    if [ $? -eq 0 ]; then
      ASK_TO_REBOOT=1
    fi
  else
    if ! LOCALE_LINE="$(grep -E "^$1( |$)" /usr/share/i18n/SUPPORTED)"; then
      return 1
    fi
    export LC_ALL=C
    export LANG=C
    LG="/etc/locale.gen"
    NEW_LANG="$(echo $LOCALE_LINE | cut -f1 -d " ")"
    [ -L "$LG" ] && [ "$(readlink $LG)" = "/usr/share/i18n/SUPPORTED" ] && rm -f "$LG"
    echo "$LOCALE_LINE" > /etc/locale.gen
    update-locale --no-checks LANG
    update-locale --no-checks "LANG=$NEW_LANG"
    dpkg-reconfigure -f noninteractive locales
  fi
}

do_change_timezone() {
  if [ "$INTERACTIVE" = True ]; then
    dpkg-reconfigure tzdata
  else
    TIMEZONE="$1"
    if [ ! -f "/usr/share/zoneinfo/$TIMEZONE" ]; then
      return 1;
    fi
    rm /etc/localtime
    echo "$TIMEZONE" > /etc/timezone
    dpkg-reconfigure -f noninteractive tzdata 2> /dev/null
  fi
}

do_configure_keyboard() {
  printf "Reloading keymap. This may take a short while\n"
  rm -f /etc/console-setup/cached_*
  if [ "$INTERACTIVE" = True ]; then
    dpkg-reconfigure keyboard-configuration
  else
    KEYMAP="$1"
    sed -i /etc/default/keyboard -e "s/^XKBLAYOUT.*/XKBLAYOUT=\"$KEYMAP\"/"
    dpkg-reconfigure -f noninteractive keyboard-configuration
  fi
  if [ "$INIT" = "systemd" ]; then
    systemctl restart keyboard-setup
  fi
  setsid sh -c 'exec setupcon --save -k --force <> /dev/tty1 >&0 2>&1'
  udevadm trigger --subsystem-match=input --action=change
  return 0
}

get_hostname() {
  tr -d " \t\n\r" < /etc/hostname
}

do_hostname() {
  if [ "$INTERACTIVE" = True ]; then
    whiptail --msgbox "\
Please note: RFCs mandate that a hostname's labels \
may contain only the ASCII letters 'a' through 'z' (case-insensitive),
the digits '0' through '9', and the hyphen.
Hostname labels cannot begin or end with a hyphen.
No other symbols, punctuation characters, or blank spaces are permitted.\
" 20 70 1
  fi
  CURRENT_HOSTNAME=$(get_hostname)
  if [ "$INTERACTIVE" = True ]; then
    NEW_HOSTNAME=$(whiptail --inputbox "Please enter a hostname" 20 60 "$CURRENT_HOSTNAME" 3>&1 1>&2 2>&3)
  else
    NEW_HOSTNAME="$1"
    true
  fi
  if [ $? -eq 0 ]; then
    if [ "$INIT" = "systemd" ] && systemctl -q is-active dbus && ! ischroot; then
      hostnamectl set-hostname "$NEW_HOSTNAME" 2> /dev/null
    else
      echo "$NEW_HOSTNAME" > /etc/hostname
    fi
    sed -i "s/127\.0\.1\.1.*$CURRENT_HOSTNAME/127.0.1.1\t$NEW_HOSTNAME/g" /etc/hosts
    ASK_TO_REBOOT=1
  fi
}

list_wlan_interfaces() {
  for dir in /sys/class/net/*/wireless; do
    if [ -d "$dir" ]; then
      IFACE="$(basename "$(dirname "$dir")")"
      if wpa_cli -i "$IFACE" status > /dev/null 2>&1; then
        echo "$IFACE"
      fi
    fi
  done
}

do_wifi_ssid_passphrase() {
  RET=0

  if systemctl -q is-active dhcpcd; then
    IFACE="$(list_wlan_interfaces | head -n 1)"

    if [ -z "$IFACE" ]; then
      if [ "$INTERACTIVE" = True ]; then
        whiptail --msgbox "No wireless interface found" 20 60
      fi
      return 1
    fi

    if ! wpa_cli -i "$IFACE" status > /dev/null 2>&1; then
      if [ "$INTERACTIVE" = True ]; then
        whiptail --msgbox "Could not communicate with wpa_supplicant" 20 60
      fi
      return 1
    fi
  elif ! systemctl -q is-active NetworkManager; then
    if [ "$INTERACTIVE" = True ]; then
        whiptail --msgbox "No supported network connection manager found" 20 60
      fi
      return 1
  fi

  SSID="$1"
  while [ -z "$SSID" ] && [ "$INTERACTIVE" = True ]; do
    if ! SSID=$(whiptail --inputbox "Please enter SSID" 20 60 3>&1 1>&2 2>&3); then
      return 0
    elif [ -z "$SSID" ]; then
      whiptail --msgbox "SSID cannot be empty. Please try again." 20 60
    fi
  done

  PASSPHRASE="$2"
  while [ "$INTERACTIVE" = True ]; do
    if ! PASSPHRASE=$(whiptail --passwordbox "Please enter passphrase. Leave it empty if none." 20 60 3>&1 1>&2 2>&3); then
      return 0
    else
      break
    fi
  done

  # Escape special characters for embedding in regex below
  ssid="$(echo "$SSID" \
   | sed 's;\\;\\\\;g' \
   | sed -e 's;\.;\\\.;g' \
         -e 's;\*;\\\*;g' \
         -e 's;\+;\\\+;g' \
         -e 's;\?;\\\?;g' \
         -e 's;\^;\\\^;g' \
         -e 's;\$;\\\$;g' \
         -e 's;\/;\\\/;g' \
         -e 's;\[;\\\[;g' \
         -e 's;\];\\\];g' \
         -e 's;{;\\{;g'   \
         -e 's;};\\};g'   \
         -e 's;(;\\(;g'   \
         -e 's;);\\);g'   \
         -e 's;";\\\\\";g')"

  HIDDEN=${3:-0}
  PLAIN=${4:-1}

  if systemctl -q is-active dhcpcd; then
    wpa_cli -i "$IFACE" list_networks \
     | tail -n +2 | cut -f -2 | grep -P "\t$ssid$" | cut -f1 \
     | while read -r ID; do
      wpa_cli -i "$IFACE" remove_network "$ID" > /dev/null 2>&1
    done

    ID="$(wpa_cli -i "$IFACE" add_network)"
    wpa_cli -i "$IFACE" set_network "$ID" ssid "\"$SSID\"" 2>&1 | grep -q "OK"
    RET=$((RET + $?))

    if [ -z "$PASSPHRASE" ]; then
      wpa_cli -i "$IFACE" set_network "$ID" key_mgmt NONE 2>&1 | grep -q "OK"
      RET=$((RET + $?))
    else
      if [ "$PLAIN" = 1 ]; then
        PASSPHRASE="\"$PASSPHRASE\""
      fi
      wpa_cli -i "$IFACE" set_network "$ID" psk "$PASSPHRASE" 2>&1 | grep -q "OK"
      RET=$((RET + $?))
    fi
    if [ "$HIDDEN" -ne 0 ]; then
      wpa_cli -i "$IFACE" set_network "$ID" scan_ssid 1 2>&1 | grep -q "OK"
      RET=$((RET + $?))
    fi
    if [ $RET -eq 0 ]; then
      wpa_cli -i "$IFACE" enable_network "$ID" > /dev/null 2>&1
    else
      wpa_cli -i "$IFACE" remove_network "$ID" > /dev/null 2>&1
      if [ "$INTERACTIVE" = True ]; then
        whiptail --msgbox "Failed to set SSID or passphrase" 20 60
      fi
    fi
    wpa_cli -i "$IFACE" save_config > /dev/null 2>&1
    echo "$IFACE_LIST" | while read -r IFACE; do
      wpa_cli -i "$IFACE" reconfigure > /dev/null 2>&1
    done
  else
    if [ "$HIDDEN" -ne 0 ]; then
      nmcli device wifi connect "$SSID"  password "$PASSPHRASE" hidden true | grep -q "activated"
    else
      nmcli device wifi connect "$SSID"  password "$PASSPHRASE" | grep -q "activated"
    fi
    RET=$((RET + $?))
  fi

  return "$RET"
}


do_boot_behaviour() {
  if [ "$INTERACTIVE" = True ]; then
    BOOTOPT=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "Boot Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT \
      "B1 Console" "Text console, requiring user to login" \
      "B2 Console Autologin" "Text console, automatically logged in as '$USER' user" \
      "B3 Desktop" "Desktop GUI, requiring user to login" \
      "B4 Desktop Autologin" "Desktop GUI, automatically logged in as '$USER' user" \
      3>&1 1>&2 2>&3)
  else
    BOOTOPT=$1
    true
  fi
  if [ $? -eq 0 ]; then
    case "$BOOTOPT" in # Handle default target
      B1*|B2*) # Console
        systemctl --quiet set-default multi-user.target
        ;;
      B3*|B4*) # Desktop
        if [ -e /etc/init.d/lightdm ]; then
          systemctl --quiet set-default graphical.target
        else
          whiptail --msgbox "Do 'sudo apt-get install lightdm' to allow configuration of boot to desktop" 20 60 2
          return 1
        fi
        ;;
      *)
        whiptail --msgbox "Programmer error, unrecognised boot option" 20 60 2
        return 1
        ;;
    esac
    case "$BOOTOPT" in # Handle autologin
      B1*|B3*) # Autologin disabled
        if [ -z "${BOOTOPT%%B3*}" ]; then
          sed /etc/lightdm/lightdm.conf.d/22-hobot-autologin.conf -i -e "s/^autologin-user=.*/#autologin-user=/"
        fi
        sed /lib/systemd/system/getty@.service -i -e 's/^ExecStart=.*/ExecStart=-\/sbin\/agetty -o '\''-p -- \\\\u'\'' --noclear %I \$TERM/'
        ;;
      B2*|B4*) # Autologin enabled
        if [ -z "${BOOTOPT%%B4*}" ]; then
          sed /etc/lightdm/lightdm.conf.d/22-hobot-autologin.conf -i -e "s/^\(#\|\)autologin-user=.*/autologin-user=$USER/"
        fi
        sed /lib/systemd/system/getty@.service -i -e "s/^ExecStart=.*/ExecStart=-\/sbin\/agetty --autologin sunrise --noclear %I \$TERM/"
        ;;
    esac
    if [ "$INIT" = "systemd" ]; then
      systemctl daemon-reload
    fi
    ASK_TO_REBOOT=1
  fi
}


do_fb_console_resolution() {
  if [ "$INTERACTIVE" = True ]; then
    output=$(get_hdmi_res)
    height=$(echo "$output" | cut -d',' -f1)
    width=$(echo "$output" | cut -d',' -f2)
    default_resolution="${width}x${height}"

    modes_file="/sys/class/graphics/fb0/modes"
    options=()
    original_lines=()
    default_option_index=-1

    while read -r line; do
      resolution=$(echo "$line" | cut -d ':' -f 2)
      if [ "$(echo "$resolution" | sed 's/p-[0-9]\+$//')" = "$default_resolution" ]; then
        default_option_index=${#options[@]}
      fi

      options+=("$resolution" "")
      original_lines+=("$line" "")
    done < "$modes_file"

    chosen_resolution=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --default-item \
      "${options[$default_option_index]}" --menu "Set FB Console Resolution" $WT_HEIGHT $WT_WIDTH \
      $WT_MENU_HEIGHT "${options[@]}" --cancel-button Back --ok-button Select 3>&1 1>&2 2>&3)
    RET=$?
  else 
    chosen_resolution=$1
    RET=0
  fi
    if [ $RET -eq 1 ]; then
      return 0
    elif [ $RET -eq 0 ]; then
      for ((i=0; i<${#options[@]}; i++)); do
        if [ "${options[$i]}" = "$chosen_resolution" ]; then
          chosen_resolution="${original_lines[$i]}"
          break
        fi
      done

      echo "$chosen_resolution" > /sys/class/graphics/fb0/mode

      read -t 10 -p "Please enter 'yes' in 10 seconds to confirm your selection:   " confirm
      if [ "$confirm" = "yes" ]; then
        whiptail --msgbox "Your resolution has been changed:  $chosen_resolution" $WT_HEIGHT $WT_WIDTH
        set_config_var fb_console_width $(echo "$chosen_resolution" | sed 's/.*:\([0-9]\+\)x\([0-9]\+\).*/\1/') ${CONFIG}
        set_config_var fb_console_height $(echo "$chosen_resolution" | sed 's/.*:\([0-9]\+\)x\([0-9]\+\).*/\2/') ${CONFIG}
        set_config_var fb_console_refresh_rate $(echo "$chosen_resolution" | sed 's/.*-//') ${CONFIG}
      else
        #fall back
        echo "${original_lines[$default_option_index]}" > /sys/class/graphics/fb0/mode
        whiptail --msgbox "Your resolution is restored" $WT_HEIGHT $WT_WIDTH

      fi
      if [ "$INTERACTIVE" = True ]; then
        ASK_TO_REBOOT=1
      fi
    fi
}

get_leds () {
  if [ ! -e /sys/class/leds/ACT/trigger ] ; then
    echo -1
  elif grep -q "\\[heartbeat\\]" /sys/class/leds/ACT/trigger ; then
    echo 0
  elif grep -q "\\[default-on\\]" /sys/class/leds/ACT/trigger ; then
    echo 1
  else
    echo -1
  fi
}

do_leds() {
  CURRENT=$(get_leds)
  if [ $CURRENT -eq -1 ] ; then
    if [ "$INTERACTIVE" = True ]; then
      whiptail --msgbox "The LED behaviour cannot be changed on this model of RDK" 20 60 1
    fi
    return 1
  fi
  DEFAULT=--defaultno
  if [ $CURRENT -eq 0 ]; then
    DEFAULT=
  fi
  if [ "$INTERACTIVE" = True ]; then
    whiptail --yesno "Would you like the power LED to flash with heartbeat?" $DEFAULT 20 60 2
    RET=$?
  else
    RET=$1
  fi
  if [ $RET -eq 0 ]; then
    LEDSET="heartbeat"
    STATUS="flash with heartbeat"
  elif [ $RET -eq 1 ]; then
    LEDSET="default-on"
    STATUS="be on constantly"
  else
    return $RET
  fi
  sed $CONFIG -i -e "s/dtparam=act_led_trigger=.*/dtparam=act_led_trigger=$LEDSET/"
  if ! grep -q "dtparam=act_led_trigger" $CONFIG ; then
    sed $CONFIG -i -e "\$adtparam=act_led_trigger=$LEDSET"
  fi
  echo $LEDSET | tee /sys/class/leds/ACT/trigger > /dev/null
  if [ "$INTERACTIVE" = True ]; then
    whiptail --msgbox "The power LED will $STATUS" 20 60 1
  fi
}


get_browser() {
  echo $(update-alternatives --display x-www-browser | grep currently | cut -d " " -f 7 | cut -d / -f 4)
}

do_browser() {
  if [ "$INTERACTIVE" = True ]; then
    RES=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "Select Browser" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT \
      "1" "Chromium" \
      "2" "Firefox" \
      3>&1 1>&2 2>&3)
  else
    RES=""
    BROWSER=$1
    true
  fi
  if [ $? -eq 0 ]; then
    if [ "$RES" = "1" ] ; then
      if is_installed chromium; then
        BROWSER="chromium"
        BSTRING="Chromium"
      else
        add-apt-repository ppa:xtradeb/apps -y
        apt update
        if apt-get install -y chromium; then
          BROWSER="chromium"
          BSTRING="Chromium"
        fi
      fi
    elif [ "$RES" = "2" ] ; then
      BROWSER="firefox"
      BSTRING="Firefox"
    fi
    update-alternatives --set x-www-browser /usr/bin/$BROWSER > /dev/null
    if [ -z $2 ] ; then
      sudo -u $USER xdg-settings set default-web-browser $BROWSER.desktop
    else
      sudo -u $2 xdg-settings set default-web-browser $BROWSER.desktop
    fi
    if [ "$INTERACTIVE" = True ]; then
      whiptail --msgbox "Default browser set to $BSTRING" 20 60 1
    fi
  fi
}

do_drm_display_choice() {
  if [ "$INTERACTIVE" = True ]; then
    RES=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "Select Browser" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT \
      "1" "DSI" \
      "2" "HDMI" \
      3>&1 1>&2 2>&3)
  else
    RES=""
    BROWSER=$1
    true
  fi
  if [ $? -eq 0 ]; then
    if [ "$RES" = "1" ] ; then
      if [ -e /etc/X11/xorg.conf.d/xorg_dsi_ignore.conf ]; then
          mv /etc/X11/xorg.conf.d/xorg_dsi_ignore.conf /etc/X11/xorg.conf.d/xorg_dsi_ignore.conf.disable
      fi
      if [ -e /etc/X11/xorg.conf.d/xorg_hdmi_ignore.conf.disable ]; then
          mv /etc/X11/xorg.conf.d/xorg_hdmi_ignore.conf.disable /etc/X11/xorg.conf.d/xorg_hdmi_ignore.conf
      fi
      BSTRING="DSI"
    elif [ "$RES" = "2" ] ; then
      if [ -e /etc/X11/xorg.conf.d/xorg_hdmi_ignore.conf ]; then
          mv /etc/X11/xorg.conf.d/xorg_hdmi_ignore.conf /etc/X11/xorg.conf.d/xorg_hdmi_ignore.conf.disable
      fi
      if [ -e /etc/X11/xorg.conf.d/xorg_dsi_ignore.conf.disable ]; then
          mv /etc/X11/xorg.conf.d/xorg_dsi_ignore.conf.disable /etc/X11/xorg.conf.d/xorg_dsi_ignore.conf
      fi
      BSTRING="HDMI"
    fi
    if [ "$INTERACTIVE" = True ]; then
      whiptail --msgbox "Default display set to $BSTRING" 20 60 1
      ASK_TO_REBOOT=1
    fi
  fi
}

do_drm_display_choice_gpu() {
  if [ "$INTERACTIVE" = True ]; then
    RES=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "Select Browser" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT \
      "1" "CPU" \
      "2" "GPU" \
      3>&1 1>&2 2>&3)
  else
    RES=""
    BROWSER=$1
    true
  fi
  if [ $? -eq 0 ]; then
    if [ "$RES" = "1" ] ; then
      if [ -e /etc/X11/xorg.conf.d/2-dr-accel.conf ]; then
          mv /etc/X11/xorg.conf.d/2-dr-accel.conf /etc/X11/xorg.conf.d/2-dr-accel.conf.disable
      fi
      BSTRING="CPU"
    elif [ "$RES" = "2" ] ; then
      if [ -e /etc/X11/xorg.conf.d/2-dr-accel.conf.disable ]; then
          mv /etc/X11/xorg.conf.d/2-dr-accel.conf.disable /etc/X11/xorg.conf.d/2-dr-accel.conf
      fi
      BSTRING="GPU"
    fi
    if [ "$INTERACTIVE" = True ]; then
      whiptail --msgbox "Default display set to $BSTRING" 20 60 1
      ASK_TO_REBOOT=1
    fi
  fi
}

update_lcd_config() {
    local lcd_size="$1"

    [ -e /etc/X11/xorg.conf.d/xorg_dsi_ignore.conf ] && \
        mv -f /etc/X11/xorg.conf.d/xorg_dsi_ignore.conf /etc/X11/xorg.conf.d/xorg_dsi_ignore.conf.disable

    [ -e /etc/X11/xorg.conf.d/xorg_hdmi_ignore.conf.disable ] && \
        mv -f /etc/X11/xorg.conf.d/xorg_hdmi_ignore.conf.disable /etc/X11/xorg.conf.d/xorg_hdmi_ignore.conf

    if [ -f "${CONFIG}" ]; then
        if grep -q "^dtoverlay=dsi-waveshare-panel-overlay-" "${CONFIG}"; then
            sed -i "s|^dtoverlay=dsi-waveshare-panel-overlay-.*|dtoverlay=dsi-waveshare-panel-overlay-${lcd_size}|" "${CONFIG}"
        else
            echo "dtoverlay=dsi-waveshare-panel-overlay-${lcd_size}" >> "${CONFIG}"
        fi
    fi
}

do_lcd_choice() {
  if [ "$INTERACTIVE" = True ]; then
    RES=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "Select Browser" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT \
      "1" "UNSET(HDMI)" \
      "2" "2.8inch DSI LCD" \
      "3" "3.4inch DSI LCD (C)" \
      "4" "4.3inch DSI LCD" \
      "5" "7inch DSI LCD (C)" \
      "6" "7.9inch DSI LCD" \
      "7" "8inch DSI LCD (C)" \
      "8" "10.1inch DSI LCD (C)" \
      "9" "11.9inch DSI LCD" \
      3>&1 1>&2 2>&3)
  else
    RES=""
    BROWSER=$1
    true
  fi
  if [ $? -eq 0 ]; then
    if [ "$RES" = "1" ] ; then
      if [ -e /etc/X11/xorg.conf.d/xorg_hdmi_ignore.conf ]; then
          mv /etc/X11/xorg.conf.d/xorg_hdmi_ignore.conf /etc/X11/xorg.conf.d/xorg_hdmi_ignore.conf.disable
      fi
      if [ -e /etc/X11/xorg.conf.d/xorg_dsi_ignore.conf.disable ]; then
          mv /etc/X11/xorg.conf.d/xorg_dsi_ignore.conf.disable /etc/X11/xorg.conf.d/xorg_dsi_ignore.conf
      fi
      sed -i "/^dtoverlay=dsi-waveshare-panel-overlay-/d" "${CONFIG}"
      BSTRING="HDMI"
    elif [ "$RES" = "2" ] ; then
      update_lcd_config "2_8_inch"
      BSTRING="2.8inch DSI LCD"
    elif [ "$RES" = "3" ] ; then
      update_lcd_config "3_4_inch"
      BSTRING="3.4inch DSI LCD (C)"
    elif [ "$RES" = "4" ] ; then
      update_lcd_config "4_3_inch"
      BSTRING="4.3inch DSI LCD"
    elif [ "$RES" = "5" ] ; then
      update_lcd_config "7_0_inchC"
      BSTRING="7inch DSI LCD (C)"
    elif [ "$RES" = "6" ] ; then
      update_lcd_config "7_9_inch"
      BSTRING="7.9inch DSI LCD"
    elif [ "$RES" = "7" ] ; then
      update_lcd_config "8_0_inch"
      BSTRING="8inch DSI LCD (C)"
    elif [ "$RES" = "8" ] ; then
      update_lcd_config "10_1_inch"
      BSTRING="10.1inch DSI LCD (C)"
    elif [ "$RES" = "9" ] ; then
      update_lcd_config "11_9_inch"
      BSTRING="11.9inch DSI LCD"
    fi
    if [ "$INTERACTIVE" = True ]; then
      whiptail --msgbox "Default display set to $BSTRING" 20 60 1
      ASK_TO_REBOOT=1
    fi
  fi
}

do_update_miniboot()
{
  DEFAULT=--defaultno
  DO_DOWNLOAD=0

  if [ "$INTERACTIVE" = True ]; then
    whiptail --yesno "Would you like update the minimal boot image in nand flash?\n\nCaution: Abnormal interruptions are not allowed during the upgrade process!" $DEFAULT 20 60 2
    [ $? -eq 0 ] || return
  fi

  if [ "$INTERACTIVE" = True ]; then
    whiptail --yesno "Do you want to download the latest hobot-miniboot from the internet?\n\nPlease ensure the network connection is stable before continuing." $DEFAULT 20 60 2
    [ $? -eq 0 ] && DO_DOWNLOAD=1
  fi

  if [ "$DO_DOWNLOAD" = 1 ] || ! is_installed hobot-miniboot; then
    echo "Attempting to install hobot-miniboot..."
    apt update;
    apt-get install -y hobot-miniboot; 
  fi

  echo "Starting rdk-miniboot-update..."
  rdk-miniboot-update
}

get_vnc_resolution() {
  if [ -e /etc/xdg/autostart/vnc_xrandr.desktop ] ; then
    grep fb /etc/xdg/autostart/vnc_xrandr.desktop | cut -f 15 -d ' '
  else
    echo ""
  fi
}

do_vnc_resolution() {
  if [ "$INTERACTIVE" = True ]; then
    CUR=$(get_vnc_resolution)
    if [ "$CUR" = "" ] ; then
      CUR=640x480
    fi
    FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --default-item $CUR --menu "Set VNC Resolution" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
      "640x480" "" "720x480" "" "800x600" "" "1024x768" "" "1280x720" "" "1280x1024" "" "1600x1200" "" "1920x1080" "" 3>&1 1>&2 2>&3)
    RET=$?
  else
    FUN=$1
    RET=0
  fi
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    cat > /etc/xdg/autostart/vnc_xrandr.desktop << EOF
[Desktop Entry]
Type=Application
Name=vnc_xrandr
Comment=Set resolution for VNC
NoDisplay=true
Exec=sh -c "if ! (xrandr | grep -q -w connected) ; then /usr/bin/xrandr --fb $FUN ; fi"
EOF
    if [ "$INTERACTIVE" = True ]; then
      whiptail --msgbox "The resolution is set to $FUN" 20 60 1
      ASK_TO_REBOOT=1
    fi
  fi
}

get_ssh() {
  if service ssh status | grep -q inactive; then
    echo 1
  else
    echo 0
  fi
}

do_ssh() {
  if [ -e /var/log/regen_ssh_keys.log ] && ! grep -q "^finished" /var/log/regen_ssh_keys.log; then
    whiptail --msgbox "Initial ssh key generation still running. Please wait and try again." 20 60 2
    return 1
  fi
  DEFAULT=--defaultno
  if [ $(get_ssh) -eq 0 ]; then
    DEFAULT=
  fi
  if [ "$INTERACTIVE" = True ]; then
    whiptail --yesno \
      "Would you like the SSH server to be enabled?\n\nCaution: Default and weak passwords are a security risk when SSH is enabled!" \
      $DEFAULT 20 60 2
    RET=$?
  else
    RET=$1
  fi
  if [ $RET -eq 0 ]; then
    ssh-keygen -A &&
    update-rc.d ssh enable &&
    invoke-rc.d ssh start &&
    STATUS=enabled
  elif [ $RET -eq 1 ]; then
    update-rc.d ssh disable &&
    invoke-rc.d ssh stop &&
    STATUS=disabled
  else
    return $RET
  fi
  if [ "$INTERACTIVE" = True ]; then
    whiptail --msgbox "The SSH server is $STATUS" 20 60 1
  fi
}

get_vnc() {
  if systemctl status x11vnc.service  | grep -q -w active; then
    echo 0
  else
    echo 1
  fi
}

do_vnc() {
  DEFAULT=--defaultno
  if [ $(get_vnc) -eq 0 ]; then
    DEFAULT=
  fi
  APT_GET_FLAGS=""
  if [ "$INTERACTIVE" = True ]; then
    whiptail --yesno "Would you like the VNC Server to be enabled?" $DEFAULT 20 60 2
    RET=$?
  else
    RET=$1
    APT_GET_FLAGS="-y"
  fi
  if [ $RET -eq 0 ]; then
    if is_installed x11vnc; then
      systemctl disable x11vnc.service
      systemctl stop x11vnc.service
    fi

    if is_installed x11vnc || apt-get install "$APT_GET_FLAGS" x11vnc; then
      whiptail --msgbox "You will now be asked to enter a password for the VNC server" 20 60 1
      mkdir -p /etc/.vnc
      vncpasswd /etc/.vnc/passwd &&
      whiptail --msgbox "Password setted successfully" 20 60 1
      systemctl enable x11vnc.service &&
      systemctl start x11vnc.service &&
      STATUS=enabled
    else
      return 1
    fi
  elif [ $RET -eq 1 ]; then
    if is_installed x11vnc; then
      systemctl disable x11vnc.service
      systemctl stop x11vnc.service
    fi
    STATUS=disabled
  else
    return $RET
  fi
  if [ "$INTERACTIVE" = True ]; then
    whiptail --msgbox "The VNC Server is $STATUS" 20 60 1
  fi
}

warn_box() {
  text="$1"
  return $(whiptail --title "WARNNING" --msgbox "$text" 20 60 1)
}

update_status() {
  local dtb_name=$1
  local options=()
  local confstate=
  for peri in ${!peri_status[@]}
  do
    status=`fdtget -t s ${dtb_name} ${peri} status 2> /dev/null`
    if [ ! -z $status ];then
      peri_status[${peri}]="$status"
    fi
    options+=("$peri" "                     ${peri_status[$peri]}")
  done
  peri_select=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" \
    --menu "Peripherals bus config" \
    $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT \
    --cancel-button Back \
    --ok-button Select \
    "${options[@]}" \
    3>&1 1>&2 2>&3)
  ret=$?
  if [ $ret -ne 0 ];then 
    return 1 
  fi
  unset options
  # echo peri_select=$peri_select
  # echo peri_status=${peri_status[$peri_select]}
  peri_ops ${dtb_name} $peri_select ${peri_status[$peri_select]}
  ret=$?
  if [ $ret -eq "0" ];then
    if [ "x${peri_status[$peri_select]}" == x"okay" ];then
      confstate="disabled"
    elif [ "x${peri_status[$peri_select]}" == x"disabled" ];then
      confstate="okay"
    else
      warn_box "undefined fdt node status !"
    fi
    apply_status ${dtb_name} ${peri_select} ${confstate}
    ret=$?
    if [ $ret -ne "0" ];then
      warn_box "fdtput get some err: ${options} ${peri_select} !"
    fi
    unset confstate
  fi
}

apply_status() {
  local dtb_name=$1
  local peri=$2
  local status=$3
  local array=${conf_peris[$peri]}
  local confstate="disabled"
  array=${array//,/ }
  if [ "x${status}" == x"okay" ];then
    confstate="disabled"
  elif [ "x${status}" == x"disabled" ];then
    :
  else
    warn_box "undefined fdt node status !"
  fi
  for cp in "${array}"
  do
    fdtput -t s ${dtb_name} ${cp} status ${confstate} 2> /dev/null
  done
  apply_state="true"
  return $(fdtput -t s ${dtb_name} ${peri} status ${status} 2> /dev/null)
}

declare -A rdk_x5_conflict_peris=(
  [serial3]="i2c5"
  [i2c5]="serial3"
  [i2c0]="pwm2"
  [pwm2]="i2c0"
  [spi2]="pwm0,pwm1"
  [pwm0]="spi2"
  [pwm1]="spi2"
  [i2c1]="pwm3"
  [pwm3]="i2c1"
)

peri_ops() {
  local dtb_name=$1
  local peri=$2
  local status=$3
  local options=()
  local string=()
  local somep="false"
  local cperis=
  local conflicts
  local conflict_list=""

  board_type_string=$(get_rdk_type_string)

  if [ "x${status}" == x"okay" ];then
    options=("dis")
  else
    options=("en")
  fi
  if [ ! -z "${conf_peris[$peri]}" ];then
    peris=${conf_peris[$peri]}
    for cperi in ${peris//,/ }
    do
      if [ x${peri_status[$cperi]} == x"okay" ];then
        somep="true"
        cperis="${cperis} ${cperi}"
      fi
    done
    if [ x${somep} == x"true" ];then
      string=("Doing this and the ${cperis[@]} will be disabled")
    else
      string=("")
    fi
  else
    string=("")
  fi

  if [[ "$board_type_string" == *x5* ]]; then
    if [ "$options" == "en" ] && [ -n "${rdk_x5_conflict_peris[$peri]}" ]; then
      conflicts=${rdk_x5_conflict_peris[$peri]}
      for cperi in ${conflicts//,/ }; do
        if [ "x${peri_status[$cperi]}" == "xokay" ]; then
          conflict_list="$conflict_list $cperi"
        fi
      done
      if [ -n "$conflict_list" ]; then
        string="$string\nEnabling $peri will disable:${conflict_list}"
      fi
    fi
  fi

  whiptail --title "Your select" \
    --yesno "Are you sure want to ${options}able $peri? \
    \n${string}" \
    20 60 \
    3>&1 1>&2 2>&3
  ret=$?
  if [ $ret -eq 0 ];then
    for cperi in ${peris//,/ }
    do
      if [ x${peri_status[$cperi]} == x"okay" ];then
        apply_status ${dtb_name} $cperi "disabled"
        ret=$?
        if [ $ret -ne "0" ];then
          warn_box "fdtput get some err: $options $cperi !"
          return ret
        fi
      fi
    done

    if [[ "$board_type_string" == *x5* ]]; then
      if [ "$options" == "en" ] && [ -n "${rdk_x5_conflict_peris[$peri]}" ]; then
        for cperi in ${rdk_x5_conflict_peris[$peri]//,/ }; do
          if [ "x${peri_status[$cperi]}" == "xokay" ]; then
            apply_status "${dtb_name}" "$cperi" "disabled"
          fi
        done
      fi
    fi

  fi
  return $ret
}

do_peripheral() {
  board_type_string=$(get_rdk_type_string)
  case $board_type_string in
  x5*)
    config="/etc/hobot.conf/x5rdk.conf"
    ;; 
  x3_rdk_v1*)
    config="/etc/hobot.conf/x3pi.conf"
    ;;
  x3_rdk_v2*)
    config="/etc/hobot.conf/rdkx3_v2_1.conf"
    ;;
  x3_md*)
    config="/etc/hobot.conf/x3cm.conf"
    ;;
  *)
    echo "Unsupport board type for config!!"
    exit -1
    ;;
  esac
  case $board_type_string in
  "x5_rdk_v1")
      dtb_name="x5-rdk.dtb"
      ;;
  "x5_rdk_v2")
      dtb_name="x5-rdk-v1p0.dtb"
      ;;
  "x5_md_v1")
      dtb_name="x5-md-v0p1.dtb"
      ;;
  "x5_md_v2")
      dtb_name="x5-md-v0p2.dtb"
      ;;
  "x5_md_v3")
      dtb_name="x5-md-v0p2.dtb"
      ;;
  "x5_md_v4")
      dtb_name="x5-md-v0p2.dtb"
      ;;
  "x5_md_v5")
      dtb_name="x5-md-v0p2.dtb"
      ;;
  "x5_md_v6")
      dtb_name="x5-md-v1p2.dtb"
      ;;
  "x3_rdk_v1*")
      dtb_name="hobot-x3-pi.dtb"
      ;;
  "x3_rdk_v2")
      dtb_name="hobot-x3-pi_v2_1.dtb"
      ;;
  "x3_md_v1")
      dtb_name="hobot-x3-cm.dtb"
      ;;
  *)
      echo "Unsupport board type for dtb_name!!"
      exit -1
      ;;
  esac
  if [ -f "/boot/hobot/${dtb_name}" ];then
      cp "/boot/hobot/${dtb_name}" ${dtb_name}
  else
      echo "Dtb file not exist!!"
      exit -1
  fi

  if [ -z $dtb_name ];then
      echo "No dtb file find!!"
      exit -1
  fi

  if [ ! -f $config ];then
    echo "file ${config} is not exist!"
    exit -1
  fi

  declare -A peri_status
  declare -A conf_peris

  apply_state="false"

  for line in $(cat $config)
  do
      arr=(${line//:/ })
      peri=${arr[0]}
      peri_status[$peri]="unkowned"
      conf_peris[$peri]=${arr[1]}
  done

  while true; do
      update_status $dtb_name
      ret=$?
      if [ $ret -ne 0 ];then
          break
      fi
  done

  if [ x${apply_state} == x"true" ];then
      cp ${dtb_name} "/boot/hobot/${dtb_name}"
      ASK_TO_REBOOT=1
  fi

  rm -rf $dtb_name ${bootfile}
}

do_wifi_antenna()
{
  if [ "$INTERACTIVE" = True ]; then
    FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --default-item "Onboard" --menu "Set VNC Resolution" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
      "Onboard" "" "External" ""  3>&1 1>&2 2>&3)
    RET=$?
  else
    FUN=$1
    RET=0
  fi
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    if [ "${FUN}" = "Onboard" ]; then
      /bin/switch_antenna trace
      set_config_var antenna_option trace ${CONFIG}
    elif [ "${FUN}" = "External" ]; then
      /bin/switch_antenna cable
      set_config_var antenna_option cable ${CONFIG}
    fi

    if [ "$INTERACTIVE" = True ]; then
      whiptail --msgbox "The Wi-Fi antenna is switch to ${FUN} antenna" 20 60 1
    fi
  fi
}

get_cpu_boost() {
  boost=$(tr -d " \t\n\r" < /sys/devices/system/cpu/cpufreq/boost)
  if [ "${boost}" = "0" ]; then
    echo 0
  else
    echo 1
  fi
}

do_cpu_boost() {
  if [ "$INTERACTIVE" = True ]; then
    whiptail --msgbox "\
Enabling overclocking will increase CPU power consumption.
Please install a sufficient radiator(such as enlarging the
radiator, using a cooling fan) to avoid system instability
caused by excessive temperature.\
" 20 70 1
  fi

  DEFAULT=--defaultno
  if [ $(get_cpu_boost) -eq 0 ]; then
    DEFAULT=
  fi

  if [ "$INTERACTIVE" = True ]; then
    whiptail --yesno \
      "Would you like the CPU boost to be enabled?" \
      $DEFAULT 20 60 2
    RET=$?
  else
    RET=$1
  fi
  if [ $RET -eq 0 ]; then
    set_config_var arm_boost 1 ${CONFIG}
    echo 1 > /sys/devices/system/cpu/cpufreq/boost
    STATUS=enabled
  elif [ $RET -eq 1 ]; then
    set_config_var arm_boost 0 ${CONFIG}
    echo 0 > /sys/devices/system/cpu/cpufreq/boost
    STATUS=disabled
  else
    return $RET
  fi
  if [ "$INTERACTIVE" = True ]; then
    whiptail --msgbox "The CPU boost is $STATUS" 20 60 1
    ASK_TO_REBOOT=1
  fi
}

get_cpu_governor() {
  if [ -e /sys/devices/system/cpu/cpufreq/policy0/scaling_governor ] ; then
    tr -d " \t\n\r" < /sys/devices/system/cpu/cpufreq/policy0/scaling_governor
  else
    echo ""
  fi
}

do_cpu_governor() {
  if [ "$INTERACTIVE" = True ]; then
    CUR=$(get_cpu_governor)
    if [ "$CUR" = "" ] ; then
      CUR=performance
    fi
    FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" \
      --default-item $CUR --menu "Set CPU governor" \
      $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
      "conservative" "" "ondemand" "" "userspace" "" "powersave" "" "performance" "" "schedutil" "" 3>&1 1>&2 2>&3)
    RET=$?
  else
    FUN=$1
    RET=0
  fi
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    set_config_var governor $FUN ${CONFIG}
    echo $FUN > /sys/devices/system/cpu/cpufreq/policy0/scaling_governor
    if [ "$INTERACTIVE" = True ]; then
      whiptail --msgbox "The cpu governor is set to $FUN" 20 60 1
      ASK_TO_REBOOT=1
    fi
  fi
}

get_cpu_frequency() {
  if [ -e /sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq ] ; then
    tr -d " \t\n\r" < /sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq
  else
    echo ""
  fi
}

do_cpu_frequency() {
  if [ $(get_cpu_governor) != "userspace" ]; then
    whiptail --msgbox "The cpu frequency can only be set when the governor is set to userspace" 20 60 2
    return 0
  fi
  if [ "$INTERACTIVE" = True ]; then
    CUR=$(get_cpu_frequency)
    if [ "$CUR" = "" ] ; then
      CUR=1200000
    fi

    available_frequencies=$(cat /sys/devices/system/cpu/cpufreq/policy0/scaling_available_frequencies | tr -d "\t\n\r\0" | sed 's/ / '[normal]' /g')
    if [ $(get_cpu_boost) -eq 1 ]; then
      boost_frequencies=$(cat /sys/devices/system/cpu/cpufreq/policy0/scaling_boost_frequencies | tr -d "\t\n\r\0" | sed 's/ / [boost] /g')
      available_frequencies="$available_frequencies $boost_frequencies"
    fi

    FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" \
      --default-item $CUR --menu "Set CPU frequency" \
      $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
      ${available_frequencies} 3>&1 1>&2 2>&3)
    RET=$?
  else
    FUN=$1
    RET=0
  fi
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    set_config_var frequency $FUN ${CONFIG}
    echo $FUN > /sys/devices/system/cpu/cpufreq/policy0/scaling_setspeed
    if [ "$INTERACTIVE" = True ]; then
      whiptail --msgbox "The cpu frequency is set to $FUN" 20 60 1
      ASK_TO_REBOOT=1
    fi
  fi
}

do_cpu_frequency_menu() {
  FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" \
      --menu "Configure CPU frequency" \
      $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
      "C1 CPU Boost" "Configure CPU overclocking" \
      "C2 CPU Governor" "Configure the CPU frequency governor mode" \
      "C3 CPU Frequency" "Configure the CPU to run at a fixed frequency (only Governor = userspace)" \
      3>&1 1>&2 2>&3)
  RET=$?
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    case "$FUN" in
      C1\ *) do_cpu_boost ;;
      C2\ *) do_cpu_governor ;;
      C3\ *) do_cpu_frequency ;;
      *) whiptail --msgbox "Programmer error: unrecognized option" 20 60 1 ;;
    esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1
  fi
}

get_total_memory_x3()
{
  total_mem=$(awk '/MemTotal/ {print $2}' /proc/meminfo)

  # Round to the nearest 1, 2, 4 or 8 multiple
  rounded_mem=$(( (total_mem + 512 * 1024) / (1024 * 1024) ))  # Convert to GB and round
  echo ${rounded_mem}
}

get_ion_memory_x3 ()
{
  if [ -e /proc/device-tree/reserved-memory/ion_cma/size ] ; then
    ion_cma_size_hex=$(xxd -s 4 -l 4 -p /proc/device-tree/reserved-memory/ion_cma/size | tr -d " \t\n\r")
    ion_cma_size_dec=$((16#${ion_cma_size_hex}))
    ion_cma_size_mb=$((ion_cma_size_dec / (1024 * 1024)))
    echo ${ion_cma_size_mb}"MB"
  else
    echo "672MB"
  fi
}

do_config_ion_memory_x3 ()
{
  if [ "$INTERACTIVE" = True ]; then
    CUR=$(get_ion_memory_x3)
    if [ "$CUR" = "" ] ; then
      CUR=672MB
    fi
    total_mem=$(get_total_memory_x3)
    if [ ${total_mem} -ge 4 ]; then
      FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --default-item $CUR --menu "Set VNC Resolution" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
        "512MB" "" "672MB" "" "768MB" "" "1024MB" "" "1280MB" "" "1536MB" "" "1664MB" "" "1700MB" "" "1900MB" "Only supported on 4GB memory models" 3>&1 1>&2 2>&3)
    else
       FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --default-item $CUR --menu "Set VNC Resolution" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
        "512MB" "" "672MB" "" "768MB" "" "1024MB" "" "1280MB" "" "1536MB" "" "1664MB" "" "1700MB" "" 3>&1 1>&2 2>&3)
    fi
    RET=$?
  else
    FUN=$1
    RET=0
  fi
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    ion_cma_size_mb=$(echo ${FUN} | sed 's/MB//')
    ion_cma_size_hex=$(printf "0x%x" "$((ion_cma_size_mb * 1024 * 1024))")
    if grep -q "dtoverlay=ion_resize,size=" "${CONFIG}" || grep -q "#dtoverlay=ion_resize,size=" "${CONFIG}"; then
      sed -i "s/\(dtoverlay=ion_resize,size=\|#dtoverlay=ion_resize,size=\).*/dtoverlay=ion_resize,size=${ion_cma_size_hex}/" "${CONFIG}"
    else
      echo "dtoverlay=ion_resize,size=${ion_cma_size_hex}" >> "${CONFIG}"
    fi
    if [ "$INTERACTIVE" = True ]; then
      whiptail --msgbox "The ion memory is set to ${FUN}" 20 60 1
      ASK_TO_REBOOT=1
    fi
  fi
}

get_ion_cma_memory_x5 ()
{
  ion_size=$(awk '/total size/ {print $5}' /sys/kernel/debug/ion/heaps/ion_cma)
  ion_size=$(( ion_size / (1024 * 1024) ))
  echo ${ion_size}"MB"
}

get_cma_reserved_memory_x5 ()
{
  ion_size=$(awk '/total size/ {print $5}' /sys/kernel/debug/ion/heaps/cma_reserved)
  ion_size=$(( ion_size / (1024 * 1024) ))
  echo ${ion_size}"MB"
}

get_carveout_memory_x5 ()
{
  ion_size=$(awk '/total size/ {print $5}' /sys/kernel/debug/ion/heaps/carveout)
  ion_size=$(( ion_size / (1024 * 1024) ))
  echo ${ion_size}"MB"
}

do_config_ion_memory_x5 ()
{
  if [ "$INTERACTIVE" = True ]; then
    CUR=$(get_ion_cma_memory_x5)+$(get_cma_reserved_memory_x5)+$(get_carveout_memory_x5)
    if [ "$CUR" = "" ] ; then
      CUR=128MB+320MB+320MB
    fi
    FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --default-item $CUR --menu "Set VNC Resolution" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
    "128MB+320MB+320MB" "" "192MB+384MB+384MB" "" "256MB+512MB+512MB" "" "320MB+640MB+640MB" "" "512MB+1024MB+1024MB" "" 3>&1 1>&2 2>&3)
    RET=$?
  else
    FUN=$1
    RET=0
  fi
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    IFS='+' read -r ion_cma_size_mb ion_reserved_size_mb ion_carveout_size_mb <<< "$FUN"

    ion_cma_size_mb=$(echo ${ion_cma_size_mb} | sed 's/MB//')
    ion_cma_size_hex=$(printf "0x%x" "$((ion_cma_size_mb * 1024 * 1024))")

    ion_reserved_size_mb=$(echo ${ion_reserved_size_mb} | sed 's/MB//')
    ion_reserved_size_hex=$(printf "0x%x" "$((ion_reserved_size_mb * 1024 * 1024))")

    ion_carveout_size_mb=$(echo ${ion_carveout_size_mb} | sed 's/MB//')
    ion_carveout_size_hex=$(printf "0x%x" "$((ion_carveout_size_mb * 1024 * 1024))")

    if grep -q "ion=ion_cma_size=" "${CONFIG}" || grep -q "#ion=ion_cma_size=" "${CONFIG}"; then
      sed -i "s/\(ion=ion_cma_size=\|#ion=ion_cma_size=\).*/ion=ion_cma_size=${ion_cma_size_hex}/" "${CONFIG}"
    else
      echo "ion=ion_cma_size=${ion_cma_size_hex}" >> "${CONFIG}"
    fi

    if grep -q "ion=ion_reserved_size=" "${CONFIG}" || grep -q "#ion=ion_reserved_size=" "${CONFIG}"; then
      sed -i "s/\(ion=ion_reserved_size=\|#ion=ion_reserved_size=\).*/ion=ion_reserved_size=${ion_carveout_size_hex}/" "${CONFIG}"
    else
      echo "ion=ion_reserved_size=${ion_carveout_size_hex}" >> "${CONFIG}"
    fi

    if grep -q "ion=ion_carveout_size=" "${CONFIG}" || grep -q "#ion=ion_carveout_size=" "${CONFIG}"; then
      sed -i "s/\(ion=ion_carveout_size=\|#ion=ion_carveout_size=\).*/ion=ion_carveout_size=${ion_carveout_size_hex}/" "${CONFIG}"
    else
      echo "ion=ion_carveout_size=${ion_carveout_size_hex}" >> "${CONFIG}"
    fi
    if [ "$INTERACTIVE" = True ]; then
      whiptail --msgbox "The ion memory is set to ${FUN}" 20 60 1
      ASK_TO_REBOOT=1
    fi
  fi
}

do_config_ion_memory() {
  board_type_string=$(get_rdk_type_string)
  
  case "$board_type_string" in
    x5*)
      do_config_ion_memory_x5
      ;;
    x3*)
      do_config_ion_memory_x3
      ;;
    *)
      whiptail --msgbox "Unsupported board type: $board_type_string\nION memory configuration failed!" 12 60
      return 1
      ;;
  esac
}

do_expand_rootfs() {
  rm -f /etc/.do_expand_partiton /etc/.do_resizefs_rootfs
  /etc/init.d/hobot-resizefs start
  if [ "$INTERACTIVE" = True ]; then
    whiptail --msgbox "Root partition has been resized" 20 60 1
  fi
}

get_proxy() {
  SCHEME="$1"
  VAR_NAME="${SCHEME}_proxy"
  if [ -f /etc/profile.d/proxy.sh ]; then
    # shellcheck disable=SC1091
    . /etc/profile.d/proxy.sh
  fi
  eval "echo \$$VAR_NAME"
}

do_proxy() {
  SCHEMES="$1"
  ADDRESS="$2"
  if [ "$SCHEMES" = "all" ]; then
    CURRENT="$(get_proxy http)"
    SCHEMES="http https ftp rsync"
  else
    CURRENT="$(get_proxy "$SCHEMES")"
  fi
  if [ "$INTERACTIVE" = True ]; then
    if [ "$SCHEMES" = "no" ]; then
      STRING="Please enter a comma separated list of addresses that should be excluded from using proxy servers.\\nEg: localhost,127.0.0.1,localaddress,.localdomain.com"
    else
      STRING="Please enter proxy address.\\nEg: http://user:pass@proxy:8080"
    fi
    if ! ADDRESS="$(whiptail --inputbox "$STRING"  20 60 "$CURRENT" 3>&1 1>&2 2>&3)"; then
      return 0
    fi
  fi
  for SCHEME in $SCHEMES; do
    unset "${SCHEME}_proxy"
    CURRENT="$(get_proxy "$SCHEME")"
    if [ "$CURRENT" != "$ADDRESS" ]; then
      ASK_TO_REBOOT=1
    fi
    if [ -f /etc/profile.d/proxy.sh ]; then
      sed -i "/^export ${SCHEME}_/Id" /etc/profile.d/proxy.sh
    fi
    if [ "${SCHEME#*http}" != "$SCHEME" ]; then
      if [ -f /etc/apt/apt.conf.d/01proxy ]; then
        sed -i "/::${SCHEME}::Proxy/d" /etc/apt/apt.conf.d/01proxy
      fi
    fi
    if [ -z "$ADDRESS" ]; then
      STATUS=cleared
      continue
    fi
    STATUS=updated
    SCHEME_UPPER="$(echo "$SCHEME" | tr '[:lower:]' '[:upper:]')"
    echo "export ${SCHEME_UPPER}_PROXY=\"$ADDRESS\"" >> /etc/profile.d/proxy.sh
    if [ "$SCHEME" != "rsync" ]; then
      echo "export ${SCHEME}_proxy=\"$ADDRESS\"" >> /etc/profile.d/proxy.sh
    fi
    if [ "${SCHEME#*http}" != "$SCHEME" ]; then
      echo "Acquire::$SCHEME::Proxy \"$ADDRESS\";"  >> /etc/apt/apt.conf.d/01proxy
    fi
  done
  if [ "$INTERACTIVE" = True ]; then
    whiptail --msgbox "Proxy settings $STATUS" 20 60 1
  fi
}

do_boot_order() {
  if [ "$INTERACTIVE" = True ]; then
    BOOTOPT=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "Boot Device Order" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT \
      "B1 SD Card Boot" "Boot from SD Card if available, otherwise boot from USB" \
      "B2 EMMC Boot" "Boot from USB if available, otherwise boot from SD Card" \
      3>&1 1>&2 2>&3)
  else
    BOOTOPT=$1
    true
  fi
  if [ $? -eq 0 ]; then
    case "$BOOTOPT" in
      B1*)
        parted /dev/mmcblk0 set 2 boot off
        STATUS="SD Card"
        ;;
      B2*)
        parted /dev/mmcblk0 set 2 boot on
        STATUS="EMMC"
        ;;
      *)
        whiptail --msgbox "Programmer error, unrecognised boot option" 20 60 2
        return 1
        ;;
    esac
    ASK_TO_REBOOT=1
    if [ "$INTERACTIVE" = True ]; then
      whiptail --msgbox "$STATUS is default boot device" 20 60 1
    fi
  fi
}

do_update() {
  apt-get update &&
  apt-get install hobot-io &&
  printf "Sleeping 5 seconds before reloading srpi-config\n" &&
  sleep 5 &&
  exec srpi-config
}

nonint() {
  "$@"
}

# Needs to be run as root
if [ $(id -u) -ne 0 ]; then
  printf "Script must be run as root. Try 'sudo srpi-config'\n"
  exit 1
fi

#
# Command line options for non-interactive use
#
for i in $*
do
  case $i in
  --expand-rootfs)
    INTERACTIVE=False
    rm -f /etc/.do_expand_partiton /etc/.do_resizefs_rootfs
    /etc/init.d/hobot-resizefs start
    exit 0
    ;;
  nonint)
    INTERACTIVE=False
    "$@"
    exit $?
    ;;
  *)
    # unknown option
    ;;
  esac
done

do_system_menu() {
  FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "System Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
    "S1 Wireless LAN" "Enter SSID and passphrase" \
    "S2 Password" "Change password for the '$USER' user" \
    "S3 Hostname" "Set name for this computer on a network" \
    "S4 Boot / Auto Login" "Select boot into desktop or to command line" \
    "S5 Power LED" "Set behaviour of power LED" \
    "S6 Browser" "Choose default web browser" \
    "S7 Update Miniboot" "Update the minimal boot image in flash" \
    3>&1 1>&2 2>&3)

  RET=$?
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    case "$FUN" in
      S1\ *) do_wifi_ssid_passphrase ;;
      S2\ *) do_change_pass ;;
      S3\ *) do_hostname ;;
      S4\ *) do_boot_behaviour ;;
      S5\ *) do_leds ;;
      S6\ *) do_browser ;;
      S7\ *) do_update_miniboot ;;
      *) whiptail --msgbox "Programmer error: unrecognized option" 20 60 1 ;;
    esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1
  fi
}

do_display_menu() {
  board_type_string=$(get_rdk_type_string)
  if [[ "$board_type_string" == *x5* ]]; then	
    FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "Display Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
      "D1 Dsiplay Choice" " DSI or HDMI" \
      "D2 Dsiplay Choice" " CPU or GPU" \
      "D3 MIPI LCD Choice" " waveshare panel choice" \
      3>&1 1>&2 2>&3)
  elif [[ "$board_type_string" == *x3* ]]; then
    FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "Display Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
      "D4 FB Console Resolution" "Set resolution for framebuffer console" \
      3>&1 1>&2 2>&3)
  else
    whiptail --msgbox "Unsupported board type: $board_type_string\nDisplay configuration is not available!" 12 60
    return 1
  fi
  RET=$?
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    case "$FUN" in
      D1\ *) do_drm_display_choice ;;
      D2\ *) do_drm_display_choice_gpu ;;
      D3\ *) do_lcd_choice ;;
      D4\ *) do_fb_console_resolution ;;
      *) whiptail --msgbox "Programmer error: unrecognized option" 20 60 1 ;;
    esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1
  fi
}

get_cur_audio_hat(){
  if [ -f /etc/hobot_audio_config/cur_audio_hat ]; then
    cat /etc/hobot_audio_config/cur_audio_hat
  else
    echo "Audio Driver HAT V1"
  fi
}

BOARD_MEMORY_SIZE=0
getMemorySize()
{
    if [ -f "/sys/class/socinfo/ddr_size" ]; then
        BOARD_MEMORY_SIZE="$(cat /sys/class/socinfo/ddr_size | tr -d ' \n')"
    else
      echo "No RDK memory size found"
      exit ${EXIT_SUCCESS}
    fi
}

# Find latest applicable update version
MINIBOOT_UPDATE_IMAGE=""
MINIBOOT_UPDATE_VERSION=0
getMinibootUpdateVersion()
{
   MINIBOOT_UPDATE_VERSION=0
   getMemorySize
   match=".*/disk_nand_minimum_boot_${BOARD_MEMORY_SIZE}GB_3V3_[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].img"
   latest="$(find "/lib/firmware/rdk/miniboot/default/" -maxdepth 1 -type f -follow -regex "${match}" | sort -r | head -n1)"
   if [ -f "${latest}" ]; then
      MINIBOOT_UPDATE_VERSION=$(basename "${latest}" | awk -F_ '{print $NF}' | sed 's/\.img//')
      MINIBOOT_UPDATE_IMAGE="${latest}"
   fi
}

do_sound_devices_select() {
  board_type_string=$(get_rdk_type_string)
  if [ "$INTERACTIVE" = True ]; then
    CUR=$(get_cur_audio_hat)
    board_type_string=$(get_rdk_type_string)
    audio_options=("UNSET")

    if [[ "$board_type_string" == *x5* ]]; then
      audio_options=("""Audio Driver HAT V2"""  "    4 chn input and 2 chn ouput" \
                    """Hiwonder Audio Driver HAT"""  "    2 chn input and 1 chn output" \
                    """WM8960 Audio Driver HAT"""  "    2 chn input and 2 chn output" \
                    ""UNSET"" "    Unset audio driver hat")
    elif [[ "$board_type_string" == *x3_rdk_v1* ]]; then
      audio_options=("""Audio Driver HAT V1"""  "    4 chn input and 2 chn ouput" \
                    """Audio Driver HAT V2"""  "    4 chn input and 2 chn ouput" \
                    ""UNSET"" "    Unset audio driver hat")
    elif [ $board_type_string == "x3_rdk_v2*" ] || [ $board_type_string == "x3_md*" ]; then
      audio_options=("""Audio Driver HAT V2"""  "    4 chn input and 2 chn ouput" \
                    """Hiwonder Audio Driver HAT"""  "    2 chn input and 1 chn output" \
                    ""UNSET"" "    Unset audio driver hat")
    fi

    FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --default-item "$CUR" --menu "Select Sound Device" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
      "${audio_options[@]}" 3>&1 1>&2 2>&3)
    RET=$?
  else
    FUN=$1
    RET=0
  fi
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    audio_hat_type_string=""
    #if board is unsupport,return
    if [ $board_type_string == "null" ]; then
      echo "Unsupport board type"
      return
    fi
    #if audio is es7210+es8156
    if [ "$FUN" == "Audio Driver HAT V1" ] || [ "$FUN" == "Audio Driver HAT V2" ]; then
      if [ "$CUR" != "UNSET" ]; then
        do_unset_audio_hat
        CUR="$FUN"
      fi
      if [ -e /lib/modprobe.d/blacklist-hobot-codec-es7210.conf ]; then
        mv /lib/modprobe.d/blacklist-hobot-codec-es7210.conf /lib/modprobe.d/blacklist-hobot-codec-es7210.disable
        do_set_audio_machine
      fi
      if [[ "$board_type_string" == *x5* ]]; then
        grep -q "set-default-sink alsa_output.platform-hobot_sound_machine.stereo-fallback" /etc/pulse/default.pa || \
          echo "set-default-sink alsa_output.platform-hobot_sound_machine.stereo-fallback" | tee -a /etc/pulse/default.pa  > /dev/null 2>&1
        grep -q "load-module module-alsa-source device=hw:0,1" /etc/pulse/default.pa || \
          echo "load-module module-alsa-source device=hw:0,1" | tee -a /etc/pulse/default.pa  > /dev/null 2>&1
        grep -q "set-default-source alsa_input.hw_0_1" /etc/pulse/default.pa || \
          echo "set-default-source alsa_input.hw_0_1" | tee -a /etc/pulse/default.pa  > /dev/null 2>&1
      elif [[ "$board_type_string" == *x3* ]]; then
	      grep -q "load-module module-alsa-source device=hw:0,1" /etc/pulse/default.pa || \
	          echo "load-module module-alsa-source device=hw:0,1" | tee -a /etc/pulse/default.pa  > /dev/null 2>&1
      fi
      audio_hat_type_string="es7210_es8156"
    fi
    #use hiwonder audio codec HAT
    if [ "$FUN" == "Hiwonder Audio Driver HAT" ]; then
      if [ "$CUR" != "UNSET" ]; then
        do_unset_audio_hat
        CUR="$FUN"
      fi
      if [ -e /lib/modprobe.d/blacklist-hobot-codec-hiwonder.conf ]; then
        mv /lib/modprobe.d/blacklist-hobot-codec-hiwonder.conf /lib/modprobe.d/blacklist-hobot-codec-hiwonder.disable
        do_set_audio_machine
      fi
      if [[ "$board_type_string" == *x5* ]]; then
	      grep -q "set-default-sink alsa_output.platform-hobot_sound_machine.stereo-fallback" /etc/pulse/default.pa || \
	        echo "set-default-sink alsa_output.platform-hobot_sound_machine.stereo-fallback" | tee -a /etc/pulse/default.pa  > /dev/null 2>&1
	      grep -q "set-default-source alsa_input.platform-hobot_sound_machine.stereo-fallback" /etc/pulse/default.pa || \
	        echo "set-default-source alsa_input.platform-hobot_sound_machine.stereo-fallback" | tee -a /etc/pulse/default.pa  > /dev/null 2>&1
      fi
      audio_hat_type_string="hiwonder_rasadapter5b"
    fi
      #use wm8960 audio codec HAT
    if [ "$FUN" == "WM8960 Audio Driver HAT" ]; then
      if [ "$CUR" != "UNSET" ]; then
        do_unset_audio_hat
        CUR="$FUN"
      fi
      if [ -e /lib/modprobe.d/blacklist-hobot-codec-hiwonder.conf ]; then
        mv /lib/modprobe.d/blacklist-hobot-codec-wm8960.conf /lib/modprobe.d/blacklist-hobot-codec-wm8960.disable
        do_set_audio_machine
      fi
      if [[ "$board_type_string" == *x5* ]]; then
	      grep -q "set-default-sink alsa_output.platform-hobot_sound_machine.stereo-fallback" /etc/pulse/default.pa || \
	        echo "set-default-sink alsa_output.platform-hobot_sound_machine.stereo-fallback" | tee -a /etc/pulse/default.pa  > /dev/null 2>&1
	      grep -q "set-default-source alsa_input.platform-hobot_sound_machine.stereo-fallback" /etc/pulse/default.pa || \
	        echo "set-default-source alsa_input.platform-hobot_sound_machine.stereo-fallback" | tee -a /etc/pulse/default.pa  > /dev/null 2>&1
      fi
      audio_hat_type_string="wm8960"
    fi
    #if user didn't unset audio hat
    if [ "$FUN" != "UNSET" ]; then
      dtb_board_type="x5_rdk"
      if [[ "$board_type_string" == *x3_rdk_v1* ]]; then
        dtb_board_type="rdk_v1_x"
      elif [[ "$board_type_string" == *x3_rdk_v2* ]]; then
        tb_board_type="rdk_v2"
      elif [[ "$board_type_string" == *x3_md* ]]; then
        dtb_board_type="rdk_md"
      fi
      #splice dtbo name,from option and board
      dtboname="audio_"$audio_hat_type_string"_"$dtb_board_type""
      #for debug,it will be commented out
      #echo $dtboname
      #set dtoverlay name to config.txt
      if grep -q "dtoverlay="$dtboname"" /boot/config.txt; then
        echo ""
      else
        echo "dtoverlay="$dtboname"" >> $CONFIG
      fi
      #stop pulseaudio,sometimes it gives some weird errors
      kill -9 $(pidof pulseaudio) > /dev/null 2>&1
      #add auto load module
      cp  /etc/hobot_audio_config/99_hobot_audio_module.conf /etc/modules-load.d/
    fi
    #set the current audio board type to UNSET step 1
    echo "$FUN" > /etc/hobot_audio_config/cur_audio_hat
    #if user unset audio hat
    if [ "$FUN" == "UNSET" ]; then
      do_unset_audio_hat
    fi
    if [[ "$board_type_string" == *x3* ]]; then
	    # check miniboot version
	    cur_miniboot_version=$(strings /dev/mtd0 | grep -E "U-Boot 2018.09.*\(" | head -n 1)
	    getMinibootUpdateVersion
	    latest_miniboot_version=$(strings $MINIBOOT_UPDATE_IMAGE | grep -E "U-Boot 2018.09.*\(" | head -n 1)
	    if [ "$cur_miniboot_version" != "$latest_miniboot_version" ];then
	      whiptail --msgbox "Your miniboot version is: $cur_miniboot_version\n\nThe latest miniboot version is: $latest_miniboot_version \n\nMaybe you need to update miniboot to enable sound card.\n\nEnter 1 System Options -> S7 Update Miniboot to upgrade miniboot." $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT
	    fi
    fi
    ASK_TO_REBOOT=1
  fi
}

# set audio machine, unset is in do unset_audio_hat()
do_set_audio_machine(){
  mv /lib/modprobe.d/blacklist-hobot-audio-common.conf /lib/modprobe.d/blacklist-hobot-audio-common.disable

}

do_unset_audio_hat(){
  #remove auto load module step 1
  directory="/lib/modprobe.d"
  for file in "$directory"/*.disable; do
    if [ -f "$file" ]; then
        new_name="${file%.disable}.conf"
        mv  "$file" "$new_name"
    fi
  done
  #remove auto load module step 2
  rm -f /etc/modules-load.d/99_hobot_audio_module.conf
  #remove alsa config step 3
  rm -f /var/lib/alsa/asound.state
  #delete dtoverlay setting step 1
  sed -i '/^dtoverlay=audio_/d' /boot/config.txt

  sed -i '/load-module module-alsa-source device=hw:0,1/d' /etc/pulse/default.pa
  sed -i '/set-default-source alsa_input.hw_0_1/d' /etc/pulse/default.pa
  sed -i '/set-default-sink alsa_output.platform-hobot_sound_machine.stereo-fallback/d' /etc/pulse/default.pa
  sed -i '/set-default-source alsa_input.platform-hobot_sound_machine.stereo-fallback/d' /etc/pulse/default.pa
}

do_imu_devices_select(){

  #imu dtoverlay filename = (dtoverlay)_(imu)_(i2c5)_(x5_rdk).dts/dtbo

  if [ "$INTERACTIVE" = True ]; then
    # CUR=$(get_cur_audio_hat)
    board_type_string=$(get_rdk_type_string)
    dtfilehead="dtoverlay_imu_"
    # audio_options=("UNSET")
    if [[ "$board_type_string" == *x5* ]]; then
      dtb_board_type="x5_rdk"
      # imu_options=(""SPI-Interface" "" "I2C-Interface" """)
      imu_options=("""BMI088-SPI-Interface"""  "    Use SPI1 as the data interface for IMU."  ""BMI088-I2C-Interface"" "    Use I2C5 as the data interface for IMU." ""ICM42688-I2C-Interface"" "    Use I2C4 or I2C6 as the data interface for Stereo Camera IMU." ""UNSET"" "    Unset IMU driver hat")
    fi
    FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --default-item "Onboard" --menu "Set IMU bmi088" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
      "${imu_options[@]}"  3>&1 1>&2 2>&3)
    RET=$?
    # echo "$FUN""  RET=""$RET"
  else
    FUN=$1
    RET=0
  fi
  if [ $RET -eq 1 ]; then
    # check select if success
    return 0
  elif [ $RET -eq 0 ]; then
    # select not error
    if [ "$FUN" == "UNSET" ]; then
      if grep -q "^dtoverlay="$dtfilehead"" $CONFIG; then
        # if exist set data del it
        sed -i "/^dtoverlay="$dtfilehead".*/d" $CONFIG
      fi
      ASK_TO_REBOOT=1
      return 0
    fi

    if [ "$FUN" == "BMI088-SPI-Interface" ]; then
      dtfile=""$dtfilehead"bmi088_spi1_"$dtb_board_type""
    elif [ "$FUN" == "BMI088-I2C-Interface" ]; then
      dtfile=""$dtfilehead"bmi088_i2c5_"$dtb_board_type""
    elif [ "$FUN" == "ICM42688-I2C-Interface" ]; then
      dtfile=""$dtfilehead"icm42688_i2c4_6_"$dtb_board_type""
    fi
    # check is there right dtoverlay config in config.txt
    if grep -q "dtoverlay="$dtfilehead"" $CONFIG; then
      # if wrong , sed with right
      sed -i "s|dtoverlay="$dtfilehead".*|dtoverlay="$dtfile"|" $CONFIG
    else
      # if not exist, echo it
      echo "dtoverlay="$dtfile"" >> $CONFIG
    fi

    ASK_TO_REBOOT=1
    return 0
  fi
}

do_v4l2_cam1(){
  dtfilehead="dtoverlay_cam1_"

  if [ "$INTERACTIVE" = "True" ]; then
    FUN=$(whiptail --title "CAM1 SET" --default-item "UNSET" --menu "CAM0 sensor choose" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
      "UNSET" "" "OV5647" "" "IMX219" "" "IMX477" "" 3>&1 1>&2 2>&3)
    RET=$?
  else
    FUN=$1
    RET=0
  fi

  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    if [ "${FUN}" = "UNSET" ]; then
      if grep -q "^dtoverlay="$dtfilehead"" $CONFIG; then
        # if exist set data del it
        sed -i "/^dtoverlay="$dtfilehead".*/d" $CONFIG
      fi
      return 0
    fi
    
    if [ "$FUN" == "OV5647" ]; then
      dtfile=""$dtfilehead"ov5647"
    elif [ "$FUN" == "IMX219" ]; then
      dtfile=""$dtfilehead"imx219"
    elif [ "$FUN" == "IMX477" ]; then
      dtfile=""$dtfilehead"imx477"
    fi

    # check is there right dtoverlay config in config.txt
    if grep -q "dtoverlay="$dtfilehead"" $CONFIG; then
      # if wrong , sed with right
      sed -i "s|dtoverlay="$dtfilehead".*|dtoverlay="$dtfile"|" $CONFIG
    else
      # if not exist, echo it
      echo "dtoverlay="$dtfile"" >> $CONFIG
    fi
  fi

  if [ "$INTERACTIVE" = "True" ]; then
    whiptail --msgbox "The cam1 sensor is set to ${FUN}" 20 60 1
  fi
}

do_v4l2_cam0(){
  dtfilehead="dtoverlay_cam0_"

  if [ "$INTERACTIVE" = "True" ]; then
    FUN=$(whiptail --title "CAM0 SET" --default-item "UNSET" --menu "CAM0 sensor choose" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
      "UNSET" "" "OV5647" "" "IMX219" "" "IMX477" "" 3>&1 1>&2 2>&3)
    RET=$?
  else
    FUN=$1
    RET=0
  fi

  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    if [ "${FUN}" = "UNSET" ]; then
      if grep -q "^dtoverlay="$dtfilehead"" $CONFIG; then
        # if exist set data del it
        sed -i "/^dtoverlay="$dtfilehead".*/d" $CONFIG
      fi
      do_v4l2_cam1
      return 0
    fi

    if [ "$FUN" == "OV5647" ]; then
      dtfile=""$dtfilehead"ov5647"
    elif [ "$FUN" == "IMX219" ]; then
      dtfile=""$dtfilehead"imx219"
    elif [ "$FUN" == "IMX477" ]; then
      dtfile=""$dtfilehead"imx477"
    fi

    # check is there right dtoverlay config in config.txt
    if grep -q "dtoverlay="$dtfilehead"" $CONFIG; then
      # if wrong , sed with right
      sed -i "s|dtoverlay="$dtfilehead".*|dtoverlay="$dtfile"|" $CONFIG
    else
      # if not exist, echo it
      echo "dtoverlay="$dtfile"" >> $CONFIG
    fi
  fi

  if [ "$INTERACTIVE" = "True" ]; then
    whiptail --msgbox "The cam0 sensor is set to ${FUN}" 20 60 1
  fi

  do_v4l2_cam1

}

do_v4l2_select(){
  v4l2configfile="/etc/init.d/v4l2_config"
  dtfilehead0="dtoverlay_cam0_"
  dtfilehead1="dtoverlay_cam1_"

  if [ "$INTERACTIVE" = "True" ]; then
    FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --default-item "HBN" --menu "Set camera interface" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
      "HBN" "" "V4L2 sif-isp-vse" ""  "V4L2 vse alone" "" 3>&1 1>&2 2>&3)
    RET=$?
  else
    FUN=$1
    RET=0
  fi

  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    if [ "${FUN}" = "HBN" ]; then
      if grep -q "v4l2_enable" $CONFIG; then
        # if exist set data del it
        sed -i "/v4l2_enable/d" $CONFIG
      fi
      if grep -q "v4l2_scene=" $CONFIG; then
        # if exist set data del it
        sed -i "/^v4l2_scene=.*/d" $CONFIG
      fi
    elif [ "${FUN}" = "V4L2 sif-isp-vse" ]; then
      if ! grep -q "v4l2_enable" $CONFIG; then
        echo "v4l2_enable" >> $CONFIG
      fi
      if grep -q "v4l2_scene=" $CONFIG; then
        # if wrong , sed with right
        sed -i 's/^v4l2_scene=.*/v4l2_scene=22/' $CONFIG
      else
        # if not exist, echo it
        echo "v4l2_scene=22" >> $CONFIG
      fi
    elif [ "${FUN}" = "V4L2 vse alone" ]; then
      if ! grep -q "v4l2_enable" $CONFIG; then
        echo "v4l2_enable" >> $CONFIG
      fi
      if grep -q "v4l2_scene=" $CONFIG; then
        # if wrong , sed with right
        sed -i 's/^v4l2_scene=.*/v4l2_scene=5/' $CONFIG
      else
        # if not exist, echo it
        echo "v4l2_scene=5" >> $CONFIG
      fi
    fi
  fi

  if [ "$INTERACTIVE" = "True" ]; then
    whiptail --msgbox "The camera interface is set to ${FUN}" 20 60 1
  fi

  if [ "${FUN}" = "V4L2 sif-isp-vse" ]; then
    do_v4l2_cam0
  else
    if grep -q "^dtoverlay="$dtfilehead0"" $CONFIG; then
      # if exist set data del it
      sed -i "/^dtoverlay="$dtfilehead0".*/d" $CONFIG
    fi
    if grep -q "^dtoverlay="$dtfilehead1"" $CONFIG; then
      # if exist set data del it
      sed -i "/^dtoverlay="$dtfilehead1".*/d" $CONFIG
    fi
  fi
  ASK_TO_REBOOT=1
}

do_V4L2_menu() {
  FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "V4L2 Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
    "I1 V4L2" "Enable/disable V4L2 interface for camera" \
    3>&1 1>&2 2>&3)
  RET=$?
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    case "$FUN" in
      I1\ *) do_v4l2_select ;;
      *) whiptail --msgbox "Programmer error: unrecognized option" 20 60 1 ;;
    esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1
  fi
}

do_interface_menu() {
  board_type_string=$(get_rdk_type_string)
  if [[ "$board_type_string" == *x5* ]]; then	
    FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "Interfacing Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
      "I1 SSH" "Enable/disable remote command line access using SSH" \
      "I2 VNC" "Enable/disable graphical remote desktop access" \
      "I3 Peripheral bus config" "Enable/disable peripheral bus(spi,i2c,serial,i2s,etc.)" \
      "I4 Configure Wi-Fi antenna" "Configure Wi-Fi antennas to use onboard or external antenna" \
      "I5 Audio" "Configure audio peripheral functions" \
      "I6 IMU" "Configure IMU peripheral functions" \
      "I7 V4L2" "Configure V4L2 functions" \
      3>&1 1>&2 2>&3)
  elif [[ "$board_type_string" == *x3* ]]; then
    FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "Interfacing Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
      "I1 SSH" "Enable/disable remote command line access using SSH" \
      "I2 VNC" "Enable/disable graphical remote desktop access" \
      "I3 Peripheral bus config" "Enable/disable peripheral bus(spi,i2c,serial,i2s,etc.)" \
      "I4 Configure Wi-Fi antenna" "Configure Wi-Fi antennas to use onboard or external antenna" \
      "I5 Audio" "Configure audio peripheral functions" \
      3>&1 1>&2 2>&3)
  fi
  RET=$?
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    case "$FUN" in
      I1\ *) do_ssh ;;
      I2\ *) do_vnc ;;
      I3\ *) do_peripheral ;;
      I4\ *) do_wifi_antenna ;;
      I5\ *) do_sound_devices_select ;;
      I6\ *) do_imu_devices_select ;;
      I7\ *) do_V4L2_menu ;;
      *) whiptail --msgbox "Programmer error: unrecognized option" 20 60 1 ;;
    esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1
  fi
}

do_performance_menu() {
  FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "Performance Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
      "P1 CPU frequency" "Configure CPU frequency" \
      "P2 ION memory" "Configure ION memory size for BPU and multimedia" \
      3>&1 1>&2 2>&3)
  RET=$?
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    case "$FUN" in
      P1\ *) do_cpu_frequency_menu ;;
      P2\ *) do_config_ion_memory ;;
      *) whiptail --msgbox "Programmer error: unrecognized option" 20 60 1 ;;
    esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1
  fi
}

do_internationalisation_menu() {
  FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "Localisation Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
    "L1 Locale" "Configure language and regional settings" \
    "L2 Timezone" "Configure time zone" \
    "L3 Keyboard" "Set keyboard layout to match your keyboard" \
    3>&1 1>&2 2>&3)
  RET=$?
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    case "$FUN" in
      L1\ *) do_change_locale ;;
      L2\ *) do_change_timezone ;;
      L3\ *) do_configure_keyboard ;;
      *) whiptail --msgbox "Programmer error: unrecognized option" 20 60 1 ;;
    esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1
  fi
}

do_advanced_menu() {
  if is_rdkmd ; then
    FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "Advanced Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
      "A1 Expand Filesystem" "Ensures that all of the SD card is available" \
      "A2 Network Proxy Settings" "Configure network proxy settings" \
      "A3 Boot Order" "Choose network or USB device boot" \
      3>&1 1>&2 2>&3)
  else
   FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "Advanced Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
      "A1 Expand Filesystem" "Ensures that all of the SD card is available" \
      "A2 Network Proxy Settings" "Configure network proxy settings" \
      3>&1 1>&2 2>&3)
  fi
  RET=$?
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    case "$FUN" in
      A1\ *) do_expand_rootfs ;;
      A2\ *) do_proxy_menu ;;
      A3\ *) do_boot_order ;;
      *) whiptail --msgbox "Programmer error: unrecognized option" 20 60 1 ;;
    esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1
  fi
}

do_isp_imx219() {
  local FOV_SELECTED
  local TUNING_PATH="/usr/hobot/lib/sensor"
  local TARGETS=("640x480" "1632x1232" "1920x1080" "3264x2464")

  if [ "$INTERACTIVE" = True ]; then
    FOV_SELECTED=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" \
      --menu "Select FOV Profile" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT \
      "1" "FOV 79.3°" \
      "2" "FOV 120°" \
      3>&1 1>&2 2>&3)
  else
    FOV_SELECTED="$1"
  fi

  [ $? -ne 0 ] && return 1

  case "$FOV_SELECTED" in
    "1")
      local PROFILE="fov79"
      ;;
    "2")
      local PROFILE="fov120"
      ;;
    *)
      echo "Invalid selection"
      return 1
      ;;
  esac

  for res in "${TARGETS[@]}"; do
    local src="${TUNING_PATH}/imx219_${PROFILE}_${res}_tuning.json"
    local dst="${TUNING_PATH}/imx219_${res}_tuning.json"
    if [ -f "$src" ]; then
      cp "$src" "$dst"
    else
      echo "Warning: Missing $src"
    fi
  done

  if [ "$INTERACTIVE" = True ]; then
    whiptail --msgbox "ISP effects set to: $PROFILE" 20 60 1
  fi

  return 0
}

do_sensor_isp() {
  FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "Advanced Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
    "A1 IMX219" "Switch ISP effects for 79.3° / 120° FOV" \
    3>&1 1>&2 2>&3)

  RET=$?
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    case "$FUN" in
      A1\ *) do_isp_imx219 ;;
      *) whiptail --msgbox "Programmer error: unrecognized option" 20 60 1 ;;
    esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1
  fi
}

do_proxy_menu() {
  FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "Network Proxy Settings" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
    "P1 All" "Set the same proxy for all schemes" \
    "P2 HTTP" "Set the HTTP proxy" \
    "P3 HTTPS" "Set the HTTPS/SSL proxy" \
    "P4 FTP" "Set the FTP proxy" \
    "P5 RSYNC" "Set the RSYNC proxy" \
    "P6 Exceptions" "Set addresses for which a proxy server should not be used" \
    3>&1 1>&2 2>&3)
  RET=$?
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    case "$FUN" in
      P1\ *) do_proxy all ;;
      P2\ *) do_proxy http ;;
      P3\ *) do_proxy https ;;
      P4\ *) do_proxy ftp ;;
      P5\ *) do_proxy rsync ;;
      P6\ *) do_proxy no;;
      *) whiptail --msgbox "Programmer error: unrecognized option" 20 60 1 ;;
    esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1
  fi
}

do_finish() {
  if [ $ASK_TO_REBOOT -eq 1 ]; then
    whiptail --yesno "Would you like to reboot now?" 20 60 2
    if [ $? -eq 0 ]; then # yes
      sync
      reboot
    fi
  fi
  exit 0
}

#
# Interactive use loop
#
if [ "$INTERACTIVE" = True ]; then
  [ -e $CONFIG ] || touch $CONFIG
  calc_wt_size
  while [ "$USER" = "root" ] || [ -z "$USER" ]; do
    if ! USER=$(whiptail --inputbox "srpi-config could not determine the default user.\\n\\nWhat user should these settings apply to?" 20 60 pi 3>&1 1>&2 2>&3); then
      return 0
    fi
  done
  backtitle=$(cat /proc/device-tree/model | tr -d '\0')
  while true; do
    if [[ "$board_type_string" == *x5* ]]; then
	    FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --backtitle "${backtitle}" --menu "Setup Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Finish --ok-button Select \
	      "1 System Options" "Configure system settings" \
	      "2 Display Options" "Configure display settings" \
	      "3 Interface Options" "Configure connections to peripherals" \
	      "4 Performance Options" "Configure performance settings" \
	      "5 Localisation Options" "Configure language and regional settings" \
	      "6 Advanced Options" "Configure advanced settings" \
	      "7 Sensor Profiles" "Configure ISP settings for different FOVs" \
	      "8 Update" "Update this tool to the latest version" \
	      "9 About srpi-config" "Information about this configuration tool" \
	      3>&1 1>&2 2>&3)
    else
        FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --backtitle "${backtitle}" --menu "Setup Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Finish --ok-button Select \
	      "1 System Options" "Configure system settings" \
	      "2 Display Options" "Configure display settings" \
	      "3 Interface Options" "Configure connections to peripherals" \
	      "4 Performance Options" "Configure performance settings" \
	      "5 Localisation Options" "Configure language and regional settings" \
	      "6 Advanced Options" "Configure advanced settings" \
	      "8 Update" "Update this tool to the latest version" \
	      "9 About srpi-config" "Information about this configuration tool" \
	      3>&1 1>&2 2>&3)
    fi
    RET=$?
    if [ $RET -eq 1 ]; then
      do_finish
    elif [ $RET -eq 0 ]; then
      case "$FUN" in
        1\ *) do_system_menu ;;
        2\ *) do_display_menu ;;
        3\ *) do_interface_menu ;;
        4\ *) do_performance_menu ;;
        5\ *) do_internationalisation_menu ;;
        6\ *) do_advanced_menu ;;
        7\ *) do_sensor_isp ;;
        8\ *) do_update ;;
        9\ *) do_about ;;
        *) whiptail --msgbox "Programmer error: unrecognized option" 20 60 1 ;;
      esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1
    else
      exit 1
    fi
  done
fi

