#!/bin/sh

#add stm32_eth_config script to enable USB Ethernet & MSC gadget This script configures USB Gadget
#configfs to use USB OTG as a USB Ethernet Gadget with Remote NDIS (RNDIS), well supported by Microsoft
#Windows and Linux.

if [ ! -e /etc/default/usbcdc ];then
    ECM0=172.31.255.192;
    printf "ECM0=\"%s\";\n" ${ECM0} > /etc/default/usbcdc
else
    source /etc/default/usbcdc
fi;

ARCH=$(cut -d- -f1 /etc/rpm/platform)
ARCH_FAMILY=$(echo ${ARCH} |tr '_' '-' |cut -d- -f1)

if [ "${ARCH_FAMILY}" == "raspberrypi" ];then
    PROD="Comb NS (${ARCH_FAMILY})"
 else
    PROD=$(tr -d '\0' <  /proc/device-tree/model)
fi;

ARCH=$(cut -d- -f1 /etc/rpm/platform)
ARCH_FAMILY=$(echo ${ARCH} |tr '_' '-' |cut -d- -f1)

configfs="/sys/kernel/config/usb_gadget"
g=g1
c=c.1
d="${configfs}/${g}"
func_eth=rndis.0
func_ms=mass_storage.0

VENDOR_ID="0x1d6b"
PRODUCT_ID="0x0104"

IP="192.168.7.2"
NETMASK="255.255.255.0"

#MAC address for ethernet-over-USB can be defined here
MAC_HOST_CUST=""
MAC_DEV_CUST=""

