#!/bin/sh
#(c) Copyright Barry Kauler Dec. 2010. License GPL v3 /usr/share/doc/legal.
#called from pupdial. Based upon earlier scripts by Richard Erwin.
#there were scripts in /etc/init.d created by Richard, now moved to here.
#101205 use modem-stats to eliminate non-responsive ttyUSB ports.
#101206 wait. remember previous modem.
#101207 if usb-modeswitch has already set /dev/gsmmodem, use it.
#101207 modem plugged in at bootup, may not trigger usb-modeswitch, replay uevents.
#101210, 101211 tweaks.

#hso.ko: this site http://www.pharscape.org/hso.html states that the hso driver is in kernel
#2.6.27. Yes, it is in kernel/drivers/net/usb/hso.ko. It is also in the 2.6.30.* kernel.
#however it is missing from 2.6.31 and later kernels...
#oh, i see why. I have configured 2.6.31 and later with 'rfkill' turned off, which
#hso requires: in kernel source drivers/net/usb/Kconfig:
#config USB_HSO
#	tristate "Option USB High Speed Mobile Devices"
#	depends on USB && RFKILL
#101210 ...I was able to compile it separately, have put it in zzz pkg, for testing.

#101206
prevMODEM=''
if [ -h /dev/modem ];then #maybe set by internal modem detected at bootup, or previous run of pupdial this session.
 prevMODEM="`readlink /dev/modem | sed -e 's%/dev/%%'`"
 rm -f /dev/modem
fi

chat_with_func() { #device passed in, ex: ttyUSB0
 rm -f /tmp/pupdial_port_test 2> /dev/null
 #TODO maybe send +++ to return modem to command-mode.
 #hangs if modem unplugged or turned off (contrary to what docs say)...
 modem-stats -c "ATZ" $1 > /tmp/pupdial_port_test &
 sleep 5 #v413
 killall modem-stats
 if [ -e /tmp/pupdial_port_test ];then
  if [ -s /tmp/pupdial_port_test ];then #nonzero size.
   grep "^OK" /tmp/pupdial_port_test > /dev/null 2>&1
   [ $? -eq 0 ] && return 0 #success
  fi
 fi
 return 1
}

MODEM=''

hPID=0 #101211 do not display msg on 2nd entry...
if [ ! $1 ];then
 yaf-splash -bg orange -placement center -close never -fontsize large -text "$(gettext 'Please wait, probing for hotpluggable (external) modems...')" &
 hPID=$!
fi

#101206 wait...
BRKCNT=0
while [ $BRKCNT -lt 40 ];do #101211 bump 30 to 40.
 OK=0
 [ "`ls -1 /pinstall.*.sh 2>/dev/null`" = "" ] && [ "`pidof usb_modeswitch`" = "" ] && [ "`pidof usb_modeswitch_status`" = "" ] && OK=$(($OK+1))
 sleep 1
 [ "`ls -1 /pinstall.*.sh 2>/dev/null`" = "" ] && [ "`pidof usb_modeswitch`" = "" ] && [ "`pidof usb_modeswitch_status`" = "" ] && OK=$(($OK+1))
 [ -f /tmp/usb_modeswitch_status_flag_success ] && OK=2 #see usb_modeswitch_status.
 [ $OK -eq 2 ] && break
 BRKCNT=$(($BRKCNT+1))
done

#101207 if usb-modeswitch has already set this, use it...
if [ -h /dev/gsmmodem ];then
 gMODEM="`readlink /dev/gsmmodem`"
 if [ -e /dev/${gMODEM} ];then
  ln -snf $gMODEM /dev/modem
  [ $hPID -ne 0 ] && kill $hPID
  exit
 else
  rm -f /dev/gsmmodem
 fi
fi

