VoCore2: Monitor/Sniffer on WiFi

It is pretty simple by using mt7628.ko(or directly use firmware http://vonger.cn/misc/vocore2/20180419V.bin)

First install libpcap.ipk and tcpdump.ipk

Then MonitorMode=2 is MONITOR_MODE_FULL, =1 is MONITOR_MODE_REGULAR_RX, =0 is OFF.

ifconfig mon0 up
iwpriv ra0 set MonitorMode=2
tcpdump -i mon0 -w /tmp/store.cap -vv

or tcpdump -i ra0 -w /tmp/store.cap -vv

The raw data is saved to /tmp/store.cap.
Now we can use wireshark to read store.cap, check the data we get from net. 🙂

PS: CMCC-XXX is everywhere, noise…

VoCore2: Show Multiple SSIDs(up to 16 SSID)

Today when I hack the mt7628 driver, I find this hidden feature( maybe not hidden, but at least no documentation at all )

Example come first, if we want 4 different SSIDs in same VoCore2, need to setting up /etc/wireless/mt7628/mt7628.dat

This is only works for mediatek wifi driver mt7628.ko, not sure if mt76 works.

Modify BssidNum, set it to 4.

BssidNum=4
SSID1=VoCore2
SSID2=VoCore2-GUEST
SSID3=VoCore2-HOST
SSID4=VoCore2-NAS

Then reboot, you will find four raX device in your device list.

ra1       Available private ioctls :
          set              (8BE2) : set 1536 char  & get   0      
          show             (8BF1) : set 1024 char  & get   0      
          get_site_survey  (8BED) : set   0       & get 1024 char 
          set_wsc_oob      (8BF9) : set 1024 char  & get 1024 char 
          get_mac_table    (8BEF) : set 1024 char  & get 1024 char 
          e2p              (8BE7) : set 1024 char  & get 1024 char 
          bbp              (8BE3) : set 1024 char  & get 1024 char 
          mac              (8BE5) : set 1024 char  & get 1024 char 
          rf               (8BF3) : set 1024 char  & get 1024 char 
          get_wsc_profile  (8BF2) : set 1024 char  & get 1024 char 
          get_ba_table     (8BF6) : set 1024 char  & get 1024 char 
          stat             (8BE9) : set 1024 char  & get 1024 char 

br-lan    no private ioctls.

mon0      Available private ioctls :
          set              (8BE2) : set 1536 char  & get   0      
          show             (8BF1) : set 1024 char  & get   0      
          get_site_survey  (8BED) : set   0       & get 1024 char 
          set_wsc_oob      (8BF9) : set 1024 char  & get 1024 char 
          get_mac_table    (8BEF) : set 1024 char  & get 1024 char 
          e2p              (8BE7) : set 1024 char  & get 1024 char 
          bbp              (8BE3) : set 1024 char  & get 1024 char 
          mac              (8BE5) : set 1024 char  & get 1024 char 
          rf               (8BF3) : set 1024 char  & get 1024 char 
          get_wsc_profile  (8BF2) : set 1024 char  & get 1024 char 
          get_ba_table     (8BF6) : set 1024 char  & get 1024 char 
          stat             (8BE9) : set 1024 char  & get 1024 char 

ra2       Available private ioctls :
          set              (8BE2) : set 1536 char  & get   0      
          show             (8BF1) : set 1024 char  & get   0      
          get_site_survey  (8BED) : set   0       & get 1024 char 
          set_wsc_oob      (8BF9) : set 1024 char  & get 1024 char 
          get_mac_table    (8BEF) : set 1024 char  & get 1024 char 
          e2p              (8BE7) : set 1024 char  & get 1024 char 
          bbp              (8BE3) : set 1024 char  & get 1024 char 
          mac              (8BE5) : set 1024 char  & get 1024 char 
          rf               (8BF3) : set 1024 char  & get 1024 char 
          get_wsc_profile  (8BF2) : set 1024 char  & get 1024 char 
          get_ba_table     (8BF6) : set 1024 char  & get 1024 char 
          stat             (8BE9) : set 1024 char  & get 1024 char 

lo        no private ioctls.

eth0.1    no private ioctls.

apcli0    Available private ioctls :
          set              (8BE2) : set 1536 char  & get   0      
          show             (8BF1) : set 1024 char  & get   0      
          get_site_survey  (8BED) : set   0       & get 1024 char 
          set_wsc_oob      (8BF9) : set 1024 char  & get 1024 char 
          get_mac_table    (8BEF) : set 1024 char  & get 1024 char 
          e2p              (8BE7) : set 1024 char  & get 1024 char 
          bbp              (8BE3) : set 1024 char  & get 1024 char 
          mac              (8BE5) : set 1024 char  & get 1024 char 
          rf               (8BF3) : set 1024 char  & get 1024 char 
          get_wsc_profile  (8BF2) : set 1024 char  & get 1024 char 
          get_ba_table     (8BF6) : set 1024 char  & get 1024 char 
          stat             (8BE9) : set 1024 char  & get 1024 char 

ra3       Available private ioctls :
          set              (8BE2) : set 1536 char  & get   0      
          show             (8BF1) : set 1024 char  & get   0      
          get_site_survey  (8BED) : set   0       & get 1024 char 
          set_wsc_oob      (8BF9) : set 1024 char  & get 1024 char 
          get_mac_table    (8BEF) : set 1024 char  & get 1024 char 
          e2p              (8BE7) : set 1024 char  & get 1024 char 
          bbp              (8BE3) : set 1024 char  & get 1024 char 
          mac              (8BE5) : set 1024 char  & get 1024 char 
          rf               (8BF3) : set 1024 char  & get 1024 char 
          get_wsc_profile  (8BF2) : set 1024 char  & get 1024 char 
          get_ba_table     (8BF6) : set 1024 char  & get 1024 char 
          stat             (8BE9) : set 1024 char  & get 1024 char 

ra0       Available private ioctls :
          set              (8BE2) : set 1536 char  & get   0      
          show             (8BF1) : set 1024 char  & get   0      
          get_site_survey  (8BED) : set   0       & get 1024 char 
          set_wsc_oob      (8BF9) : set 1024 char  & get 1024 char 
          get_mac_table    (8BEF) : set 1024 char  & get 1024 char 
          e2p              (8BE7) : set 1024 char  & get 1024 char 
          bbp              (8BE3) : set 1024 char  & get 1024 char 
          mac              (8BE5) : set 1024 char  & get 1024 char 
          rf               (8BF3) : set 1024 char  & get 1024 char 
          get_wsc_profile  (8BF2) : set 1024 char  & get 1024 char 
          get_ba_table     (8BF6) : set 1024 char  & get 1024 char 
          stat             (8BE9) : set 1024 char  & get 1024 char 

eth0      no private ioctls.

eth0.2    no private ioctls.

apcli1    Available private ioctls :
          set              (8BE2) : set 1536 char  & get   0      
          show             (8BF1) : set 1024 char  & get   0      
          get_site_survey  (8BED) : set   0       & get 1024 char 
          set_wsc_oob      (8BF9) : set 1024 char  & get 1024 char 
          get_mac_table    (8BEF) : set 1024 char  & get 1024 char 
          e2p              (8BE7) : set 1024 char  & get 1024 char 
          bbp              (8BE3) : set 1024 char  & get 1024 char 
          mac              (8BE5) : set 1024 char  & get 1024 char 
          rf               (8BF3) : set 1024 char  & get 1024 char 
          get_wsc_profile  (8BF2) : set 1024 char  & get 1024 char 
          get_ba_table     (8BF6) : set 1024 char  & get 1024 char 
          stat             (8BE9) : set 1024 char  & get 1024 char 

Now we can use every ra0, ra1, ra2, ra3 same time by one VoCore2. 🙂
And we can setting network, firewall to use them for guest, nas etc…

PS: it support up to 16 ssids, you need to modify its setting in the same file.

Have fun!

mine is working so well.

VoCore2: Port mt7628.ko to LuCI 8

Install LuCI to the firmware, get some errors:

Tue May 15 00:07:30 2018 daemon.notice netifd: Interface 'wan' has link connectivity
Tue May 15 00:07:30 2018 daemon.notice netifd: radio0 (844): uci: Parse error (too many arguments) at line 24, byte 24
Tue May 15 00:07:30 2018 user.notice firewall: Reloading firewall due to ifup of lan (br-lan)
Tue May 15 00:11:10 2018 daemon.err uhttpd[794]: luci: accepted login on / for root from 192.168.61.231
Tue May 15 00:11:23 2018 daemon.err uhttpd[794]: /usr/lib/lua/luci/dispatcher.lua:509: Failed to execute arcombine dispatcher target for entry '/admin/network/network/wwan'.
Tue May 15 00:11:23 2018 daemon.err uhttpd[794]: The called action terminated with an exception:
Tue May 15 00:11:23 2018 daemon.err uhttpd[794]: /usr/lib/lua/luci/template.lua:97: Failed to execute template 'cbi/map'.
Tue May 15 00:11:23 2018 daemon.err uhttpd[794]: A runtime error occured: /usr/lib/lua/luci/template.lua:97: Failed to execute template 'cbi/nsection'.
Tue May 15 00:11:23 2018 daemon.err uhttpd[794]: A runtime error occured: /usr/lib/lua/luci/template.lua:97: Failed to execute template 'cbi/ucisection'.
Tue May 15 00:11:23 2018 daemon.err uhttpd[794]: A runtime error occured: /usr/lib/lua/luci/template.lua:97: Failed to execute template 'cbi/tabcontainer'.
Tue May 15 00:11:23 2018 daemon.err uhttpd[794]: A runtime error occured: /usr/lib/lua/luci/template.lua:97: Failed to execute template 'cbi/network_ifacelist'.
Tue May 15 00:11:23 2018 daemon.err uhttpd[794]: A runtime error occured: /usr/lib/lua/luci/model/network.lua:1277: bad argument #4 to '?' (no value)
Tue May 15 00:11:23 2018 daemon.err uhttpd[794]: stack traceback:
Tue May 15 00:11:23 2018 daemon.err uhttpd[794]: 	[C]: in function 'assert'
Tue May 15 00:11:23 2018 daemon.err uhttpd[794]: 	/usr/lib/lua/luci/dispatcher.lua:509: in function 'dispatch'
Tue May 15 00:11:23 2018 daemon.err uhttpd[794]: 	/usr/lib/lua/luci/dispatcher.lua:127: in function 
Tue May 15 00:12:19 2018 daemon.err uhttpd[794]: /usr/lib/lua/luci/dispatcher.lua:509: Failed to execute arcombine dispatcher target for entry '/admin/network/network/wwan'.
Tue May 15 00:12:19 2018 daemon.err uhttpd[794]: The called action terminated with an exception:
Tue May 15 00:12:19 2018 daemon.err uhttpd[794]: /usr/lib/lua/luci/template.lua:97: Failed to execute template 'cbi/map'.
Tue May 15 00:12:19 2018 daemon.err uhttpd[794]: A runtime error occured: /usr/lib/lua/luci/template.lua:97: Failed to execute template 'cbi/nsection'.
Tue May 15 00:12:19 2018 daemon.err uhttpd[794]: A runtime error occured: /usr/lib/lua/luci/template.lua:97: Failed to execute template 'cbi/ucisection'.
Tue May 15 00:12:19 2018 daemon.err uhttpd[794]: A runtime error occured: /usr/lib/lua/luci/template.lua:97: Failed to execute template 'cbi/tabcontainer'.
Tue May 15 00:12:19 2018 daemon.err uhttpd[794]: A runtime error occured: /usr/lib/lua/luci/template.lua:97: Failed to execute template 'cbi/network_ifacelist'.
Tue May 15 00:12:19 2018 daemon.err uhttpd[794]: A runtime error occured: /usr/lib/lua/luci/model/network.lua:1277: bad argument #4 to '?' (no value)
Tue May 15 00:12:19 2018 daemon.err uhttpd[794]: stack traceback:
Tue May 15 00:12:19 2018 daemon.err uhttpd[794]: 	[C]: in function 'assert'
Tue May 15 00:12:19 2018 daemon.err uhttpd[794]: 	/usr/lib/lua/luci/dispatcher.lua:509: in function 'dispatch'
Tue May 15 00:12:19 2018 daemon.err uhttpd[794]: 	/usr/lib/lua/luci/dispatcher.lua:127: in function 
Tue May 15 00:12:28 2018 daemon.err uhttpd[794]: /usr/lib/lua/luci/dispatcher.lua:509: Failed to execute arcombine dispatcher target for entry '/admin/network/network/lan'.
Tue May 15 00:12:28 2018 daemon.err uhttpd[794]: The called action terminated with an exception:
Tue May 15 00:12:28 2018 daemon.err uhttpd[794]: /usr/lib/lua/luci/template.lua:97: Failed to execute template 'cbi/map'.
Tue May 15 00:12:28 2018 daemon.err uhttpd[794]: A runtime error occured: /usr/lib/lua/luci/template.lua:97: Failed to execute template 'cbi/nsection'.
Tue May 15 00:12:28 2018 daemon.err uhttpd[794]: A runtime error occured: /usr/lib/lua/luci/template.lua:97: Failed to execute template 'cbi/ucisection'.
Tue May 15 00:12:28 2018 daemon.err uhttpd[794]: A runtime error occured: /usr/lib/lua/luci/template.lua:97: Failed to execute template 'cbi/tabcontainer'.
Tue May 15 00:12:28 2018 daemon.err uhttpd[794]: A runtime error occured: /usr/lib/lua/luci/template.lua:97: Failed to execute template 'cbi/network_ifacelist'.
Tue May 15 00:12:28 2018 daemon.err uhttpd[794]: A runtime error occured: /usr/lib/lua/luci/model/network.lua:1277: bad argument #4 to '?' (no value)
Tue May 15 00:12:28 2018 daemon.err uhttpd[794]: stack traceback:
Tue May 15 00:12:28 2018 daemon.err uhttpd[794]: 	[C]: in function 'assert'
Tue May 15 00:12:28 2018 daemon.err uhttpd[794]: 	/usr/lib/lua/luci/dispatcher.lua:509: in function 'dispatch'
Tue May 15 00:12:28 2018 daemon.err uhttpd[794]: 	/usr/lib/lua/luci/dispatcher.lua:127: in function 
Tue May 15 00:19:48 2018 daemon.err uhttpd[794]: /usr/lib/lua/luci/dispatcher.lua:509: Failed to execute arcombine dispatcher target for entry '/admin/network/network/lan'.
Tue May 15 00:19:48 2018 daemon.err uhttpd[794]: The called action terminated with an exception:
Tue May 15 00:19:48 2018 daemon.err uhttpd[794]: /usr/lib/lua/luci/template.lua:97: Failed to execute template 'cbi/map'.
Tue May 15 00:19:48 2018 daemon.err uhttpd[794]: A runtime error occured: /usr/lib/lua/luci/template.lua:97: Failed to execute template 'cbi/nsection'.
Tue May 15 00:19:48 2018 daemon.err uhttpd[794]: A runtime error occured: /usr/lib/lua/luci/template.lua:97: Failed to execute template 'cbi/ucisection'.
Tue May 15 00:19:48 2018 daemon.err uhttpd[794]: A runtime error occured: /usr/lib/lua/luci/template.lua:97: Failed to execute template 'cbi/tabcontainer'.
Tue May 15 00:19:48 2018 daemon.err uhttpd[794]: A runtime error occured: /usr/lib/lua/luci/template.lua:97: Failed to execute template 'cbi/network_ifacelist'.
Tue May 15 00:19:48 2018 daemon.err uhttpd[794]: A runtime error occured: /usr/lib/lua/luci/model/network.lua:1277: bad argument #4 to '?' (no value)
Tue May 15 00:19:48 2018 daemon.err uhttpd[794]: stack traceback:
Tue May 15 00:19:48 2018 daemon.err uhttpd[794]: 	[C]: in function 'assert'
Tue May 15 00:19:48 2018 daemon.err uhttpd[794]: 	/usr/lib/lua/luci/dispatcher.lua:509: in function 'dispatch'
Tue May 15 00:19:48 2018 daemon.err uhttpd[794]: 	/usr/lib/lua/luci/dispatcher.lua:127: in function 
Tue May 15 00:38:37 2018 daemon.info dnsmasq-dhcp[1152]: DHCPREQUEST(br-lan) 192.168.61.231 78:4f:43:5b:75:57
Tue May 15 00:38:37 2018 daemon.info dnsmasq-dhcp[1152]: DHCPACK(br-lan) 192.168.61.231 78:4f:43:5b:75:57 Vongers-MBP-2
Tue May 15 00:38:37 2018 daemon.warn odhcpd[705]: DHCPV6 SOLICIT IA_NA from 00010001217b622f784f435b7557 on br-lan: ok fd2d:f637:12aa::4e9/128
Tue May 15 00:38:38 2018 daemon.warn odhcpd[705]: DHCPV6 REQUEST IA_NA from 00010001217b622f784f435b7557 on br-lan: ok fd2d:f637:12aa::4e9/128

I did not install iwinfo, so that should be one of the problem.
LuCI netdev interface can not be edit, that should be something missed.

VoCore2: Setup OpenWrt in MacOS 10.13

Just copy from openwrt official site.

I used to use port but brew looks better now.

First, install brew.

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

It is broken when I install it, need to set privilege for some folders, you can call “brew doctor” to get instruction then fix it or search google 🙂

brew install coreutils diffutils findutils gawk gnu-getopt gnu-tar grep wget quilt xz gnu-time

note: in my macbook, I find getopt do not support –long. Looks like default it will find the getopt from MacOS (/usr/bin) but not the one from brew.

add this line to your ~/.profile, so system will search and use gnu-getopt first.(this path will be different if version of getopt changed)

export PATH="/usr/local/Cellar/gnu-getopt/1.1.6/bin:$PATH"

Then make a virtual disk by disk-utils, must be case sensitive disk, size around 20GB.

Clone openwrt latest version from github to the new disk.

git clone https://github.com/openwrt/openwrt.git

Then make menuconfig, everything will work.

If you want install mt7628.ko into the firmware, follow the tutorial at https://github.com/vonger/vocore2

VoCore2: Port mt7628.ko to LuCI 7

I find VoCore2 led is not working with new driver mt7628,ko, it is because in /etc/config/system, led is set to “wlan0” which is used by mt76 drivers.

So make a simple patch to fix it.

diff -Naur a/target/linux/ramips/base-files/etc/board.d/01_leds b/target/linux/ramips/base-files/etc/board.d/01_leds
--- a/target/linux/ramips/base-files/etc/board.d/01_leds
+++ b/target/linux/ramips/base-files/etc/board.d/01_leds
@@ -443,10 +443,10 @@
 	set_wifi_led "vocore:green:status"
 	;;
 vocore2)
