#!/bin/bash
#
# filename: /etc/hotplug/usb/codemeter (0755)
# Version .. 4.20.500 2010-02-24
# Author ... Heiko Abraham (ha), WIBU-SYSTEMS AG
#
# Kernel USB hotplug params include:
# ACTION=%s [add or remove]
# And if usbdevfs is configured, also:
# DEVICE=/proc/bus/usb/%03d/%03d
#
# See /etc/hotplug/usb.agent for mor information
#-------------------------------------------------------------
#
# revision 
# 2008-10-24 add ThreadCheck (Mr. A. Heider)

cd /etc/hotplug
 
REMOVERDIR="/var/run/usb"
MYDATE=`LANG=C date  "+%Y.%m.%d %H:%M:%S"`
MYCONFIG='/etc/wibu/CodeMeter/Server.ini'
CMSIGNAL='USR1'
MAKEWAIT=0
LINUXDIST="unknown"
CMSYSFS=${SYSFS}
if [ ! -z "${DEVPATH}" ] ; then
  if [ -z "${CMSYSFS}" ] ; then
    CMSYSFS=/sys
  fi
fi

CM_PROD1="64f/4f9"
CM_PROD2="64f/3e9"
CM_PROD3="64f/3f2"
CM_PROD4="64f/3f3"
CM_PROD5="64f/3f4"


# read configfile
if [ -f ${MYCONFIG} ] ; then
  USE_LOG=`cat ${MYCONFIG} | grep '^UseHotplugLog' | sed 's/^UseHotplugLog=//'`
else 
  # use default config
  USE_LOG=0
fi

if [ -d /dev/shm ] ; then
  if [ "${USE_LOG}x" ==  "1x" ] ; then 
    LOGF=/dev/shm/codemeter_hotplug.log
  else
    LOGF=/dev/null
  fi
else
  LOGF=/dev/null
fi

if [ -f /etc/redhat-release ] ; then
  # RedHat Linux (8/9)
  LINUXDIST="RedHat"
  LINUXREV=`cat /etc/redhat-release | sed s/.*release\ // | sed s/\ .*//`
fi
if [ -f /etc/mandrake-release ] ; then
  # Mandrake Linux (9/10)
  LINUXDIST="Mandrake"
  LINUXREV=""
fi
if [ -f /etc/fedora-release ] ; then
  # Fedora Linux (Core1/2/3/4/5/6/7)
  LINUXDIST="Fedora"
  LINUXREV=`cat /etc/redhat-release | sed s/.*release\ // | sed s/\ .*//`
fi
if [ -f /etc/SuSE-release ] ; then
  # SuSE Linux (9.x/10/11)
  LINUXDIST="SuSE"
  LINUXREV=`cat /etc/SuSE-release | tr "\n" ' ' | sed s/.*=\ //`
fi
if [ -f /etc/debian_version ] ; then
  # Debian 3.0/3.1 or ubuntu 5.x, 6.x, 7.x, 8.x
  LINUXDIST="Debian"
  LINUXREV=`cat /etc/debian_version`
fi



if [ "${LINUXDIST}" == "SuSE" ] ; then
  # Hotplug workaround for SuSE
  MAKEWAIT=1
fi



