From 46a563b98097d110936ce40dceaa180f61205415 Mon Sep 17 00:00:00 2001 From: John Klug Date: Mon, 17 Aug 2020 18:08:50 -0500 Subject: Fix chat_wrapper to handle COPS=2, CFUN=0 state --- recipes-core/multitech/config/chat_wrapper | 182 ++++++++++++++++++--- recipes-core/multitech/config/chat_wrapper.default | 12 +- recipes-core/multitech/config/ppp/peers/cdma | 2 +- recipes-core/multitech/config/ppp/peers/lvw2 | 2 +- recipes-core/multitech/config_2.3.bb | 68 +++++++- 5 files changed, 237 insertions(+), 29 deletions(-) (limited to 'recipes-core') diff --git a/recipes-core/multitech/config/chat_wrapper b/recipes-core/multitech/config/chat_wrapper index f1fd30c..b0bf9e5 100755 --- a/recipes-core/multitech/config/chat_wrapper +++ b/recipes-core/multitech/config/chat_wrapper @@ -18,30 +18,117 @@ # If there are not #MT AT+CGDCONT= lines, then any line without # a comment chararacter before AT+CGDONT= is accepted, but only the # last one in the file. +# +# On entry to this script, file descriptor 0 is the modem. +# For ppp to work, stty must work on file descriptor 0. +# If stty fails, so will ppp. NAME=chat_wrapper CONFIG=/etc/default/${NAME} +CHAT_WRAPPER_RECURSION=/run/chat_wrapper_recursion + function finish { ${LOG} "Launch:" "$@" - exec "$@" + exec "$@" # NOTREACHED } +# This function is used to determine if the modem and serial driver +# are working. In testing, the driver has gotten into states where +# stty fails. Before the chat script is started, the ioctl TCGETS is +# performed, and will fail if the driver is hung. This same function +# is called by stty. The modem port used by pppd is STDIN. Cases +# have been observed on the H5 where radio-cmd works, but stty does +# not, resulting in pppd failing. When this happens, radio-reset is +# the best thing to try. +function sanity +{ + if ! log=$(stty 2>&1) || ! [[ $(radio-cmd -t10000 'AT') =~ ^OK ]]; then + ${LOG} "Modem has issues, so see if we can try again" + ${LOG} "stty error: $(log)" + array=( ) + # our parent is PPID, which is pppd. Get the pppd + # parameter list. + while IFS= read -r -d '' eparm; do + execarg+=( "$eparm" ) + done < <(cat /proc/$PPID/cmdline) + i=0 + ${LOG} "List parameters" + while ((i < ${#execarg[@]})) ; do + ${LOG} "$i: ${execarg[$i]}" + ((i++)) + done + if [[ ${execarg[0]} == "pppd" ]] ; then + execarg[0]=/usr/sbin/pppd + fi + + # Break any recursion loop. + if [[ -f ${CHAT_WRAPPER_RECURSION} ]] ; then + ${LOG} "Failure: modem is still unresponsive after reset" + rm -f ${CHAT_WRAPPER_RECURSION} + exit 1 + fi + touch ${CHAT_WRAPPER_RECURSION} + ${LOG} "Bad TTY, possibly due to modem in bad state" + ${LOG} "Reset modem, and we relaunch pppd" + # Our terminal is the modem. When we reset the modem, + # we will be sent a SIGHUP. Ignore it (:). + trap : SIGHUP + /usr/sbin/mts-io-sysfs store radio-reset 0 + sleep 5 + count=0 + while ((count < 60)) ; do + # Wait for radio-reset to get the modem responding + if [[ $(radio-cmd -t10000 'AT') =~ ^OK ]]; then + # parent is dying, so remove the pppd locks for the new pppd. + for f in /run/lock/LCK..modem_at0 /run/lock/LCK..modem_at1 ; do + if [[ -f $f ]] ; then + mypid=$(cat $f) + ${LOG} "PPID is $PPID, pid is $mypid" + # Remove the lock, if it belongs to our parent, pppd + if [ $mypid = $PPID ] ; then + ${LOG} "match $mypid $PPID" + sleep 60 + rm -f $f + else + ${LOG} "mismatch |$mypid| |$PPID|" + fi + fi + done + # Locks gone, so start new pppd + nohup "${execarg[@]}" >/dev/null 2>&1 & + # Tell our parent we failed, which causes our pppd to terminate. + exit 1 + else + sleep 5 + fi + done + ${LOG} "ERROR: After five minutes the modem is still not ready" + exit 1 + fi + return 0 +} # End of sanity function + +# If > 0, need to wait because we were not registered. +WAITREG=0 + [[ -f $CONFIG ]] || exit 1 . ${CONFIG} : ${REGWAITTIME:=300} : ${FINALWAIT:=5} +: ${COPSWAIT:=10} +: ${CFUNWAIT:=10} : ${LOG:="/usr/bin/logger -t ${NAME} -p daemon.notice"} ${LOG} Timeout is $REGWAITTIME, execute "$@" ((i=$#)) chatscript="${!i}" -${LOG} Parsing chat script "$chatscript" +${LOG} Parsing chat script "$chatscript" # CONTEXT is last context string in chat script CONTEXT=$(egrep "^#MT[[:space:]]+(AT\+CGDCONT=.*)" ${chatscript} | tail -1) if ((${#CONTEXT} == 0)) ; then @@ -60,9 +147,25 @@ if ((${#CONTEXT} == 0)) ; then fi ((CONTEXTNUM=${BASH_REMATCH[2]})) +# Make sure CFUN=1, in case the last pppd was aborted with it set to 0. +${LOG} "Verify CFUN=1" +cfun=$(/usr/bin/radio-cmd ${RADIOOPTION} -t10000 'AT+CFUN?') +result1=$? +if ((result1 != 0)) || ((${#cfun} == 0)) ; then + ${LOG} "Is modem in bad state -- \"CFUN?\" is broken?" + sanity + ((WAITREG++)) +fi +if ! [[ $cfun =~ ^\+CFUN:\ 1[,[:space:]] ]] ; then + /usr/bin/radio-cmd ${RADIOOPTION} -t10000 'AT+CFUN=1' + ${LOG} "Just set CFUN=1 so wait ${CFUNWAIT} seconds" + sleep ${CFUNWAIT} + ((WAITREG++)) +fi ${LOG} "Using Context ${CONTEXTNUM} based on chat script: ${CONTEXT}" + # At this point if there is no context number, we can skip everything else. # Get Modem's context settings @@ -137,7 +240,15 @@ if [[ $MPDP != $PDP ]] || [[ $MAPN != $APN ]] || \ ${LOG} "$MCONTEXT" ${LOG} "Dropping registration with carrier to set context" # Need to deregister + ((WAITREG++)) /usr/bin/radio-cmd ${RADIOOPTION} -t10000 'AT+COPS=2' + + count=10 + while ((count > 0)) && ! [[ $(/usr/bin/radio-query ${RADIOOPTION} --netreg) =~ ^NOT\ REGISTERED$ ]] ; do + sleep 2 + ((count--)) + done + # H5 radios do not like addresses that are empty with "" if ((${#ADDR} == 0)) ; then CMDSTR="AT+CGDCONT=${CONTEXTNUM},\"${PDP}\",\"${APN}\",,$DCOMP,${HCOMP}${FULLBOAT}" @@ -154,7 +265,7 @@ if [[ $MPDP != $PDP ]] || [[ $MAPN != $APN ]] || \ ((count--)) || true LOGMSG=$(/usr/bin/radio-cmd ${RADIOOPTION} -t10000 "${CMDSTR}" 2>&1) result=$? - ${LOG} "Result ${result}, Got response ${LOGMSG}" + ${LOG} "Setting context: Result ${result}, Got response ${LOGMSG}" if [[ $LOGMSG =~ ERROR ]] ; then result=1 fi @@ -163,13 +274,16 @@ if [[ $MPDP != $PDP ]] || [[ $MAPN != $APN ]] || \ # re-enable the modem to defaults. /usr/bin/radio-cmd ${RADIOOPTION} -t10000 'AT+COPS=0' - sleep 1 # Some older modems will not re-register after the COPS # command if you do not reset them using CFUN. /usr/bin/radio-cmd ${RADIOOPTION} -t10000 'AT+CFUN=0' + ${LOG} "Set COPS=0, CFUN=1, so wait ${CFUNWAIT} seconds" + sleep ${CFUNWAIT} /usr/bin/radio-cmd ${RADIOOPTION} -t10000 'AT+CFUN=1' + sleep ${CFUNWAIT} + # Abort PPP if the Context is not correct. We don't want # to cause the carrier to disable the account by dialing # out with a bad APN. @@ -179,27 +293,47 @@ if [[ $MPDP != $PDP ]] || [[ $MAPN != $APN ]] || \ fi sleep 1 ${LOG} "New context is set. Wait up to $REGWAITTIME seconds to register" - # Wait for registration - uptime=$(cat /proc/uptime) - [[ $uptime =~ ^([^\.]*) ]] - t0=${BASH_REMATCH[1]} - while ! [[ $(/usr/bin/radio-query ${RADIOOPTION} --netreg) =~ ^REGISTERED$ ]] ; do - sleep 5 - uptime=$(cat /proc/uptime) - [[ $uptime =~ ^([^\.]*) ]] - t1=${BASH_REMATCH[1]} - if ((t1-t0 > REGWAITTIME)) ; then - ${LOG} "$((t1-t0)) seconds has expired" - exit 1 - fi - done - uptime=$(cat /proc/uptime) - [[ $uptime =~ ^([^\.]*) ]] - t1=${BASH_REMATCH[1]} - ${LOG} "Re-registered in $((t1-t0)) seconds -- wait ${FINALWAIT} more seconds" - sleep $FINALWAIT else - ${LOG} "Context $CONTEXTNUM matches and nothing to do." + ${LOG} "Context $CONTEXTNUM matches verify COPS, then wait for registration." + # Check and set COPS and CFUN to be sure we were not interrupted at some point + # in the past. + cops=$(/usr/bin/radio-cmd ${RADIOOPTION} -t10000 'AT+COPS?') + result0=$? + + if ((result0 != 0)) || ! [[ $cops =~ ^\+COPS:\ 0, ]] ; then + /usr/bin/radio-cmd ${RADIOOPTION} -t10000 'AT+COPS=0' + ((WAITREG++)) + ${LOG} "Just set COPS=0 so wait ${COPSWAIT} seconds" + sleep ${COPSWAIT} + fi + +fi +# Wait for registration +uptime=$(cat /proc/uptime) +[[ $uptime =~ ^([^\.]*) ]] +t0=${BASH_REMATCH[1]} +while ! [[ $(/usr/bin/radio-query ${RADIOOPTION} --netreg) =~ ^REGISTERED$ ]] ; do + sleep 5 + ((WAITREG++)) + uptime=$(cat /proc/uptime) + [[ $uptime =~ ^([^\.]*) ]] + t1=${BASH_REMATCH[1]} + if ((t1-t0 > REGWAITTIME)) ; then + ${LOG} "$((t1-t0)) seconds has expired without registration" + sanity + fi +done +uptime=$(cat /proc/uptime) +[[ $uptime =~ ^([^\.]*) ]] +t1=${BASH_REMATCH[1]} +${LOG} "Re-registered in $((t1-t0)) seconds" +if ((WAITREG > 0)) ; then + ${LOG} "Wait ${FINALWAIT} more seconds" + sleep $FINALWAIT fi +sanity + +rm -f ${CHAT_WRAPPER_RECURSION} finish "$@" + # NOTREACHED diff --git a/recipes-core/multitech/config/chat_wrapper.default b/recipes-core/multitech/config/chat_wrapper.default index a1b4e41..164086a 100644 --- a/recipes-core/multitech/config/chat_wrapper.default +++ b/recipes-core/multitech/config/chat_wrapper.default @@ -9,7 +9,11 @@ REGWAITTIME=300 # before attempting a PPP connection. # This is ignored if the context is # already set correctly in the modem. -FINALWAIT=5 +# and the device was registered before +# ppp was started. +# This needs to be long enough to allow +# the modem to stabilize after registration. +FINALWAIT=60 # Option for radio-query, radio-cmd # Used by /usr/libexec/ppp/chat_wrapper, @@ -18,3 +22,9 @@ RADIOOPTION="-d /dev/modem_at1" # Device to use if RADIOOPTION fails: RADIOOPTION2="-d /dev/modem_at0" + +# How long to wait when COPS is set to 0 +COPSWAIT=10 + +# How long to wait when CFUN is set to 1 +CFUNWAIT=10 diff --git a/recipes-core/multitech/config/ppp/peers/cdma b/recipes-core/multitech/config/ppp/peers/cdma index 3fc231f..cc670b3 100644 --- a/recipes-core/multitech/config/ppp/peers/cdma +++ b/recipes-core/multitech/config/ppp/peers/cdma @@ -6,4 +6,4 @@ usepeerdns noauth crtscts novj -connect '/usr/sbin/chat -v -t 90 -f /etc/ppp/peers/cdma_chat' +connect '/usr/libexec/ppp/chat_wrapper /usr/sbin/chat -v -t 90 -f /etc/ppp/peers/cdma_chat' diff --git a/recipes-core/multitech/config/ppp/peers/lvw2 b/recipes-core/multitech/config/ppp/peers/lvw2 index 773f1dd..23709d2 100644 --- a/recipes-core/multitech/config/ppp/peers/lvw2 +++ b/recipes-core/multitech/config/ppp/peers/lvw2 @@ -8,4 +8,4 @@ ipcp-restart 10 noauth crtscts novj -connect '/usr/sbin/chat -v -t 90 -f /etc/ppp/peers/lvw2_chat' +connect '/usr/libexec/ppp/chat_wrapper /usr/sbin/chat -v -t 90 -f /etc/ppp/peers/lvw2_chat' diff --git a/recipes-core/multitech/config_2.3.bb b/recipes-core/multitech/config_2.3.bb index 629cd72..a48941a 100644 --- a/recipes-core/multitech/config_2.3.bb +++ b/recipes-core/multitech/config_2.3.bb @@ -3,8 +3,9 @@ SECTION = "base" LICENSE = "MIT" RDEPENDS_${PN} += "bash" LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" -PR = "r7" -PACKAGES =+ "${PN}-mths" +PACKAGE_ARCH = "all" +PR = "r9" +PACKAGES =+ "${PN}-mths ${PN}-wifi-bt-ap" inherit update-rc.d inherit allarch @@ -19,12 +20,14 @@ SRC_URI = "\ file://ppp \ file://config.init \ file://config-mths \ + file://config-wifi-bt-ap \ file://chat_wrapper \ file://chat_wrapper.default \ file://99_radio \ " RDEPENDS_${PN}-mths += "${PN}" +RDEPENDS_${PN}-wifi-bt-ap += " bluez5 bluez5-pand hostap-daemon dnsmasq rs9113-noarch " CONFFILES_${PN} += "${sysconfdir}/defaults.tar.gz" CONFIGFILES = "network/interfaces ppp" @@ -59,6 +62,16 @@ fakeroot do_install () { install -m 0755 ${WORKDIR}/chat_wrapper ${D}${libexecdir}/ppp/ install -m 0644 ${WORKDIR}/chat_wrapper.default ${D}${sysconfdir}/default/chat_wrapper install -m 0644 ${WORKDIR}/99_radio ${D}${sysconfdir}/default/volatiles + + install -d ${D}/usr/share + cp -a ${WORKDIR}/config-wifi-bt-ap/* ${D}/ + # README does not usually go on an embedded device. + rm ${D}/README + echo 'List out files' + find ${D}/usr/share/config-wifi-bt-ap -type f + find ${D}/usr/share/config-wifi-bt-ap -type f | xargs chmod 0644 + find ${D}/usr/share/config-wifi-bt-ap | xargs chown root:root + find ${D}/usr/share -type d | xargs chmod 0755 } FILES_${PN} = "${sysconfdir}/defaults.tar.gz ${sysconfdir}/default_pass" @@ -66,6 +79,7 @@ FILES_${PN} += "${sysconfdir}/init.d/config ${sysconfdir}/default ${libexecdir}/ FILES_${PN} += "${sysconfdir}/default/volatiles" FILES_${PN}-mths = "${sysconfdir}/defaults-mths.tar.gz" +FILES_${PN}-wifi-bt-ap = "/usr/share/config-wifi-bt-ap" # Create the hotspot version of defaults.tar.gz pkg_postinst_${PN}-mths() { @@ -93,3 +107,53 @@ pkg_postinst_${PN}-mths() { # Comment out the final line for a trace. rm -rf $X } + + +pkg_postinst_${PN}-wifi-bt-ap() { + US="$D/usr/share/config-wifi-bt-ap" + ND="$D/etc/network" + mkdir ${US}/old + cd /var/config + # Make a backup + tar -T ${US}/backup.list.txt -cf $D/var/config/var-config-wifi-bt-ap-bkup.tar.gz + # Add new interfaces + if ! grep "^auto wifi1$" ${ND}/interfaces ; then + echo >>${ND}/interfaces + cat $US/wifi1.append >>${ND}/interfaces + fi + if ! grep "^auto pan0$" ${ND}/interfaces ; then + echo >>${ND}/interfaces + cat $US/pan0.append >>${ND}/interfaces + fi + + # Copy other files into place + cp -a ${US}/var/config /var + + # Record files we created + md5sum $(cat ${US}/backup.list.txt) >$D/var/config/bkup-wifi-bt-ap.md5 + + # Restart daemons + /etc/init.d/dnsmasq stop + /etc/init.d/bt-pan stop + /etc/init.d/bluetooth stop + /etc/init.d/hostapd stop + /etc/init.d/rs9113 stop + /etc/init.d/rs9113 start + /etc/init.d/bluetooth start + /etc/init.d/hostapd start + /etc/init.d/bt-pan start + /etc/init.d/dnsmasq start +} + +pkg_prerm_${PN}-wifi-bt-ap() { + cd /var/config + if md5sum -c $D/var/config/bkup-wifi-bt-ap.md5 ; then + if [ -f $D/var/config/var-config-wifi-bt-ap-bkup.tar.gz ] ; then + tar -xf $D/var/config/var-config-wifi-bt-ap-bkup.tar.gz + else + echo Cannot restore anything because backup is missing + fi + else + echo 'Cannot restore old configuration, because it has changed since the backup' + fi +} -- cgit v1.2.3