-	set_wifi_led "$boardname:fuchsia:status"
+	set_wifi_led "$boardname:fuchsia:status" "ra0"
 	;;
 vocore2lite)
-	set_wifi_led "$boardname:green:status"
+	set_wifi_led "$boardname:green:status" "ra0"
 	;;
 w502u)
 	set_usb_led "$boardname:blue:usb"

Note: new version VoCore2 I plan to use red led, one reason is red more like heart than fuchsia, so when we transfer data, it is like its heartbeat, this is my VoCore2 Ultimate first design.
Another reason…fuchsia led is very shortage, every time it is hard to get (looks like not many people use it) 🙂

VoCore2: Port mt7628.ko to LuCI 6

I think it is working now 🙂

1. copy /etc/config/wireless from current vocore2 firmware to same folder.
2. copy /lib/netifd/wireless/ralink.sh from current vocore2 firmware to same folder.
3. chmod +x /lib/netifd/wireless/ralink.sh

Then reboot, at least ap mode is working.
Still some parameters and sta mode are not working, but these bugs should be easy to fix 🙂

OK, next time I can make a patch and put to github.

VoCore2: Port mt7628.ko to LuCI 5

Back to the old firmware based on OpenWrt CC. So only file related is /lib/netifd/wireless/ralink.sh

