[OpenWrt-Devel] [PATCH 1/2] [packages] add support for Huawei NCM modems
Maarten Deprez
deprez.maarten at gmail.com
Sat Mar 28 16:28:50 EDT 2015
Adds support for Huawei NCM modems, which expect ndisdup commands at a
separate cdc-wdm device, supported by kmod-usb-net-huawei-cdc-ncm.
This builds on the work of Oskari Rauta at
https://sites.google.com/site/variousopenwrt/huawei-e3267 . In
particular, i added a lot of resilience. It has provided me with a
stable connection on Huawei E303 and E398 modems during the last few
months.
Signed-off-by: Maarten Deprez <deprez.maarten at gmail.com>
diff --git a/net/huawei-ncm/Makefile b/net/huawei-ncm/Makefile
new file mode 100644
index 0000000..27a0bcc
--- /dev/null
+++ b/net/huawei-ncm/Makefile
@@ -0,0 +1,52 @@
+#
+# Copyright (C) 2015 Maarten Deprez <deprez.maarten at gmail.com
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=huawei-ncm
+PKG_VERSION:=1
+PKG_RELEASE:=0
+PKG_LICENSE:=GPLv2
+
+PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/huawei-ncm
+ SECTION:=net
+ CATEGORY:=Network
+ DEPENDS:=+kmod-usb-net-huawei-cdc-ncm
+ TITLE:=Huawei NCM protocol
+ PKGARCH:=all
+ MAINTAINER:=Maarten Deprez <deprez.maarten at gmail.com>
+endef
+
+define Package/huawei-ncm/description
+ Protocol scripts to make and maintain connections to 3G/4G networks
over huawei NCM modems
+endef
+
+define Build/Prepare
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+endef
+
+define Package/huawei-ncm/install
+ $(INSTALL_DIR) $(1)/lib/netifd/proto
+ $(INSTALL_BIN) ./files/lib/netifd/proto/huawei_ncm.sh
$(1)/lib/netifd/proto/huawei_ncm.sh
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) ./files/usr/bin/* $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) ./files/usr/sbin/* $(1)/usr/sbin/
+ $(INSTALL_DIR) $(1)/usr/lib/huawei-ncm
+ $(INSTALL_DATA) ./files/usr/lib/huawei-ncm/*.sh $(1)/usr/lib/huawei-ncm/
+endef
+
+$(eval $(call BuildPackage,huawei-ncm))
diff --git a/net/huawei-ncm/files/lib/netifd/proto/huawei_ncm.sh
b/net/huawei-ncm/files/lib/netifd/proto/huawei_ncm.sh
new file mode 100755
index 0000000..a75880c
--- /dev/null
+++ b/net/huawei-ncm/files/lib/netifd/proto/huawei_ncm.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+
+. /lib/functions.sh
+. ../netifd-proto.sh
+init_proto "$@"
+
+proto_huawei_ncm_init_config() {
+ renew_handler=1
+
+ proto_config_add_string 'pin'
+ proto_config_add_string 'apn'
+ proto_config_add_string 'mode'
+ proto_config_add_string 'freq'
+ proto_config_add_string 'timeout'
+ proto_config_add_string 'interval'
+}
+
+proto_huawei_ncm_setup() {
+ local config="$1"
+ local iface="$2"
+
+ local pin apn mode freq timeout interval
+ json_get_vars pin apn mode freq timeout interval
+
+ proto_export "INTERFACE=$config"
+ proto_run_command "$config" /usr/sbin/huawei-ncm-connect -vvv \
+ -p /var/run/huawei-ncm-$iface.pid \
+ -s /lib/netifd/dhcp.script \
+ -m "${mode:-2,0}" \
+ -f "${freq:-0}" \
+ -n "$pin" \
+ -t "${timeout:-15}" \
+ -i "${interval:-60}" \
+ "$iface" \
+ "$apn"
+
+}
+
+proto_huawei_ncm_renew() {
+ local config="$1"
+ proto_kill_command "$config" SIGHUP
+}
+
+proto_huawei_ncm_teardown() {
+ local config="$1"
+ proto_kill_command "$config"
+}
+
+add_protocol huawei_ncm
diff --git a/net/huawei-ncm/files/usr/bin/huawei-ncm-cells
b/net/huawei-ncm/files/usr/bin/huawei-ncm-cells
new file mode 100755
index 0000000..9443a96
--- /dev/null
+++ b/net/huawei-ncm/files/usr/bin/huawei-ncm-cells
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+VERBOSITY=1
+IFACE="$1"
+
+
+### includes
+
+. /usr/lib/huawei-ncm/error.sh
+. /usr/lib/huawei-ncm/find-modem.sh
+. /usr/lib/huawei-ncm/modem.sh
+
+
+### find and init modem
+
+find_modem
+MODEM="$PCUI"
+init_modem
+
+m=$(modem '^CELLINFO=?') || exit $?
+
+for i in $(echo "$m" | sed -e 's/[()]//g' -e 's/,/\n/g'); do
+
+ n="$(modem "^CELLINFO=$i"
'^[0-9]\+,[0-9]\+,-[0-9]\+,-[0-9]\+$')" || exit $?
+
+ [ -n "$n" ] || continue
+
+ printf '%s [%d dBm / %d dBm]\n' \
+ "$(echo "$n" | cut -d, -f1)" \
+ "$(echo "$n" | cut -d, -f3)" \
+ "$(echo "$n" | cut -d, -f4)"
+
+done
diff --git a/net/huawei-ncm/files/usr/bin/huawei-ncm-info
b/net/huawei-ncm/files/usr/bin/huawei-ncm-info
new file mode 100755
index 0000000..1b358cd
--- /dev/null
+++ b/net/huawei-ncm/files/usr/bin/huawei-ncm-info
@@ -0,0 +1,116 @@
+#!/bin/sh
+
+VERBOSITY=1
+IFACE="$1"
+
+
+### includes
+
+. /usr/lib/huawei-ncm/error.sh
+. /usr/lib/huawei-ncm/find-modem.sh
+. /usr/lib/huawei-ncm/modem.sh
+
+
+### find and init modem
+
+find_modem
+init_modem "$PCUI"
+
+
+### product information
+
+modem I . |
+while read i; do
+
+ case "$i" in
+ Manufacturer:*)
+ echo -n "vendor ";;
+ Model:*)
+ echo -n "model ";;
+ Revision:*)
+ echo -n "firmware ";;
+ IMEI:*)
+ echo -n "imei ";;
+ *) continue;;
+ esac
+
+ echo "$i" | sed 's/^[^:]*: //'
+
+done
+
+
+### network
+
+m="$(modem '+COPS?')" || exit $?
+echo -n "provider "
+echo "$m" | cut -d, -f3 | sed 's/"//g'
+
+
+### mode
+
+m="$(modem '^SYSCFG?')" || exit $?
+echo -n "mode "
+
+case "$(echo "$m" | cut -d, -f1,2)" in
+ 2,0) echo "Auto";;
+ 2,1) echo "GSM, WCDMA";;
+ 2,2) echo "WCDMA, GSM";;
+ 13,*) echo "GSM";;
+ 14,*) echo "WCDMA";;
+ *) echo "Unknown";;
+esac
+
+
+### data bandwidth
+
+m="$(modem '+CGEQNEG=1')" || exit $?
+printf "uplink %s kbps\n" "$(echo "$m" | cut -d, -f3)"
+printf "downlink %s kbps\n" "$(echo "$m" | cut -d, -f4)"
+
+
+### frequency lock
+
+m="$(modem '^FREQLOCK?')" || exit $?
+echo -n "freqlock "
+echo "$m" | cut -d, -f2
+
+
+### cell
+
+modem '+CREG=2'
+m="$(modem '+CREG?')" || exit $?
+i="$(echo "$m" | cut -d, -f3 | sed 's/"//g')"
+[ -n "$i" ] && printf "lac 0x%x (%d)\n" $((0x$i)) $((0x$i))
+i="$(echo "$m" | cut -d, -f4 | sed 's/"//g')"
+[ -n "$i" ] && printf "ci 0x%x (%d)\n" $((0x$i)) $((0x$i))
+
+
+### cell info
+
+if m="$(modem '^CELLINFO=0' '^[0-9]\+,[0-9]\+,-[0-9]\+,-[0-9]\+$')"; then
+ echo -n "freq "
+ echo "$m" | cut -d, -f1
+fi
+
+
+### network technology
+
+#m="$(modem '^SYSINFOEX')" || exit $?
+#printf "network %s / %s\n" \
+# "$(echo "$m" | cut -d, -f7 | sed 's/"//g')" \
+# "$(echo "$m" | cut -d, -f9 | sed 's/"//g')"
+
+
+### reception: csq / rssi
+
+m="$(modem '+CSQ')" || exit $?
+i="$(echo "$m" | cut -d, -f1)"
+[ -n "$i" ] && printf "signal %d%% (%d / 31)\n" $((($i * 100 + 16) / 31)) $i
+[ -n "$i" ] && printf "rssi %d dBm\n" $(($i * 2 - 113))
+
+
+### reception: rcsp / ecio
+
+m="$(modem '^CSNR?')" || exit $?
+printf "rcsp %d dBm\n" "$(echo "$m" | cut -d, -f1)"
+printf "ecio %d dBm\n" "$(echo "$m" | cut -d, -f2)"
diff --git a/net/huawei-ncm/files/usr/lib/huawei-ncm/error.sh
b/net/huawei-ncm/files/usr/lib/huawei-ncm/error.sh
new file mode 100644
index 0000000..9affe46
--- /dev/null
+++ b/net/huawei-ncm/files/usr/lib/huawei-ncm/error.sh
@@ -0,0 +1,14 @@
+### error function
+
+VERBOSITY="${VERBOSITY:-1}"
+
+error () {
+ [ $VERBOSITY -ge 1 ] && echo "$@" >&2
+ exit 1
+}
+
+vecho () {
+ v=$1; shift
+ [ $VERBOSITY -ge $v ] &&
+ echo "$@" >&2
+}
diff --git a/net/huawei-ncm/files/usr/lib/huawei-ncm/find-modem.sh
b/net/huawei-ncm/files/usr/lib/huawei-ncm/find-modem.sh
new file mode 100644
index 0000000..b06df97
--- /dev/null
+++ b/net/huawei-ncm/files/usr/lib/huawei-ncm/find-modem.sh
@@ -0,0 +1,223 @@
+#include error.sh
+
+### load module with checking
+
+# load_module (module, [timeout])
+
+load_module () {
+
+ vecho 2 -n "Loading $1 module... "
+
+ local t=0
+
+ while ! [ -d "/sys/module/$1" ]; do
+
+ if ! [ $((t++)) -lt ${2:-3} ]; then
+ vecho 2 "timeout!" || vecho 1 "timeout loading $1 module"
+ return 1
+ fi
+
+ if ! modprobe "$1"; then
+ vecho 2 "failed!" || vecho 1 "unable to load $1 module"
+ return 1
+ fi
+
+ sleep 1
+
+ done
+
+ vecho 2 "ok!"
+ return 0
+
+}
+
+
+### find huawei modem device
+
+# is_huawei_modem (iface)
+is_huawei_modem () {
+ [ "$(basename "$(readlink "/sys/class/net/$1/device/driver")")" =
huawei_cdc_ncm ]
+}
+
+# find_modem_iface ([iface], [timeout])
+find_modem_iface () {
+
+ vecho 2 -n "Looking for huawei-cdc-ncm modem... "
+
+ local i t=0
+
+ while true; do
+
+ for i in $([ -n "$1" ] && echo "$1" || ls /sys/class/net); do
+ is_huawei_modem "$i" || continue
+ IFACE="$i"; break 2
+ done
+
+ if ! [ $((t++)) -lt ${2:-5} ]; then
+ vecho 2 "failed" || vecho 1 "no huawei-cdc-ncm modem found"
+ return 1
+ fi
+
+ sleep 1
+
+ done
+
+ usbpath="$(readlink -f "/sys/class/net/$IFACE/device")"
+
+ vecho 2 "ok!"
+ return 0
+
+}
+
+
+### find interfaces
+# use AT^SETPORT="FF;1,16,3,2" and restart
+# to enable (only) necessary interfaces
+
+check_interfaces () {
+ [ -c "$MODEM" -a -c "$PCUI" -a -c "$WDM" ]
+}
+
+find_interfaces () {
+
+ vecho 2 -n "Enumerating interfaces on $IFACE... "
+
+ local i
+
+ unset MODEM PCUI DIAG WDM
+
+ for i in /sys/class/net/"$IFACE"/device/../*:*; do
+ case $(cat "$i"/bInterfaceProtocol) in
+ 01) MODEM="/dev/$(basename "$i"/tty*)";;
+ 02) PCUI="/dev/$(basename "$i"/tty*)";;
+ 03) DIAG="/dev/$(basename "$i"/tty*)";;
+ 16) WDM="/dev/$(basename "$i/usbmisc"/*)";;
+ esac
+ done
+
+
+ # check if necessary interfaces are present
+
+ if ! check_interfaces; then
+ vecho 1 "missing interfaces from $IFACE:" \
+ "$( [ -c "$MODEM" ] || echo modem )" \
+ "$( [ -c "$PCUI" ] || echo pcui )" \
+ "$( [ -c "$WDM" ] || echo wdm )"
+ return 1
+ fi
+
+ vecho 2 "ok!"
+ return 0
+
+}
+
+
+### usb connection path
+
+cumpath () {
+
+ local p i
+
+ read p
+
+ while read i; do
+ p="$p/$i"
+ echo "$i" | grep -qx "$1" &&
+ echo "$p"
+ done
+
+}
+
+usb_path () {
+ echo "$1" | sed -e 's@\(^.*/usb[0-9]\+\|[^/]\+\)/@\1\n at g' |
+ cumpath '[0-9.-]\+'
+}
+
+
+### reset last usb hub in path
+
+usbpath=
+
+reset_usb () {
+
+ [ -x /usr/bin/usbreset ] || return 1
+ [ -n "$usbpath" ] || return 1
+
+ local dev i
+
+ vecho 2 -n "Trying to recover usb connectivity... "
+
+ usb_path "$usbpath" | tac |
+
+ while read i; do
+
+ vecho 3 -n "($(basename "$i")) "
+
+ [ -d "$i" ] || continue
+ [ -f "$i/busnum" -a -f "$i/devnum" ] || continue
+
+ dev=$(printf '%03d/%03d\n' $(cat "$i/busnum") $(cat "$i/devnum"))
+ vecho 3 -n "--> [$dev] "
+
+ usbreset $dev || break
+
+ vecho 2 "ok!"
+ return 0
+
+ done
+
+ vecho 2 "failed!"
+ return 1
+
+}
+
+
+### reset modem device
+
+reset_modem () {
+
+ [ -c "$MODEM" ] || return 1
+
+ vecho 2 -n "Resetting modem $IFACE... "
+
+ echo -en "AT+CFUN=4\r\n" > "$MODEM"
+ sleep 1
+ echo -en "AT+CFUN=6,0\r\n" > "$MODEM"
+
+ vecho 2 "ok!"
+ return 0
+
+}
+
+
+### find modem
+
+iface="$IFACE"
+
+find_modem () {
+ find_modem_iface "$iface" "${1:-10}" &&
+ find_interfaces
+}
+
+
+### find modem with resilience
+
+find_modem_hard () {
+
+ local t=0
+
+ load_module huawei_cdc_ncm || return 1
+
+ while true; do
+
+ find_modem ${1:-30} && return 0
+
+ [ $((t++)) -lt 2 ] || return 1
+
+ reset_modem ||
+ #reset_usb ||
+ return 1
+
+ done
+
+}
diff --git a/net/huawei-ncm/files/usr/lib/huawei-ncm/modem.sh
b/net/huawei-ncm/files/usr/lib/huawei-ncm/modem.sh
new file mode 100644
index 0000000..0cba57c
--- /dev/null
+++ b/net/huawei-ncm/files/usr/lib/huawei-ncm/modem.sh
@@ -0,0 +1,70 @@
+#include error.sh
+
+### open modem device
+
+modem=
+
+init_modem () {
+ local m="${1:-$MODEM}"
+ [ -c "$m" ] || error "modem $m does not exist"
+ [ $VERBOSITY -ge 4 ] && echo "Opening modem $m" >&2
+ exec 5<> "$m" || error "failed to open modem: $m"
+ echo -en 'ATE0\r\n' >&5
+ while read -rt1 -u5 i; do true; done
+ modem="$m"
+}
+
+
+### send command and read response
+
+modem() {
+
+ [ -n "$modem" ] || error "modem not initialized"
+
+ echo -en "AT$1\r\n" >&5
+
+ if [ -n "$2" ]; then
+ match="$2"
+ select=
+ else
+ match="^$(echo "$1" | grep -o "^\W\w\+"):"
+ select='s/^.*: *//'
+ fi
+
+ err=timeout; t0=$(($(date +%s)+10))
+ while [ $((t=t0-$(date +%s))) -gt 0 ] && read -r -t$t -u5 i; do
+
+ i="$(echo "$i" | sed 's/\r$//')"
+
+ vecho 4 "modem: $1: $i" >&2
+
+ #echo "$i" | grep -q "^AT" && continue
+
+ if echo "$i" | grep -q '^OK'; then
+ err=; break
+ fi
+
+ if echo "$i" | grep -q '^ERROR'; then
+ err="command error"; break
+ fi
+
+ if echo "$i" | grep -q '^CME ERROR:'; then
+ err="cme error ${i#*:}"; break
+ fi
+
+ if echo "$i" | grep -q "$match"; then
+ echo "$i" | sed "$select"
+ continue
+ fi
+
+ n=$((n+1))
+
+ done
+
+ if [ -n "$err" ]; then
+ vecho 1 "modem error: $1: $err" >&2
+ return 1
+ fi
+
+ return 0
+}
diff --git a/net/huawei-ncm/files/usr/sbin/huawei-ncm-connect
b/net/huawei-ncm/files/usr/sbin/huawei-ncm-connect
new file mode 100755
index 0000000..90f8152
--- /dev/null
+++ b/net/huawei-ncm/files/usr/sbin/huawei-ncm-connect
@@ -0,0 +1,367 @@
+#!/bin/sh
+
+
+### error handling and logging
+
+. /usr/lib/huawei-ncm/error.sh
+
+
+### interrupt handlers
+
+int=
+run=1
+renew=
+connection=0
+
+sleep=
+
+wsleep () {
+ sleep "$@" & sleep=$!
+ wait $sleep; sleep=
+ [ -n "$run" ]
+}
+
+trap 'run=; [ -n "$sleep" ] && kill $sleep; vecho 2 "interrupt!"' TERM
+trap 'renew=1; [ -n "$sleep" ] && kill $sleep; vecho 2 "renew!"' HUP
+trap 'kill -TERM $$; int=1' INT
+trap '[ -n "$PID" ] && rm -f "$PID"' EXIT
+
+
+### check arguments
+
+PID=
+PIN=
+MODE=
+FREQ=
+SCRIPT=/lib/netifd/dhcp.script
+TIMEOUT=15
+INTERVAL=60
+VERBOSITY=1
+
+usage () {
+
+ if [ $VERBOSITY -ge 1 ]; then
+ echo "Usage: $0 [ options ] <interface> <apn>" >&2
+ echo "Options:" >&2
+ echo " -p <pidfile> save PID in <pidfile>" >&2
+ echo " -m <mode> set modem to network <mode>" >&2
+ echo " -f <freq> lock frequency to <freq>" >&2
+ echo " -n <pin> pin code of the card" >&2
+ echo " -s <script> use <script> as DHCP script" >&2
+ echo " -t <timeout> time to wait for network and data
connection" >&2
+ echo " -i <interval> connection checking interval" >&2
+ fi
+
+ exit 2
+}
+
+while getopts ":p:m:f:n:s:t:i:qvh" i; do
+ case $i in
+ p) PID="$OPTARG";;
+ m) MODE="$OPTARG";;
+ f) FREQ="$OPTARG";;
+ n) PIN="$OPTARG";;
+ s) SCRIPT="$OPTARG";;
+ t) TIMEOUT="$OPTARG";;
+ i) INTERVAL="$OPTARG";;
+ q) VERBOSITY=$((VERBOSITY-1));;
+ v) VERBOSITY=$((VERBOSITY+1));;
+ h) usage;;
+ ?) vecho 1 "Invalid option: -$OPTARG"; usage;;
+ :) vecho 1 "Option -$OPTARG needs an argument"; usage;;
+ esac
+done
+
+shift $(($OPTIND-1))
+
+if [ $# -ne 2 ]; then
+ vecho 1 "Expecting two arguments"
+ usage
+fi
+
+IFACE="$1"
+APN="$2"
+
+
+### save pid
+
+if [ -n "$PID" ]; then
+ echo $$ > "$PID"
+fi
+
+
+### include modem functions
+
+. /usr/lib/huawei-ncm/find-modem.sh
+. /usr/lib/huawei-ncm/modem.sh
+
+
+### check pin state
+
+check_pin () {
+
+ vecho 2 -n "Checking PIN... "
+
+ m="$(modem '^CPIN?')" || exit $?
+ pin="$(echo "$m" | cut -d, -f1)"
+ times="$(echo "$m" | cut -d, -f2)"
+
+ case "$pin" in
+
+ READY)
+ vecho 2 "ok!"
+ ;;
+
+ SIM\ PIN)
+
+ ### don't try to unlock in face of failed tries
+ if [ "$times" != 3 ]; then
+ vecho 1 "SIM card locked with non-virgin 'times'
record; won't try to unlock"
+ exit 1
+ fi
+
+ ### check if PIN was given
+ if [ -z "$PIN" ]; then
+ vecho 1 "SIM card locked but no PIN specified"
+ exit 1
+ fi
+
+
+ ### try to unlock
+
+ modem "^CPIN=\"$PIN\"" || exit $?
+
+ ;;
+
+ *)
+ vecho 1 "SIM card locked with $pin code ($m)"
+ exit 1
+ ;;
+ esac
+}
+
+### set mode if requested
+
+set_mode () {
+
+ [ -z "$MODE" ] && return
+
+ vecho 2 -n "Setting mode... "
+
+ ### default: no change
+ mode=16,3
+
+ ### calculate mode
+
+ case "$MODE" in
+ gsm) mode=13,0 ;;
+ wcdma) mode=14,0 ;;
+ gsmfirst) mode=2,1 ;;
+ wcdmafirst) mode=2,2 ;;
+ auto) mode=2,0 ;;
+ esac
+
+ ### set mode
+ modem "^SYSCFG=$mode,3fffffff,2,4" || exit $?
+
+ vecho 2 "ok!"
+}
+
+
+### lock to frequency if requested
+
+lock_frequency () {
+
+ [ -n "$FREQ" ] || return 0
+
+ vecho 2 -n "Locking frequency... "
+
+ if [ "$FREQ" = "0" ]; then
+ modem "^FREQLOCK=0" || exit $?
+ else
+ modem "^FREQLOCK=1,$FREQ" || exit $?
+ fi
+
+ vecho 2 "ok!"
+ return 0
+
+}
+
+
+### wait for network registration
+
+register () {
+
+ vecho 2 -n "Waiting for network... "
+
+ for i in $(seq "$TIMEOUT"); do
+ stat="$(modem '+CREG?' | cut -d, -f2)" || exit $?
+ [ "$stat" == 1 ] && break
+ wsleep 1 || return 1
+ vecho 2 -en "\b. "
+ done
+
+ if [ "$stat" != 1 ]; then
+ vecho 2 "timeout" || vecho 1 "timeout while waiting for network"
+ return 1
+ fi
+
+ vecho 2 "ok!"
+ return 0
+}
+
+
+### check +CGPADDR response
+is_connected () {
+ [ -n "$1" -a "$1" != '"0.0.0.0"' ]
+}
+
+
+### establish data connection
+
+connect () {
+
+ vecho 2 -n "Establishing data connection... "
+
+ echo -en "AT^NDISDUP=1,1,\"$APN\"\r\n" > "$WDM"
+ connection=1
+
+ for i in $(seq "$TIMEOUT"); do
+ ip="$(modem '+CGPADDR=1' | cut -d, -f2)" || exit $?
+ is_connected "$ip" && break
+ wsleep 1 || return 1
+ vecho 2 -en "\b. "
+ done
+
+ if ! is_connected "$ip"; then
+ vecho 2 "timeout" || vecho 1 "timeout waiting for data connection"
+ return 1
+ fi
+
+ vecho 2 "ok"
+ return 0
+
+}
+
+
+### request address
+
+dhcp () {
+
+ vecho 2 -n "Running udhcpc... "
+
+ ifconfig "$IFACE" up &&
+ udhcpc -i "$IFACE" -s "$SCRIPT" -f -t 0 -q
+
+ [ -n "$run" ] || return 1
+
+ if [ $? -gt 0 ]; then
+ vecho 1 "failed to get ip address"
+ return 1
+ fi
+
+ connection=2
+ vecho 2 "ok"
+ return 0
+
+}
+
+### take a break
+
+nap () {
+
+ ### sleep...
+
+ vecho 3 -n "Taking a nap... "
+
+ wsleep "$INTERVAL" || return 1
+ [ -z "$renew" ] || return 1
+
+ vecho 3 "wake up"
+ return 0
+
+}
+
+
+### check connection
+check () {
+
+ [ $connection -ne 2 ] && return 1
+
+ vecho 3 -n "Checking connection... "
+
+ ip="$(modem '+CGPADDR=1' | cut -d, -f2)" || exit $?
+
+ if ! is_connected "$ip"; then
+ connection=0
+ vecho 2 "lost connection"
+ return 1
+ fi
+
+ vecho 3 "ok!"
+ return 0
+
+}
+
+### disconnect
+
+disconnect () {
+
+ [ $connection -ge 1 ] || return
+
+ vecho 2 -n "Disconnecting... "
+
+ echo -en "AT^NDISDUP=1,0\r\n" > "$WDM"
+
+ for i in $(seq "$TIMEOUT"); do
+ ip="$(modem '+CGPADDR=1' | cut -d, -f2)" || exit $?
+ [ -z "$ip" ] && break
+ wsleep 1
+ vecho 2 -en "\b. "
+ done
+
+ if [ -n "$ip" ]; then
+ vecho 2 "timeout" || vecho 1 "timeout waiting for disconnection"
+ return 1
+ fi
+
+ vecho 1 "disconnected"
+ connection=0
+ return 0
+
+}
+
+
+### connection loop
+
+while [ -n "$run" ]; do
+
+ if ! find_modem_hard; then
+ vecho 1 "Couldn't find modem; sleeping 10 minutes"
+ wsleep 600
+ continue
+ fi
+
+ init_modem
+
+ check_pin
+ set_mode
+ lock_frequency
+
+ register &&
+ connect &&
+ dhcp
+
+ renew=
+ while [ -n "$run" ]; do
+ nap && check || break
+ done
+
+ check_interfaces &&
+ disconnect
+
+done
+
+if [ -n "$int" ]; then
+ kill -INT -$$
+fi
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
More information about the openwrt-devel
mailing list