#!/bin/bash
# xorg - xorg plugin for postplug
# Copyright (c) 2004-2025 by Silvan Calarco <silvan.calarco@mambasoft.it>
# Copyright (c) 2004-2007 by Davide Madrisan <davide.madrisan@gmail.com>

if [ $UID != 0 ]; then
   echo "$0: must be superuser." >&2
   exit 1
fi

[ -r /etc/sysconfig/keyboard ] && . /etc/sysconfig/keyboard
[ -r /etc/sysconfig/postplug ] && . /etc/sysconfig/postplug
[ -r /etc/sysconfig/machine ] && . /etc/sysconfig/machine

me="xorg"

. /etc/postplug/postplug.defs

XORGCONF=/etc/X11/xorg.conf

# xorg_section_screen_config()
#    write a new xorg configuration
# args:
#    $1 : default color depth
#    $2 : file with the video modes (one per line)
function xorg_section_screen_config() {
   # fixme: this deletes from first subsection "Display" to the endsection
   sed '/SubSection "Display"/,/EndSection/s/.*//p' $XORGCONF | \
      grep -v "^\s*$" > $XORGCONF.new

   for i in `seq 1 ${#COLORDEPTHS[@]}`; do
      echo -n "\
        SubSection \"Display\"
                Modes    " >> $XORGCONF.new
      grep "${COLORDEPTHS[$i-1]} bpp" $2 | tac | \
         while read mode skip; do
            echo -n "\"${mode%,*}\" " >> $XORGCONF.new
         done
      echo "
                Depth     ${COLORDEPTHS[$i-1]}
        EndSubSection" >> $XORGCONF.new
   done
   echo "EndSection" >> $XORGCONF.new

   mv $XORGCONF $XORGCONF.save
   mv $XORGCONF.new $XORGCONF
}

## xorg_set_alternatives()
##    set alternatives and xorg configuration for specific video drivers
#function xorg_set_alternatives() {
#if [ "$VIDEODRIVER" = "nvidia" ]; then
#   grep -q '^[^#]*\"AllowGLXWithComposite\"' $XORGCONF ||
#   sed -i -e '/Driver\W*"nvidia"/a\
#        Option      \"RenderAccel\" \"true\"\
#        Option      \"AllowGLXWithComposite\" \"on\"\
#        Option      \"NoLogo\" \"true\"' $XORGCONF
#fi
#}

function xorg_d_configure_input() {
   # Keyboard configuration (Xorg >= 1.8 uses /etc/X11/xorg.conf.d)
   [ ! -e /etc/X11/xorg.conf.d/00-keyboard.conf ] && {

      if [ ! "$XKB_MODEL" -o ! "$XKB_LAYOUT" ]; then
         case "${LANG:0:2}" in
         it)
#            XKB_MODEL="pc105"
            XKB_LAYOUT="it" ;;
         de)
#            XKB_MODEL="pc105"
            XKB_LAYOUT="de" ;;
         es)
#            XKB_MODEL="pc105"
            XKB_LAYOUT="es" ;;
         fr)
#            XKB_MODEL="pc105"
            XKB_LAYOUT="fr" ;;
         *)
#            XKB_MODEL="pc104"
            XKB_LAYOUT="us" ;;
         esac
      fi

     cat > /etc/X11/xorg.conf.d/00-keyboard.conf << __EOF
# Created by postplug
Section "InputClass"
	Identifier "system-keyboard"
	MatchIsKeyboard "on"
	Option "XkbLayout" "$XKB_LAYOUT"
__EOF
     [ "$XKB_MODEL" ] && echo "	Option \"XkbModel\" \"$XKB_MODEL\"" >>/etc/X11/xorg.conf.d/00-keyboard.conf
     [ "$XKB_VARIANT" ] && echo "	Option \"XkbVariant\" \"$XKB_VARIANT\"" >>/etc/X11/xorg.conf.d/00-keyboard.conf
     if [ "${SYSTEM_MANUFACTURER:0:5}" = "Apple" ]; then
        XKB_OPTIONS="${XKB_OPTIONS},lv3:rwin_switch"
     fi
     [ "$XKB_OPTIONS" ] && echo "	Option \"XkbOptions\" \"$XKB_OPTIONS\"" >>/etc/X11/xorg.conf.d/00-keyboard.conf
     echo "EndSection" >>/etc/X11/xorg.conf.d/00-keyboard.conf
   }

   if [ -e /etc/X11/xorg.conf.d/10-keyboard.conf ]; then
      rm -f /etc/X11/xorg.conf.d/10-keyboard.conf
   fi
   if [ -e /etc/X11/xorg.conf.d/15-keyboard-apple.conf ]; then
      rm -f /etc/X11/xorg.conf.d/15-keyboard-apple.conf
   fi
}