#101206 has anything changed?...
prevUSBIDS=''
USBIDS="`lsusb 2>/dev/null | tr -s ' ' | cut -f 6 -d ' ' | sort -u | tr '\n' ' '`"
[ -f /var/local/pupdial/usbids ] && prevUSBIDS="`cat /var/local/pupdial/usbids`"
echo -n "$USBIDS" > /var/local/pupdial/usbids
#PCIIDS="`lspci -n | tr -s ' ' | cut -f 3 -d ' ' | sort -u | tr '\n' ' '`"
#if [ -f /var/local/pupdial/pciids ];then
# prevPCIIDS="`cat /var/local/pupdial/pciids`"
#else
# prevPCIIDS="$PCIIDS"
#fi
#echo -n "$PCIIDS" > /var/local/pupdial/pciids

#hso.ko not always present... well check them all...
USBSERIAL='' ; CDC_ACM='' ; HSO='' ; NOZOMI='' ; DGCUSBDCP='' ; IPWIRELESS=''
if modinfo usbserial >/dev/null 2>&1 ;then USBSERIAL=usbserial ;fi
if modinfo cdc_acm >/dev/null 2>&1 ;then CDC_ACM=cdc_cm ;fi
if modinfo hso >/dev/null 2>&1 ;then HSO=hso ;fi
if modinfo nozomi >/dev/null 2>&1 ;then NOZOMI=nozomi ;fi
if modinfo dgcusbdcp >/dev/null 2>&1 ;then DGCUSBDCP=dgcusbdcp ;fi
if modinfo ipwireless >/dev/null 2>&1 ;then IPWIRELESS=ipwireless ;fi

USBMODEMS="$USBSERIAL $CDC_ACM $DGCUSBDCP"
PCMCIAMODEMS="$HSO $IPWIRELESS $NOZOMI"
#listed in order that we should probe... $USBSERIAL $CDC_ACM $DGCUSBDCP $HSO $IPWIRELESS $NOZOMI

#Let high-speed modems to be detected by hso init script...
FLAGHSO=''
[ "$HSO" != "" ] && [ "`grep -l -s 'Modem' /sys/class/tty/ttyHS?*/hsotype`" != "" ] && FLAGHSO='yes'

#####Allusbserial#####
if [ "$USBSERIAL" ];then
 if [ ! -h /dev/modem ];then #If a different modem selected, quit.
  if lsmod | grep '^usbserial ' >/dev/null ;then
   if [ "$FLAGHSO" = "" ];then
    #Select interrupt-type device - first one or one identified in log as modem.
    INTERRUPTLIST="`grep -H -s 'Interrupt' /sys/bus/usb/devices/*-*:*.*/ep_??/type | cut -f 1-6 -d /`"
    DEVLISTUSB="`ls -1 -d /sys/bus/usb/devices/*-*:*.*/tty????* 2>/dev/null | sed 's/ /\n/g' | grep -F "$INTERRUPTLIST" | cut -f 7 -d / | sed 's/\(tty...\)\([0-9]$\)/\10\2/' | sort | sed 's/\(tty...\)\(0\)/\1/'`"
    DEVMLIST="`grep -s 'converter now attached' /var/log/messages | grep ' modem ' | grep -o 'ttyUSB[0-9][0-9]*' | sort -u`"
    if [ "$DEVLISTUSB" != "" ] && [ "$DEVMLIST" != "" ];then
     MODEMS="`echo "$DEVLISTUSB" | grep -F "$DEVMLIST"`"
    else
     MODEMS="$DEVMLIST"
    fi
    if [ "$MODEMS" != "" ];then #101205
     #101206 avoid unecessary modem probing...
     prevUSBMODEM=''
     [ -f /var/local/pupdial/usb_modem_port ] && prevUSBMODEM="`cat /var/local/pupdial/usb_modem_port`"
     [ "$USBIDS" = "$prevUSBIDS" ] && [ "$prevUSBMODEM" ] && [ "`echo "$MODEMS" | grep "$prevUSBMODEM"`" != "" ] && ln -snf $prevUSBMODEM /dev/modem
     if [ ! -h /dev/modem ];then
      for MODEM in $MODEMS
      do
       chat_with_func /dev/${MODEM}
       [ $? -eq 0 ] && break
       MODEM=''
      done
      if [ "$MODEM" != "" ];then
       ln -snf $MODEM /dev/modem
       echo -n "$MODEM" > /var/local/pupdial/usb_modem_port
      fi
     fi
    fi
   fi
  fi
 fi
