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!

VoCore2: Port mt7628.ko to LuCI 2

Keep study 🙂

This is the /etc/config/wireless from old version vocore2(Linux 3.18) which is working well with uci system. Thanks to its contributors. It is from Linkit.

config wifi-device	radio0
	option type     ralink
	option variant	mt7628
	option country	CN
	option hwmode	11g
	option htmode	HT40
	option channel  auto
	option disabled	0

config wifi-iface ap
	option device   radio0
	option mode	ap
	option network  lan
	option ifname   ra0
	option ssid	VoCore2
	option encryption none 

config wifi-iface sta
	option device   radio0
	option mode	sta
	option network  wwan
	option ifname   apcli0
	option led 	mediatek:orange:wifi
	option ssid	UplinkAp
	option key	SecretKey
	option encryption psk
	option disabled	1

Note: this file is generated by /lib/wifi/ralink.sh:detect_ralink

Now we can add some log to /lib/netifd/wireless/ralink.sh, check how it read the file and how it call the driver to setup the connection.

It is a pretty long script…

If my last blog is correct, it will call “enable_ralink” … what? no such function…
OK, let’s add some log to it. In every function head, we can add “echo xxxxxx_function >> /tmp/vocore2.log”, it will show the called function name into vocore2.log.

But nothing show in the file…so it is not used at all!

How it works? just a mystery.

Emm, it won’t help, get rid of it, let’s check openwrt with mt76 script, that one works without hack.

No luck today, try tomorrow.

To be continue…

VoCore2: Port mt7628.ko to LuCI

This will be a long journey…
LuCI should be the most easy way to setting router.

I will study from start, try to learn how uci system works and how LuCI works with current openwrt system.

I know something about C/C++, maybe RF, PCB layout or even physics, but I am absolutely a noob of script especially bash.

Lucky me, 50% UCI system is based on shell script. 🙂 So I have a chance to learn it.

For wifi turn on or turn off, all I know is the magic command “wifi”, so what is it?

I find it actually a script, its path can be found by call “which wifi”

interface code of /sbin/wifi

case "$1" in
	down) wifi_updown "disable" "$2";;
	detect) wifi_detect_notice ;;
	config) wifi_config ;;
	status) ubus_wifi_cmd "status" "$2";;
	reload) wifi_reload "$2";;
	reload_legacy) wifi_reload_legacy "$2";;
	--help|help) usage;;
	*) ubus call network reload; wifi_updown "enable" "$2";;
esac

After couple of hours painful decode wifi script, looks like once we call wifi, it will goto ‘*) ubus call network reload; wifi_updown “enable” “$2”;;

I reach a dead end at the beginning. What is this “ubus call network reload”? Is it an important part of uci system? I directly run it in command line, nothing happens…OK, ignore it.

PS: That’s why I hate script, you will be very hard to find what it is exactly doing.

Next it is “wifi_updown enable”. Good name, from its name I know it is able to control enable/disable wifi.

_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 "$@"
}

$DEVICE, this should come from scan_wifi.

wifi script it will read /lib/wifi/mt7628.sh, and once we run wifi, it will call function in mt7628.sh, scan_mt7628/enable_mt7628/disable_mt7628 and all the parameters are from /etc/config/wireless.

To Be Continue…

VoCore2: Port mt7628.ko for Linux 4.14 Part2

I have upload source code of uictx to github: https://github.com/Vonger/uictx.git, and also mt7628 driver.
So you can make your own latest version of openwrt now.

PS: please help me do a homework 🙂

1. use it as a OpenWRT feeds, so people do not have to manually do the compile.

2. combine the api to UCI, so we can use UCI and /etc/config/wireless to control the wifi.

Feel free to submit patch.

Note: my last firmware 20180419.bin have some log like this:

lts
[  108.175895] mmc0: error -22 whilst initialising MMC card
[  108.263953] mtk-sd 10130000.sdhci: no support for card's volts

This is because you do not have SD card hardware. We have two ways, one call “rmmod mtk_sd” in console.

Another, use this firmware :p
http://vonger.cn/misc/vocore2/20180419V.bin

md5: 41fc7dfb02bd183de8a520ad146a65b8

I added shellinabox to this firmware, so you can directly access to console without using ssh or putty. Open 192.168.61.1:4200.

Or third way, compile your own firmware without mtk_sd.

Happy hacking!!

VoCore2: Port mt7628.ko to Linux4.14

Yes, I have successfully port mt7628.ko to latest openwrt based on Linux 4.14.

Here is the firmware: http://vonger.cn/misc/vocore2/20180419.bin

md5: 547fba4379e61fefb145cef2e1c30609

This firmware can not working with uci system yet…

PS: I am still study UCI…

But I write a simple replace.
It is a cgi-bin app, can run in /www/cgi-bin or directly run in console command line.

if you want to use it as webserver, just run http://192.168.61.1/cgi-bin/uictx?f=sta_disconnect in your browser.

if you want to use it as command, just run uictx “f=sta_disconnect” in command line.

 

### ap_set_ssid

