#!/bin/sh
#
# Copyright (c) 2013, The Linux Foundation. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of The Linux Foundation nor the names of its
#       contributors may be used to endorse or promote products derived from
#       this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE DISCLAIMED.  IN NO
# EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# DESCRIPTION:  DIAG+ADB+ECM

configure_android_gadget()
{
    local gadget_fs=/sys/class/android_usb/android${num}
    #echo $mode > /sys/bus/platform/devices/usb_bam/enable
    echo 0 > ${gadget_fs}/enable
    echo $vid > ${gadget_fs}/idVendor
    echo $pid > ${gadget_fs}/idProduct
    echo $devclass > ${gadget_fs}/bDeviceClass
    echo $devsubclass > ${gadget_fs}/bDeviceSubClass
    echo $devprotocol > ${gadget_fs}/bDeviceProtocol
    echo $diagstr > ${gadget_fs}/f_diag/clients
    echo $serialstr > ${gadget_fs}/f_serial/transports
    echo QTI,BAM_DMUX > ${gadget_fs}/f_rmnet/transports
    echo BAM_DMUX > ${gadget_fs}/f_usb_mbim/mbim_transports
    echo $compstr > ${gadget_fs}/functions
    echo $remotewakeup > ${gadget_fs}/remote_wakeup

    echo $manufacturer > ${gadget_fs}/iManufacturer
    echo $product > ${gadget_fs}/iProduct
    echo $serial > ${gadget_fs}/iSerial

    compstr=`grep -w ffs ${gadget_fs}/functions || true`
    if [[ $mode = "hsusb" && ! -z "$compstr" && -d ${gadget_fs}/f_ffs ]] ; then
        echo adb > ${gadget_fs}/f_ffs/aliases
    fi

    echo 1 > ${gadget_fs}/enable
}

configure_configfs_gadget()
{
    local configfs_home=/sys/kernel/config/usb_gadget
    local gadget_home=${configfs_home}/g$((num+1))
    local strings_home=${gadget_home}/strings/0x409
    local config_home=${gadget_home}/configs/c.$((num+1))
    local cstring_home=${config_home}/strings/0x409
    local gdev=`ls -1 /sys/class/udc/`
    local supported=" serial:gser.0"`
                   `" modem:cser.dun.0"`
                   `" ecm:ecm.usb0"`
                   `" diag:diag.diag"`
                   `" nmea:cser.nmea.1"`
                   `" rmnet:rmnet_bam.rmnet_bam_dmux"`
                   `" usb_mbim:mbim.mbim"`
                   `" rawdat:cser.raw.2"`
                   `" audio:uac1_legacy.uac1_legacy0"`
                   `" storage:mass_storage.0"

    # Disable gadget in case it was enabled
    if [ -w ${gadget_home}/UDC ]; then
        if [ ! -z `cat ${gadget_home}/UDC` ]; then
            echo "" > ${gadget_home}/UDC
        fi
    fi

    if [ ! -d ${configfs_home} ]; then
        mount none /sys/kernel/config -t configfs
        mkdir ${gadget_home}
    fi
    echo "0x$vid" > ${gadget_home}/idVendor
    echo "0x$pid" > ${gadget_home}/idProduct
    mkdir -p ${strings_home}
    echo ${manufacturer} > ${strings_home}/manufacturer
    echo ${product} > ${strings_home}/product
    echo ${serial} > ${strings_home}/serialnumber

    mkdir -p ${config_home}

    # Update bmAttributes if remotewakup enabled.
    # Referring include\uapi\linux\usb\ch9.h,
    # D7:     Reserved (set to one)
    # D6:     Self-powered
    # D5:     Remote Wakeup
    # D4...0: Reserved (reset to zero)
    [ $remotewakeup == "1" ] && echo 0xA0 > ${config_home}/bmAttributes

    # Replace "serial" in compstr with the interface list (nmea, modem);
    # Translate interface list into function names.
    # smdnmea --> nmea
    # smd     --> modem (if CMUX over USB disabled)
    # tty     --> modem (if CMUX over USB enabled)
    # rawdat  --> rawdat
    local serialif=`echo "${serialstr}"| sed -r -e 's/smdnmea/nmea/g' -e 's/(smd|tty)/modem/g'`

    # update compstr to replace "serial" with the interface list.
    compstr="${compstr/serial/${serialif}}"

    # Space separated list
    complist=`echo ${compstr} | sed -e 's/,/ /g'`

    # Clear and symlink gadget configuration files, build configuration string
    cd ${gadget_home}
    idx=0
    configuration=""
    rm -f configs/c.$((num+1))/f*
    for comp in ${complist}; do
        match=`echo ${supported} | xargs -n1 | grep -iw "${comp}"`
        if [ -n "${match}" ]; then
            idx=$((idx+1))
            func=`echo ${match} | cut -f 2 -d':'`
            name=`echo ${func} | cut -f 1 -d'.'`
            if [ ${idx} -eq 1 ]; then
                configuration="${name}"
            else
                configuration="${configuration},${name}"
            fi
            mkdir -p functions/${func}
            ln -s functions/${func} configs/c.$((num+1))/f${idx}
        fi
    done
    cd

    # Write configuration string
    mkdir -p ${cstring_home}
    echo "${configuration}" > ${cstring_home}/configuration

    # Enable gadget
    echo "${gdev}" > ${gadget_home}/UDC
}