#!/bin/sh
. /lib/netifd/netifd-wireless.sh

init_wireless_driver "$@"
maclist=""
force_channel=""

drv_ralink_init_device_config() {
	config_add_string country variant log_level short_preamble
	config_add_boolean noscan
	config_add_int channel
}

drv_ralink_init_iface_config() {
	config_add_string 'auth_server:host'
	config_add_string auth_secret
	config_add_int 'auth_port:port'

	config_add_string ifname apname mode ssid encryption key key1 key2 key3 key4 wps_pushbutton macfilter led
        config_add_boolean hidden isolate
        config_add_array 'maclist:list(macaddr)'
}

drv_ralink_cleanup() {
	logger drv_ralink_cleanup
}

ralink_setup_ap(){
	local name="$1"
	local eap=0

	json_select config
	json_get_vars mode ifname ssid encryption key key1 key2 key3 key4 wps_pushbutton server port hidden isolate macfilter
	json_get_values maclist maclist

	ifconfig $ifname up

	[ -z "$force_channel" ] || iwpriv $ifname set Channel=$force_channel
	[ "$isolate" = 1 ] || isolate=0
	iwpriv $ifname set NoForwarding=$isolate
	iwpriv $ifname set NoForwardingBTNBSSID=$isolate
	iwpriv $ifname set NoForwardingMBCast=$isolate
	
	[ "$hidden" = 1 ] || hidden=0
	iwpriv $ifname set HideSSID=$hidden

	wsc_methods=0
	wsc_mode=0
	case "$encryption" in
	psk*|mixed*)
		local enc="WPA2PSK"
		case "$encryption" in
			psk | psk+*) enc=WPAPSK;;
			psk2 | psk2*) enc=WPA2PSK;;
			mixed*) enc=WPAPSKWPA2PSK;;
			wpa | wpa+*) eap=1; enc=WPA;;
			wpa2*) eap=1; enc=WPA2;;
		esac
		local crypto="AES"
		case "$encryption" in
			*tkip+aes*) crypto=TKIPAES;;
			*tkip*) crypto=TKIP;;
		esac
		[ "$eap" = "1" ] && {
			iwpriv $ifname set RADIUS_Server=$server
			iwpriv $ifname set RADIUS_Port=$port
			iwpriv $ifname set RADIUS_Key=$key
			iwpriv $ifname set own_ip_addr=192.168.1.1
			iwpriv $ifname set IEEE8021X=0
			iwpriv $ifname set EAPifname=eth0.2
			iwpriv $ifname set PreAuthIfname=br-lan
		}
		iwpriv $ifname set AuthMode=$enc
		iwpriv $ifname set EncrypType=$crypto
		iwpriv $ifname set IEEE8021X=0
		iwpriv $ifname set "SSID=${ssid}"
		[ "$eap" = "1" ] || iwpriv $ifname set "WPAPSK=${key}"
		iwpriv $ifname set DefaultKeyID=2
		iwpriv $ifname set "SSID=${ssid}"
		if [ "$wps_pushbutton" == "1" ]; then
			wsc_methods=128
			wsc_mode=7
		fi
		;;
	wep)
		iwpriv $ifname set AuthMode=WEPAUTO
		iwpriv $ifname set EncrypType=WEP
		iwpriv $ifname set IEEE8021X=0
		for idx in 1 2 3 4; do
			json_get_var keyn key${idx}
			[ -n "$keyn" ] && iwpriv $ifname set "Key${idx}=${keyn}"
		done
		iwpriv $ifname set DefaultKeyID=${key}
		iwpriv $ifname set "SSID=${ssid}"
		;;
	none)
		iwpriv $ifname set "SSID=${ssid}"
		;;
	esac

	iwpriv $ifname set WscConfMode=$wsc_mode
	iwpriv $ifname set WscConfStatus=2
	iwpriv $ifname set WscMode=2
	iwpriv $ifname set ACLClearAll=1
	[ -n "$maclist" ] && {
		for m in ${maclist}; do
			logger iwpriv $ifname set ACLAddEntry="$m"
			iwpriv $ifname set ACLAddEntry="$m"
		done
	}
	case "$macfilter" in
	allow)
		iwpriv $ifname set AccessPolicy=1
		;;
	deny)
		iwpriv $ifname set AccessPolicy=2
		;;
	*)
		iwpriv $ifname set AccessPolicy=0
		;;
	esac
	json_select ..


	wireless_add_vif "$name" "$ifname"
}

