dji-sdk/Payload-SDK

Probelm setting up DJI_USE_UART_AND_USB_BULK_DEVICE in Jetson Orin Nano

Opened this issue · 10 comments

Hello,
I am working on the latest Matrice M3TD drone with dock2 right now and we are trying to establish PSDK connection with the M3TD using Jetson Orin Nano. We are using the PSDK version 3.8. Initially I tried to use DJI_USE_UART_AND_NETWORK_DEVICE and I got an error suggesting that I should use DJI_USE_UART_AND_USB_BULK_DEVICE as DJI_USE_UART_AND_NETWORK_DEVICE is not supported in M3TD. I tried to follow this guide for Jetson Nano. But while doing so I am facing some issues as I couldn't see the devices /dev/usb-ffs/bulk1 and /dev/usb-ffs/bulk2. I searched the internet and found another person facing the same issue. That person tried connecting the E-port's USB-C output to the USB A port instead of the USB-C port and he overcame that issue. But I tried the same and it doesn't work.

here is my nv-l4t-usb-device-mode-start.sh code:

#!/bin/bash

# Copyright (c) 2017-2020, NVIDIA CORPORATION.  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 NVIDIA CORPORATION 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 BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE 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.

set -e

script_dir="$(cd "$(dirname "$0")" && pwd)"
. "${script_dir}/nv-l4t-usb-device-mode-config.sh"

# Wait for any modules to load and initialize
for attempt in $(seq 60); do
    udc_dev_t210=700d0000.xudc
    if [ -e "/sys/class/udc/${udc_dev_t210}" ]; then
        udc_dev="${udc_dev_t210}"
        break
    fi
    udc_dev_t186=3550000.usb
    if [ -e "/sys/class/udc/${udc_dev_t186}" ]; then
        udc_dev="${udc_dev_t186}"
        break
    fi
    sleep 1
done
if [ "${udc_dev}" == "" ]; then
    echo No known UDC device found
    exit 1
fi

macs_file="${script_dir}/mac-addresses"
if [ -f "${macs_file}" ]; then
    . "${macs_file}"
else
    # Generate unique data
    if [ -f /proc/device-tree/serial-number ]; then
        random="$(md5sum /proc/device-tree/serial-number|cut -c1-12)"
    else
        random="$(echo "no-serial"|md5sum|cut -c1-12)"
    fi
    # Extract 6 bytes
    b1="$(echo "${random}"|cut -c1-2)"
    b2="$(echo "${random}"|cut -c3-4)"
    b3="$(echo "${random}"|cut -c5-6)"
    b4="$(echo "${random}"|cut -c7-8)"
    b5="$(echo "${random}"|cut -c9-10)"
    b6="$(echo "${random}"|cut -c11-12)"
    # Clear broadcast/multicast, set locally administered bits
    b1="$(printf "%02x" "$(("0x${b1}" & 0xfe | 0x02))")"
    # Set 4 LSBs to unique value per interface
    b6_rndis_h="$(printf "%02x" "$(("0x${b6}" & 0xfc | 0x00))")"
    b6_rndis_d="$(printf "%02x" "$(("0x${b6}" & 0xfc | 0x01))")"
    b6_ecm_h="$(printf "%02x" "$(("0x${b6}" & 0xfc | 0x02))")"
    b6_ecm_d="$(printf "%02x" "$(("0x${b6}" & 0xfc | 0x03))")"
    # Construct complete MAC per interface
    mac_rndis_h="${b1}:${b2}:${b3}:${b4}:${b5}:${b6_rndis_h}"
    mac_rndis_d="${b1}:${b2}:${b3}:${b4}:${b5}:${b6_rndis_d}"
    mac_ecm_h="${b1}:${b2}:${b3}:${b4}:${b5}:${b6_ecm_h}"
    mac_ecm_d="${b1}:${b2}:${b3}:${b4}:${b5}:${b6_ecm_d}"
    # Save values for next boot
    echo "mac_rndis_h=${mac_rndis_h}" > "${macs_file}"
    echo "mac_rndis_d=${mac_rndis_d}" >> "${macs_file}"
    echo "mac_ecm_h=${mac_ecm_h}" >> "${macs_file}"
    echo "mac_ecm_d=${mac_ecm_d}" >> "${macs_file}"
fi

mkdir -p /sys/kernel/config/usb_gadget/l4t
cd /sys/kernel/config/usb_gadget/l4t

# If this script is modified outside NVIDIA, the idVendor and idProduct values
# MUST be replaced with appropriate vendor-specific values.
echo 0x0955 > idVendor
echo 0x7020 > idProduct
# BCD value. Each nibble should be 0..9. 0x1234 represents version 12.3.4.
echo 0x0002 > bcdDevice

# Informs Windows that this device is a composite device, i.e. it implements
# multiple separate protocols/devices.
echo 0xEF > bDeviceClass
echo 0x02 > bDeviceSubClass
echo 0x01 > bDeviceProtocol

mkdir -p strings/0x409
if [ -f /proc/device-tree/serial-number ]; then
    serialnumber="$(cat /proc/device-tree/serial-number|tr -d '\000')"
else
    serialnumber=no-serial
fi
echo "${serialnumber}" > strings/0x409/serialnumber
# If this script is modified outside NVIDIA, the manufacturer and product values
# MUST be replaced with appropriate vendor-specific values.
echo "NVIDIA" > strings/0x409/manufacturer
echo "Linux for Tegra" > strings/0x409/product

cfg=configs/c.1
mkdir -p "${cfg}"
cfg_str=""

# Note: RNDIS must be the first function in the configuration, or Windows'
# RNDIS support will not operate correctly.
if [ ${enable_rndis} -eq 1 ]; then
    cfg_str="${cfg_str}+RNDIS"
    func=functions/rndis.usb0
    mkdir -p "${func}"
    echo "${mac_rndis_h}" > "${func}/host_addr"
    echo "${mac_rndis_d}" > "${func}/dev_addr"
    ln -sf "${func}" "${cfg}"

    # Informs Windows that this device is compatible with the built-in RNDIS
    # driver. This allows automatic driver installation without any need for
    # a .inf file or manual driver selection.
    echo 1 > os_desc/use
    echo 0xcd > os_desc/b_vendor_code
    echo MSFT100 > os_desc/qw_sign
    echo RNDIS > "${func}/os_desc/interface.rndis/compatible_id"
    echo 5162001 > "${func}/os_desc/interface.rndis/sub_compatible_id"
    ln -sf "${cfg}" os_desc
fi

# If two USB configs are created, and the second contains RNDIS and ACM, then
# Windows will ignore at the ACM function in that config. Consequently, this
# script creates only a single USB config.
if [ ${enable_acm} -eq 1 ]; then
    cfg_str="${cfg_str}+ACM"
    func=functions/acm.GS0
    mkdir -p "${func}"
    ln -sf "${func}" "${cfg}"