fi

#####Cdcacm#####
if [ "$CDC_ACM" ];then
 if [ ! -h /dev/modem ];then #If a different modem selected, quit.
  if lsmod | grep '^cdc_acm ' >/dev/null ;then
   if [ "$FLAGHSO" = "" ];then
    #Select interrupt-type device - first one or one identified in log as modem.
    INTERRUPTLIST="`grep -H -s 'Interrupt' /sys/bus/usb/devices/*-*:*.*/ep_??/type | cut -f 1-6 -d /`"
    DEVLISTACM="`ls -1 -d /sys/bus/usb/devices/*-*:*.*/tty/tty????* 2>/dev/null | sed 's/ /\n/g' | grep -F "$INTERRUPTLIST" | cut -f 8 -d / | sed 's/\(tty...\)\([0-9]$\)/\10\2/' | sort | sed 's/\(tty...\)\(0\)/\1/'`"
    DEVMLIST="`grep -s ': USB ACM device$' /var/log/messages | grep -o 'ttyACM[0-9][0-9]*' | sort -u`"
    if [ "$DEVLISTACM" != "" ] && [ "$DEVMLIST" != "" ];then
     MODEM="`echo "$DEVLISTACM" | grep -F "$DEVMLIST" | head -n 1`"
    else
     MODEM="`echo "$DEVMLIST" | head -n 1`"
    fi
    if [ "$MODEM" != "" ];then
     [ ! -e /dev/$MODEM ] && [ -e /dev/input/$MODEM ] && ln -snf input/$MODEM /dev/$MODEM  #device name for pupdial
     ln -snf $MODEM /dev/modem
    fi
   fi
  fi
 fi
fi

#####Dgcmodem#####
if [ "$DGCUSBDCP" ];then
 if [ ! -h /dev/modem ];then #If a different modem selected, quit.
  if lsmod | grep '^dgcusbdcp ' >/dev/null ;then
   WAITMAX=20 ; WAITCNT=0
   until [ "`lsmod | grep '^cdc_acm '`" != "" ];do
    [ $WAITCNT -gt $WAITMAX ] && break
    WAITCNT=`expr $WAITCNT + 1`
    sleep 1
   done
   if [ $WAITCNT -le $WAITMAX ];then
    if [ "$FLAGHSO" = "" ];then
     if [ "`grep 'adding union descriptor for cdc_acm' /var/log/messages | grep 'dgcusbdcp'`" != "" ];then
      #Select interrupt-type device - first one or one identified in log as probably a DGC modem.
      INTERRUPTLIST="`grep -H -s 'Interrupt' /sys/bus/usb/devices/*-*:*.*/ep_??/type | cut -f 1-6 -d /`"
      DEVLISTACM="`ls -1 -d /sys/bus/usb/devices/*-*:*.*/tty/tty????* 2>/dev/null | sed 's/ /\n/g' | grep -F "$INTERRUPTLIST" | cut -f 8 -d / | sed 's/\(tty...\)\([0-9]$\)/\10\2/' | sort | sed 's/\(tty...\)\(0\)/\1/'`"
      grep -q 'd[gc][cg]usbdcp' /var/log/messages && DEVMLIST="`grep -o -E -s 'd[gc][cg]usbdcp|ttyACM[0-9][0-9]*' /var/log/messages | sed -e '1,/d[gc][cg]usbdcp/d' -e '/d[gc][cg]usbdcp/Q'`" || DEVMLIST=""
      if [ "$DEVLISTACM" != "" ] && [ "$DEVMLIST" != "" ];then
       MODEM="`echo "$DEVLISTACM" | grep -F "$DEVMLIST" | head -n 1`"
      else
       MODEM="`echo "$DEVMLIST" | head -n 1`"
      fi
      if [ "$MODEM" != "" ];then
       [ ! -e /dev/$MODEM ] && [ -e /dev/input/$MODEM ] && ln -snf input/$MODEM /dev/$MODEM  #device name for pupdial
       ln -snf $MODEM /dev/modem #v433 end
      fi
     fi
    fi
   fi   
  fi
 fi