ralink_setup_sta(){
	local name="$1"

	json_select config
	json_get_vars mode apname ifname ssid encryption key key1 key2 key3 key4 wps_pushbutton disabled led

	[ "$disabled" = "1" ] && return

	key=
	case "$encryption" in
		psk*|mixed*) json_get_vars key;;
		wep) json_get_var key key1;;
	esac
	json_select ..

	/sbin/ap_client "ra0" "$ifname" "${ssid}" "${key}" "${led}"
	sleep 1
	wireless_add_process "$(cat /tmp/apcli-${ifname}.pid)" /sbin/ap_client ra0 "$ifname" "${ssid}" "${key}" "${led}"

	wireless_add_vif "$name" "$ifname"
}

drv_ralink_setup() {
	local ifname="$1"
	local bcn_active=0
	wmode=9
	VHT=0
	VHT_SGI=0
	HT=0
	EXTCHA=0

	sta_disabled="$(uci get wireless.sta.disabled)"

	[ "${sta_disabled}" = "1" ] && bcn_active=1

	json_select config
	json_get_vars variant country channel htmode log_level short_preamble noscan:0
	json_select ..

	[ "$short_preamble" = 1 ] || short_preamble=0 

	case ${htmode:-none} in
	HT20)
		wmode=10
		HT=0
		;;
	HT40)
		wmode=10
		HT=1
		EXTCHA=1
		;;
	VHT20)
		wmode=15
		HT=0
		VHT=0
		VHT_SGI=1
		;;
	VHT40)
		wmode=15
		HT=1
		VHT=0
		VHT_SGI=1
		EXTCHA=1
		;;
	VHT80)
		wmode=15
		HT=1
		VHT=1
		VHT_SGI=1
		EXTCHA=1
		;;
	*)
		case $hwmode in
		a) wmode=2;;
		g) wmode=3;;
		esac
		;;
	esac

	if [ "$auto_channel" -gt 0 ]; then
		force_channel=""
		channel=0
		auto_channel=3
	else
		force_channel=$channel
		auto_channel=0
	fi

	coex=1
	[ "$noscan" -gt 0 ] && coex=0

	cat /etc/Wireless/${variant}_tpl.dat > /tmp/${variant}.dat
	cat >> /tmp/${variant}.dat << EOF