# (re)create the '/tmp/.ICE-unix' directory with the right permissions
rm -fr /tmp/.ICE-unix
install -m 1777 -o root -g root -d /tmp/.ICE-unix

# video hardware change detection
if [ -e /dev/nvhost-ctrl ]; then
   VIDEO_DEV="NVIDIA TEGRA"
else
   VIDEO_DEV="`lspci -n 2>/dev/null | grep " 03[0-9][0-9]: "`"
   [ "$VIDEO_DEV" ] || VIDEO_DEV="embedded-unknown"
fi

if [ -e $XORGCONF -a -e $postpluglibdir/xorg.cache ]; then
   VIDEO_DEV_CACHED="`cat $postpluglibdir/xorg.cache`"
   [ "$VIDEO_DEV" = "$VIDEO_DEV_CACHED" ] || {
      logmsg "$me" "warning: video device appears to have changed; re-probing"
      mv $XORGCONF $XORGCONF.postplug.save
   }
fi

if [ -e $XORGCONF ]; then
   VIDEODRIVERS=(`sed -n "/Section[ \t]\"Device\"/,/EndSection/{s/^[ \t]*Driver[ \t]*\"\(.*\)\"/\1/p}" $XORGCONF`)
   # assume first driver as default videodriver
   VIDEODRIVER=${VIDEODRIVERS[0]}

   [ -e /sys/module/nouveau/parameters/modeset ] && NOUVEAU_MODESET=`cat /sys/module/nouveau/parameters/modeset`
   [ "$NOUVEAU_MODESET" = "-1" ] && NOUVEAU_MODESET=1
   [ -e /sys/module/radeon/parameters/modeset ] && RADEON_MODESET=`cat /sys/module/radeon/parameters/modeset`
   [ "$RADEON_MODESET" = "-1" ] && RADEON_MODESET=1

   if [ "$VIDEODRIVER" = "nvidia" -a "$NOUVEAU_MODESET" = "1" ]; then
     # replace nvidia with nouveau
     mv $XORGCONF $XORGCONF.postplug.nvidia.save
     rmmod nvidia
     echo "blacklist nvidia" > /etc/modprobe.d/postplug-nouveau.conf
     VIDEODRIVER=""
   elif [ "$NOUVEAU_MODESET" = "0" ]; then
     # replace nouveau with nvidia (NOUVEAU_MODESET=0 means we have nvidia chip)
     mv $XORGCONF $XORGCONF.postplug.nouveau.save
     rmmod nouveau
     rm -f /etc/modprobe.d/postplug-nouveau.conf
     VIDEODRIVER="nvidia"
   fi
fi

if [ ! -e $XORGCONF ]; then
#
# Create a new Xorg configuration file
#
   if [ -e /dev/nvhost-ctrl -a -e $XORGCONF.tegra ]; then
      # use default xorg.conf for Tegra
      cp $XORGCONF.tegra $XORGCONF
   else
      logmsg "$me" "info: creating a dummy empty xorg.conf"
      echo "# Dummy empty xorg.conf file created by postplug" > $XORGCONF
   fi
   let "CONFCREATED = 1"
   VIDEODRIVERS=(`sed -n "/Section[ \t]\"Device\"/,/EndSection/{s/^[ \t]*Driver[ \t]*\"\(.*\)\"/\1/p}" $XORGCONF`)
   # assume first driver as default videodriver
   VIDEODRIVER=${VIDEODRIVERS[0]}
fi