fi

# Copy system version information into the exposed filesystem image,
# so that any system that's attached to the USB port can identify this device.
# Do this even if $enable_ums!=1, since $fs_img is locally mounted too.
mntpoint="/mnt/l4t-devmode-$$"
rm -rf "${mntpoint}"
mkdir -p "${mntpoint}"
mount -o loop "${fs_img}" "${mntpoint}"
rm -rf "${mntpoint}/version"
mkdir -p "${mntpoint}/version"
if [ -f /etc/nv_tegra_release ]; then
    cp /etc/nv_tegra_release "${mntpoint}/version"
fi
if dpkg -s nvidia-l4t-core > /dev/null 2>&1; then
    dpkg -s nvidia-l4t-core > "${mntpoint}/version/nvidia-l4t-core.dpkg-s.txt"
fi
cp -r /proc/device-tree/chosen/plugin-manager "${mntpoint}/version/plugin-manager"
umount "${mntpoint}"
rm -rf "${mntpoint}"

if [ ${enable_ums} -eq 1 ]; then
    cfg_str="${cfg_str}+UMS"
    func=functions/mass_storage.0
    mkdir -p "${func}"
    ln -sf "${func}" "${cfg}"
    # Prevent users from corrupting the disk image; make it read-only
    echo 1 > "${func}/lun.0/ro"
    echo "${fs_img}" > "${func}/lun.0/file"
fi

if [ ${enable_ecm} -eq 1 ]; then
    cfg_str="${cfg_str}+${ecm_ncm_name}"
    func=functions/${ecm_ncm}.usb0
    mkdir -p "${func}"
    echo "${mac_ecm_h}" > "${func}/host_addr"
    echo "${mac_ecm_d}" > "${func}/dev_addr"
    ln -sf "${func}" "${cfg}"
fi

enable_bulk=1
if [ ${enable_bulk} -eq 1 ]; then
    mkdir -p /dev/usb-ffs
    
    cfg_str="${cfg_str}+BULK1" 
    mkdir -p /dev/usb-ffs/bulk1
    func=functions/ffs.bulk1
    mkdir -p "${func}"
    ln -sf "${func}" "${cfg}"
    mount -o mode=0777 -o uid=2000 -o gid=2000 -t functionfs bulk1 /dev/usb-ffs/bulk1
    /home/nvidia/Desktop/nano-usb-config/startup_bulk /dev/usb-ffs/bulk1 &
    sleep 3


    cfg_str="${cfg_str}+BULK2" 
    mkdir -p /dev/usb-ffs/bulk2
    func=functions/ffs.bulk2
    mkdir -p "${func}"
    ln -sf "${func}" "${cfg}"
    mount -o mode=0777 -o uid=2000 -o gid=2000 -t functionfs bulk2 /dev/usb-ffs/bulk2
    /home/nvidia/Desktop/nano-usb-config/startup_bulk /dev/usb-ffs/bulk2 &
    sleep 3
fi


mkdir -p "${cfg}/strings/0x409"
# :1 in the variable expansion strips the first character from the value. This
# removes the unwanted leading + sign. This simplifies the logic to construct
# $cfg_str above; it can always add a leading delimiter rather than only doing
# so unless the string is previously empty.
echo "${cfg_str:1}" > "${cfg}/strings/0x409/configuration"

# Create and configure the network bridge before setting the UDC device. This
# ensures that no matter how quickly udev events (which run -runtime-start.sh)
# are triggered after setting the UDC device below, the bridge device is
# guaranteed to exist, so -runtime-start.sh is guaranteed to be able to
# configure it.
#
# Set the device to "down" initially; if/when -runtime-start.sh runs in response
# to cable presence, the interface will be set to "up".
/sbin/brctl addbr l4tbr0
/sbin/ifconfig l4tbr0 down

echo "${udc_dev}" > UDC

# Ethernet devices require additional configuration. This must happen after the
# UDC device is assigned, since that triggers the creation of the Tegra-side
# Ethernet interfaces.
#
# This script always assigns any-and-all Ethernet devices to an Ethernet
# bridge, and assigns the static IP to that bridge. This allows the script to
# more easily handle the potentially variable set of Ethernet devices.
#
# If your custom use-case requires separate IP addresses per interface, or
# only ever has one interface active, you may modify this script to skip
# bridge creation, and assign IP address(es) directly to the interface(s).

if [ ${enable_rndis} -eq 1 ]; then
    /sbin/brctl addif l4tbr0 "$(cat functions/rndis.usb0/ifname)"
    /sbin/ifconfig "$(cat functions/rndis.usb0/ifname)" up
fi

if [ ${enable_ecm} -eq 1 ]; then
    /sbin/brctl addif l4tbr0 "$(cat functions/${ecm_ncm}.usb0/ifname)"
    /sbin/ifconfig "$(cat functions/${ecm_ncm}.usb0/ifname)" up
fi

cd - # Out of /sys/kernel/config/usb_gadget

# Create a local disk device that exposes the same filesystem image that's
# exported over USB. This will allow local users to see the files too.
/sbin/losetup -f -r "${fs_img}"

exit 0

I have modified the path of startup_bulk and I have modified the line with udc_dev_t186=3550000.usb
in line 41 since that threw an error.

But this still doesn't work. I need some support to fix this.

I have some updates:

I made some new changes to the nv-l4t-usb-device-mode-start.sh file:

#!/bin/bash
set -ex

# Ensure the script runs as root
if [ "$(id -u)" -ne 0 ]; then
    echo "This script must be run as root"
    exit 1
fi

# Load required modules
sudo modprobe configfs
sudo modprobe libcomposite
sudo modprobe usb_f_fs

# Mount configfs if not already mounted
if ! mountpoint -q /sys/kernel/config; then
    sudo mount -t configfs none /sys/kernel/config
fi

script_dir="$(cd "$(dirname "$0")" && pwd)"
. "${script_dir}/nv-l4t-usb-device-mode-config.sh"

# Wait for any modules to load and initialize
for attempt in $(seq 60); do
    udc_dev_t210=700d0000.xudc
    if [ -e "/sys/class/udc/${udc_dev_t210}" ]; then
        udc_dev="${udc_dev_t210}"
        break
    fi
    udc_dev_t186=3550000.usb
    if [ -e "/sys/class/udc/${udc_dev_t186}" ]; then
        udc_dev="${udc_dev_t186}"
        break
    fi
    sleep 1
done
if [ "${udc_dev}" == "" ]; then
    echo No known UDC device found
    exit 1
fi

macs_file="${script_dir}/mac-addresses"
if [ -f "${macs_file}" ]; then
    . "${macs_file}"
