On 28.11.2013, at 17:46, Dirk Neukirchen <dirkneukirc...@web.de> wrote:

> 
> Shouldn't the patch be splitted because of different features?
> ( luci, non-luci stuff, hardware (huawai config))

Don't know - I originally built it for one single device, so for me - it is one 
package - which for others, I breaked into several packages and made modular 
for possible support of other devices that I at the moment cannot by myself 
support as I don't have them nor am going to get, unless my current device 
breaks and I for some reason get another brand/model.

> 
> 
>> 1) support for Huawei E3672 dongle (initially no other dongles supported)
> (from patch) huawei_e3276.gcom
> Where is the typo here?

You tell me.

> 
> this patch adds ncm_xhr.js
>> diff --git 
>> a/package/network/services/ncm/files/www/luci-static/resources/ncm_xhr.js 
>> b/package/network/services/ncm/files/www/luci-static/resources/ncm_xhr.js
>> new file mode 100644
>> index 0000000..c01e8ac
>> --- /dev/null
>> +++ b/package/network/services/ncm/files/www/luci-static/resources/ncm_xhr.js
> 
> however - there is already such file on my router
> without ncm there

Yes- but I needed some extra functionality that file didn't provide - so I 
rolled my own modification of the file.

Status works like this:
1) page loads and says that it is detecting device
2) device is detected and page receives used driver and some other data about 
it.It then uses this data to report if dongle is not present, dongle is not 
supported or ncm is not being used.
    end here - if any of those is the case.
3) now that we have: modem's tty and we know "driver" (at command set) that we 
should use to retrieve information, we check that at command set for device 
exists and if not - report that it's not supported (might be supported if 
there's a package for such at set, but local system does not have it installed 
or user removed 'em) - end here
4) get carrier information with at set we found out we need to use. Then 
publish carrier information. Loop this until we have all required carrier data.
5) get cell and signal information and loop this while user is on the page..

Some of this data must be carrier back as a parameter and that's why I had to 
add this to ncm_xhr.js - if you know you can use already existing xhr.js - go 
for it.

> 
> There are some whitespace errors:
> 
> git apply <4474-ncm-support.patch
> <stdin>:576: trailing whitespace.
>       driver=$(echo "$cardinfo" | grep "driver '" | awk '{ gsub("\x27", ""); 
> print $2; }')    
> <stdin>:658: trailing whitespace.
>       [ "$driver" == "-" ] || 
> <stdin>:659: trailing whitespace.
>               [ -e "$device" ] && 
> <stdin>:970: trailing whitespace.
>                                               
> luci.fs.access(table.concat({"/etc/gcom/ncm/carrier/",rv["driver"], ".gcom"}, 
> "")) and 
> warning: 4 lines add whitespace errors.

Really? I tried to take care of those. Crappy job from me :)
Well, whitespace should had been taken' care by this:

diff --git a/package/network/services/ncm/Makefile 
b/package/network/services/ncm/Makefile
new file mode 100644
index 0000000..a37e3ed
--- /dev/null
+++ b/package/network/services/ncm/Makefile
@@ -0,0 +1,151 @@
+#
+# Copyright (C) 2007-2013 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ncm
+PKG_VERSION:=1.0
+PKG_RELEASE:=1
+PKG_MAINTAINER:=Oskari Rauta <oskari.ra...@gmail.com>
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)-$(PKG_RELEASE)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ncm/Default
+  VERSION:=$(PKG_VERSION)-$(PKG_RELEASE)
+  URL:=http://openwrt.org/
+  MAINTAINER:=Oskari Rauta <oskari.ra...@gmail.com>
+endef
+
+define Package/ncm
+$(call Package/ncm/Default)
+  SECTION:=net
+  CATEGORY:=Network
+  TITLE:=Protocol support for NCM
+  DEPENDS:=+netifd +comgt +kmod-usb-net-cdc-ncm +kmod-usb-serial
+endef
+
+define Package/ncm/description
+ This package contains protocol support for NCM.
+endef
+
+define Package/ncm-huawei-e3276
+$(call Package/ncm/Default)
+  SECTION:=net
+  CATEGORY:=Network
+  TITLE:=Huawei E3276 support for NCM protocol
+  DEPENDS:=+ncm +comgt +kmod-usb-serial
+endef
+
+define Package/ncm-huawei-e3276/description
+ This package contains communication scripts for Huawei E3276
+endef
+
+define Package/luci-proto-ncm
+$(call Package/ncm/Default)
+  SECTION:=luci
+  CATEGORY:=LuCI
+  SUBMENU:=6. Protocols
+  TITLE:=Support for NCM
+  DEPENDS:=+ncm
+endef
+
+define Package/luci-proto-ncm/description
+ This package contains LuCI support for NCM
+endef
+
+define Package/luci-mod-ncm-status
+$(call Package/ncm/Default)
+  SECTION:=luci
+  CATEGORY:=LuCI
+  SUBMENU:=2. Modules
+  TITLE:=LuCI NCM Status Module
+  DEPENDS:=+luci-mod-admin-core +ncm +comgt +kmod-usb-serial
+endef
+
+define Package/luci-mod-ncm-status/description
+ LuCI NCM Status Module
+endef
+
+define Build/Prepare
+       mkdir -p $(PKG_BUILD_DIR)
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile/Default
+endef
+
+Build/Compile = $(Build/Compile/Default)
+
+define Package/ncm/install
+       $(INSTALL_DIR) $(1)/lib
+       $(INSTALL_DIR) $(1)/lib/netifd
+       $(INSTALL_DIR) $(1)/lib/netifd/proto
+       $(INSTALL_DIR) $(1)/etc
+       $(INSTALL_DIR) $(1)/etc/gcom
+       $(INSTALL_DIR) $(1)/etc/gcom/ncm
+       $(INSTALL_DIR) $(1)/etc/gcom/ncm/signal
+       $(INSTALL_DIR) $(1)/etc/gcom/ncm/carrier
+       $(INSTALL_DIR) $(1)/etc/gcom/ncm/setmode
+       $(INSTALL_DIR) $(1)/etc/gcom/ncm/connect
+       $(INSTALL_DIR) $(1)/etc/gcom/ncm/initscripts
+       $(INSTALL_BIN) ./files/lib/netifd/proto/ncm.sh $(1)/lib/netifd/proto/
+       $(INSTALL_DATA) ./files/etc/gcom/ncm/getcardinfo.gcom $(1)/etc/gcom/ncm/
+endef
+
+define Package/ncm-huawei-e3276/install
+       $(INSTALL_DIR) $(1)/etc
+       $(INSTALL_DIR) $(1)/etc/gcom
+       $(INSTALL_DIR) $(1)/etc/gcom/ncm
+       $(INSTALL_DIR) $(1)/etc/gcom/ncm/signal
+       $(INSTALL_DIR) $(1)/etc/gcom/ncm/carrier
+       $(INSTALL_DIR) $(1)/etc/gcom/ncm/setmode
+       $(INSTALL_DIR) $(1)/etc/gcom/ncm/connect
+       $(INSTALL_DIR) $(1)/etc/gcom/ncm/initscripts
+       $(INSTALL_DATA) ./files/etc/gcom/ncm/signal/huawei_e3276.gcom 
$(1)/etc/gcom/ncm/signal/
+       $(INSTALL_DATA) ./files/etc/gcom/ncm/carrier/huawei_e3276.gcom 
$(1)/etc/gcom/ncm/carrier/
+       $(INSTALL_DATA) ./files/etc/gcom/ncm/setmode/huawei_e3276.gcom 
$(1)/etc/gcom/ncm/setmode/
+       $(INSTALL_DATA) ./files/etc/gcom/ncm/connect/huawei_e3276.gcom 
$(1)/etc/gcom/ncm/connect/
+       $(INSTALL_DATA) ./files/etc/gcom/ncm/initscripts/huawei_e3276.gcom 
$(1)/etc/gcom/ncm/initscripts/
+endef
+
+define Package/luci-proto-ncm/install
+       $(INSTALL_DIR) $(1)/usr
+       $(INSTALL_DIR) $(1)/usr/lib
+       $(INSTALL_DIR) $(1)/usr/lib/lua
+       $(INSTALL_DIR) $(1)/usr/lib/lua/luci
+       $(INSTALL_DIR) $(1)/usr/lib/lua/luci/model
+       $(INSTALL_DIR) $(1)/usr/lib/lua/luci/model/network
+       $(INSTALL_DIR) $(1)/usr/lib/lua/luci/model/cbi
+       $(INSTALL_DIR) $(1)/usr/lib/lua/luci/model/cbi/admin_network
+       $(INSTALL_DATA) ./files/usr/lib/lua/luci/model/network/proto_ncm.lua 
$(1)/usr/lib/lua/luci/model/network/
+       $(INSTALL_DATA) 
./files/usr/lib/lua/luci/model/cbi/admin_network/proto_ncm.lua 
$(1)/usr/lib/lua/luci/model/cbi/admin_network/
+endef
+
+define Package/luci-mod-ncm-status/install
+       $(INSTALL_DIR) $(1)/usr
+       $(INSTALL_DIR) $(1)/usr/lib
+       $(INSTALL_DIR) $(1)/usr/lib/lua
+       $(INSTALL_DIR) $(1)/usr/lib/lua/luci
+       $(INSTALL_DIR) $(1)/usr/lib/lua/luci/view
+       $(INSTALL_DIR) $(1)/usr/lib/lua/luci/view/ncm
+       $(INSTALL_DIR) $(1)/usr/lib/lua/luci/controller
+       $(INSTALL_DIR) $(1)/www
+       $(INSTALL_DIR) $(1)/www/luci-static
+       $(INSTALL_DIR) $(1)/www/luci-static/resources
+       $(INSTALL_DATA) ./files/usr/lib/lua/luci/view/ncm/status.htm 
$(1)/usr/lib/lua/luci/view/ncm/
+       $(INSTALL_DATA) ./files/usr/lib/lua/luci/controller/ncmstatus.lua 
$(1)/usr/lib/lua/luci/controller/
+       $(INSTALL_DATA) ./files/www/luci-static/resources/ncm_xhr.js 
$(1)/www/luci-static/resources/
+endef
+
+$(eval $(call BuildPackage,ncm))
+$(eval $(call BuildPackage,ncm-huawei-e3276))
+$(eval $(call BuildPackage,luci-proto-ncm))
+$(eval $(call BuildPackage,luci-mod-ncm-status))
diff --git 
a/package/network/services/ncm/files/etc/gcom/ncm/carrier/huawei_e3276.gcom 
b/package/network/services/ncm/files/etc/gcom/ncm/carrier/huawei_e3276.gcom
new file mode 100644
index 0000000..58684fd
--- /dev/null
+++ b/package/network/services/ncm/files/etc/gcom/ncm/carrier/huawei_e3276.gcom
@@ -0,0 +1,56 @@
+opengt
+set com 115200n81
+set comecho off
+set senddelay 0.02
+waitquiet 0.2 0.2
+flash 0.1
+
+:getprovider
+ send "AT+COPS?^m"
+ let $r="+COPS:"
+ gosub readresult
+ system "echo \""+$x+"\" | awk -F\"[:,]\" '{print \"provider \\x27\" $4 
\"\\x27\"}'"
+
+:getmode
+ send "AT^^SYSCFGEX?^m"
+ let $r="^^SYSCFGEX:"
+ gosub readresult
+ system "echo \""+$x+"\" | awk -F\"[:,]\" '{ \\
+       if ( $2 == \"01\" ) print \"mode \\x27\" \"2G\\x27\"; \\
+       else if ( $2 == \"02\" ) print \"mode \\x27\" \"3G\\x27\"; \\
+       else if ( $2 == \"03\" ) print \"mode \\x27\" \"LTE\\x27\"; \\
+       else if ( $2 == \"0201\" ) print \"mode \\x27\" \"3G Preferred\\x27\"; 
\\
+       else if ( $2 == \"030201\" ) print \"mode \\x27\" \"LTE 
Preferred\\x27\"; \\
+       else if (( $2 == \"00\" ) or ( $2 == \"0\" )) print \"mode \\x27\" 
\"Automatic/Any\\x27\"; \\
+       else print \"mode \\x27\" \"Unknown\\x27\";}'"
+
+:getrate
+ send "AT+CGEQNEG=1^m"
+ let $r="+CGEQNEG:"
+ gosub readresult
+ system "echo \""+$x+"\" | awk -F\"[:,]\" '{ print \"downlink \\x27\" int($5) 
\"kbps\\x27\"; print \"uplink \\x27\" int($4) \"kbps\\x27\"; }'"
+ goto done
+
+:readresult
+ let i=5
+ let $x=""
+:loop
+ get 1 "^m" $s
+ let l=len($r)
+ if len($s) < l goto loop1
+ if $mid($s,1,l) <> $r goto loop1
+ let $x=$mid($s,1,len($s)-1)
+ return
+:loop1
+ if len($s) < 2 goto loop2
+ if $mid($s,1,2) = "ER" return
+ if $mid($s,1,2) = "CO" return
+:loop2
+ if i = 0 return
+ let i=i-1
+ sleep 0.25
+ goto loop
+
+:done
+ exit 0
+^@^@
diff --git 
a/package/network/services/ncm/files/etc/gcom/ncm/connect/huawei_e3276.gcom 
b/package/network/services/ncm/files/etc/gcom/ncm/connect/huawei_e3276.gcom
new file mode 100644
index 0000000..d7a604c
--- /dev/null
+++ b/package/network/services/ncm/files/etc/gcom/ncm/connect/huawei_e3276.gcom
@@ -0,0 +1,63 @@
+opengt
+set com 115200n81
+set comecho off
+set senddelay 0.05
+waitquiet 1 0.2
+
+:start
+ if $env("USE_DISCONNECT")="1" goto disconnect
+ send "AT^^NDISDUP=1,1,\""
+ send $env("USE_APN")
+
+ if $env("USE_AUTHTYPE")="-1" goto noauth
+ else goto auth
+
+:noauth
+ send "\"^m"
+ goto result
+
+:auth
+ send "\",\""
+ send $env("USE_USERID")
+ send "\",\""
+ send $env("USE_PASSWORD")
+ send "\","
+ send $env("USE_AUTHTYPE")
+ send "^m"
+ goto result
+
+:result
+ waitfor 5 "OK","ERR","ERROR"
+ if % = 0 goto connok
+ if % = 1 goto connerr
+ if % = 2 goto connerr
+
+:connok
+ print "WWAN connection established.\r\n"
+ goto done
+
+:connerr
+ print "WWAN error. Connection failed.\r\n"
+ exit 1
+
+:disconnect
+ send "AT^^NDISDUP=1,0,\""
+ send $env("USE_APN")
+ send "\"^m"
+
+ waitfor 5 "OK","ERR","ERROR"
+ if % = 0 goto disconnok
+ if % = 1 goto disconnerr
+ if % = 2 goto disconnerr
+
+:disconnok
+ print "WWAN connection disconnected.\r\n"
+ goto done
+
+:disconnerr
+ print "WWAN disconnection error.\r\n"
+ exit 1
+
+:done
+ exit 0
+^@^@
diff --git a/package/network/services/ncm/files/etc/gcom/ncm/getcardinfo.gcom 
b/package/network/services/ncm/files/etc/gcom/ncm/getcardinfo.gcom
new file mode 100644
index 0000000..79bea16
--- /dev/null
+++ b/package/network/services/ncm/files/etc/gcom/ncm/getcardinfo.gcom
@@ -0,0 +1,38 @@
+opengt
+ set com 115200n81
+ set comecho on
+ set senddelay 0.02
+ waitquiet 0.2 0.2
+ flash 0.1
+
+:start
+ let i=0
+
+:waitfordevice
+ waitquiet 2 0.5
+ inc i
+ send "AT^m"
+ waitfor 4 "OK","ERR","ERROR"
+ if % = 0 goto detect
+ if i < 5 goto waitfordevice
+ print "Error: Dongle not responding."
+ exit 1
+
+:detect
+ send "ATI^m"
+ waitfor 1 "ATI^m"
+ get 1 "OK" $s
+
+:output
+ system "echo \""+$s+"\" | grep \"Manufacturer:\" | awk '{print \"vendor 
\\x27\" $2 \"\\x27\"; }'"
+ system "echo \""+$s+"\" | grep \"Model:\" | awk '{print \"model \\x27\" $2 
\"\\x27\"; }'"
+ system "echo \""+$s+"\" | grep \"Revision:\" | awk '{print \"firmware \\x27\" 
$2 \"\\x27\"; }'"
+ system "echo \""+$s+"\" | grep \"IMEI:\" | awk '{print \"imei \\x27\" $2 
\"\\x27\"; }'"
+ system "echo \""+$s+"\" | egrep -i '^^Manufacturer|^^Model' | cut -d ' ' -f 2 
| tr -d '\r' | tr '\n' '_' | sed \"s/\\(.*\\)_$/\\'\\1\\'\\n/\" | awk '{ 
gsub(\"\\x27\", \"\"); \\
+       if ( $1 == \"huawei_E3276\" ) print \"driver \\x27huawei_e3276\\x27\"; 
\\
+       else print \"driver \\x27-\\x27\";}'"
+
+ goto continue
+
+:continue
+ exit 0
diff --git 
a/package/network/services/ncm/files/etc/gcom/ncm/initscripts/huawei_e3276.gcom 
b/package/network/services/ncm/files/etc/gcom/ncm/initscripts/huawei_e3276.gcom
new file mode 100644
index 0000000..7d60abd
--- /dev/null
+++ 
b/package/network/services/ncm/files/etc/gcom/ncm/initscripts/huawei_e3276.gcom
@@ -0,0 +1,31 @@
+opengt
+set com 115200n81
+set comecho off
+set senddelay 0.02
+waitquiet 0.2 0.2
+flash 0.1
+
+:start
+ send "AT^m"
+ waitfor 4 "OK","ERR","ERROR"
+ if % = 1 goto initerror
+ if % = 2 goto initerror
+
+ send "ATZ^m"
+ waitfor 4 "OK","ERR","ERROR"
+ if % = 1 goto initerror
+ if % = 2 goto initerror
+
+ send "ATQ V1 E1 S0=0^m"
+ waitfor 4 "OK","ERR","ERROR"
+ if % = 0 goto continue
+ if % = 1 goto initerror
+ if % = 2 goto initerror
+
+:modeerror
+ print "Error while initializing dongle.\n"
+ exit 1
+
+:continue
+ print "Dongle initialization complete.\n"
+ exit 0
diff --git 
a/package/network/services/ncm/files/etc/gcom/ncm/setmode/huawei_e3276.gcom 
b/package/network/services/ncm/files/etc/gcom/ncm/setmode/huawei_e3276.gcom
new file mode 100644
index 0000000..275cca4
--- /dev/null
+++ b/package/network/services/ncm/files/etc/gcom/ncm/setmode/huawei_e3276.gcom
@@ -0,0 +1,56 @@
+# set wwan mode from environment
+opengt
+ set com 115200n81
+ set senddelay 0.02
+ waitquiet 1 0.2
+ flash 0.1
+
+:start
+ if $env("MODE")="2g" goto 2g
+ if $env("MODE")="3g" goto 3g
+ if $env("MODE")="lte" goto lte
+ if $env("MODE")="prefer3g" goto prefer3g
+ if $env("MODE")="preferlte" goto preferlte
+ goto auto
+
+:auto
+ send "AT^^SYSCFGEX=\"00\",3FFFFFFF,2,4,7FFFFFFFFFFFFFFF,,^m"
+ goto result
+
+:2g
+ send "AT^^SYSCFGEX=\"01\",3FFFFFFF,2,4,7FFFFFFFFFFFFFFF,,^m"
+ goto result
+
+:3g
+ send "AT^^SYSCFGEX=\"02\",3FFFFFFF,2,4,7FFFFFFFFFFFFFFF,,^m"
+ goto result
+
+:lte
+ send "AT^^SYSCFGEX=\"03\",3FFFFFFF,2,4,7FFFFFFFFFFFFFFF,,^m"
+ goto result
+
+:prefer3g
+ send "AT^^SYSCFGEX=\"0201\",3FFFFFFF,2,4,7FFFFFFFFFFFFFFF,,^m"
+ goto result
+
+:preferlte
+ send "AT^^SYSCFGEX=\"030201\",3FFFFFFF,2,4,7FFFFFFFFFFFFFFF,,^m"
+ goto result
+
+:result
+ waitfor 8 "OK","ERR","ERROR"
+ if % = 0 goto continue
+ if % = 1 goto modeerror
+ if % = 2 goto modeerror
+ print "Timeout setting WWAN mode!\n"
+ exit 1
+
+:modeerror
+ print "Error setting WWAN mode!\n"
+ exit 1
+
+:continue
+ print "WWAN mode set to '"
+ print $env("MODE")
+ print "'\r\n"
+ exit 0
diff --git 
a/package/network/services/ncm/files/etc/gcom/ncm/signal/huawei_e3276.gcom 
b/package/network/services/ncm/files/etc/gcom/ncm/signal/huawei_e3276.gcom
new file mode 100644
index 0000000..a2ddb61
--- /dev/null
+++ b/package/network/services/ncm/files/etc/gcom/ncm/signal/huawei_e3276.gcom
@@ -0,0 +1,61 @@
+opengt
+set com 115200n81
+set comecho off
+set senddelay 0.02
+waitquiet 0.2 0.2
+flash 0.1
+
+:getcell
+ send "AT+CREG=2^m"
+ let $r="OK"
+ gosub readresult
+ if $r <> $x goto getnetwork
+
+ send "AT+CREG?^m"
+ let $r="+CREG:"
+ gosub readresult
+ system "echo \""+$x+"\" | awk -F\"[:,]\" '{print \"cellid \\x27\" \"0x\" $5 
\" (\" (\"0x\"$5)+0 \")\\x27\"; print \"lac \\x27\" \"0x\" $4 \" (\" 
(\"0x\"$4)+0 \")\\x27\";}'"
+
+:getnetwork
+ send "AT^^SYSINFOEX^m"
+ let $r="^^SYSINFOEX:"
+ gosub readresult
+ system "echo \""+$x+"\" | awk -F\"[:,]\" '{print \"network \\x27\" $8 \" / \" 
$10 \"\\x27\";}'"
+
+:getsignalstrength
+ send "AT+CSQ^m"
+ let $r="+CSQ:"
+ gosub readresult
+ system "echo \""+$x+"\" | awk -F\"[:,]\" '{ print \"signal \\x27\" int(($2 * 
100 / 31)+0.5) \"%\\x27\"; print \"rssi \\x27\" int(2 * $2 - 113) \"dBm\\x27\"; 
print \"csq \\x27\" int($2) \"\\x27\"; }'"
+
+:getnoicelevels
+ send "AT^^CSNR?^m"
+ let $r="^^CSNR:"
+ gosub readresult
+ system "echo \""+$x+"\" | awk -F\"[:,]\" '{ print \"rcsp \\x27\" int($2) 
\"dBm\\x27\"; print \"ecio \\x27\" int($3) \"dB\\x27\";}'"
+
+ goto done
+
+:readresult
+ let i=5
+ let $x=""
+:loop
+ get 1 "^m" $s
+ let l=len($r)
+ if len($s) < l goto loop1
+ if $mid($s,1,l) <> $r goto loop1
+ let $x=$mid($s,1,len($s)-1)
+ return
+:loop1
+ if len($s) < 2 goto loop2
+ if $mid($s,1,2) = "ER" return
+ if $mid($s,1,2) = "CO" return
+:loop2
+ if i = 0 return
+ let i=i-1
+ sleep 0.25
+ goto loop
+
+:done
+ exit 0
+^@^@
diff --git a/package/network/services/ncm/files/lib/netifd/proto/ncm.sh 
b/package/network/services/ncm/files/lib/netifd/proto/ncm.sh
new file mode 100755
index 0000000..62b00b8
--- /dev/null
+++ b/package/network/services/ncm/files/lib/netifd/proto/ncm.sh
@@ -0,0 +1,137 @@
+#!/bin/sh
+
+. /lib/functions.sh
+. ../netifd-proto.sh
+init_proto "$@"
+
+proto_ncm_init_config() {
+       proto_config_add_string "device"
+       proto_config_add_string "mode"
+       proto_config_add_string "apn"
+       proto_config_add_string "pincode"
+       proto_config_add_string "authtype"
+       proto_config_add_string "delay"
+       proto_config_add_string "username"
+       proto_config_add_string "password"
+       proto_config_add_string "ipaddr"
+       proto_config_add_string "netmask"
+       proto_config_add_string "hostname"
+       proto_config_add_string "clientid"
+       proto_config_add_string "vendorid"
+       proto_config_add_boolean "broadcast"
+       proto_config_add_string "reqopts"
+       proto_config_add_string "iface6rd"
+       proto_config_add_string "sendopts"
+}
+
+proto_ncm_setup() {
+       local config="$1"
+       local iface="$2"
+
+       local device mode apn pincode authtype delay username password
+       local ipaddr hostname clientid vendorid broadcast reqopts iface6rd 
sendopts
+       local cardinfo brand model driver
+       local dialupscript modescript initscript
+
+       json_get_vars device mode apn pincode delay authtype username password
+       json_get_vars ipaddr hostname clientid vendorid broadcast reqopts 
iface6rd sendopts
+
+       [ -e "$device" ] || {
+               proto_set_available "$interface" 0
+               return 1
+       }
+
+       cardinfo=$(gcom -d "$device" -s /etc/gcom/ncm/getcardinfo.gcom)
+       brand=$(echo "$cardinfo" | grep "vendor '" | awk '{ gsub("\x27", ""); 
print $2; }')
+       model=$(echo "$cardinfo" | grep "model '" | awk '{ gsub("\x27", ""); 
print $2; }')
+       driver=$(echo "$cardinfo" | grep "driver '" | awk '{ gsub("\x27", ""); 
print $2; }')
+
+       [ "$driver" = "-" ] && {
+               logger Detected $brand $model. Device is not supported.
+               proto_notify_error "$interface" UNSUPPORTED_DEVICE
+               proto_block_restart "$interface"
+               return 1
+       }
+
+       initscript="/etc/gcom/ncm/initscripts/$driver.gcom"
+       modescript="/etc/gcom/ncm/setmode/$driver.gcom"
+       dialupscript="/etc/gcom/ncm/connect/$driver.gcom"
+
+       logger Detected $brand $model. Using driver $driver.
+
+       if [ -n "$pincode" ]; then
+               PINCODE="$pincode" gcom -d "$device" -s /etc/gcom/setpin.gcom 
|| {
+                       proto_notify_error "$interface" PIN_FAILED
+                       proto_block_restart "$interface"
+                       return 1
+               }
+       fi
+
+       [ -e "$initscript" ] &&
+               gcom -d "$device" -s "$initscript"
+
+       [ "$authtype" = "pap" ] && authtype=1 || {
+               [ "$authtype" = "chap" ] && authtype=2 || {
+                       [ "$authtype" = "cleartext" ] && authtype=0 ||
+                               authtype=-1
+               }
+       }
+
+       [ -e "$modescript" ] &&
+               MODE="$mode" gcom -d "$device" -s "$modescript"
+
+       [ -e "$dialupscript" ] || {
+               logger Dial-up script for driver $driver is missing.
+               proto_notify_error "$interface" SCRIPT_MISSING
+               proto_block_restart "$interface"
+               return 1
+       }
+
+       USE_DISCONNECT="0" USE_APN="$apn" USE_AUTHTYPE="$authtype" 
USE_USERID="$username" USE_PASSWORD="$password" \
+               gcom -d "$device" -s "$dialupscript"
+
+       [ ! -z "${delay##*[!0-9]*}" ] && [ "$delay" != "0" ] && /bin/sleep 
$delay
+
+       local opt dhcpopts
+       for opt in $reqopts; do
+               append dhcpopts "-O $opt"
+       done
+
+       for opt in $sendopts; do
+               append dhcpopts "-x $opt"
+       done
+
+       [ "$broadcast" = 1 ] && broadcast="-B" || broadcast=
+       [ -n "$clientid" ] && clientid="-x 0x3d:${clientid//:/}" || 
clientid="-C"
+       [ -n "$iface6rd" ] && proto_export "IFACE6RD=$iface6rd"
+
+       proto_export "INTERFACE=$config"
+       proto_run_command "$config" udhcpc \
+               -p /var/run/udhcpc-$iface.pid \
+               -s /lib/netifd/dhcp.script \
+               -f -t 0 -i "$iface" \
+               ${ipaddr:+-r $ipaddr} \
+               ${hostname:+-H $hostname} \
+               ${vendorid:+-V $vendorid} \
+               $clientid $broadcast $dhcpopts
+}
+
+proto_ncm_teardown() {
+       local interface="$1"
+       local device apn cardinfo driver dialupscript
+
+       json_get_vars device apn
+
+       cardinfo=$(gcom -d "$device" -s /etc/gcom/ncm/getcardinfo.gcom)
+       driver=$(echo "$cardinfo" | grep "driver '" | awk '{ gsub("\x27", ""); 
print $2; }')
+       dialupscript="/etc/gcom/ncm/connect/$driver.gcom"
+
+       [ "$driver" == "-" ] ||
+               [ -e "$device" ] &&
+                       [ -e "$dialupscript" ] &&
+                               USE_DISCONNECT="1" USE_APN="$apn" gcom -d 
"$device" -s "$dialupscript"
+
+       proto_kill_command "$interface"
+}
+
+add_protocol ncm
diff --git 
a/package/network/services/ncm/files/usr/lib/lua/luci/controller/ncmstatus.lua 
b/package/network/services/ncm/files/usr/lib/lua/luci/controller/ncmstatus.lua
new file mode 100755
index 0000000..cfb6b20
--- /dev/null
+++ 
b/package/network/services/ncm/files/usr/lib/lua/luci/controller/ncmstatus.lua
@@ -0,0 +1,8 @@
+module("luci.controller.ncmstatus", package.seeall)
+
+function index()
+       local page
+
+       page = entry({"admin", "status", "ncm"}, template("ncm/status"), _("Ncm 
status"))
+       page.dependent = true
+end
diff --git 
a/package/network/services/ncm/files/usr/lib/lua/luci/model/cbi/admin_network/proto_ncm.lua
 
b/package/network/services/ncm/files/usr/lib/lua/luci/model/cbi/admin_network/proto_ncm.lua
new file mode 100644
index 0000000..dfaa02e
--- /dev/null
+++ 
b/package/network/services/ncm/files/usr/lib/lua/luci/model/cbi/admin_network/proto_ncm.lua
@@ -0,0 +1,120 @@
+--[[
+LuCI - Lua Configuration Interface
+
+Copyright 2011 Jo-Philipp Wich <x...@subsignal.org>
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+]]--
+
+local map, section, net = ...
+
+local device, apn, mode, pincode, authtype, username, password
+local delay, bcast, defaultroute, peerdns, dns, metric, clientid, vendorclass
+
+
+device = section:taboption("general", Value, "device", translate("Modem 
device"))
+device.rmempty = false
+
+local device_suggestions = nixio.fs.glob("/dev/tty[A-Z]*")
+       or nixio.fs.glob("/dev/tts/*")
+
+if device_suggestions then
+       local node
+       for node in device_suggestions do
+               device:value(node)
+       end
+end
+
+mode = section:taboption("general", ListValue, "mode", translate("Service 
mode"))
+mode:value("2g", translate("2G only"))
+mode:value("3g", translate("3G only"))
+mode:value("lte", translate("LTE only"))
+mode:value("prefer3g", translate("Prefer 3G"))
+mode:value("preferlte", translate("Prefer LTE"))
+mode:value("auto", translate("Automatic / Any"))
+mode.rmempty = false
+mode.default = "auto"
+
+
+apn = section:taboption("general", Value, "apn", translate("APN"))
+
+
+pincode = section:taboption("general", Value, "pincode", translate("PIN"))
+
+
+authtype = section:taboption("general", ListValue, "authtype", 
translate("Authentication type"))
+authtype:value("none", translate("None"))
+authtype:value("cleartext", translate("Clear text"))
+authtype:value("pap", translate("PAP"))
+authtype:value("chap", translate("CHAP"))
+authtype.rmempty = false
+authtype.default = "none"
+
+
+username = section:taboption("general", Value, "username", translate("PAP/CHAP 
username"))
+
+
+password = section:taboption("general", Value, "password", translate("PAP/CHAP 
password"))
+password.password = true
+
+
+bcast = section:taboption("advanced", Flag, "broadcast",
+       translate("Use broadcast flag"),
+       translate("Required for certain ISPs, e.g. Charter with DOCSIS 3"))
+
+bcast.default = bcast.disabled
+
+
+defaultroute = section:taboption("advanced", Flag, "defaultroute",
+       translate("Use default gateway"),
+       translate("If unchecked, no default route is configured"))
+
+defaultroute.default = defaultroute.enabled
+
+
+peerdns = section:taboption("advanced", Flag, "peerdns",
+       translate("Use DNS servers advertised by peer"),
+       translate("If unchecked, the advertised DNS server addresses are 
ignored"))
+
+peerdns.default = peerdns.enabled
+
+
+dns = section:taboption("advanced", DynamicList, "dns",
+       translate("Use custom DNS servers"))
+
+dns:depends("peerdns", "")
+dns.datatype = "ipaddr"
+dns.cast     = "string"
+
+
+delay = section:taboption("advanced", Value, "delay",
+       translate("Dongle connection delay"))
+delay.default    = "20"
+delay.placeholder = translate("seconds")
+delay.datatype   = "uinteger"
+
+
+metric = section:taboption("advanced", Value, "metric",
+       translate("Use gateway metric"))
+
+metric.placeholder = "0"
+metric.datatype           = "uinteger"
+
+clientid = section:taboption("advanced", Value, "clientid",
+       translate("Client ID to send when requesting DHCP"))
+
+
+vendorclass = section:taboption("advanced", Value, "vendorid",
+       translate("Vendor Class to send when requesting DHCP"))
+
+
+luci.tools.proto.opt_macaddr(section, ifc, translate("Override MAC address"))
+
+
+mtu = section:taboption("advanced", Value, "mtu", translate("Override MTU"))
+mtu.placeholder = "1492"
+mtu.datatype   = "max(9200)"
diff --git 
a/package/network/services/ncm/files/usr/lib/lua/luci/model/network/proto_ncm.lua
 
b/package/network/services/ncm/files/usr/lib/lua/luci/model/network/proto_ncm.lua
new file mode 100644
index 0000000..dd8dbe4
--- /dev/null
+++ 
b/package/network/services/ncm/files/usr/lib/lua/luci/model/network/proto_ncm.lua
@@ -0,0 +1,60 @@
+--[[
+LuCI - Network model - 3G, PPP, PPtP, PPPoE and PPPoA protocol extension
+
+Copyright 2011 Jo-Philipp Wich <x...@subsignal.org>
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+]]--
+
+local netmod = luci.model.network
+
+local _, p
+for _, p in ipairs({"ncm"}) do
+
+       local proto = netmod:register_protocol(p)
+
+       function proto.get_i18n(self)
+               return luci.i18n.translate("NCM")
+       end
+
+       function proto.ifname(self)
+               return p .. "-" .. self.sid
+       end
+
+       function proto.opkg_package(self)
+               return "kmod-usb-net-cdc-ncm"
+       end
+
+       function proto.is_installed(self)
+               return nixio.fs.access("/lib/netifd/proto/ncm.sh")
+       end
+
+       function proto.is_floating(self)
+               return false
+       end
+
+       function proto.is_virtual(self)
+               return false
+       end
+
+       function proto.get_interfaces(self)
+               return netmod.protocol.get_interfaces(self)
+       end
+
+       function proto.contains_interface(self, ifc)
+               return netmod.protocol.contains_interface(self, ifc)
+       end
+
+       netmod:register_pattern_virtual("^%s-%%w" % p)
+end
diff --git 
a/package/network/services/ncm/files/usr/lib/lua/luci/view/ncm/status.htm 
b/package/network/services/ncm/files/usr/lib/lua/luci/view/ncm/status.htm
new file mode 100644
index 0000000..5568b7f
--- /dev/null
+++ b/package/network/services/ncm/files/usr/lib/lua/luci/view/ncm/status.htm
@@ -0,0 +1,283 @@
+<%#
+LuCI - Lua Configuration Interface
+Copyright 2008 Steven Barth <ste...@midlink.org>
+Copyright 2008-2011 Jo-Philipp Wich <x...@subsignal.org>
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+-%>
+
+<%
+       require "luci.sys"
+       require "luci.fs"
+
+       local rv = {
+               gothw           = "0",
+               gotcarrier      = "0",
+               gotsignal       = "0",
+               hwrefresh       = "0",
+               modemdev        = "",
+               driver          = "",
+               vendor          = "",
+               model           = "",
+               notification    = "",
+               firmware        = "",
+               imei            = "",
+               provider        = "",
+               mode            = "",
+               downlink        = "",
+               uplink          = "",
+               cellid          = "",
+               lac             = "",
+               network         = "",
+               signal          = "",
+               rssi            = "",
+               csq             = "",
+               rcsp            = "",
+               ecio            = ""
+       }
+
+       if luci.http.formvalue("gothw") == "1" then
+               rv["gothw"] = luci.http.formvalue("gothw") or "0"
+               rv["modemdev"] = luci.http.formvalue("modemdev")
+               rv["driver"] = luci.http.formvalue("driver")
+               rv["gotcarrier"] = luci.http.formvalue("gotcarrier") or "0"
+               rv["gotsignal"] = luci.http.formvalue("gotsignal") or "0"
+               rv["hwrefresh"] = luci.http.formvalue("hwrefresh") or "0"
+       else
+               local uci = require "luci.model.uci".cursor()
+               if uci:get("network", "wan", "proto") == "ncm" then
+                       rv["modemdev"] = uci:get("network", "wan", "device") or 
"0"
+               else
+                       if luci.http.formvalue("status") == "1" then
+
+                               rv["notification"] = "[ WAN is not using NCM 
protocol ]"
+                               rv["hwrefresh"] = "0"
+                               rv["gothw"] = "0"
+                               rv["driver"] = "-"
+
+                               luci.http.prepare_content("application/json")
+                               luci.http.write_json(rv)
+
+                               return
+                       end
+
+               end
+
+       end
+
+       if ( luci.http.formvalue("status") == "1" and rv["driver"] ~= "-" ) then
+
+               if luci.fs.access(rv["modemdev"]) then
+
+                       if rv["gothw"] == "0" then
+
+                               local modemhw = 
luci.sys.exec(table.concat({"/usr/bin/gcom -d ", rv["modemdev"], " -s 
/etc/gcom/ncm/getcardinfo.gcom"}, ""))
+
+                               for k, v in string.gmatch(modemhw, "(%w+) 
'(.-)'") do
+                                       rv[k] = v
+                               end
+
+                               if rv["driver"] == "" then
+                                       rv["driver"] = "-"
+                               end
+
+                               if ( rv["vendor"] == "" or rv["model"] == "" or 
rv["firmware"] == "" or rv["imei"] == "" or rv["driver"] == "" ) then
+                                       rv["gothw"] = "0"
+                               elseif (rv["driver"] ~= "-" and
+                                               
luci.fs.access(table.concat({"/etc/gcom/ncm/carrier/",rv["driver"], ".gcom"}, 
"")) and
+                                               
luci.fs.access(table.concat({"/etc/gcom/ncm/signal/", rv["driver"], ".gcom"}, 
""))) then
+                                       rv['gothw'] = "1"
+                               else
+                                       rv["notification"] = " [ Unsupported 
dongle ]";
+                                       rv["driver"] = "-"
+                                       rv["gothw"] = "0"
+                                       rv["hwrefresh"] = "1"
+                               end
+
+                       elseif rv["gotcarrier"] == "0" then
+
+                               if rv["driver"] ~= "-" then
+
+                                       local modemcarrier = 
luci.sys.exec(table.concat({"/usr/bin/gcom -d ", rv["modemdev"], " -s 
/etc/gcom/ncm/carrier/", rv["driver"], ".gcom"}, ""))
+
+                                       for k, v in string.gmatch(modemcarrier, 
"(%w+) '(.-)'") do
+                                               rv[k] = v
+                                       end
+
+                                       if ( rv["provider"] == "" or 
rv["downlink"] == "" or rv["uplink"] == "" or rv["mode"] == "" ) then
+                                               rv["gotcarrier"] = "0"
+                                       else
+                                               rv["gotcarrier"] = "1"
+                                       end
+
+                               else
+                                       rv["gotcarrier"] = "1"
+                               end
+
+                       else
+
+                               if rv["driver"] ~= "-" then
+
+                                       local modemsignal = 
luci.sys.exec(table.concat({"/usr/bin/gcom -d ", rv["modemdev"], " -s 
/etc/gcom/ncm/signal/", rv["driver"], ".gcom"}, ""))
+
+                                       for k, v in string.gmatch(modemsignal, 
"(%w+) '(.-)'") do
+                                               rv[k] = v
+                                       end
+                                       rv["gotsignal"] = "1"
+                               end
+
+                       end
+               else
+
+                       rv["notification"] = table.concat({"[ ", 
rv["modemdev"], ": Device not present. ]"}, "")
+
+               end
+
+       end
+
+       if ( luci.http.formvalue("status") == "1" ) then
+
+               luci.http.prepare_content("application/json")
+               luci.http.write_json(rv)
+
+               return
+
+       end
+
+-%>
+
+<%+header%>
+
+<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
+<script type="text/javascript" src="<%=resource%>/ncm_xhr.js"></script>
+<script type="text/javascript">//<![CDATA[
+
+       function capitalize(s)
+       {
+               return s.toLowerCase().replace( /\b./g, function(a){ return 
a.toUpperCase(); } );
+       };
+
+       XHR2.poll(5, '<%=REQUEST_URI%>', { status: 1 },
+               function(x, info)
+               {
+
+                       var e;
+
+                       if (e = document.getElementById('notification'))
+                               e.innerHTML = info.notification;
+
+                       if (( gothwD == "0" && info.gothw == "1" ) || ( 
info.hwrefresh == "1" )) {
+
+                               if (e = document.getElementById('name'))
+                                       e.innerHTML = capitalize(info.vendor) + 
" " + capitalize(info.model);
+
+                               if (e = document.getElementById('firmware'))
+                                       e.innerHTML = info.firmware;
+
+                               if (e = document.getElementById('imei'))
+                                       e.innerHTML = info.imei;
+                       }
+
+                       if ( gotcarrierD == "0" && info.gotcarrier == "1" ) {
+
+                               if (e = document.getElementById('provider'))
+                                       e.innerHTML = info.provider;
+
+                               if (e = document.getElementById('linkspeed'))
+                                       if ( info.downlink != "" && info.uplink 
!= "" )
+                                               e.innerHTML = info.downlink + " 
/ " + info.uplink ;
+
+                               if (e = document.getElementById('mode'))
+                                       e.innerHTML = info.mode;
+
+                       }
+
+                       if ( info.gotsignal == "1" ) {
+
+                               if (e = document.getElementById('cellid'))
+                                       e.innerHTML = info.cellid;
+
+                               if (e = document.getElementById('lac'))
+                                       e.innerHTML = info.lac;
+
+                               if (e = document.getElementById('network'))
+                                       e.innerHTML = info.network;
+
+                               if (e = document.getElementById('signal'))
+                                       e.innerHTML = info.signal;
+
+                               if (e = document.getElementById('csq'))
+                                       e.innerHTML = info.csq;
+
+                               if (e = document.getElementById('rssi'))
+                                       e.innerHTML = info.rssi;
+
+                               if (e = document.getElementById('rcsp'))
+                                       e.innerHTML = info.rcsp;
+
+                               if (e = document.getElementById('ecio'))
+                                       e.innerHTML = info.ecio;
+
+                       }
+
+                       modemdevD = info.modemdev;
+                       driverD = info.driver;
+                       gothwD = info.gothw;
+                       gotcarrierD = info.gotcarrier;
+                       hwrefreshD = info.hwrefresh;
+                       gotsignalD = info.gotsignal;
+
+               }
+       );
+
+//]]></script>
+
+<h2><a id="content" name="content"><%:NCM Status%></a></h2>
+<small style="color: #777;" id="notification"></small>
+
+<fieldset class="cbi-section">
+       <legend id="name"><%:Detecting dongle%></legend>
+
+       <table width="100%" cellspacing="10">
+               <tr><td width="33%"><%:Firmware version%></td><td 
id="firmware"></td></tr>
+               <tr><td width="33%"><%:IMEI%></td><td id="imei"></td></tr>
+       </table>
+</fieldset>
+
+<fieldset class="cbi-section">
+       <legend><%:Network%></legend>
+
+       <table width="100%" cellspacing="10">
+               <tr><td width="33%"><%:Provider%></td><td 
id="provider"></td></tr>
+               <tr><td width="33%"><%:Downlink/Uplink%></td><td 
id="linkspeed"></td></tr>
+               <tr><td width="33%"><%:Mode%></td><td id="mode"></td></tr>
+       </table>
+</fieldset>
+
+<fieldset class="cbi-section">
+       <legend><%:Cell%></legend>
+
+       <table width="100%" cellspacing="10">
+               <tr><td width="33%"><%:Location Area Code%></td><td 
id="lac"></td></tr>
+               <tr><td width="33%"><%:Cell ID%></td><td id="cellid"></td></tr>
+       </table>
+</fieldset>
+
+<fieldset class="cbi-section">
+       <legend><%:Signal level%></legend>
+
+       <table width="100%" cellspacing="10">
+               <tr><td width="33%"><%:Network%></td><td id="network"></td></tr>
+               <tr><td width="33%"><%:Signal strength%></td><td 
id="signal"></td></tr>
+               <tr><td width="33%"><%:CSQ%></td><td id="csq"></td></tr>
+               <tr><td width="33%"><%:RSSI%></td><td id="rssi"></td></tr>
+               <tr><td width="33%"><%:RCSP%></td><td id="rcsp"></td></tr>
+               <tr><td width="33%"><%:ECIO%></td><td id="ecio"></td></tr>
+       </table>
+</fieldset>
+<%+footer%>
diff --git 
a/package/network/services/ncm/files/www/luci-static/resources/ncm_xhr.js 
b/package/network/services/ncm/files/www/luci-static/resources/ncm_xhr.js
new file mode 100644
index 0000000..c01e8ac
--- /dev/null
+++ b/package/network/services/ncm/files/www/luci-static/resources/ncm_xhr.js
@@ -0,0 +1,254 @@
+/*
+ * xhr.js - XMLHttpRequest helper class
+ * (c) 2008-2010 Jo-Philipp Wich
+ */
+
+var gothwD = "0";
+var gotcarrierD = "0";
+var gotsignalD = "0";
+var hwrefreshD = "0";
+var modemdevD = ""
+var driverD = ""
+
+XHR2 = function()
+{
+       this.reinit = function()
+       {
+               if (window.XMLHttpRequest) {
+                       this._xmlHttp = new XMLHttpRequest();
+               }
+               else if (window.ActiveXObject) {
+                       this._xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
+               }
+               else {
+                       alert("dongle_xhr.js: XMLHttpRequest is not supported 
by this browser!");
+               }
+       }
+
+       this.busy = function() {
+               if (!this._xmlHttp)
+                       return false;
+
+               switch (this._xmlHttp.readyState)
+               {
+                       case 1:
+                       case 2:
+                       case 3:
+                               return true;
+
+                       default:
+                               return false;
+               }
+       }
+
+       this.abort = function() {
+               if (this.busy())
+                       this._xmlHttp.abort();
+       }
+
+       this.get = function(url,data,callback)
+       {
+               this.reinit();
+
+               var xhr2  = this._xmlHttp;
+               var code = this._encode(data);
+
+               url = location.protocol + '//' + location.host + url;
+
+               if (code)
+                       if (url.substr(url.length-1,1) == '&')
+                               url += code;
+                       else
+                               url += '?' + code;
+
+               xhr2.open('GET', url, true);
+
+               xhr2.onreadystatechange = function()
+               {
+                       if (xhr2.readyState == 4) {
+                               var json = null;
+                               if (xhr2.getResponseHeader("Content-Type") == 
"application/json") {
+                                       try {
+                                               json = eval('(' + 
xhr2.responseText + ')');
+                                       }
+                                       catch(e) {
+                                               json = null;
+                                       }
+                               }
+
+                               callback(xhr2, json);
+                       }
+               }
+
+               xhr2.send(null);
+       }
+
+       this.post = function(url,data,callback)
+       {
+               this.reinit();
+
+               var xhr2  = this._xmlHttp;
+               var code = this._encode(data);
+
+               xhr2.onreadystatechange = function()
+               {
+                       if (xhr2.readyState == 4)
+                               callback(xhr2);
+               }
+
+               xhr2.open('POST', url, true);
+               xhr2.setRequestHeader('Content-type', 
'application/x-www-form-urlencoded');
+               xhr2.setRequestHeader('Content-length', code.length);
+               xhr2.setRequestHeader('Connection', 'close');
+               xhr2.send(code);
+       }
+
+       this.cancel = function()
+       {
+               this._xmlHttp.onreadystatechange = function(){};
+               this._xmlHttp.abort();
+       }
+
+       this.send_form = function(form,callback,extra_values)
+       {
+               var code = '';
+
+               for (var i = 0; i < form.elements.length; i++)
+               {
+                       var e = form.elements[i];
+
+                       if (e.options)
+                       {
+                               code += (code ? '&' : '') +
+                                       form.elements[i].name + '=' + 
encodeURIComponent(
+                                               e.options[e.selectedIndex].value
+                                       );
+                       }
+                       else if (e.length)
+                       {
+                               for (var j = 0; j < e.length; j++)
+                                       if (e[j].name) {
+                                               code += (code ? '&' : '') +
+                                                       e[j].name + '=' + 
encodeURIComponent(e[j].value);
+                                       }
+                       }
+                       else
+                       {
+                               code += (code ? '&' : '') +
+                                       e.name + '=' + 
encodeURIComponent(e.value);
+                       }
+               }
+
+               if (typeof extra_values == 'object')
+                       for (var key in extra_values)
+                               code += (code ? '&' : '') +
+                                       key + '=' + 
encodeURIComponent(extra_values[key]);
+
+               return(
+                       (form.method == 'get')
+                               ? this.get(form.getAttribute('action'), code, 
callback)
+                               : this.post(form.getAttribute('action'), code, 
callback)
+               );
+       }
+
+       this._encode = function(obj)
+       {
+               obj = obj ? obj : { };
+               obj['gothw'] = gothwD;
+               obj['gotcarrier'] = gotcarrierD;
+               obj['gotsignal'] = gotsignalD;
+               obj['hwrefresh'] = hwrefreshD;
+               obj['modemdev'] = modemdevD;
+               obj['driver'] = driverD;
+               obj['_'] = Math.random();
+
+               if (typeof obj == 'object')
+               {
+                       var code = '';
+                       var self = this;
+
+                       for (var k in obj)
+                               code += (code ? '&' : '') +
+                                       k + '=' + encodeURIComponent(obj[k]);
+
+                       return code;
+               }
+
+               return obj;
+       }
+}
+
+XHR2.get = function(url, data, callback)
+{
+       (new XHR2()).get(url, data, callback);
+}
+
+XHR2.poll = function(interval, url, data, callback)
+{
+       if (isNaN(interval) || interval < 1)
+               interval = 5;
+
+       if (!XHR2._q)
+       {
+               XHR2._t = 0;
+               XHR2._q = [ ];
+               XHR2._r = function() {
+                       for (var i = 0, e = XHR2._q[0]; i < XHR2._q.length; e = 
XHR2._q[++i])
+                       {
+                               if (!(XHR2._t % e.interval) && !e.xhr2.busy())
+                                       e.xhr2.get(e.url, e.data, e.callback);
+                       }
+
+                       XHR2._t++;
+               };
+       }
+
+       XHR2._q.push({
+               interval: interval,
+               callback: callback,
+               url:      url,
+               data:     data,
+               xhr2:      new XHR2()
+       });
+
+       XHR2.run();
+}
+
+XHR2.halt = function()
+{
+       if (XHR2._i)
+       {
+               /* show & set poll indicator */
+               try {
+                       
document.getElementById('xhr_poll_status').style.display = '';
+                       
document.getElementById('xhr_poll_status_on').style.display = 'none';
+                       
document.getElementById('xhr_poll_status_off').style.display = '';
+               } catch(e) { }
+
+               window.clearInterval(XHR2._i);
+               XHR2._i = null;
+       }
+}
+
+XHR2.run = function()
+{
+       if (XHR2._r && !XHR2._i)
+       {
+               /* show & set poll indicator */
+               try {
+                       
document.getElementById('xhr_poll_status').style.display = '';
+                       
document.getElementById('xhr_poll_status_on').style.display = '';
+                       
document.getElementById('xhr_poll_status_off').style.display = 'none';
+               } catch(e) { }
+
+               /* kick first round manually to prevent one second lag when 
setting up
+                * the poll interval */
+               XHR2._r();
+               XHR2._i = window.setInterval(XHR2._r, 1000);
+       }
+}
+
+XHR2.running = function()
+{
+       return !!(XHR2._r && XHR2._i);
+}
_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel

Reply via email to