if [ "$CONFCREATED" = "1" -a "$VIDEODRIVER" ]; then

   [ "`grep nomodeset /proc/cmdline`" ] && nomodeset=1

   if [ "$nomodeset" = "1" -a "$VIDEODRIVER" = "nouveau" ]; then
      sed -i "s|Driver\W*\"nouveau\"|Driver      \"nvidia\"|" $XORGCONF
      VIDEODRIVER=nvidia
      rmmod nouveau nvidia
   fi

   case "$VIDEODRIVER" in
      vesa|vga) sed -i -e '/Section "Screen"/a\
        #DefaultColorDepth 24' $XORGCONF ;;
      *) sed -i -e '/Section "Screen"/a\
        DefaultColorDepth 24' $XORGCONF ;;
   esac

   # NVIDIA Compiz/3d configuration options 
   if [ "$VIDEODRIVER" == "nvidia" ]; then
      sed -i -e '/Section "Screen"/a\
        Option	"AddARGBGLXVisuals" "true"\
        Option	"DisableGLXRootClipping" "true"' $XORGCONF
   fi

   # Nouveau configuration options 
   if [ "$VIDEODRIVER" == "nouveau" ]; then
      sed -i -e '/Driver.*"nouveau"/a\
        Option      "GLXVBlank" "true"' $XORGCONF
   fi

   # Configure fonts
   sed -i '/fonts\/Type1/d;s@\(.*X11/fonts.*\)/@\1:unscaled@' $XORGCONF
   fc-cache

   # Configure keyboard

   # NOTE:
   #   see: /etc/X11/xkb/README.config
   #        /usr/lib/X11/doc/README.XKB-Config
   #        The X Keyboard Extension: Protocol Specification
   #           <URL:http://www.x-docs.org/XKB/XKBproto.pdf>
   #        xkb configuration
   #           <URL:http://www.tsu.ru/~pascal/en/xkb>
   #
   #        /etc/X11/xkb/rules/xfree86.lst  (commonest file of rules)
   #
   # The parameters are:
   #   XkbRules   - files of rules to be used for keyboard mapping composition
   #   XkbModel   - name of model of your keyboard type
   #   XkbLayout  - layout(s) you intend to use
   #   XkbVariant - variant(s) of layout you intend to use
   #   XkbOptions - extra xkb configuration options
   #
   # XkbVariant has been left out: that means the default variant named basic is loaded.

   if [ ! "$XKB_MODEL" -o ! "$XKB_LAYOUT" ]; then
      case "${LANG:0:2}" in
      it)
         XKB_MODEL="pc105"
         XKB_LAYOUT="it" ;;
      de)
         XKB_MODEL="pc105"
         XKB_LAYOUT="de" ;;
      es)
         XKB_MODEL="pc105"
         XKB_LAYOUT="es" ;;
      fr)
         XKB_MODEL="pc105"
         XKB_LAYOUT="fr" ;;
      *)
         XKB_MODEL="pc104"
         XKB_LAYOUT="us" ;;
      esac
   fi

   if [ -n "XKbOptions" ]; then
      sed -i -e "/Identifier\W*\"Keyboard.*\"/a\\
        Option      \"XkbModel\" \"$XKB_MODEL\"\\
        Option      \"XkbLayout\" \"$XKB_LAYOUT\"\\
        Option      \"XKbOptions\" \"$XKB_OPTIONS\"" $XORGCONF
   else
      sed -i -e "/Identifier\W*\"Keyboard.*\"/a\\
        Option      \"XkbModel\" \"$XKB_MODEL\"\\
        Option      \"XkbLayout\" \"$XKB_LAYOUT\"" $XORGCONF
   fi

   # global mouse modifications to default configuration
   sed -i -e '/"CorePointer"/i \
        Option      "AllowMouseOpenFail"' $XORGCONF