Beacon=${bcn_active}
BssidNum=4
HT_BW=${HT:-0}
HT_EXTCHA=${EXTCHA:-0}
CountryCode=${country}
WirelessMode=${wmode:-9}
Channel=${channel:-8}
AutoChannelSelect=$auto_channel
Debug=${log_level:-3}
SSID1=${ssid:-OpenWrt}
HT_BSSCoexistence=$coex
WscConfMethods=680
EOF
	for_each_interface "ap" ralink_setup_ap
	for_each_interface "sta" ralink_setup_sta
	wireless_set_up
	LED="$(uci get wireless.sta.led)"
	sta_disabled="$(uci get wireless.sta.disabled)"
	[ "${sta_disabled}" = "1" -a -n "${LED}" -a -f /sys/class/leds/${LED}/trigger ] && ap_client ${LED} set
}

ralink_teardown() {
	json_select config
	json_get_vars ifname
	json_select ..

	ifconfig $ifname down

	LED="$(uci get wireless.sta.led)"
	[ -n "${LED}" -a -f /sys/class/leds/${LED}/trigger ] && ap_client ${LED} clear
}

drv_ralink_teardown() {
	wireless_process_kill_all
	for_each_interface "ap sta" ralink_teardown
}

add_driver ralink

This code is using iwpriv setting up the driver, so it should be directly working.
drv_ralink_setup get country, channel, htmode, and setting this in driver.
then enable every ap interface and sta interface by ralink_setup_ap/ralink_setup_sta.