– used to set current ap ssid name.
– usage: ap_set_ssid [ssid]
– example: http://192.168.61.1/cgi-bin/uictx?f=ap_set_ssid&p1=VoCore2

### ap_set_password

– used to set current ap ssid password.
– usage: ap_set_password [password]
– example: http://192.168.61.1/cgi-bin/uictx?f=ap_set_password&p1=12345678

## Scan API

### ap_scan

– get nearby ssid, bssid, and signal strength.
– usage: ap_scan
– example: http://192.168.61.1/cgi-bin/uictx?f=ap_scan
– return: {“status”:”success”, “message”:””, “ssid1″:”KB86”, “bssid1″:”30:b4:9e:a6:99:bb”, “signal1″:”99”, “ssid2″:””, “bssid2″:”28:6c:07:cc:e7:46”, “signal2″:”18”, “ssid3″:”CX-8888”, “bssid3″:”30:c8:9e:aa:e6:2f”, “signal3″:”57”}

## Station Mode API

### sta_connect

– connect to nearby access point as client device. if everything is correct, it will alloc a ip for apcli0. MUST call ap_scan before sta_connect.
– usage:
– normal ap: sta_connect [ssid] [password]
– hidden ap: sta_connect “” [password] [bssid]
– example1: http://192.168.61.1/cgi-bin/uictx?f=sta_connect&p1=MY%20ROUTE&p2=88884444

note: in the example, “MY ROUTE” has a space, it needs to convert into url format.

– example2: http://192.168.61.1/cgi-bin/uictx?f=sta_connect&p1=&p2=88884444&p3=30:b4:9e:a6:99:bb

### sta_disconnect

– disconnect from connected access point, you will immediatily disconnect from your router and vocore will back to ap mode.
– usage: sta_disconnect
– example: http://192.168.61.1/cgi-bin/uictx?f=sta_disconnect

Source code I will upload to github soon.

 

PS: do not forget setting up the network first.

uci add_list firewall.@zone[1].network="wwan"
uci set network.wan=interface
uci set network.wan.ifname=eth0.2
uci set network.wan.force_link=1
uci set network.wan.proto=dhcp
uci set network.wwan=interface
uci set network.wwan.ifname=apcli0
uci set network.wwan.proto=dhcp
uci commit

VoCore2 + DOOM Port

[embedyt] https://www.youtube.com/watch?v=homxYyDKVis[/embedyt]

I spend around 10 hours finish this, looks like it is pretty easy to port exists project to using VoCore2 display.

First checkout source code from git@github.com:Vonger/Doom.git, thanks for its contributor jeffdoggett, other DOOM source code I can not even compile 🙂

Only need to change one file /Doom/Source/i_video.c

//
// DESCRIPTION:
//	DOOM graphics stuff for VoCore2 Display, OpenWrt.
//  based on i_video.c.
//
//-----------------------------------------------------------------------------

#include "includes.h"
#include "libvodisp.h"

unsigned int SCREENWIDTH = 320;
unsigned int SCREENHEIGHT = 200;
unsigned int ORIGSCREENWIDTH = 320;
unsigned int ORIGSCREENHEIGHT = 200;

union pixel {
    struct _rgb {
        unsigned char red;
        unsigned char green;
        unsigned char blue;
    }rgb;
    unsigned int full:24;
};
static union pixel palette_table[256];
static byte *framebuffer;

void I_InitGraphics (void)
{
    framebuffer = malloc(800 * 480 * 3);
    memset(framebuffer, 0, 800 * 480 * 3);

    vodisp_connect();
}

void I_ShutdownGraphics(void)
{
    vodisp_disconnect();
}

void I_SetPalette (byte* palette)
{
    unsigned int colour = 0;
    do {
        palette_table[colour].rgb.blue   = gammatable[usegamma][*palette++];
        palette_table[colour].rgb.green = gammatable[usegamma][*palette++];
        palette_table[colour].rgb.red  = gammatable[usegamma][*palette++];
    } while (++colour < 256);
}

void I_FinishUpdate (void)
{
    byte *src = screens[0], *dst = framebuffer;
    int i, j, pos;

    for (j = 0; j < SCREENHEIGHT; j++) {
        pos = j * 480 * 3;
        for (i = 0; i < SCREENWIDTH; i++)
            *(unsigned int *)(dst + pos + i * 3) = palette_table[*src++].full;
    }

    vodisp_write_frame(framebuffer);
}

void I_ReadScreen (byte* scr)
{
    memcpy(scr, screens[0], SCREENWIDTH * SCREENHEIGHT);
}

void I_InitKeyboard (void)
{
}

void I_UpdateNoBlit (void)
{
}

void I_SetScreenSize (void)
{
}

void I_SetWindowName (const char * title)
{
}

void I_StartFrame (void)
{
}

void I_StartTic (void)
{
}

Here is necessary library and Makefile, you might need to modify.

Download: http://vonger.cn/misc/vocore2/doom.openwrt.tar.xz, uncompress and put it in /Doom/Source then compile.