#   echo "$XORGCONF" > $postplugnew_file

   # Final probe
   [ -f /var/log/Xorg.5.log ] && rm -f /var/log/Xorg.5.log

   # sync to avoid filesystem corruption in case of system hang on probe
   sync

   xinit /bin/true -- :5

   if [ -r /var/log/Xorg.5.log ]; then

      if [ "`grep '\[KMS\] Kernel modesetting enabled' /var/log/Xorg.5.log`" ]; then
         logmsg "$me" "info: "$"KMS enabled: assuming autodetect works for PANEL_SIZE and HSYNC_RANGE"
         PANEL_SIZE_DETECTED="true"
         HSYNC_RANGE_NOT_DETECTED=""
      else
         if  [ "`grep 'hsync range of 28.00-33.00 kHz' /var/log/Xorg.5.log`" -o \
               "`grep 'The EDID read for display device CRT-0 is invalid' /var/log/Xorg.5.log`" ]; then
            # no values could be autodetected by DDC, so use a failsafe low value (30-49)
            HSYNC_RANGE_NOT_DETECTED="true"
         fi

         [ "`grep 'Printing DDC gathered Modelines' /var/log/Xorg.5.log`" ] && PANEL_SIZE_DETECTED="true"
         [ "`grep 'EDID vendor \"' /var/log/Xorg.5.log`" ] && PANEL_SIZE_DETECTED="true"
         [ "`grep 'Adding EDID-provided mode' /var/log/Xorg.5.log`" ] && PANEL_SIZE_DETECTED="true"
         [ "`grep -i 'Panel size from' /var/log/Xorg.5.log`" ] && PANEL_SIZE_DETECTED="true"
         [ "`grep -i 'Panel size is' /var/log/Xorg.5.log`" ] && PANEL_SIZE_DETECTED="true"
         [ "`grep -i 'Panel Size ' /var/log/Xorg.5.log`" ] && PANEL_SIZE_DETECTED="true"
         [ "`grep 'VESA VBE DDC read successfully' /var/log/Xorg.5.log`" ] && PANEL_SIZE_DETECTED="true"
         [ "`grep 'LCD on internal LVDS' /var/log/Xorg.5.log`" ] && PANEL_SIZE_DETECTED="true"
         [ "`grep 'LCD on internal LVDS' /var/log/Xorg.5.log`" ] && PANEL_SIZE_DETECTED="true"
         [ "`grep 'LVDS.* using initial mode' /var/log/Xorg.5.log`" ] && PANEL_SIZE_DETECTED="true"

         # nvidia driver: CRT-. EDID not got?
         if [ "`grep 'Unable to read EDID for display device CRT-.' /var/log/Xorg.5.log`" -o \
              "`grep 'Unable to get display device CRT-..s EDID' /var/log/Xorg.5.log`" ]; then
            # nvidia driver: disable CRT-x from being used by default if DFP-0 is present
            [ "`grep 'DFP-0' /var/log/Xorg.5.log`" ] && {
               sed -i -e '/Section "Screen"/a\
              Option "ConnectedMonitor" "DFP"' $XORGCONF
            } || {
               HSYNC_RANGE_NOT_DETECTED="true"
               unset PANEL_SIZE_DETECTED
            }
         else
            # nvidia driver: we trust in nvidia-auto-select
            [ "`grep 'nvidia-auto-select' /var/log/Xorg.5.log`" ] && PANEL_SIZE_DETECTED="true"
         fi

         # fglrx driver
         [ "`grep 'EDID Version:' /var/log/Xorg.5.log`" ] && PANEL_SIZE_DETECTED="true"

         [ "$autoresvideo" ] && PANEL_SIZE_DETECTED="true"
      fi

      [ "$XORG_DETECT_SCREEN_SIZE" = off -o "$lowresvideo" ] && unset PANEL_SIZE_DETECTED

      [ "$HSYNC_RANGE_NOT_DETECTED" ] && {
         logmsg "$me" "\
warning: DDC hsync range cannot be detected, setting default of 30-49 kHz"
         sed -i -e '/Section\W*"Monitor"/a\
           HorizSync    30-49' $XORGCONF
      }

      [ "$HSYNC_RANGE_NOT_DETECTED" -a ! "$PANEL_SIZE_DETECTED" ] &&
         sed -i -e '/SubSection "Display"/a\
               Modes "1024x768" "800x600" "640x480"' $XORGCONF
   else
      logmsg "$me" "warning: "$"Xorg probe failed!"
   fi
fi

[ "$VIDEO_DEV" -a "$VIDEO_DEV" != "$VIDEO_DEV_CACHED" ] &&
   echo "$VIDEO_DEV" > $postpluglibdir/xorg.cache

####################################
#
# Xorg dynamic configuration section
#
####################################

