From 41ea0df456cc09bcc701d1ea783975d82dc56ad5 Mon Sep 17 00:00:00 2001 From: John Klug Date: Tue, 21 Dec 2021 11:17:53 -0600 Subject: AT&T Data-Only Requirements --- recipes-connectivity/ppp/files/init.patch | 10 +- recipes-connectivity/ppp/files/wait_for_reset | 45 ----- recipes-connectivity/ppp/ppp_%.bbappend | 13 +- recipes-core/multitech/config/chat_wrapper | 258 ++++++++++++++++++++------ 4 files changed, 212 insertions(+), 114 deletions(-) delete mode 100755 recipes-connectivity/ppp/files/wait_for_reset diff --git a/recipes-connectivity/ppp/files/init.patch b/recipes-connectivity/ppp/files/init.patch index 00ae09a..333c428 100644 --- a/recipes-connectivity/ppp/files/init.patch +++ b/recipes-connectivity/ppp/files/init.patch @@ -7,9 +7,9 @@ diff -Naru orig/init new/init . /etc/init.d/functions +. /etc/default/ppp +if [[ $RADIORESETWAIT == yes ]] ; then -+ . /usr/libexec/ppp/wait_for_reset ++ WAITFORRESET=/usr/bin/mts-wait-for-cell-reset +else -+ function wait_for_reset { :; } ++ WAITFORRESET=":" +fi + +mkdir -p /run/ppp || true @@ -21,7 +21,7 @@ diff -Naru orig/init new/init case "$1" in start) echo -n "Starting up PPP link: pppd" -+ wait_for_reset ++ ${WAITFORRESET} if [ "$RUNFILE" = "1" ]; then + logger "ppp_on_boot" /etc/ppp/ppp_on_boot @@ -35,13 +35,13 @@ diff -Naru orig/init new/init + if [ "$RUNFILE" = "1" ]; then poff sleep 5 -+ wait_for_reset ++ ${WAITFORRESET} /etc/ppp/ppp_on_boot - else + else poff provider sleep 5 -+ wait_for_reset ++ ${WAITFORRESET} pppd call provider fi echo "." diff --git a/recipes-connectivity/ppp/files/wait_for_reset b/recipes-connectivity/ppp/files/wait_for_reset deleted file mode 100755 index e77df77..0000000 --- a/recipes-connectivity/ppp/files/wait_for_reset +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash - -# For ppp to work, stty must work on file descriptor 0. -# If stty fails, so will ppp. - -NAME=wait_for_reset - -: ${LOG:="/usr/bin/logger -t ${NAME} -p daemon.notice"} - -USR2=12 -TERM=15 -# Child used to set our PID in the radio-reset-monitor -function sleep_reset -{ - # Wait for parent to enter wait. - trap "exit 0" $TERM - while [[ $(ps -h -o wchan -p $PPID) != do_wait ]] ; do usleep 100 ; done - ${LOG} Register for SIGUSR2 when radio-reset complete - echo "$$" "$USR2" >/sys/devices/platform/mts-io/radio-reset-monitor - discovered=$(cat /sys/devices/platform/mts-io/radio-udev-discovery) - if ((discovered == 1)) ; then - # reset is not in progress. - exit 0 - fi - sleep 4294967295 # Hopefully forever - exit 0 -} - -# Wait for radio-reset to complete -function wait_for_reset -{ - # Wait for radio reset/modem discovery - trap ":" $USR2 - in_reset=$(cat /sys/devices/platform/mts-io/radio-udev-discovery) - if ((in_reset == 0)) ; then - sleep_reset & - wait $! - # pgrep is needed to find the sleep process - echo "pgrep -P: $(pgrep -P $!)" - pgrep -P $! | xargs kill - ${LOG} "radio-reset is complete" - fi - echo "$$" "0" >/sys/devices/platform/mts-io/radio-reset-monitor - trap "" $USR2 -} diff --git a/recipes-connectivity/ppp/ppp_%.bbappend b/recipes-connectivity/ppp/ppp_%.bbappend index fafe176..0a7e818 100644 --- a/recipes-connectivity/ppp/ppp_%.bbappend +++ b/recipes-connectivity/ppp/ppp_%.bbappend @@ -10,16 +10,11 @@ SRC_URI_append = "\ file://init.patch;patchdir=.. \ file://default.patch;patchdir=.. \ file://poff.patch;patchdir=.. \ - file://wait_for_reset \ file://default" PR = "r12" -PACKAGES =+ "${PN}-radioresetwait ${PN}-waitforresetfunc" -FILES_${PN}-waitforresetfunc = "${libexecdir}/ppp/wait_for_reset" - -RDEPENDS_${PN}-radioresetwait += "${PN}-waitforresetfunc" -RDEPENDS_${PN}-waitforresetfunc += "bash" +PACKAGES =+ "${PN}-radioresetwait" ALLOW_EMPTY_${PN}-radioresetwait = "1" @@ -29,10 +24,8 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/files:" CONFFILES_${PN} += "${sysconfdir}/init.d/ppp" do_install_append() { - install -d -m 755 ${D}/${sysconfdir}/default/ - install -m 644 ${WORKDIR}/default ${D}/${sysconfdir}/default/ppp - install -d -m 755 ${D}/${libexecdir}/ppp - install -m 755 ${WORKDIR}/wait_for_reset ${D}/${libexecdir}/ppp/wait_for_reset + install -d -m 755 ${D}/${sysconfdir}/default/ + install -m 644 ${WORKDIR}/default ${D}/${sysconfdir}/default/ppp } pkg_postinst_${PN}-radioresetwait() { diff --git a/recipes-core/multitech/config/chat_wrapper b/recipes-core/multitech/config/chat_wrapper index a693661..42e7507 100755 --- a/recipes-core/multitech/config/chat_wrapper +++ b/recipes-core/multitech/config/chat_wrapper @@ -22,7 +22,6 @@ # 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. -. /usr/libexec/ppp/wait_for_reset NAME=chat_wrapper CONFIG=/etc/default/${NAME} @@ -31,30 +30,7 @@ RQCMD="/usr/bin/radio-query ${RADIOOPTION}" : ${LOG:="/usr/bin/logger -t ${NAME} -p daemon.notice"} -function finish -{ - ${LOG} "Launch:" "$@" - 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 -{ - id="^[0-9][0-9][0-9][0-9][0-9][0-9]" - if ! log=$(stty 2>&1) || ! [[ $($RQCMD --iccid) =~ $id ]] ; then - ${LOG} "Modem has response issues, so see if we can try again" - if ((${#log} > 0)); then - ${LOG} "stty error: ${log}" - fi - array=( ) +function do_radio_reset { # our parent is PPID, which is pppd. Get the pppd # parameter list. while IFS= read -r -d '' eparm; do @@ -69,38 +45,30 @@ function sanity 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" - ${LOG} "Failure: Verify that modem and SIM are in place" - rm -f ${CHAT_WRAPPER_RECURSION} - exit 1 - fi - touch ${CHAT_WRAPPER_RECURSION} - ${LOG} "Bad TTY, possibly due to modem in bad state/no SIM detected" - ${LOG} "Reset modem, and we relaunch pppd" + # No returning from this function. pppd will be + # restarted by us. # 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 - wait_for_reset - ${LOG} "Completed wait_for_reset" + /usr/bin/mts-wait-for-cell-reset + ${LOG} "Completed mts-wait-for-cell-reset" count=0 while ((count < 60)) ; do + ((count++)) # Wait for radio-reset to get the modem responding - if [[ $(radio-cmd -t10000 'AT') =~ ^OK ]]; then + if [[ $(radio-cmd ${RADIOOPTION} -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) mypid="${mypid#"${mypid%%[![:space:]]*}"}" - mypid="${mypid%"${mypid##*[![:space:]]}"}" + mypid="${mypid%"${mypid##*[![:space:]]}"}" ${LOG} "PPID is $PPID, pid is $mypid" # Remove the lock, if it belongs to our parent, pppd + # or if it is empty. if ((${#mypid} == 0)) || [[ $mypid = $PPID ]] ; then ${LOG} "match $mypid $PPID" - sleep 60 rm -f $f else ${LOG} "mismatch |$mypid| |$PPID|" @@ -108,16 +76,181 @@ function sanity fi done # Locks gone, so start new pppd + ${LOG} "{$execarg[0]}" nohup "${execarg[@]}" >/dev/null 2>&1 & # Tell our parent we failed, which causes our pppd to terminate. exit 1 else - sleep 5 + sleep 1 fi done ${LOG} "ERROR: After five minutes the modem is still not ready" ${LOG} "ERROR: Verify that SIM is in place" exit 1 +} + + +function finish +{ + ${LOG} "Launch:" "$@" + exec "$@" + # NOTREACHED +} + +function set_telit_dataonly +{ + local result result1 mode cemode calldisa needreset + needreset=1 # 1 means no reset of cell modem (function exit status) + cemode=$(/usr/bin/radio-cmd ${RADIOOPTION} -t10000 'AT+CEMODE?' 2>&1) + result=$? + if ((result == 0)) ; then + if [[ $cemode =~ CEMODE:[[:space:]]*([0-9]+) ]] ; then + mode=${BASH_REMATCH[1]} + if ((${#mode} > 0)) && ((mode != 2)) ; then + ${LOG} "Attempting to set CEMODE to 2" + cemode1=$(/usr/bin/radio-cmd ${RADIOOPTION} -t10000 "AT+CEMODE=2" 2>&1) + result1=$? + needreset=0 + ${LOG} "radio-cmd AT+CEMODE=2 command yields $cemode1 with exit status $result1" + ${LOG} "Cellular modem will be reset after attmpted CEMODE change." + fi + else + ${LOG} "radio-cmd AT+CEMODE? command yields $cemode" + fi + else + ${LOG} "radio-cmd AT+CEMODE? command yields $cemode with exit status $result" + fi + + calldisa=$(/usr/bin/radio-cmd ${RADIOOPTION} -t10000 'AT#CALLDISA?' 2>&1) + result=$? + if ((result == 0)) ; then + if [[ $calldisa =~ CALLDISA:[[:space:]]*([0-9,]+) ]] ; then + mode=${BASH_REMATCH[1]} + if [[ ${mode} != 1,1 ]] ; then + ${LOG} "Attempting to set CALLDISA to 1,1" + cemode1=$(/usr/bin/radio-cmd ${RADIOOPTION} -t10000 "AT#CALLDISA=1,1" 2>&1) + result1=$? + needreset=0 + ${LOG} "radio-cmd AT+CALLDISA=1,1 command yields $cemode1 with exit status $result1" + ${LOG} "Cellular modem must be reset after attmpted calldisa change." + fi + else + ${LOG} "radio-cmd AT+CALLDISA? command yields $calldisa" + fi + else + ${LOG} "radio-cmd AT+CALLDISA? command yields $calldisa with exit status $result" + fi + return $needreset +} + +function set_quectel_dataonly +{ + local result result1 ue ims sms vc needreset + needreset=1 # 1 means no reset of cell modem (function exit status) + ue=$(radio-cmd ${RADIOOPTION} -t10000 'AT+QNVFR="/nv/item_files/modem/mmode/ue_usage_setting"' 2>&1) + result=$? + if ((result == 0)) ; then + if [[ $ue =~ QNVFR:[[:space:]]*([0-9]+)[[:space:]]+ ]] ; then + if [[ ${BASH_REMATCH[1]} != 01 ]] ; then + ${LOG} "Attempting to set ue usage to 01" + ue=$(radio-cmd ${RADIOOPTION} -t10000 'AT+QNVFW="/nv/item_files/modem/mmode/ue_usage_setting",01' 2>&1) + result1=$? + needreset=0 + ${LOG} "write ue_usage_setting yields $ue with exit status $result1" + fi + else + ${LOG} "read ue_usage_setting yields $ue" + fi + else + ${LOG} "read ue_usage_setting yields $ue with exit status $result" + fi + + ims=$(radio-cmd ${RADIOOPTION} -t10000 'AT+QNVFR="/nv/item_files/ims/IMS_enable"' 2>&1) + result=$? + if ((result == 0)) ; then + if [[ $ims =~ QNVFR:[[:space:]]*([0-9]+)[[:space:]]+ ]] ; then + if [[ ${BASH_REMATCH[1]} != 00 ]] ; then + ${LOG} "Attempting to set IMS_enable to 00" + ims=$(radio-cmd ${RADIOOPTION} -t10000 'AT+QNVFW="/nv/item_files/ims/IMS_enable",00' 2>&1) + result1=$? + needreset=0 + ${LOG} "write IMS_enable yields $ims with exit status $result1" + fi + else + ${LOG} "read IMS_enable yields $ims" + fi + else + ${LOG} "read IMS_enable yields $ims with exit status $result" + fi + + vc=$(radio-cmd ${RADIOOPTION} -t10000 'AT+QNVR=5280,0' 2>&1) + result=$? + if ((result == 0)) ; then + if [[ $vc =~ QNVR:[[:space:]]\"*([0-9]+)\" ]] ; then + if [[ ${BASH_REMATCH[1]} != 010102000000000000 ]] ; then + ${LOG} "Attempting to set sms to 01" + vc=$(radio-cmd ${RADIOOPTION} -t10000 'AT+QNVW=5280,0,"0102000000000000"' 2>&1) + result1=$? + needreset=0 + ${LOG} "voice turn off yields $vc with exit status $result1" + fi + else + ${LOG} "read voice state yields $vc" + fi + else + ${LOG} "read voice state yields $vc with exit status $result" + fi + + sms=$(radio-cmd ${RADIOOPTION} -t10000 'AT+QNVFR="/nv/item_files/modem/mmode/sms_only"' 2>&1) + result=$? + if ((result == 0)) ; then + if [[ $sms =~ QNVFR:[[:space:]]\"*([0-9]+) ]] ; then + if [[ ${BASH_REMATCH[1]} != 01 ]] ; then + ${LOG} "Attempting to set sms to 01" + sms=$(radio-cmd ${RADIOOPTION} -t10000 'AT+QNVFW="/nv/item_files/modem/mmode/sms_only",01' 2>&1) + result1=$? + needreset=0 + ${LOG} "sms turn on yields $sms with exit status $result1" + fi + else + ${LOG} "read sms state yields $sms" + fi + else + ${LOG} "read sms state yields $sms with exit status $result" + fi + + return $needreset +} + +# 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 +{ + id="^[0-9][0-9][0-9][0-9][0-9][0-9]" + if ! log=$(stty 2>&1) || ! [[ $($RQCMD --iccid) =~ $id ]] ; then + ${LOG} "Modem has response issues, so see if we can try again" + if ((${#log} > 0)); then + ${LOG} "stty error: ${log}" + fi + + # Break any recursion loop. + if [[ -f ${CHAT_WRAPPER_RECURSION} ]] ; then + ${LOG} "Failure: modem is still unresponsive after reset" + ${LOG} "Failure: Verify that modem and SIM are in place" + rm -f ${CHAT_WRAPPER_RECURSION} + exit 1 + fi + touch ${CHAT_WRAPPER_RECURSION} + ${LOG} "Bad TTY, possibly due to modem in bad state/no SIM detected" + ${LOG} "Reset modem, and we relaunch pppd" + + do_radio_reset fi return 0 } # End of sanity function @@ -127,7 +260,7 @@ WAITREG=0 [[ -f $CONFIG ]] || exit 1 -. ${CONFIG} +. ${CONFIG} : ${REGWAITTIME:=300} : ${FINALWAIT:=5} @@ -139,7 +272,7 @@ ${LOG} Timeout is $REGWAITTIME, execute "$@" # Wait for udev to discover modem has been reset. -wait_for_reset +/usr/bin/mts-wait-for-cell-reset ((i=$#)) chatscript="${!i}" @@ -172,12 +305,30 @@ if ((result1 != 0)) || ((${#cfun} == 0)) ; then sanity ((WAITREG++)) fi +# Must have a readable SIM in order to set DATA Mode +if ((SETATTDATAMODE == 1)) ; then + CARRIER=$($RQCMD --carrier 2>&1) + if [[ $CARRIER =~ ^AT\&T[[:space:]]+Wireless ]] ; then + MODEL=$($RQCMD --model 2>&1) + ${LOG} "Cellular modem is $MODEL" + if [[ ${MODEL} == EG25 ]] || [[ ${MODEL} == EG95 ]] ; then + if set_quectel_dataonly ; then + do_radio_reset + fi + else # Could be a problem when we add new Quectel models + if set_telit_dataonly ; then + do_radio_reset + fi + fi + fi +fi # Set ATT Data Mode + 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 +fi # Set CFUN=1 ${LOG} "Using Context ${CONTEXTNUM} based on chat script: ${CONTEXT}" @@ -192,11 +343,11 @@ if [[ $MCONTEXT =~ ^[Ee][Rr][Rr][Oo][Rr] ]] ; then MCONTEXT=$(/usr/bin/radio-cmd ${RADIOOPTION} -t10000 'AT+CGDCONT?' 2>&1 | tr -d '\r') CRESULT=$? fi - + if ! [[ $MCONTEXT =~ \+CGDCONT:[[:space:]]+${CONTEXTNUM},\"([^\"]*)\",\"([^\"]*)\",\"([^\"]*)\",([0-9]+),([0-9]+)([^$'\n']*) ]] ; then logger -s -p daemon.error "No valid context in modem. Is it ready?" echo "$MCONTEXT" | logger -s -p daemon.error - echo "Result is $CRESULT" | logger -s -p daemon.error + echo "Result is $CRESULT" | logger -s -p daemon.error if [[ $MCONTEXT =~ ^[Ee][Rr][Rr][Oo][Rr] ]] ; then logger -s -p daemon.error "Context query response error. Diagnose ..." sanity @@ -243,7 +394,7 @@ if [[ $MADDR != $ADDR ]] ; then ADDRMATCH=1 fi fi -fi +fi # Only update context on a mismatch between chat and modem. if [[ $MPDP != $PDP ]] || [[ $MAPN != $APN ]] || \ @@ -284,9 +435,9 @@ if [[ $MPDP != $PDP ]] || [[ $MAPN != $APN ]] || \ count=10 while ((count > 0)) && ! [[ $($RQCMD --netreg) =~ ^NOT\ REGISTERED$ ]] ; do sleep 2 - ((count--)) + ((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}" @@ -299,7 +450,7 @@ if [[ $MPDP != $PDP ]] || [[ $MAPN != $APN ]] || \ # If we fail to set the APN, sleep and try it again for up to 10 seconds. result=1 count=10 - while ((result != 0)) && ((count > 0)) ; do + while ((result != 0)) && ((count > 0)) ; do ((count--)) || true LOGMSG=$(/usr/bin/radio-cmd ${RADIOOPTION} -t10000 "${CMDSTR}" 2>&1) result=$? @@ -338,10 +489,9 @@ else cops=$(/usr/bin/radio-cmd ${RADIOOPTION} -t10000 'AT+COPS?') result0=$? - if ((result0 != 0)) || ! [[ $cops =~ ^\+COPS:[[:space:]]0[,[:space:]] ]] ; then + if ((result0 != 0)) || ! [[ $cops =~ ^\+COPS:\ 0, ]] ; then /usr/bin/radio-cmd ${RADIOOPTION} -t10000 'AT+COPS=0' ((WAITREG++)) - ${LOG} "Cops status was $cops" ${LOG} "Just set COPS=0 so wait ${COPSWAIT} seconds" sleep ${COPSWAIT} fi @@ -360,7 +510,7 @@ while ! [[ $($RQCMD --netreg) =~ ^(REGISTERED|ROAMING)$ ]] ; do if ((t1-t0 > REGWAITTIME)) ; then ${LOG} "$((t1-t0)) seconds has expired without registration" sanity - fi + fi done uptime=$(cat /proc/uptime) [[ $uptime =~ ^([^\.]*) ]] -- cgit v1.2.3