ralink_setup_ap get "mode ifname ssid encryption key key1 key2 key3 key4 wps_pushbutton server port hidden isolate macfilter" and setting up those value in mt7628.ko by iwpriv directly.

ralink_setup_sta is the ap+sta mode, it will call /sbin/ap_client to setup the ap+sta mode.

Everything is clear, I can make my own ralink.sh based on this beautiful script 🙂

VoCore Screen: Update with Raspberry Pi

I have updated the screen SDK and ADD RASPBERRY PI support, it is in SDK named lib/raspi/libvodisp.so

Like all other linux system, raspberry pi must use root to send data through USB…my raspberryPi is very slow(maybe it is because its index is zero, power consume is pretty high…1 watt+ 🙂

Currently SDK already has base function to show something on the screen, but still left a lot to do…

1. More Color Mode Support: 8bit colors, 16bit colors

enable this to support more games with less CPU, such as NEOGEO/FC, etc…

2. Linux Kernel Driver(fbcon)

enable this to enable console data directly output to screen and a real frame buffer function.

3. Rotated/Mirror Support

hardware support for fast convert speed.

4. RGB/BGR Pixel Order

5. Backlight PWM Control

6. Touch Screen

Hopefully once I finish step 1 and 2 in a few weeks, I can open source the kernel code. Currently this core firmware code is write by C and ASM and it is very ugly(or tricky) anyway I do not plan to open source it. But I will provide blob(vodisp.ko) with detailed documentation and interfaces later.

Actually the interface of vodisp.ko is pretty simple, just two, one is used to setting up the chip — I call it “connect” or “open”, another is used to send RGB or BGR pixel data from USB to screen, I call it “write”.

Emm, I guess we can use standard C interface for driver: open/close/write/ioctl, ioctl is good enough do the setting up job 🙂

VoCore2: Port mt7628.ko to LuCI 4

now create simple test script in /lib/netifd/wireless/mt7628.sh

#!/bin/sh
. /lib/netifd/netifd-wireless.sh
. /lib/netifd/hostapd.sh

init_wireless_driver "$@"

drv_mt7628_setup() {
	echo drv_mt7628_setup >> /tmp/wifi.log
}

drv_mt7628_teardown() {
	echo drv_mt7628_teardown >> /tmp/wifi.log
}

drv_mt7628_cleanup() {
        hostapd_common_cleanup
}

drv_mt7628_init_device_config() {
	echo drv_mt7628_init_device_config >> /tmp/wifi.log
}

drv_mt7628_init_iface_config() {
	echo drv_mt7628_init_iface_config >> /tmp/wifi.log
}

add_driver mt7628

other setting file in /etc/config/wireless

config wifi-device 'ra0'
	option type 'mt7628'
	option channel '11'
	option hwmode '11g'
	option path 'platform/10300000.wmac'
	option htmode 'HT20'
	option disabled '0'

config wifi-iface 'default-ap'
	option device 'ra0'
	option network 'lan'
	option mode 'ap'
	option ssid 'VoCore2'
	option encryption 'none'

mt7628 can be replace to others, such as mac80211 etc…this must be same in the file name, the function name and in setting file option type.

reboot and check /tmp/wifi.log

drv_mt7628_init_device_config
drv_mt7628_init_iface_config
drv_mt7628_setup
drv_mt7628_teardown
drv_mt7628_setup
drv_mt7628_teardown
drv_mt7628_setup
drv_mt7628_teardown
drv_mt7628_setup
drv_mt7628_teardown

It is almost done!

VoCore2: Port mt7628.ko to LuCI 3

Get some progress 🙂

PS: This uci system is so hard to understand, it has executables, libraries and also scripts without any documentation…I guess from beginning its designer never think about portable…

The real call wifi up/down is this from /sbin/wifi: ubus_wifi_cmd “$cmd” “$2”

_wifi_updown() {                                
        for device in ${2:-$DEVICES}; do (       
                config_get disabled "$device" disabled
                [ "$disabled" = "1" ] && {       
                        echo "'$device' is disabled"
                        set disable                   
                }                                     
                config_get iftype "$device" type    
                if eval "type ${1}_$iftype" 2>/dev/null >/dev/null; then
                        eval "scan_$iftype '$device'"                   
                        eval "${1}_$iftype '$device'" || echo "$device($iftype): ${1} failed"
                elif [ ! -f /lib/netifd/wireless/$iftype.sh ]; then                          
                        echo "$device($iftype): Interface type not supported"                
                fi                                                           
        ); done                                                              
}                                                                                            
                                                                                             
wifi_updown() {                                                              
        cmd=down                                                             
        [ enable = "$1" ] && {                                          
                _wifi_updown disable "$2"                                                    
                ubus_wifi_cmd "$cmd" "$2"                                                    
                scan_wifi                                                                    
                cmd=up                                                                       
        }                                                                                    
        ubus_wifi_cmd "$cmd" "$2"                                            
        _wifi_updown "$@"                                                    
} 

Rest code…I do not understand yet, maybe separated setting up?

Now check ubus_wifi_cmd

ubus_wifi_cmd() {
        local cmd="$1"
        local dev="$2"

        json_init
        [ -n "$2" ] && json_add_string device "$2"
        ubus call network.wireless "$1" "$(json_dump)"
}

Once we run wifi, in this function, it is calling

ubus call network.wireless down { }
ubus call network.wireless up { }

This should be different from old version, because I can not find any function named “mac80211_enable” or “enable_mac80211”, so the script enable way is not working anymore.

What is ubus…?
It is a small application used to transfer data between processes by socket/udp protocol.

It has many protocol, and this protocol is hard coded in the ubus source code by C.

root@OpenWrt:/etc# ubus list
dhcp
dnsmasq
hostapd.wlan0
log
network
network.device
network.interface
network.interface.lan
network.interface.loopback
network.wireless
service
system

You see? network.wireless is one of its compose.
At least ubus I can find some tutorials 🙂

I can run ubus monitor to check what is transfer when I call wifi down.

-> 070d3ffa #00000003         status: {"status":0}
-> 3aa4a160 #3aa4a160          hello: {}
<- 3aa4a160 #00000000         lookup: {"objpath":"network.wireless"}
-> 3aa4a160 #00000000           data: {"objpath":"network.wireless","objid":-946844025,"objtype":976669475,"signature":{"up":{},"down":{},"status":{},"notify":{},"get_validate":{}}}
-> 3aa4a160 #00000000         status: {"status":0}
<- 3aa4a160 #c7904e87         invoke: {"objid":-946844025,"method":"down","data":{}}
-> 7d12fdb8 #3aa4a160         invoke: {"objid":-946844025,"method":"down","data":{},"user":"root","group":"root"}
<- 7d12fdb8 #3aa4a160         status: {"status":0,"objid":-946844025}
-> 3aa4a160 #c7904e87         status: {"status":0,"objid":-946844025}

Emm, still no clue where it goes…
Have to search the source code, key word “network.wireless”

Catch it! I get something at “netifd-2018-04-03-xxxx”. So I guess network.wireless is registered in this netifd/ubus.c

static struct ubus_object wireless_object = {
        .name = "network.wireless",
        .type = &wireless_object_type,
        .methods = wireless_object_methods,
        .n_methods = ARRAY_SIZE(wireless_object_methods),
};

This interface looks much better, I can guess with its name “wireless_object_methods” must contains the feature to control wireless up and down.

I am right 🙂 In same ubus.c I find its define.

static struct ubus_method wireless_object_methods[] = {
        { .name = "up", .handler = netifd_handle_wdev_up },
        { .name = "down", .handler = netifd_handle_wdev_down },
        { .name = "status", .handler = netifd_handle_wdev_status },
        { .name = "notify", .handler = netifd_handle_wdev_notify },
        { .name = "get_validate", .handler = netifd_handle_wdev_get_validate },
};

Now let’s check what is netifd_handle_wdev_up, in same file too.

static int
netifd_handle_wdev_up(struct ubus_context *ctx, struct ubus_object *obj,
                      struct ubus_request_data *req, const char *method,
                      struct blob_attr *msg)
{
        struct wireless_device *wdev;
        int ret;

        wdev = get_wdev(msg, &ret);
        if (ret == UBUS_STATUS_NOT_FOUND)
                return ret;

        if (wdev) {
                wireless_device_set_up(wdev);
        } else {
                vlist_for_each_element(&wireless_devices, wdev, node)
                        wireless_device_set_up(wdev);
        }

        return 0;
}

static int
netifd_handle_wdev_down(struct ubus_context *ctx, struct ubus_object *obj,
                        struct ubus_request_data *req, const char *method,
                        struct blob_attr *msg)
{
        struct wireless_device *wdev;
        int ret;

        wdev = get_wdev(msg, &ret);
        if (ret == UBUS_STATUS_NOT_FOUND)
                return ret;

        if (wdev) {
                wireless_device_set_down(wdev);
        } else {
                vlist_for_each_element(&wireless_devices, wdev, node)
                        wireless_device_set_down(wdev);
        }

        return 0;
}

They are all calling wireless_device_set_up/wireless_device_set_down, in wireless.c

static void
__wireless_device_set_up(struct wireless_device *wdev)
{
        if (wdev->disabled)
                return;

        if (wdev->retry_setup_failed)
                return;

        if (!wdev->autostart)
                return;

        if (wdev->state != IFS_DOWN || config_init)
                return;

        free(wdev->prev_config);
        wdev->prev_config = NULL;
        wdev->state = IFS_SETUP;
        wireless_device_run_handler(wdev, true);
}

check wireless_device_run_handler, same file

static void
wireless_device_run_handler(struct wireless_device *wdev, bool up)
{
        const char *action = up ? "setup" : "teardown";
        const char *argv[6];
        char *config;
        int i = 0;
        int fds[2] = { -1, -1 };

        D(WIRELESS, "Wireless device '%s' run %s handler\n", wdev->name, action);
        if (!up && wdev->prev_config) {
                config = blobmsg_format_json(wdev->prev_config, true);
                free(wdev->prev_config);
                wdev->prev_config = NULL;
        } else {
                prepare_config(wdev, &b, up);
                config = blobmsg_format_json(b.head, true);
        }

        argv[i++] = wdev->drv->script;
        argv[i++] = wdev->drv->name;
        argv[i++] = action;
        argv[i++] = wdev->name;
        argv[i++] = config;
        argv[i] = NULL;

        if (up && pipe(fds) == 0) {
                wdev->script_proc_fd.fd = fds[0];
                uloop_fd_add(&wdev->script_proc_fd,
                             ULOOP_READ | ULOOP_EDGE_TRIGGER);
        }

        netifd_start_process(argv, NULL, &wdev->script_task);

        if (fds[1] >= 0)
                close(fds[1]);

        free(config);
}

Haha, I guess it is running script here.

What is in argv… I do not know, but should be easy, let’s add log to the file.

main.c:netifd_start_process

...

 if (pfds[1] > 2)
     close(pfds[1]);

+{
+    FILE *fp = fopen("/tmp/netifd.log", "a+");
+    int id = 0;
+    for (; argv[id]; id++)
+        fprintf(fp, "%d: %s\n", id, argv[id]);
+    fclose(fp);
+}

 execvp(argv[0], (char **) argv);
...

make package/network/config/netifd

Get this result:

0: ./mac80211.sh
1: mac80211
2: setup
3: radio0
4: {"config":{"channel":"11","hwmode":"11g","path":"platform\/10300000.wmac","htmode":"HT20","disabled":false},"interfaces":{"0":{"bridge":"br-lan","config":{"mode":"ap","ssid":"OpenWrt","encryption":"none","network":["lan"],"mode":"ap"}}}}

The parameters are send to netifd-wireless.sh:init_wireless_driver
name = mac80211
cmd = setup
interface = radio0
data = {…}

init_wireless_driver() {
	name="$1"; shift
	cmd="$1"; shift

	case "$cmd" in
		dump)
			add_driver() {
				eval "drv_$1_cleanup"

				json_init
				json_add_string name "$1"

				json_add_array device
				_wdev_common_device_config
				eval "drv_$1_init_device_config"
				json_close_array

				json_add_array iface
				_wdev_common_iface_config
				eval "drv_$1_init_iface_config"
				json_close_array

				json_dump
			}
		;;
		setup|teardown)
			interface="$1"; shift
			data="$1"; shift
			export __netifd_device="$interface"

			add_driver() {
				[[ "$name" == "$1" ]] || return 0
				_wdev_handler "$1" "$cmd"
			}
		;;
	esac
}

Setup will call: _wdev_handler mac80211 setup

_wdev_handler() {                                     
        json_load "$data"                             
                                                      
        json_select config                            
        _wdev_prepare_channel                         
        json_select ..                                
                                                      
        eval "drv_$1_$2 \"$interface\""               
}     

that is drv_mac80211_setup, this function is in /lib/netifd/wireless/mac80211.sh, from my test, it will only run once at startup wifi.

Now everything is clear, time to move on merge the driver!