##### Create Remover Script, 
# used by RedHat 8/9, Fedora, Debian 3.1 and Ubuntu 5.x
# on RedHat 8/9, Fedora Core1       like Debian 3.1
# on Fedora Core 4 and Kernel 2.4:  REMOVER=/var/run/usb/$(echo $DEVICE | sed -e 's;/;%;g')
# on Fedora Core 4 and Kernel 2.6:  REMOVER=/var/run/usb/$(echo -n $SYSFS/$DEVPATH | sed -e 's;/;%;g')
# on Debian 3.1:                    REMOVER=/var/run/usb/`echo "$INTERFACE/$PRODUCT/$TYPE" | sed -e 's;/;%;g'`
CreateRemoveScript ( ) {
  REMOVER_DIR="$1"
  INTERFACE_STRING="$2"
  MY_DEVICE="$3"
  MY_SCRIPT="$4"
  if [ ! -z "${REMOVER_DIR}" ] ; then
    mkdir -p ${REMOVER_DIR}
    if [ -z "${REMOVER}" ] ; then 
      if [ "${MY_DEVICE}" == "" ] ; then
        helper=`echo "${INTERFACE_STRING}" | sed -e 's;/;%;g'`
        if [ "${DEVPATH}" != "" ]; then
          # kernel 2.6
          if [ "${LINUXDIST}" == "Fedora" ] ; then 
            helper=$(readlink -f ${CMSYSFS}/${DEVPATH} | sed -e 's;/;%;g')
          fi  
        fi
        echo '#!/bin/bash' > ${REMOVER_DIR}/${helper}
        echo "${MY_SCRIPT}" >> ${REMOVER_DIR}/${helper}
        chmod a+x ${REMOVER_DIR}/${helper}
        echo "  REMOVER:   ${REMOVER_DIR}/${helper}" >> $LOGF
      else
        helper=`echo ${MY_DEVICE} | sed -e 's;/;%;g'`
        if [ "${DEVPATH}" != "" ]; then
          # kernel 2.6
          if [ "${LINUXDIST}" == "Fedora" ] ; then 
            helper=$(readlink -f ${CMSYSFS}/${DEVPATH} | sed -e 's;/;%;g')
          fi
        fi
        echo '#!/bin/bash' > ${REMOVER_DIR}/${helper}
        echo "$0" >> ${REMOVER_DIR}/${helper}
        chmod a+x ${REMOVER_DIR}/${helper}
        echo "  REMOVER:   ${REMOVER_DIR}/${helper}" >> $LOGF
        echo "  G-REMOVER: ${REMOVER}" >> $LOGF
      fi
    else 
      # Remover is pre-defined 
      echo '#!/bin/bash'     > ${REMOVER}
      echo "${MY_SCRIPT}" >> ${REMOVER}
      chmod a+x ${REMOVER}
      echo "  REMOVER: ${REMOVER} (pre-defined)" >> $LOGF
    fi
  fi
}