set_frmnet_module_param()
{
    local frmnet_module_param1=/sys/module/g_android/parameters/num_rmnet_swi
    local frmnet_module_param2=/sys/module/usb_f_rmnet_bam/parameters/num_rmnet_swi

    if [ -w "${frmnet_module_param1}" ]; then
        frmnet_module_param=${frmnet_module_param1}
    elif [ -w "${frmnet_module_param2}" ]; then
        frmnet_module_param=${frmnet_module_param2}
    else
        return
    fi

    numnet=$(/usr/bin/ud_getusbinfo NUMNET)
    if [ $? -eq 0 ]; then
        echo $numnet > ${frmnet_module_param}
    fi
}

echo "Switching to composition sierra_dev (1199:68C0)"

if [ "x$1" = "xy" ]; then
        num="1"
        mode="hsic"
else
        num="0"
        mode="hsusb"
fi

vid=$(/usr/bin/ud_getusbinfo VID)
if [ $? -ne 0 ];
then
  echo "ud_getusbinfo gets VID failed"
  vid=1199
fi

pid=$(/usr/bin/ud_getusbinfo PID)
if [ $? -ne 0 ];
then
  echo "ud_getusbinfo gets PID failed"
  pid=68C0
fi

devclass=$(/usr/bin/ud_getusbinfo DEVC)
if [ $? -ne 0 ];
then
  echo "ud_getusbinfo gets DEVC failed"
  devclass=239
fi

devsubclass=$(/usr/bin/ud_getusbinfo DEVS)
if [ $? -ne 0 ];
then
  echo "ud_getusbinfo gets DEVS failed"
  devsubclass=2
fi

devprotocol=$(/usr/bin/ud_getusbinfo DEVP)
if [ $? -ne 0 ];
then
  echo "ud_getusbinfo gets DEVP failed"
  devprotocol=1
fi

diagstr=$(/usr/bin/ud_getusbinfo DIAGSTR)
if [ $? -ne 0 ];
then
  echo "ud_getusbinfo gets DIAGSTR failed"
  diagstr='diag'
fi

serialstr=$(/usr/bin/ud_getusbinfo SERIALSTR)
if [ $? -ne 0 ];
then
  echo "ud_getusbinfo gets SERIALSTR failed"
  serialstr='smd,tty'
fi

compstr=$(/usr/bin/ud_getusbinfo COMPSTR)
if [ $? -ne 0 ];
then
  echo "ud_getusbinfo gets COMPSTR failed"
  compstr='diag,ffs,serial'
fi
# filter out adb gadget if adbd is not installed
if [ ! -x /sbin/adbd ]; then
  compstr=`echo $compstr | sed -e s/^ffs,//g -e s/,ffs//g -e s/^ffs$//g`
fi

remotewakeup=$(/usr/bin/ud_getusbinfo REM)
if [ $? -ne 0 ];
then
  echo "ud_getusbinfo gets REM failed"
  remotewakeup=1
fi

manufacturer=$(/usr/bin/ud_getusbinfo MANU)
if [ $? -ne 0 ];
then
  echo "ud_getusbinfo gets MANU failed"
  manufacturer='Sierra Wireless, Incorporated'
fi

product=$(/usr/bin/ud_getusbinfo PROD)
if [ $? -ne 0 ];
then
  echo "ud_getusbinfo gets PROD failed"
  product='AR758x'
fi

serial=$(/usr/bin/ud_getusbinfo SER)
if [ $? -ne 0 ];
then
  echo "ud_getusbinfo gets SER failed"
  serial='0123456789ABCDEF'
fi

# Pass number of rmnets, to driver
set_frmnet_module_param

# Check if configfs gadget is supported and configure accordingly
configfs_g_support=`zcat /proc/config.gz |grep CONFIG_USB_CONFIGFS=y`
configfs_fs_support=`zcat /proc/config.gz |grep CONFIG_CONFIGFS_FS=y`
if [[ "x${configfs_g_support}" = "x" || "x${configfs_fs_support}" = "x" ]]
then
    configure_android_gadget
else
    configure_configfs_gadget
fi
