# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you 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.
#
. $CORE_PATH/hw/scripts/common.sh

CFG_RESET="reset halt"

#
# FILE_NAME must contain the name of the file to load
# FLASH_OFFSET must contain the offset in flash where to place it
#
openocd_sn() {
    OCD_SERIAL_FILE=openocd_serial.cfg

    if [ -n "$STLINK_SN" ]; then
        echo "adapter serial $STLINK_SN" > $OCD_SERIAL_FILE
    elif [ -n "$JLINK_SN" ]; then
        echo "adapter serial $JLINK_SN" > $OCD_SERIAL_FILE
    elif [ -n "$MYNEWT_VAL_MYNEWT_DEBUGGER_SN" ]; then
        echo "adapter serial $MYNEWT_VAL_MYNEWT_DEBUGGER_SN" > $OCD_SERIAL_FILE
    else
        return
    fi
    # Add the debugger serial number file to the OpenOCD CFG options
    CFG="$CFG -f $OCD_SERIAL_FILE"
}

openocd_load () {
    OCD_CMD_FILE=.openocd_cmds

    windows_detect
    parse_extra_jtag_cmd $EXTRA_JTAG_CMD

    if [ $WINDOWS -eq 1 ] ; then
        FILE_NAME=`cygpath -u $FILE_NAME`
    fi
    echo "$EXTRA_JTAG_CMD" > $OCD_CMD_FILE
    echo "init" >> $OCD_CMD_FILE
    echo "$CFG_RESET" >> $OCD_CMD_FILE
    echo "$CFG_POST_INIT" >> $OCD_CMD_FILE
    echo "flash write_image erase $FILE_NAME $FLASH_OFFSET" >> $OCD_CMD_FILE

    openocd_sn

    if [ -z $FILE_NAME ]; then
        echo "Missing filename"
        exit 1
    fi
    if [ ! -f "$FILE_NAME" ]; then
        # tries stripping current path for readability
        FILE=${FILE_NAME##$(pwd)/}
        echo "Cannot find file" $FILE
        exit 1
    fi
    if [ -z $FLASH_OFFSET ]; then
        echo "Missing flash offset"
        exit 1
    fi

    echo "Downloading" $FILE_NAME "to" $FLASH_OFFSET

    openocd $CFG -f $OCD_CMD_FILE $EXTRA_JTAG_CMD -c shutdown

    if [ $? -ne 0 ]; then
        exit 1
    fi
    rm $OCD_CMD_FILE
    return 0
}

#
# NO_GDB should be set if gdb should not be started
# FILE_NAME should point to elf-file being debugged
#
openocd_debug () {
    OCD_CMD_FILE=.openocd_cmds

    windows_detect
    gdb_detect
    parse_extra_jtag_cmd $EXTRA_JTAG_CMD

    echo "gdb_port $PORT" > $OCD_CMD_FILE
    echo "telnet_port $(($PORT+1))" >> $OCD_CMD_FILE
    echo "$EXTRA_JTAG_CMD" >> $OCD_CMD_FILE

    if [ -z "$NO_GDB" ]; then
        if [ -z $FILE_NAME ]; then
            echo "Missing filename"
            exit 1
        fi
        if [ ! -f "$FILE_NAME" ]; then
            echo "Cannot find file" $FILE_NAME
            exit 1
        fi

        if [ $WINDOWS -eq 1 ]; then
            #
            # Launch openocd in a separate command interpreter, to make sure
            # it doesn't get killed by Ctrl-C signal from bash.
            #

            CFG=`echo $CFG | sed 's/\//\\\\/g'`
            $COMSPEC /C "start $COMSPEC /C openocd -l openocd.log $CFG -f $OCD_CMD_FILE -c init -c halt"
        else
            #
            # Block Ctrl-C from getting passed to openocd.
            #
            set -m
            openocd $CFG -f $OCD_CMD_FILE -c init -c halt >openocd.log 2>&1 &
            openocdpid=$!
            set +m
        fi

        GDB_CMD_FILE=.gdb_cmds

        echo "target remote localhost:$PORT" > $GDB_CMD_FILE
        if [ ! -z "$RESET" ]; then
            echo "mon reset halt" >> $GDB_CMD_FILE
        fi

        echo "$EXTRA_GDB_CMDS" >> $GDB_CMD_FILE

        if [ $WINDOWS -eq 1 ]; then
            FILE_NAME=`echo $FILE_NAME | sed 's/\//\\\\/g'`
            $COMSPEC /C "start $COMSPEC /C $GDB -x $GDB_CMD_FILE $FILE_NAME"
        else
            set -m
            $GDB -x $GDB_CMD_FILE $FILE_NAME
            set +m
            rm $GDB_CMD_FILE
            sleep 1
            if [ -d /proc/$openocdpid ] ; then
                kill -9 $openocdpid
            fi
        fi
    else
        # No GDB, wait for openocd to exit
        openocd $CFG -f $OCD_CMD_FILE -c init -c halt
        return $?
    fi

    if [ ! -x "$COMSPEC" ]; then
        rm $OCD_CMD_FILE
    fi
    return 0
}

openocd_halt () {
    openocd $CFG -c init -c "halt" -c shutdown
    ret=$?
    [ -f $OCD_SERIAL_FILE ] && rm $OCD_SERIAL_FILE
    return $ret
}

openocd_reset_run () {
    openocd $CFG -c init -c "reset run" -c shutdown
    ret=$?
    [ -f $OCD_SERIAL_FILE ] && rm $OCD_SERIAL_FILE
    return $ret
}

openocd_detect_interface () {
    detect_programmer
    case $DETECTED_PROGRAMMER in
        cmsis-dap)
            OPENOCD_INTERFACE='cmsis-dap'
            ;;
        stlink-v2-1)
            OPENOCD_INTERFACE='stlink-v2-1'
            ;;
        *) # default is passed by argument or 'stlink'
            OPENOCD_INTERFACE=${1:=stlink}
            ;;
    esac
}