if [ "$ACTION" == "add" ] ; then 
  ##### Action "add" - new hotplug event
    PROD=`echo "${PRODUCT}" | sed 's/\/[0-9]*$//'`
    if [ "$PROD" == ${CM_PROD1} -o "$PROD" == ${CM_PROD2} -o "$PROD" == ${CM_PROD3} -o "$PROD" == ${CM_PROD4} -o "$PROD" == ${CM_PROD5} ] ; then
      echo "####### new hotplug event incoming" >> $LOGF
      echo "  ACTION:    ${ACTION} (${MYDATE})" >>  $LOGF
      echo "  PRODUCT:   ${PRODUCT}  (${DEVICE})" >>  $LOGF
      if [ ! -z "${DEVPATH}" ] ; then
        echo "  DEVPATH:   ${DEVPATH}" >>  $LOGF
      fi

    fi
  
    if [ "$PROD" == ${CM_PROD1} -o "$PROD" == ${CM_PROD2} -o "$PROD" == ${CM_PROD3} -o "$PROD" == ${CM_PROD4} -o "$PROD" == ${CM_PROD5} ] ; then
      # setup remover script for hotplug
      if [ "${LINUXDIST}" == "RedHat" -o "${LINUXDIST}" == "Debian" -o "${LINUXDIST}" == "Fedora" ] ; then
        # create remover script
        CreateRemoveScript "${REMOVERDIR}"  "${INTERFACE}/${PRODUCT}/${TYPE}" "${DEVICE}" "$0" 
      fi

      # load kernel modules
      /sbin/modprobe usb-storage
      /sbin/modprobe sg
      /sbin/modprobe vfat

      # wait for sysfs
      SEND_SIGNAL=1
      if [ ! -z "${DEVPATH}" ] ; then 
        if [ -f ${CMSYSFS}/${DEVPATH}/manufacturer ] ; then 
          echo "  hotplug (${ACTION}) event finish (root device)" >> $LOGF
          SEND_SIGNAL=0
        else
          declare WaitLoop=0
          for (( WaitLoop = 1; WaitLoop <= 20; WaitLoop++ )); do
            # wait for Dev-setup
            sleep 1 
            # DEV_NODE=/dev/sg3 (on older kernels)
            # DEV_NODE=21:3 (on newer kernels)
            DEV_NODE=`cat ${CMSYSFS}/${DEVPATH}/host[0-9]*/target[0-9]*/[0-9]*/generic/device/generic/dev`
            if [ ! -z "${DEV_NODE}" ] ; then
              # DEV_NODE_SG=`echo "${DEV_NODE}" | sed 's/^[0-9].*:/\/dev\/sg/'`
              sleep 1
              break;
            fi
            DEV_NODE_C=`echo "${DEV_NODE}" | grep ':'`
            if [ ! -z "${DEV_NODE_C}" ] ; then 
              DEV_NODE_SG=`echo "${DEV_NODE}" | sed 's/^[0-9].*:/\/dev\/sg/'`
              if [ ! -z "${DEV_NODE_SG}" ] ; then
                sleep 1
                break;
              fi
            fi
            # echo "  wait for ${DEV_NODE} (${MYDATE})" >>  $LOGF
          done
        fi 

        if [ "${MAKEWAIT}x" == "1x" ] ; then
          # on SuSE Linux 9.1 - 9.3 we required a long waiting time while hwscan is finish 
          sleep 3
        fi 
      
        # send hotplug signal, if server is startup 
        if [ "${SEND_SIGNAL}x" = "1x" ] ; then
          PSVAL=`ps -AHc | grep 'CodeMeterLin' | sed 's/^ *//' | sed 's/ .*$//'`
          if [ ! -z "${PSVAL}" ] ; then
            for P in ${PSVAL} ; do
              HASSIGH=3
              if [ -f /proc/${P}/status ]; then 
                HASSIGH=`cat /proc/${P}/status | grep '^Threads' | sed 's/.*\t//'` 
              fi 
              if [ $((0x${HASSIGH})) -gt 4 ]; then 
                kill -${CMSIGNAL} ${P} 
                echo "  send signal to $P" >> $LOGF 
                break; 
              else 
                echo "  pid ${P} not yet ready for ${CMSIGNAL}" >> $LOGF 
              fi
            done
          fi
        fi
        echo "  hotplug (${ACTION}) event finish (${MYDATE})" >> $LOGF
      fi
    fi
    
else
  ##### Action "remove" - new hotplug event
    PROD=`echo "${PRODUCT}" | sed 's/\/[0-9]*$//'`
    if [ "$PROD" == ${CM_PROD1}  -o "$PROD" == ${CM_PROD2} -o "$PROD" == ${CM_PROD3} -o "$PROD" == ${CM_PROD4} -o "$PROD" == ${CM_PROD5} ] ; then
      echo "####### new hotplug event incoming" >> $LOGF
      echo "  ACTION:    ${ACTION} (${MYDATE})" >>  $LOGF
      echo "  PRODUCT:   ${PRODUCT} (${DEVICE})" >>  $LOGF

      # send hotplug signal
      PSVAL=`ps -AHc | grep 'CodeMeterLin' | sed 's/^ *//' | sed 's/ .*$//'`
      if [ ! -z "${PSVAL}" ] ; then
        for P in ${PSVAL} ; do
          kill -${CMSIGNAL} ${P}
          # echo "# send CodeMeterLin signal to $P" >> $LOGF
          break;
        done
      fi
      echo "  hotplug (${ACTION}) event finish" >> $LOGF
    fi
fi


#-------------------------------------------------------------
# 2008-08-12 (ha)
#EOF