else
    # Generate unique data
    if [ -f /proc/device-tree/serial-number ]; then
        random="$(md5sum /proc/device-tree/serial-number | cut -c1-12)"
    else
        random="$(echo "no-serial" | md5sum | cut -c1-12)"
    fi
    # Extract 6 bytes
    b1="$(echo "${random}" | cut -c1-2)"
    b2="$(echo "${random}" | cut -c3-4)"
    b3="$(echo "${random}" | cut -c5-6)"
    b4="$(echo "${random}" | cut -c7-8)"
    b5="$(echo "${random}" | cut -c9-10)"
    b6="$(echo "${random}" | cut -c11-12)"
    # Clear broadcast/multicast, set locally administered bits
    b1="$(printf "%02x" "$(("0x${b1}" & 0xfe | 0x02))")"
    # Set 4 LSBs to unique value per interface
    b6_rndis_h="$(printf "%02x" "$(("0x${b6}" & 0xfc | 0x00))")"
    b6_rndis_d="$(printf "%02x" "$(("0x${b6}" & 0xfc | 0x01))")"
    b6_ecm_h="$(printf "%02x" "$(("0x${b6}" & 0xfc | 0x02))")"
    b6_ecm_d="$(printf "%02x" "$(("0x${b6}" & 0xfc | 0x03))")"
    # Construct complete MAC per interface
    mac_rndis_h="${b1}:${b2}:${b3}:${b4}:${b5}:${b6_rndis_h}"
    mac_rndis_d="${b1}:${b2}:${b3}:${b4}:${b5}:${b6_rndis_d}"
    mac_ecm_h="${b1}:${b2}:${b3}:${b4}:${b5}:${b6_ecm_h}"
    mac_ecm_d="${b1}:${b2}:${b3}:${b4}:${b5}:${b6_ecm_d}"
    # Save values for next boot
    echo "mac_rndis_h=${mac_rndis_h}" > "${macs_file}"
    echo "mac_rndis_d=${mac_rndis_d}" >> "${macs_file}"
    echo "mac_ecm_h=${mac_ecm_h}" >> "${macs_file}"
    echo "mac_ecm_d=${mac_ecm_d}" >> "${macs_file}"
fi

mkdir -p /sys/kernel/config/usb_gadget/l4t
cd /sys/kernel/config/usb_gadget/l4t

# If this script is modified outside NVIDIA, the idVendor and idProduct values
# MUST be replaced with appropriate vendor-specific values.
echo 0x0955 > idVendor
echo 0x7020 > idProduct
# BCD value. Each nibble should be 0..9. 0x1234 represents version 12.3.4.
echo 0x0002 > bcdDevice

# Informs Windows that this device is a composite device, i.e. it implements
# multiple separate protocols/devices.
echo 0xEF > bDeviceClass
echo 0x02 > bDeviceSubClass
echo 0x01 > bDeviceProtocol

mkdir -p strings/0x409
if [ -f /proc/device-tree/serial-number ]; then
    serialnumber="$(cat /proc/device-tree/serial-number | tr -d '\000')"
else
    serialnumber=no-serial
fi
echo "${serialnumber}" > strings/0x409/serialnumber
# If this script is modified outside NVIDIA, the manufacturer and product values
# MUST be replaced with appropriate vendor-specific values.
echo "NVIDIA" > strings/0x409/manufacturer
echo "Linux for Tegra" > strings/0x409/product

cfg=configs/c.1
mkdir -p "${cfg}"
cfg_str=""

# Note: RNDIS must be the first function in the configuration, or Windows'
# RNDIS support will not operate correctly.
if [ ${enable_rndis} -eq 1 ]; then
    cfg_str="${cfg_str}+RNDIS"
    func=functions/rndis.usb0
    mkdir -p "${func}"
    echo "${mac_rndis_h}" > "${func}/host_addr"
    echo "${mac_rndis_d}" > "${func}/dev_addr"
    ln -sf "${func}" "${cfg}"

    # Informs Windows that this device is compatible with the built-in RNDIS
    # driver. This allows automatic driver installation without any need for
    # a .inf file or manual driver selection.
    echo 1 > os_desc/use
    echo 0xcd > os_desc/b_vendor_code
    echo MSFT100 > os_desc/qw_sign
    echo RNDIS > "${func}/os_desc/interface.rndis/compatible_id"
    echo 5162001 > "${func}/os_desc/interface.rndis/sub_compatible_id"
    ln -sf "${cfg}" os_desc
fi

# If two USB configs are created, and the second contains RNDIS and ACM, then
# Windows will ignore at the ACM function in that config. Consequently, this
# script creates only a single USB config.
if [ ${enable_acm} -eq 1 ]; then
    cfg_str="${cfg_str}+ACM"
    func=functions/acm.GS0
    mkdir -p "${func}"
    ln -sf "${func}" "${cfg}"
fi

# Copy system version information into the exposed filesystem image,
# so that any system that's attached to the USB port can identify this device.
# Do this even if $enable_ums!=1, since $fs_img is locally mounted too.
mntpoint="/mnt/l4t-devmode-$$"
rm -rf "${mntpoint}"
mkdir -p "${mntpoint}"
mount -o loop "${fs_img}" "${mntpoint}"
rm -rf "${mntpoint}/version"
mkdir -p "${mntpoint}/version"
if [ -f /etc/nv_tegra_release ]; then
    cp /etc/nv_tegra_release "${mntpoint}/version"
fi
if dpkg -s nvidia-l4t-core > /dev/null 2>&1; then
    dpkg -s nvidia-l4t-core > "${mntpoint}/version/nvidia-l4t-core.dpkg-s.txt"
fi
if [ -d /proc/device-tree/chosen/plugin-manager ]; then
    cp -r /proc/device-tree/chosen/plugin-manager "${mntpoint}/version/plugin-manager"
fi
umount "${mntpoint}"
rm -rf "${mntpoint}"

if [ ${enable_ums} -eq 1 ]; then
    cfg_str="${cfg_str}+UMS"
    func=functions/mass_storage.0
    mkdir -p "${func}"
    ln -sf "${func}" "${cfg}"
    # Prevent users from corrupting the disk image; make it read-only
    echo 1 > "${func}/lun.0/ro"
    echo "${fs_img}" > "${func}/lun.0/file"
fi

if [ ${enable_ecm} -eq 1 ]; then
    cfg_str="${cfg_str}+${ecm_ncm_name}"
    func=functions/${ecm_ncm}.usb0
    mkdir -p "${func}"
    echo "${mac_ecm_h}" > "${func}/host_addr"
    echo "${mac_ecm_d}" > "${func}/dev_addr"
    ln -sf "${func}" "${cfg}"
fi