I2C=$(ls -d  /sys/bus/i2c/drivers/nau8810/*1a |cut -d/ -f7 |cut -d- -f1)

get_i2c() {
        if i2cdetect -a -r -y ${I2C} 0x${1} 0x${1} |tail -8 |cut -c5- |grep ${1} > /dev/null 2>&1;then
                return 0;
        else
                return 1;
        fi;
}

setup_route_ecm() {
	ORIGIFS=${IFS}
	local IFS
	IFS=.
	set -- $*
	IFS=${ORIGIFS}

	NW=$(($4 & 0xFFFC))
	IP=$((${NW} + 1))
	REM=$((${NW} + 2))
	BASE=${1}.${2}.${3}

	/sbin/ip link set up dev ecm0
	#Do not use label dnsmasq does not work
	/sbin/ip addr add ${BASE}.${IP}/30 brd + dev ecm0
	/sbin/ip route add default via ${BASE}.${REM} metric 250

	/sbin/ip rule add prio 50 from ${BASE}.${IP} table 50
	/sbin/ip rule add prio 50 oif ecm0 table 50
	/sbin/ip route add ${BASE}.${NW}/30 proto kernel scope link dev ecm0 src ${BASE}.${IP} metric 250 table 50
	/sbin/ip route add default via ${BASE}.${REM} metric 250 table 50
}

setup_route_ecm_stop() {
        /sbin/ip link set down dev ecm0 | :
        /sbin/ip -4 addr flush dev ecm0 | :
        /sbin/ip route flush dev ecm0 | :
        /sbin/ip route flush table 50 | :
        while /sbin/ip rule del prio 50 >/dev/null 2>&1;do :;done
}

setup_info() {
    echo ${DEV_SERIAL} > "${d}/strings/0x409/serialnumber"
    echo "Comb Communications" > "${d}/strings/0x409/manufacturer"
    echo "${PROD}" > "${d}/strings/0x409/product"
}

get_mac_address_from_serial_number(){
    sha1sum /proc/device-tree/serial-number \
    | fold -1 \
    | sed -n '1{h;d};2{y/1235679abdef/000444888ccc/;H;d};13{g;s/\n//g;p;q};s/^/:/;N;H;d'
}

do_start() {
    if [ ! -d ${configfs} ]; then
        modprobe libcomposite
        if [ ! -d ${configfs} ]; then
        exit 1
        fi
    fi

    if [ -d ${d} ]; then
        exit 0
    fi

    udc=$(ls -1 /sys/class/udc/)
    if [ -z $udc ]; then
        echo "No UDC driver registered"
        exit 1
    fi

    mkdir "${d}"
    echo ${VENDOR_ID} > "${d}/idVendor"
    echo ${PRODUCT_ID} > "${d}/idProduct"
    echo 0x0200 > "${d}/bcdUSB"
    echo "0xEF" > "${d}/bDeviceClass"
    echo "0x02" > "${d}/bDeviceSubClass"
    echo "0x01" > "${d}/bDeviceProtocol"
    echo "0x0100" > "${d}/bcdDevice"

    mkdir -p "${d}/strings/0x409"
    echo ${DEV_SERIAL} > "${d}/strings/0x409/serialnumber"
    echo "Comb Communications" > "${d}/strings/0x409/manufacturer"
    echo "Comb NS Board" > "${d}/strings/0x409/product"

    # Config
    mkdir -p "${d}/configs/${c}"
    mkdir -p "${d}/configs/${c}/strings/0x409"
    echo "Config 1: RNDIS" > "${d}/configs/${c}/strings/0x409/configuration"
    echo 250 > "${d}/configs/${c}/MaxPower"
    echo 0xC0 > "${d}/configs/${c}/bmAttributes" # self powered device

    # Windows extension to force RNDIS config
    mkdir -p "${d}/os_desc"
    echo "1" > "${d}/os_desc/use"
    echo "0xbc" > "${d}/os_desc/b_vendor_code"
    echo "MSFT100" > "${d}/os_desc/qw_sign"

    mkdir -p "${d}/functions/${func_eth}"
    mkdir -p "${d}/functions/${func_eth}/os_desc/interface.rndis"
    echo "RNDIS" > "${d}/functions/${func_eth}/os_desc/interface.rndis/compatible_id"
    echo "5162001" > "${d}/functions/${func_eth}/os_desc/interface.rndis/sub_compatible_id"

    if [ "$MAC_HOST_CUST" != "" ]; then
        echo $MAC_HOST_CUST > "${d}/functions/${func_eth}/host_addr"
    else
        mac_host=$(get_mac_address_from_serial_number)
        echo $mac_host > "${d}/functions/${func_eth}/host_addr"
    fi
    if [ "$MAC_DEV_CUST" != "" ]; then
        echo $MAC_DEV_CUST > "${d}/functions/${func_eth}/dev_addr"
    fi


    # Set up the rndis device only first
    ln -s "${d}/functions/${func_eth}" "${d}/configs/${c}"
    ln -s "${d}/configs/${c}" "${d}/os_desc"

    echo "${udc}" > "${d}/UDC"

    sleep 0.2

    interfacename=$(cat ${d}/functions/${func_eth}/ifname 2> /dev/null)
    if [ -z "${interfacename}" ];
    then
        interfacename=usb0
    fi
    # ifconfig ${interfacename} $IP netmask $NETMASK
    ifconfig ${interfacename} up
}

do_stop() {
    interfacename=$(cat ${d}/functions/${func_eth}/ifname 2> /dev/null)
    if [ -z "${interfacename}" ];
    then
        echo "Nothing to do"
        return
    fi
    ifconfig ${interfacename} down

    sleep 0.2

    echo "" > "${d}/UDC"

    rm -f "${d}/os_desc/${c}"
    [ -d "${d}/configs/${c}/${func_eth}" ] &&rm -f "${d}/configs/${c}/${func_eth}"

    [ -d "${d}/strings/0x409/" ] && rmdir "${d}/strings/0x409/"
    [ -d "${d}/configs/${c}/strings/0x409" ] && rmdir "${d}/configs/${c}/strings/0x409"
    [ -d "${d}/configs/${c}" ] && rmdir "${d}/configs/${c}"
    [ -d "${d}/functions/${func_eth}" ] && rmdir "${d}/functions/${func_eth}"
    [ -d "${d}" ] && rmdir "${d}"
}

case $1 in
    start)
        echo "Start usb gadget"
        if [ "${ARCH_FAMILY}" == "raspberrypi" ];then
            PROD="Comb NS (${ARCH_FAMILY})"
            FAMILY=0010
          elif [ "${ARCH_FAMILY:0:10}" == "stm32mp157" ];then
            PROD=$(tr -d '\0' < /proc/device-tree/model)
            FAMILY=0012
          else
            PROD=$(tr -d '\0' < /proc/device-tree/model)
            FAMILY=XXXX
        fi;

        if get_i2c 50;then
            DEV_SERIAL=$(echo -n ${FAMILY};for mac in a b c d e f;do MV=$(i2cget -y ${I2C} 0x50 0xf${mac});echo -n ${MV:2};done)
          elif get_i2c 57;then
            DEV_SERIAL=$(echo -n ${FAMILY};for mac in 2 3 4 5 6 7;do MV=$(i2cget -y ${I2C} 0x57 0xf${mac});echo -n ${MV:2};done)
          elif [ -e /sys/class/net/ethA/address ];then
            DEV_SERIAL=$(awk -F: -v FAM=${FAMILY} '{printf "%s%s%s%s%s%s%s",FAM,$1,$2,$3,$4,$5,$6}' /sys/class/net/ethA/address)
          else
            DEV_SERIAL=$(tr -d '\0' < /proc/device-tree/serial-number)
        fi;

        if [ ! -d ${d} ]; then
            do_start $2
          else
            setup_info
        fi
        setup_route_ecm ${ECM0}
        ;;
    stop)
        echo "Stop usb gadget"
        if [ -d ${d} ]; then
             setup_route_ecm_stop
             do_stop
        fi
        ;;
    restart)
        setup_route_ecm_stop
        setup_route_ecm ${ECM0}
        ;;
    *)
        echo "Usage: $0 (stop | start)"
        ;;
esac