fi

#####Hso#####
if [ "$HSO" ];then
 MODEM=''
 [ -h /dev/modem ] && MODEM="`readlink /dev/modem | grep -v '^ttyHS[0-9]$'`"
 if [ "$MODEM" = "" ];then #If a different modem selected, quit.
  if lsmod | grep '^hso ' >/dev/null ;then
   WAITCNT=0 ; WAITMAX=10
   until [ "$MODEM" != "" ];do
    MODEM="`grep -l -s 'Modem' /sys/class/tty/ttyHS[0-9][0-9]*/hsotype | head -n 1 | cut -f 5 -d /`"
    if [ "$MODEM" = "" ];then
     WAITCNT=`expr $WAITCNT + 1`
     [ $WAITCNT -gt $WAITMAX ] && break
     sleep 1
    fi
   done
   if [ $WAITCNT -le $WAITMAX ];then
    #Even if /dev/modem already set, ensure it matches detected modem.
    [ -h /dev/modem ] && rm /dev/modem
    ln -snf $MODEM /dev/modem
    [ -h /dev/ttyS_HS ] && rm /dev/ttyS_HS
    ln -snf $MODEM /dev/ttyS_HS #for pupdial probe
   fi
  fi
 fi
fi

#####Ipwireless#####
if [ "$IPWIRELESS" ];then
 if [ ! -h /dev/modem ];then #If a different modem selected, quit.
  if lsmod | grep '^ipwireless ' >/dev/null ;then
   ln -snf ttyIPWp0 ttyS_ttyIPWp0
   ln -snf ttyS_IPWp0 /dev/modem
  fi
 fi
fi

#####Nozomi#####
if [ "$NOZOMI" ];then
 if [ ! -h /dev/modem ];then #If a different modem selected, quit.
  if lsmod | grep '^nozomi ' >/dev/null ;then
   ln -snf noz0 /dev/modem
   ln -snf noz0 /dev/ttyS_NOZ0 #for pupdial probe
  fi
 fi
fi


#101207 modem plugged in at bootup, may not trigger usb-modeswitch, replay uevents...
if [ ! $1 ];then #101211 gets reentered, see below.
 if [ ! -h /dev/modem ];then
  #yaf-splash -bg purple -placement center -close never -text "Please wait, probing for hotpluggable (external) modems..." &
  #hPID=$!
  [ -e /sys/bus/pcmcia/devices ] && NEWPCMCIA="`ls /sys/bus/pcmcia/devices/*/uevent 2>/dev/null | tr '\n' ' '`"
  [ -e /sys/bus/usb/devices ] && NEWUSB="`ls /sys/bus/usb/devices/*/uevent 2>/dev/null | tr '\n' ' '`"
  for ONEUEVENT in ${NEWPCMCIA}${NEWUSB}
  do
   ONEPATH="`dirname $ONEUEVENT`"
   #the check for 'modalias' file is maybe needed for old kernel?...
   [ ! -e ${ONEPATH}/modalias ] && [ "`grep 'MODALIAS' $ONEUEVENT`" = "" ] && continue
   echo add > $ONEUEVENT
   sleep 0.1
  done
  sleep 2 #4 #101211 give plenty of time for usb-modeswitch to start.
  kill $hPID #101211
  /usr/sbin/pupdial_init_hotpluggable 2
 else
  kill $hPID
 fi
fi
###END###