enable_bulk=1
if [ ${enable_bulk} -eq 1 ]; then
    mkdir -p /dev/usb-ffs
    
    cfg_str="${cfg_str}+BULK1" 
    mkdir -p /dev/usb-ffs/bulk1
    func=functions/ffs.bulk1
    mkdir -p "${func}"
    ln -sf "${func}" "${cfg}"
    mount -o mode=0777 -o uid=2000 -o gid=2000 -t functionfs bulk1 /dev/usb-ffs/bulk1
    /home/nvidia/Desktop/nano-usb-config/startup_bulk /dev/usb-ffs/bulk1 &
    sleep 3


    cfg_str="${cfg_str}+BULK2" 
    mkdir -p /dev/usb-ffs/bulk2
    func=functions/ffs.bulk2
    mkdir -p "${func}"
    ln -sf "${func}" "${cfg}"
    mount -o mode=0777 -o uid=2000 -o gid=2000 -t functionfs bulk2 /dev/usb-ffs/bulk2
    /home/nvidia/Desktop/nano-usb-config/startup_bulk /dev/usb-ffs/bulk2 &
    sleep 3
fi

mkdir -p "${cfg}/strings/0x409"
# :1 in the variable expansion strips the first character from the value. This
# removes the unwanted leading + sign. This simplifies the logic to construct
# $cfg_str above; it can always add a leading delimiter rather than only doing
# so unless the string is previously empty.
echo "${cfg_str:1}" > "${cfg}/strings/0x409/configuration"

# Create and configure the network bridge before setting the UDC device. This
# ensures that no matter how quickly udev events (which run -runtime-start.sh)
# are triggered after setting the UDC device below, the bridge device is
# guaranteed to exist, so -runtime-start.sh is guaranteed to be able to
# configure it.
#
# Set the device to "down" initially; if/when -runtime-start.sh runs in response
# to cable presence, the interface will be set to "up".
/sbin/brctl addbr l4tbr0
/sbin/ifconfig l4tbr0 down

echo "${udc_dev}" > UDC

# Ethernet devices require additional configuration. This must happen after the
# UDC device is assigned, since that triggers the creation of the Tegra-side
# Ethernet interfaces.
#
# This script always assigns any-and-all Ethernet devices to an Ethernet
# bridge, and assigns the static IP to that bridge. This allows the script to
# more easily handle the potentially variable set of Ethernet devices.
#
# If your custom use-case requires separate IP addresses per interface, or
# only ever has one interface active, you may modify this script to skip
# bridge creation, and assign IP address(es) directly to the interface(s).

if [ ${enable_rndis} -eq 1 ]; then
    /sbin/brctl addif l4tbr0 "$(cat functions/rndis.usb0/ifname)"
    /sbin/ifconfig "$(cat functions/rndis.usb0/ifname)" up
fi

if [ ${enable_ecm} -eq 1 ]; then
    /sbin/brctl addif l4tbr0 "$(cat functions/${ecm_ncm}.usb0/ifname)"
    /sbin/ifconfig "$(cat functions/${ecm_ncm}.usb0/ifname)" up
fi

cd - # Out of /sys/kernel/config/usb_gadget

# Create a local disk device that exposes the same filesystem image that's
# exported over USB. This will allow local users to see the files too.
/sbin/losetup -f -r "${fs_img}"

exit 0

And now when I type ps -aux | grep startup_bulk I see the following:

root         674  0.0  0.0   2276   800 ?        S    16:10   0:00 /home/nvidia/Desktop/nano-usb-config/startup_bulk /dev/usb-ffs/bulk1
root        1778  0.0  0.0   2276   804 ?        S    16:10   0:00 /home/nvidia/Desktop/nano-usb-config/startup_bulk /dev/usb-ffs/bulk2
nvidia     13041  0.0  0.0  11820  2068 pts/2    S+   16:32   0:00 grep --color=auto startup_bulk

But still I get some error when trying to run the psdk with DJI_USE_UART_AND_USB_BULK_DEVICE:

nvidia@nvidia:~/Payload-SDK/build/bin$ sudo ./dji_sdk_demo_linux_cxx 
[sudo] password for nvidia: 
'Logs/latest.log' -> 'DJI_0002_20240628_16-34-03.log'
[0.009][core]-[Info]-[DjiCore_Init:101) Payload SDK Version : V3.8.0-beta.0-build.1929 
[1.160][adapter]-[Info]-[DjiAccessAdapter_Init:228) Identify aircraft series is Matrice 3D Series 
[1.160][adapter]-[Info]-[DjiAccessAdapter_Init:261) Identify mount position type is Extension Port Type 
[1.167][adapter]-[Info]-[DjiAccessAdapter_Init:362) Identity uart0 baudrate is 921600 bps 
[3.241][adapter]-[Info]-[DjiPayloadNegotiate_Init:219) Waiting payload negotiate finish. 
[4.241][adapter]-[Info]-[DjiPayloadNegotiate_Init:219) Waiting payload negotiate finish. 
[5.241][adapter]-[Info]-[DjiPayloadNegotiate_Init:219) Waiting payload negotiate finish. 
[6.241][adapter]-[Info]-[DjiPayloadNegotiate_Init:219) Waiting payload negotiate finish. 
[7.241][adapter]-[Info]-[DjiPayloadNegotiate_Init:219) Waiting payload negotiate finish. 
[8.241][adapter]-[Error]-[DjiAccessAdapter_Init:373) Payload negotiate error, returnCode = 225 
[8.241][adapter]-[Error]-[DjiAccessAdapter_Init:379) Payload negotiate error, returnCode = 225 
[8.241][core]-[Error]-[DjiCore_Init:121) Access adapter init error, stat:225 
terminate called after throwing an instance of 'std::runtime_error'
  what():  Core init error.
Aborted

More updates:

All the above test was carried out with the USB -C output of the E-Port kit connected to the USB-A port of the jetson. When I connected to the USB-C pin of the Orin Nano using a USB-C to USB-C cable I got this output:

[0.009][core]-[Info]-[DjiCore_Init:101) Payload SDK Version : V3.8.0-beta.0-build.1929 
[0.589][linker]-[Warn]-[DjiProtocol_v1Unpack:186) protocol frame crc16 error, exp:0xAB01 cur:0x4177 
[1.692][utils]-[Error]-[DjiMsgq_Send:230) semaphore wait timeout 
[1.692][linker]-[Error]-[DjiLinker_RecvTask:286) send msg to queue error 
[1.711][utils]-[Error]-[DjiMsgq_Send:230) semaphore wait timeout 
[1.711][linker]-[Error]-[DjiLinker_RecvTask:286) send msg to queue error 
[1.721][utils]-[Error]-[DjiMsgq_Send:230) semaphore wait timeout 
[1.721][linker]-[Error]-[DjiLinker_RecvTask:286) send msg to queue error 
[1.732][utils]-[Error]-[DjiMsgq_Send:230) semaphore wait timeout 
[1.732][linker]-[Error]-[DjiLinker_RecvTask:286) send msg to queue error 
[1.742][utils]-[Error]-[DjiMsgq_Send:230) semaphore wait timeout 
[1.742][linker]-[Error]-[DjiLinker_RecvTask:286) send msg to queue error 
[1.761][utils]-[Error]-[DjiMsgq_Send:230) semaphore wait timeout 
[1.761][linker]-[Error]-[DjiLinker_RecvTask:286) send msg to queue error 
[1.771][utils]-[Error]-[DjiMsgq_Send:230) semaphore wait timeout 
[1.771][linker]-[Error]-[DjiLinker_RecvTask:286) send msg to queue error 
[1.781][utils]-[Error]-[DjiMsgq_Send:230) semaphore wait timeout 
[1.781][linker]-[Error]-[DjiLinker_RecvTask:286) send msg to queue error 
[1.791][utils]-[Error]-[DjiMsgq_Send:230) semaphore wait timeout 
[1.791][linker]-[Error]-[DjiLinker_RecvTask:286) send msg to queue error 
[1.810][utils]-[Error]-[DjiMsgq_Send:230) semaphore wait timeout 
[1.810][linker]-[Error]-[DjiLinker_RecvTask:294) send msg to queue error 
[1.820][utils]-[Error]-[DjiMsgq_Send:230) semaphore wait timeout 
[1.820][linker]-[Error]-[DjiLinker_RecvTask:286) send msg to queue error 
[1.830][utils]-[Error]-[DjiMsgq_Send:230) semaphore wait timeout 
[1.830][linker]-[Error]-[DjiLinker_RecvTask:286) send msg to queue error 
[1.840][utils]-[Error]-[DjiMsgq_Send:230) semaphore wait timeout 
[1.840][linker]-[Error]-[DjiLinker_RecvTask:286) send msg to queue error 
[1.854][utils]-[Error]-[DjiMsgq_Destroy:100) send mutex destroy failed 
[1.854][linker]-[Error]-[DjiLinker_DeInit:159) destroy recv msgq error 
[1.854][adapter]-[Error]-[DjiAccessAdapter_IdentifyUart0InfoAndAircraftSeries:721) DjiLinker_DeInit, stat:255 
[1.854][adapter]-[Info]-[DjiAccessAdapter_Init:228) Identify aircraft series is Matrice 3D Series 
[1.854][adapter]-[Info]-[DjiAccessAdapter_Init:261) Identify mount position type is Extension Port Type 
[1.861][adapter]-[Info]-[DjiAccessAdapter_Init:362) Identity uart0 baudrate is 921600 bps 
[3.976][adapter]-[Info]-[DjiPayloadNegotiate_Init:219) Waiting payload negotiate finish. 
[4.976][adapter]-[Info]-[DjiPayloadNegotiate_Init:219) Waiting payload negotiate finish. 
[5.976][adapter]-[Info]-[DjiPayloadNegotiate_Init:219) Waiting payload negotiate finish. 
[6.976][adapter]-[Info]-[DjiPayloadNegotiate_Init:219) Waiting payload negotiate finish. 
[7.976][adapter]-[Info]-[DjiPayloadNegotiate_Init:219) Waiting payload negotiate finish. 

Agent comment from Leon in Zendesk ticket #110796:

Dear developer,

Hello, thank you for contacting DJI.

Actually, it is correct to connect the Type C of the E-Port expansion board to your Type C port.
According to the instructions in https://developer.dji.com/doc/payload-sdk-tutorial/en/quick-start/quick-guide/jetson-nano.html, you can ignore other instructions first. You should modify the psdk-usb-configure.sh file first, modify it according to the figure, comment line 167, modify lines 200 and 210 to your own corresponding paths, and then execute it manually with sudo to see if there is an error or whether the configuration is successful. The other part of the tutorial is to configure the boot-up automatically.

Regarding your latest news, send msg to queue error means that the serial port is blocked. We recommend that you use USB-TTL (FT232) to replace the serial port hardware for communication. This may be affected by the onboard serial port, and the serial port communication is unstable.

Thank you for your support of DJI products! I wish you all the best!

Best Regards,
DJI SDK Technical Support

°°°

Hello! I will write down everything that I have done so far. Please read everything carefully.

  1. I connected the M3TD drone to the E-Port extension kit as suggested in the tutorial with A and B lined up correctly as shown in the image.

image

  1. Then I have connect the VCC output, which is some 15V, to the DC barrel jack of the Jetson Orin Nano Dev kit as shown below.

image

  1. Then I have turned the USB mode switch to host and connected the USB-C output of the E-port to the jetson's USB-C port using a USB-C to USB-C data cable. I know for sure it is a data cable. I have confirmed it by connecting my mobile to jetson using the cable the devices can transfer data. Then I have connected the UART output of the Eport kit to the USB TTL chip and connected it to the USB A port of the jetson. We are using the USB TTL chip that you recommended in one of the previous issues that I posted. You can see the image below.

image

I know for sure the UART to USB TTL works as well. This is because, when I ran the sample programs using DJI_USE_ONLY_UART, the widgets, FC subscription, etc works. It is only when I try to subscribe the images, I get an error as I need to use USB BULK or NETWORK mode. Network mode apparently is not supported by M3TD.

Then I have modified my script by commenting line 167 and modifying lines 200 and 210. I have also edited line 41 to udc_dev_t186=3550000.usb as Orin Nano doesn't have udc_dev_t186=3550000.xudc. Then I tried running the startup script and it runs without errors. Here is what I get in my terminal:

nvidia@nvidia:~$ ls /dev/usb-ffs/*
/dev/usb-ffs/bulk1:
ep0  ep1  ep2

/dev/usb-ffs/bulk2:
ep0  ep1  ep2

nvidia@nvidia:~$ ps -aux | grep startup_bulk
root         773  0.0  0.0   2276   784 ?        S    09:51   0:00 /home/nvidia/Desktop/nano-usb-config/startup_bulk /dev/usb-ffs/bulk1
root        2040  0.0  0.0   2276   804 ?        S    09:51   0:00 /home/nvidia/Desktop/nano-usb-config/startup_bulk /dev/usb-ffs/bulk2
nvidia      3914  0.0  0.0  11820  2068 pts/1    S+   09:59   0:00 grep --color=auto startup_bulk

nvidia@nvidia:~$ ifconfig
eth0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        ether 48:b0:2d:eb:dd:84  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
        device interrupt 236  base 0x4000  

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 2714  bytes 2988778 (2.9 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 2714  bytes 2988778 (2.9 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

usb0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        ether 8a:fa:3b:dc:22:25  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

usb1: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        ether 8a:fa:3b:dc:22:27  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Finally, when I run the script, this is what I get:

nvidia@nvidia:~/Payload-SDK/build/bin$ sudo ./dji_sdk_demo_linux_cxx 
[sudo] password for nvidia: 
'Logs/latest.log' -> 'DJI_0002_20240702_10-02-40.log'
[0.006][core]-[Info]-[DjiCore_Init:101) Payload SDK Version : V3.8.0-beta.0-build.1929 
[1.174][adapter]-[Info]-[DjiAccessAdapter_Init:228) Identify aircraft series is Matrice 3D Series 
[1.174][adapter]-[Info]-[DjiAccessAdapter_Init:261) Identify mount position type is Extension Port Type 
[1.180][adapter]-[Info]-[DjiAccessAdapter_Init:362) Identity uart0 baudrate is 921600 bps 
[3.226][adapter]-[Info]-[DjiPayloadNegotiate_Init:219) Waiting payload negotiate finish. 
[4.226][adapter]-[Info]-[DjiPayloadNegotiate_Init:219) Waiting payload negotiate finish. 
[5.226][adapter]-[Info]-[DjiPayloadNegotiate_Init:219) Waiting payload negotiate finish. 
[6.226][adapter]-[Info]-[DjiPayloadNegotiate_Init:219) Waiting payload negotiate finish. 
[7.226][adapter]-[Info]-[DjiPayloadNegotiate_Init:219) Waiting payload negotiate finish. 
[8.227][adapter]-[Error]-[DjiAccessAdapter_Init:373) Payload negotiate error, returnCode = 225 
[8.227][adapter]-[Error]-[DjiAccessAdapter_Init:379) Payload negotiate error, returnCode = 225 
[8.227][core]-[Error]-[DjiCore_Init:121) Access adapter init error, stat:225 
terminate called after throwing an instance of 'std::runtime_error'
  what():  Core init error.
Aborted

Here are the contents of the log file if you are interested:

DJI_0002_20240702_10-02-40.log

I tried using the sudo dmesg | tail command to see if the USB-C port is recognizing some device and irrespective of whether I plug or unplug the USB-C output to the USB C port of jetson I get the same output:

[   19.851833] l4tbr0: port 1(usb0) entered blocking state
[   19.851871] l4tbr0: port 1(usb0) entered disabled state
[   19.852091] device usb0 entered promiscuous mode
[   19.878477] l4tbr0: port 2(usb1) entered blocking state
[   19.878501] l4tbr0: port 2(usb1) entered disabled state
[   19.881949] device usb1 entered promiscuous mode
[   19.894831] loop8: detected capacity change from 0 to 32768

I suspect that the USB-C output of the Eport is not recognized by the Orin Nano.

I am doing a lot of things to debug the hardware. In one such experiment, I connected the USB-C output of the Eport kit to my mobile phone and tried flipping the OTG Host device switch. When the switch is flipped to host my phone recognises the Eport and when I flip the switch to device my phone doesn't recognise anything. However when the Eport is is host mode the Jetson doesn't associate any IP address to either the usb0 or the usb1 ports.

Record_2024-07-02-11-06-32.mp4

Agent comment from Leon in Zendesk ticket #110796:

Dear kkishore9891,

I hope this message finds you well. Thank you for reaching out to DJI - Da-Jiang Innovations.

We appreciate the additional information you provided. The steps you outlined are quite detailed. One aspect that requires confirmation is whether your bulk link data transmission and reception are functioning correctly. This includes verifying the bulk configuration in the PSDK. For instance, while your bulk functionality may be operational, an incorrect configuration in the hal_usb_bulk.h file of the PSDK code could prevent its use within the PSDK environment. To address this, you may utilize the program at the end of the linked article to test the correctness of the BULK node: https://sdk-forum.dji.net/hc/zh-cn/articles/10232604141465-%E6%A0%91%E8%8E%93%E6%B4%BE4B%E9%85%8D%E7%BD%AEUSB-device-RNDIS-%E5%92%8C-BULK

Thank you for your support of DJI products! Wishing you every success in your endeavors.

Best Regards,

DJI - Da-Jiang Innovations SDK Technical Support

°°°

Hello,

I tried what you have suggested and this is the output that happened:

nvidia@nvidia:~/Desktop/junk$ ls
bulk-device.c

nvidia@nvidia:~/Desktop/junk$ gcc -o bulk_device bulk-device.c -I/usr/include -lusb-1.0 -lpthread
bulk-device.c: In function ‘device_Thread’:
bulk-device.c:29:8: warning: ‘return’ with a value, in function returning void
   29 | return -1;
      |        ^
bulk-device.c:15:6: note: declared here
   15 | void device_Thread()
      |      ^~~~~~~~~~~~~
bulk-device.c:36:8: warning: ‘return’ with a value, in function returning void
   36 | return -1;
      |        ^
bulk-device.c:15:6: note: declared here
   15 | void device_Thread()
      |      ^~~~~~~~~~~~~
bulk-device.c: In function ‘main’:
bulk-device.c:99:41: warning: passing argument 3 of ‘pthread_create’ from incompatible pointer type [-Wincompatible-pointer-types]
   99 | if (pthread_create(&deviceThread, NULL, device_Thread, NULL) != 0) {
      |                                         ^~~~~~~~~~~~~
      |                                         |
      |                                         void (*)()
In file included from bulk-device.c:12:
/usr/include/pthread.h:204:36: note: expected ‘void * (*)(void *)’ but argument is of type ‘void (*)()’
  204 |                            void *(*__start_routine) (void *),
      |                            ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
bulk-device.c:109:69: warning: format ‘%d’ expects argument of type ‘int’, but argument 4 has type ‘size_t’ {aka ‘long unsigned int’} [-Wformat=]
  109 | printf("libusb_bulk_transfer send failed[%d], endpointOut[%x], len[%d]\n",ret, 0x02, strlen(sendbuf));
      |                                                                    ~^                ~~~~~~~~~~~~~~~
      |                                                                     |                |
      |                                                                     int              size_t {aka long unsigned int}
      |                                                                    %ld

nvidia@nvidia:~/Desktop/junk$ ls
bulk_device  bulk-device.c

nvidia@nvidia:~/Desktop/junk$ ./bulk_device 
libusb_open_device_with_vid_pid failed

But from whatever I have seen so far, it seems the E-Port's USB-C output is not establishing connection with the jetson nano's USB-C port. Is it okay if I use a USB-C to USB-C cable or is an USB-C to OTG followed by a USB-A to USB-C required? If not maybe I am missing some drivers for the E-Port's USB-C port in the jetson nano. If it is neither most probably the E-Port's USB-C output might be malfunctioned. But I may be wrong.

Hello! Some updates! I used a USB-C to OTG cable followed by a USB-A to USB-C data cable and the USB bulk connection works now!

Agent comment from Leon in Zendesk ticket #110796:

Dear kkishore9891,

I hope this message finds you well. Thank you for reaching out to DJI Innovations.

We apologize for the delay in our response. Due to the high volume of inquiries recently, our response time has not been as ideal as we would like. We are glad that your issue has been resolved. If you have any further questions, please feel free to contact us at any time.

Thank you for your support of DJI products! Wishing you continued success.

Best Regards,

DJI Innovations SDK Technical Support

°°°

Hi @dji-dev and @kkishore9891 ,
I am trying to set up a Jetson Orin(Jetpack 6.0 Ubuntu 22.04)with DJI M30T and facing the same error, I have followed the steps suggested above but I run into this issue

"[7.197][adapter]-[Error]-[DjiAccessAdapter_Init:379) Payload negotiate info failed. Probably the usb device configuration may not be successful. Please don't register socket handler if you don't want to use the network.
[7.197][core]-[Error]-[DjiCore_Init:126) Access adapter init error, stat:225
[7.197][user]-[Error]-[main:131) Core init error"

My startup_bulk compiled using the changes suggested above.

This is my nv-l4t-usb-device-mode-start.sh and my hal_usb_bulk.h is set same as mentioned above.

#!/bin/bash

# SPDX-FileCopyrightText: Copyright (c) 2017-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: BSD-3-Clause
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# 2. 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.
#
# 3. Neither the name of the copyright holder 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.

set -e

script_dir="$(cd "$(dirname "$0")" && pwd)"
. "${script_dir}/nv-l4t-usb-device-mode-config.sh"

modprobe libcomposite

# Wait for any modules to load and initialize
for attempt in $(seq 60); do
    udc_dev=3550000.xudc
    if [ -e "/sys/class/udc/${udc_dev}" ]; then
        break
    fi
    udc_dev=3550000.usb
    if [ -e "/sys/class/udc/${udc_dev}" ]; then
        break
    fi
    udc_dev=""
    sleep 1
done
if [ "${udc_dev}" == "" ]; then
    echo No known UDC device found
    exit 1
fi

macs_file="${script_dir}/mac-addresses"
if [ -f "${macs_file}" ]; then
    . "${macs_file}"
    if ! [[ "${mac_rndis_h}" =~ ^([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}$ &&
         "${mac_rndis_d}" =~ ^([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}$ &&
         "${mac_ecm_h}" =~ ^([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}$ &&
         "${mac_ecm_d}" =~ ^([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}$ ]]; then
        rm "${macs_file}"
    fi
fi

if ! [ -f "${macs_file}" ]; then
    # Generate unique data
    if [ -f /proc/device-tree/serial-number ]; then
        random="$(md5sum /proc/device-tree/serial-number|cut -c1-12)"
    else
        random="$(echo "no-serial"|md5sum|cut -c1-12)"
    fi
    # Extract 6 bytes
    b1="$(echo "${random}"|cut -c1-2)"
    b2="$(echo "${random}"|cut -c3-4)"
    b3="$(echo "${random}"|cut -c5-6)"
    b4="$(echo "${random}"|cut -c7-8)"
    b5="$(echo "${random}"|cut -c9-10)"
    b6="$(echo "${random}"|cut -c11-12)"
    # Clear broadcast/multicast, set locally administered bits
    b1="$(printf "%02x" "$(("0x${b1}" & 0xfe | 0x02))")"
    # Set 4 LSBs to unique value per interface
    b6_rndis_h="$(printf "%02x" "$(("0x${b6}" & 0xfc | 0x00))")"
    b6_rndis_d="$(printf "%02x" "$(("0x${b6}" & 0xfc | 0x01))")"
    b6_ecm_h="$(printf "%02x" "$(("0x${b6}" & 0xfc | 0x02))")"
    b6_ecm_d="$(printf "%02x" "$(("0x${b6}" & 0xfc | 0x03))")"
    # Construct complete MAC per interface
    mac_rndis_h="${b1}:${b2}:${b3}:${b4}:${b5}:${b6_rndis_h}"
    mac_rndis_d="${b1}:${b2}:${b3}:${b4}:${b5}:${b6_rndis_d}"
    mac_ecm_h="${b1}:${b2}:${b3}:${b4}:${b5}:${b6_ecm_h}"
    mac_ecm_d="${b1}:${b2}:${b3}:${b4}:${b5}:${b6_ecm_d}"
    # Save values for next boot
    echo "mac_rndis_h=${mac_rndis_h}" > "${macs_file}"
    echo "mac_rndis_d=${mac_rndis_d}" >> "${macs_file}"
    echo "mac_ecm_h=${mac_ecm_h}" >> "${macs_file}"
    echo "mac_ecm_d=${mac_ecm_d}" >> "${macs_file}"
fi

mkdir -p /sys/kernel/config/usb_gadget/l4t
cd /sys/kernel/config/usb_gadget/l4t

# If this script is modified outside NVIDIA, the idVendor and idProduct values
# MUST be replaced with appropriate vendor-specific values.
echo 0x0955 > idVendor
echo 0x7020 > idProduct
# BCD value. Each nibble should be 0..9. 0x1234 represents version 12.3.4.
echo 0x0002 > bcdDevice

# Informs Windows that this device is a composite device, i.e. it implements
# multiple separate protocols/devices.
echo 0xEF > bDeviceClass
echo 0x02 > bDeviceSubClass
echo 0x01 > bDeviceProtocol

mkdir -p strings/0x409
if [ -f /proc/device-tree/serial-number ]; then
    serialnumber="$(cat /proc/device-tree/serial-number|tr -d '\000')"
else
    serialnumber=no-serial
fi
echo "${serialnumber}" > strings/0x409/serialnumber
# If this script is modified outside NVIDIA, the manufacturer and product values
# MUST be replaced with appropriate vendor-specific values.
echo "NVIDIA" > strings/0x409/manufacturer
echo "Linux for Tegra" > strings/0x409/product

cfg=configs/c.1
mkdir -p "${cfg}"
cfg_str=""
is_remote_wakeup=0

# Note: RNDIS must be the first function in the configuration, or Windows'
# RNDIS support will not operate correctly.
if [ ${enable_rndis} -eq 1 ]; then
    cfg_str="${cfg_str}+RNDIS"
    func=functions/rndis.usb0
    mkdir -p "${func}"
    echo "${mac_rndis_h}" > "${func}/host_addr"
    echo "${mac_rndis_d}" > "${func}/dev_addr"
    ln -sf "${func}" "${cfg}"

    # Informs Windows that this device is compatible with the built-in RNDIS
    # driver. This allows automatic driver installation without any need for
    # a .inf file or manual driver selection.
    echo 1 > os_desc/use
    echo 0xcd > os_desc/b_vendor_code
    echo MSFT100 > os_desc/qw_sign
    echo RNDIS > "${func}/os_desc/interface.rndis/compatible_id"
    echo 5162001 > "${func}/os_desc/interface.rndis/sub_compatible_id"
    ln -sf "${cfg}" os_desc

    is_remote_wakeup=1
fi

# If two USB configs are created, and the second contains RNDIS and ACM, then
# Windows will ignore at the ACM function in that config. Consequently, this
# script creates only a single USB config.
if [ ${enable_acm} -eq 1 ]; then
    cfg_str="${cfg_str}+ACM"
    func=functions/acm.GS0
    mkdir -p "${func}"
    ln -sf "${func}" "${cfg}"
fi

# Copy system version information into the exposed filesystem image,
# so that any system that's attached to the USB port can identify this device.
# Do this even if $enable_ums!=1, since $fs_img is locally mounted too.
mntpoint="/mnt/l4t-devmode-$$"
rm -rf "${mntpoint}"
mkdir -p "${mntpoint}"
modprobe loop
mount -o loop "${fs_img}" "${mntpoint}"
rm -rf "${mntpoint}/version"
mkdir -p "${mntpoint}/version"
if [ -f /etc/nv_tegra_release ]; then
    cp /etc/nv_tegra_release "${mntpoint}/version"
fi
if dpkg -s nvidia-l4t-core > /dev/null 2>&1; then
    dpkg -s nvidia-l4t-core > "${mntpoint}/version/nvidia-l4t-core.dpkg-s.txt"
fi
plug_man_dir="/proc/device-tree/chosen/plugin-manager/"
chosen_dir="/proc/device-tree/chosen/"

#if [ -d "${plug_man_dir}" ]; then
#    cp -r "${plug_man_dir}" "${mntpoint}/version/plugin-manager"
#elif [ -d "${chosen_dir}" ]; then
#    cp -r "${chosen_dir}" "${mntpoint}/version/chosen"
#fi
umount "${mntpoint}"
rm -rf "${mntpoint}"

if [ ${enable_ums} -eq 1 ]; then
    cfg_str="${cfg_str}+UMS"
    func=functions/mass_storage.0
    mkdir -p "${func}"
    ln -sf "${func}" "${cfg}"
    # Prevent users from corrupting the disk image; make it read-only
    echo 1 > "${func}/lun.0/ro"
    echo "${fs_img}" > "${func}/lun.0/file"
fi

if [ ${enable_ecm} -eq 1 ]; then
    cfg_str="${cfg_str}+${ecm_ncm_name}"
    func=functions/${ecm_ncm}.usb0
    mkdir -p "${func}"
    echo "${mac_ecm_h}" > "${func}/host_addr"
    echo "${mac_ecm_d}" > "${func}/dev_addr"
    ln -sf "${func}" "${cfg}"

    is_remote_wakeup=1
fi
enable_bulk=1

if [ ${enable_bulk} -eq 1 ]; then
    mkdir -p /dev/usb-ffs
    
    cfg_str="${cfg_str}+BULK1" 
    mkdir -p /dev/usb-ffs/bulk1
    func=functions/ffs.bulk1
    mkdir -p "${func}"
    ln -sf "${func}" "${cfg}"
    mount -o mode=0777 -o uid=2000 -o gid=2000 -t functionfs bulk1 /dev/usb-ffs/bulk1
    /home/ext75/Desktop/startup_bulk/startup_bulk /dev/usb-ffs/bulk1 &
    sleep 3


    cfg_str="${cfg_str}+BULK2" 
    mkdir -p /dev/usb-ffs/bulk2
    func=functions/ffs.bulk2
    mkdir -p "${func}"
    ln -sf "${func}" "${cfg}"
    mount -o mode=0777 -o uid=2000 -o gid=2000 -t functionfs bulk2 /dev/usb-ffs/bulk2
    /home/ext75/Desktop/startup_bulk/startup_bulk /dev/usb-ffs/bulk2 &
    sleep 3
fi
if [ ${is_remote_wakeup} -eq 1 ]; then
    echo "0xe0" > "${cfg}/bmAttributes"
else
    echo "0xc0" > "${cfg}/bmAttributes"
fi

mkdir -p "${cfg}/strings/0x409"
# :1 in the variable expansion strips the first character from the value. This
# removes the unwanted leading + sign. This simplifies the logic to construct
# $cfg_str above; it can always add a leading delimiter rather than only doing
# so unless the string is previously empty.
echo "${cfg_str:1}" > "${cfg}/strings/0x409/configuration"

# Create and configure the network bridge before setting the UDC device. This
# ensures that no matter how quickly udev events (which run -runtime-start.sh)
# are triggered after setting the UDC device below, the bridge device is
# guaranteed to exist, so -runtime-start.sh is guaranteed to be able to
# configure it.
#
# Set the device to "down" initially; if/when -runtime-start.sh runs in response
# to cable presence, the interface will be set to "up".
/sbin/brctl addbr l4tbr0
/sbin/ifconfig l4tbr0 down

echo "${udc_dev}" > UDC

# Ethernet devices require additional configuration. This must happen after the
# UDC device is assigned, since that triggers the creation of the Tegra-side
# Ethernet interfaces.
#
# This script always assigns any-and-all Ethernet devices to an Ethernet
# bridge, and assigns the static IP to that bridge. This allows the script to
# more easily handle the potentially variable set of Ethernet devices.
#
# If your custom use-case requires separate IP addresses per interface, or
# only ever has one interface active, you may modify this script to skip
# bridge creation, and assign IP address(es) directly to the interface(s).

if [ ${enable_rndis} -eq 1 ]; then
    /sbin/brctl addif l4tbr0 "$(cat functions/rndis.usb0/ifname)"
    /sbin/ifconfig "$(cat functions/rndis.usb0/ifname)" up
fi

if [ ${enable_ecm} -eq 1 ]; then
    /sbin/brctl addif l4tbr0 "$(cat functions/${ecm_ncm}.usb0/ifname)"
    /sbin/ifconfig "$(cat functions/${ecm_ncm}.usb0/ifname)" up
fi

cd - # Out of /sys/kernel/config/usb_gadget

# Create a local disk device that exposes the same filesystem image that's
# exported over USB. This will allow local users to see the files too.
/sbin/losetup -f -r "${fs_img}"

# Trigger udev events on any existing cable detection devices, which will
# cause nv-l4t-usb-device-mode-state-change.sh to run and poll for the
# current cable state. This ensures that if relevant udev events were
# emitted before this script started, then device mode is correctly set up.
udevadm trigger -v --action=change --property-match=SUBSYSTEM=android_usb
udevadm trigger -v --action=change --property-match=SUBSYSTEM=usb_role

exit 0
`

Running 'lsusb -d 0955:7020 -v' results in empty output
image

Any help regarding this would be appreciated, Thanks!