# radeon: enable a conservative power profile (mid) by default
if [ -e /sys/class/drm/card0/device/power_profile ]; then
   [ "$XORG_POWER_PROFILE" ] || XORG_POWER_PROFILE="mid"
   echo $XORG_POWER_PROFILE > /sys/class/drm/card0/device/power_profile
fi

# Configure keyboard
xorg_d_configure_input

if [ -d /sys/devices/platform/sunxi-rtc -a ! -e /etc/X11/xorg.conf.d/30-serverflags.conf ]; then
   # Workaround: disable DPMS on BananaPi
   cat > /etc/X11/xorg.conf.d/30-serverflags.conf << _EOF
Section "ServerFlags"
        Option "StandbyTime" "0"
        Option "SuspendTime" "0"
        Option "OffTime" "0"
EndSection
_EOF
fi

# enable 'Composite' extensions
if [ "$VIDEODRIVER" -a "$VIDEODRIVER" != "mga" -a ! -e /etc/X11/xorg.conf.d/40-extensions.conf ]; then
   cat > /etc/X11/xorg.conf.d/40-extensions.conf << _EOF
Section "Extensions"
        Option "Composite" "true"
EndSection
_EOF
elif [ "$VIDEODRIVER" != "mga" -a -e /etc/X11/xorg.conf.d/40-extensions.conf ]; then
   rm -f /etc/X11/xorg.conf.d/40-extensions.conf
fi

# add 'Section "DRI"'
if [ "$VIDEODRIVER" -a "$VIDEODRIVER" != "mga" -a ! -e /etc/X11/xorg.conf.d/50-dri.conf ]; then
   cat > /etc/X11/xorg.conf.d/50-dri.conf << _EOF
Section "DRI"
        Mode 0666
EndSection
_EOF
fi

if [ -d /sys/devices/platform/sunxi-rtc -a ! -e /etc/X11/xorg.conf.d/30-serverflags.conf ]; then
   # Workaround: disable DPMS on BananaPi
   cat > /etc/X11/xorg.conf.d/30-serverflags.conf << _EOF
Section "ServerFlags"
        Option "StandbyTime" "0"
        Option "SuspendTime" "0"
        Option "OffTime" "0"
EndSection
_EOF
fi

# Workaround symlink for libglx.so (or Xorg will choose the wrong one)
if [ -e /usr/lib/xorg/modules/extensions/libglx.so -a ! -e /usr/lib/xorg/modules/libglx.so ]; then
   ln -s extensions/libglx.so /usr/lib/xorg/modules/extensions/libglx.so
fi
if [ -e /usr/lib64/xorg/modules/extensions/libglx.so -a ! -e /usr/lib64/xorg/modules/libglx.so ]; then
   ln -s extensions/libglx.so /usr/lib64/xorg/modules/libglx.so
fi

[ -e $XORGCONF -a "$VIDEODRIVER" ] || exit 0

# add missing brackets to Xorg.conf device entries
sed -i "s|^[ \t]*Driver[ \t]*\([A-Za-z0-9]*\)[ \t]*$|        Driver      \"\1\"|g" $XORGCONF

# Configure Mice...

# remove wrong configuration for USBMouse (duplicating PS2MOUSE)
sed -i "/[\W]*InputDevice[\W]*"USBMouse".*/d" $XORGCONF

# remove obsolete input pointers configuration (since xorg-server 1.7)
sed -i "/[[:space:]]*InputDevice[[:space:]]*.*PS2Mouse.*/d; \
        /[[:space:]]*InputDevice[[:space:]]*.*Synaptics.*/d; \
        /[[:space:]]*InputDevice[[:space:]]*.*Alps.*/d" $XORGCONF

# remove all devices set
sed -i "/\W*Option \"Device\".*/d" $XORGCONF

# remove obsoleted XAANoOffscreenPixmaps
sed -i '/^[[:space:]]*Option[[:space:]]*"XAANoOffscreenPixmaps" "true"/d' $XORGCONF

# disable keyboard configuration for Xorg >= 1.4
sed -i "s|^\([[:space:]]*InputDevice\W*\"Keyboard0\".*\)|#\1|" $XORGCONF

# FIXME: delete empty lines
sed -i '/./,$!d' $XORGCONF

exit 0
