Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

video stream not working in M3TD #180

Open
kkishore9891 opened this issue Jul 3, 2024 · 10 comments
Open

video stream not working in M3TD #180

kkishore9891 opened this issue Jul 3, 2024 · 10 comments

Comments

@kkishore9891
Copy link

Hello! I Tried to run the sample code in M3TD after setting up USB bulk configuration. I found that the image stream is not being displayed when running the sample script as shown in the video below.

Image.Stream-2024-07-03_16.48.20.mp4

I would like to know if I need to modify anything in the sample code to recieve the image stream.

For example in my separate code base inspired from the sample test_liveview.cpp code I used a setup like this for the Matrice M30T drone as shown below:

T_DjiReturnCode LiveviewSample::StartWideCameraStream(CameraImageCallback callback, void *userData)
{
    // Obtain the decoder for Wide camera. Perhaps it will work with any decoder. Need to test.
    auto decoder = streamDecoder.find(DJI_LIVEVIEW_CAMERA_POSITION_NO_1);
    // USER_LOG_ERROR("Starting wide");
    
    // If the decoder exists, start it and associate it with a callback
    if ((decoder != streamDecoder.end()) && decoder->second)
    {
        decoder->second->init();
        decoder->second->registerCallback(callback, userData);

        return DjiLiveview_StartH264Stream(DJI_LIVEVIEW_CAMERA_POSITION_NO_1, DJI_LIVEVIEW_CAMERA_SOURCE_M30T_WIDE,
                                           LiveviewConvertH264ToRgbCallback);
    }
    // Error handling
    else
    {
        return DJI_ERROR_SYSTEM_MODULE_CODE_NOT_FOUND;
    }
}

// Function that associates a callback with the thermal camera stream and a user defined data
// in our case the user defined data is a struct object with a publisher and clock.
T_DjiReturnCode LiveviewSample::StartThermalCameraStream(CameraImageCallback callback, void *userData)
{
    // Obtain the decoder for thermal camera. Perhaps it will work with any decoder. Need to test.
    auto decoder = streamDecoder.find(DJI_LIVEVIEW_CAMERA_POSITION_NO_1);

    // If the decoder exists, start it and associate it with a callback
    if ((decoder != streamDecoder.end()) && decoder->second)
    {
        decoder->second->init();
        decoder->second->registerCallback(callback, userData);
        USER_LOG_ERROR("Starting Thermal Camera Streaming");
        return DjiLiveview_StartH264Stream(DJI_LIVEVIEW_CAMERA_POSITION_NO_1, DJI_LIVEVIEW_CAMERA_SOURCE_M30T_IR,
                                           LiveviewConvertH264ToRgbCallback);
    }
    // Error handling
    else
    {
        return DJI_ERROR_SYSTEM_MODULE_CODE_NOT_FOUND;
    }
}

This worked for the M30T drone but using something similar like DJI_LIVEVIEW_CAMERA_POSITION_NO_1 and DJI_LIVEVIEW_CAMERA_SOURCE_M3TD_IR or DJI_LIVEVIEW_CAMERA_SOURCE_M3TD_VIS doesn't send any images to the callback function. I am not sure if USB bulk might have some issue. I would first like to get the video feed working in the sample script so that I can later use that to modify our code base to accomodate the M3TD drone.

@dji-dev
Copy link
Contributor

dji-dev commented Jul 4, 2024

Agent comment from Leon in Zendesk ticket #111143:

Dear kkishore9891,

Greetings. We appreciate your contact with DJI Innovations.

Could you please test the DjiTest_LiveviewRunSample function in the test_liveview.c file located in payload-sdk\samples\sample_c\module_sample\liveview first? Afterwards, add print statements in either the DjiTest_FpvCameraStreamCallback or DjiTest_PayloadCameraStreamCallback callback functions to verify if the callback is being triggered. If the callback is not being triggered, it indicates that there may still be an issue with the bulk link.

Thank you for your support of DJI products! We wish you every success.

Best Regards,

DJI Innovations SDK Technical Support

°°°

@kkishore9891
Copy link
Author

kkishore9891 commented Jul 4, 2024

Hello I will try this and let you know but I tried something else in the Matrice M30T with the same jetson setup that confirms that there is some issue with the bulk link.

Since Matrice M30T support DJI_USE_UART_AND_NETWORK_DEVICE and DJI_USE_UART_AND_USB_BULK_DEVICE options I connected my hardware setup to M30T instead of M3TD and simply swapped DJI_USE_UART_AND_USB_BULK_DEVICE with DJI_USE_UART_AND_NETWORK_DEVICE, and the image subscription works. While the same M30T with the exact same code and hardware setup but using DJI_USE_UART_AND_USB_BULK_DEVICE instead of DJI_USE_UART_AND_NETWORK_DEVICE in the dji_sdk_config.h causes the image stream not to work in the M30T. Since M3TD doesn't support DJI_USE_UART_AND_NETWORK_DEVICE, I have never been able to get the image stream to work. But I will try what you said soon and update you.

The setup I am using is as follows:

  1. I have both Matrice M30T drone and the M3TD drone. The former supports 2 modes for image subscription BULK and Network while the latter supports only BULK.
  2. I have connected the Eport to the Eport extension kit with correct A B alignment.
  3. I have connected the UART RX TX output correctly to an FTDI chip and connected it to the USB port and everything except live view works with DJI_USE_ONLY_UART. Indicating that the hardware connection is correct.
  4. I have connected the USB-C output of the E-Port kit to a USB-C to USB-A female OTG and the connected the USB-A output to USB-C in my jetson Orin Nano using a simple USB-A to USB-C cable.
  5. Configured USB Bulk using this shell script for my Jetson Orin Nano. Look out for the lines with ### comments:
#!/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
##############################NOTE HAD TO MODIFY THIS FOR ORIN NANO#############################
    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
####################################COMMENTED OUT THIS LINE##################################
# 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
#####################################MODIFIED THIS LINE##########################################
    /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
#####################################MODIFIED THIS LINE##########################################
    /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 replaced /opt/nvidia/l4t-usb-device-mode/nv-l4t-usb-device-mode-start.sh in my Orin Nano with this script. I can see the /dev/usb-ffs/bulk1 and /dev/usb-ffs/bulk2 when I enter $ls /dev. I hope these details help. Tomorrow I am going to run the script in Jetson Nano instead of Orin Nano and I will let you know if the Bulk function works with that.

@kkishore9891
Copy link
Author

kkishore9891 commented Jul 4, 2024

Hello, so I tried to run the test_livew.c program's DjiTest_LiveviewRunSample() function as per your suggestion and added some print statements to the callback as shown in the script below:

static void DjiTest_FpvCameraStreamCallback(E_DjiLiveViewCameraPosition position, const uint8_t *buf,
                                            uint32_t bufLen)
{

    USER_LOG_INFO("FPV Stream CB");
    FILE *fp = NULL;
    size_t size;

    fp = fopen(s_fpvCameraStreamFilePath, "ab+");
    if (fp == NULL) {
        printf("fopen failed!\n");
        return;
    }

    size = fwrite(buf, 1, bufLen, fp);
    if (size != bufLen) {
        fclose(fp);
        return;
    }

    fflush(fp);
    fclose(fp);
}
 
static void DjiTest_PayloadCameraStreamCallback(E_DjiLiveViewCameraPosition position, const uint8_t *buf,
                                                uint32_t bufLen)
{
    USER_LOG_INFO("Payload Stream CB");
    FILE *fp = NULL;
    size_t size;

    fp = fopen(s_payloadCameraStreamFilePath, "ab+");
    if (fp == NULL) {
        printf("fopen failed!\n");
        return;
    }

    size = fwrite(buf, 1, bufLen, fp);
    if (size != bufLen) {
        fclose(fp);
        return;
    }

    fflush(fp);
    fclose(fp);
}

and when I ran the script, this is the output that I received:

nvidia@nvidia:~/Payload-SDK/build/bin$ sudo ./dji_sdk_demo_linux_cxx 
'Logs/latest.log' -> 'DJI_0027_20240704_15-58-59.log'
[0.009][core]-[Info]-[DjiCore_Init:106) Payload SDK Version : V3.9.0-beta.0-build.2044 
[1.060][adapter]-[Info]-[DjiAccessAdapter_Init:231) Identify aircraft series is Matrice 3D Series 
[1.060][adapter]-[Info]-[DjiAccessAdapter_Init:264) Identify mount position type is Extension Port Type 
[1.067][adapter]-[Info]-[DjiAccessAdapter_Init:365) Identity uart0 baudrate is 921600 bps 
[3.975][adapter]-[Info]-[DjiPayloadNegotiate_Init:228) Waiting payload negotiate finish. 
[4.989][core]-[Info]-[DjiIdentityVerify_UpdatePolicy:474) Updating dji sdk policy file... 
[5.990][core]-[Info]-[DjiIdentityVerify_UpdatePolicy:482) Update dji sdk policy file successfully 
[6.018][core]-[Info]-[DjiCore_Init:174) Identify AircraftType = Matrice 3TD, MountPosition = Extension Port, SdkAdapterType = None 
[6.064][gimbal]-[Error]-[DjiGimbal_Init:205) Can't support this function 
[6.064][user]-[Error]-[DjiTest_GimbalStartService:154) init gimbal module error: 0x000000E0 
[6.064][user]-[Error]-[DjiUser_ApplicationStart:316) psdk gimbal init error 
[11.065][core]-[Info]-[DjiCore_ApplicationStart:238) Start dji sdk application 
[11.065][user]-[Info]-[DjiUser_ApplicationStart:363) Application start. 

| Available commands:                                                                              |
| [0] Fc subscribe sample - subscribe quaternion and gps data                                      |
| [1] Flight controller sample - you can control flying by PSDK                                    |
| [2] Hms info manager sample - get health manger system info by language                          |
| [a] Gimbal manager sample - you can control gimbal by PSDK                                       |
| [c] Camera stream view sample - display the camera video stream                                  |
| [d] Stereo vision view sample - display the stereo image                                         |
| [e] Run camera manager sample - you can test camera's functions interactively                    |
| [f] Start rtk positioning sample - you can receive rtk rtcm data when rtk signal is ok           |

c
[17.894][user]-[Info]-[DjiTest_LiveviewRunSample:63) Liveview sample start 
[17.894][user]-[Info]-[DjiTest_LiveviewRunSample:72) --> Step 1: Init liveview module 
[18.904][user]-[Info]-[DjiTest_LiveviewRunSample:80) --> Step 2: Start h264 stream of the fpv and selected payload
 
[19.416][user]-[Info]-[DjiTest_LiveviewRunSample:113) Storing camera h264 stream, second: 1. 
[20.432][user]-[Info]-[DjiTest_LiveviewRunSample:113) Storing camera h264 stream, second: 2. 
[21.432][user]-[Info]-[DjiTest_LiveviewRunSample:113) Storing camera h264 stream, second: 3. 
[22.432][user]-[Info]-[DjiTest_LiveviewRunSample:113) Storing camera h264 stream, second: 4. 
[23.432][user]-[Info]-[DjiTest_LiveviewRunSample:113) Storing camera h264 stream, second: 5. 
[24.433][user]-[Info]-[DjiTest_LiveviewRunSample:113) Storing camera h264 stream, second: 6. 
[25.456][user]-[Info]-[DjiTest_LiveviewRunSample:113) Storing camera h264 stream, second: 7. 
[26.456][user]-[Info]-[DjiTest_LiveviewRunSample:113) Storing camera h264 stream, second: 8. 
[27.456][user]-[Info]-[DjiTest_LiveviewRunSample:113) Storing camera h264 stream, second: 9. 
[28.457][user]-[Info]-[DjiTest_LiveviewRunSample:113) Storing camera h264 stream, second: 10. 
[29.457][user]-[Info]-[DjiTest_LiveviewRunSample:113) Storing camera h264 stream, second: 11. 
[30.471][user]-[Info]-[DjiTest_LiveviewRunSample:113) Storing camera h264 stream, second: 12. 
[31.471][user]-[Info]-[DjiTest_LiveviewRunSample:113) Storing camera h264 stream, second: 13. 
[32.471][user]-[Info]-[DjiTest_LiveviewRunSample:113) Storing camera h264 stream, second: 14. 
[33.471][user]-[Info]-[DjiTest_LiveviewRunSample:113) Storing camera h264 stream, second: 15. 
[34.472][user]-[Info]-[DjiTest_LiveviewRunSample:113) Storing camera h264 stream, second: 16. 
[35.475][user]-[Info]-[DjiTest_LiveviewRunSample:113) Storing camera h264 stream, second: 17. 
[36.475][user]-[Info]-[DjiTest_LiveviewRunSample:113) Storing camera h264 stream, second: 18. 
[37.475][user]-[Info]-[DjiTest_LiveviewRunSample:113) Storing camera h264 stream, second: 19. 
[38.475][user]-[Info]-[DjiTest_LiveviewRunSample:113) Storing camera h264 stream, second: 20. 
[39.475][user]-[Info]-[DjiTest_LiveviewRunSample:127) --> Step 3: Stop h264 stream of the fpv and selected payload
 
[39.991][user]-[Info]-[DjiTest_LiveviewRunSample:146) Fpv stream is saved to file:  
[39.991][user]-[Info]-[DjiTest_LiveviewRunSample:147) Payload1 stream is saved to file: payload1_vis_stream_20240704_15-59-17.h264
 
[39.991][user]-[Info]-[DjiTest_LiveviewRunSample:151) --> Start h264 stream of the fpv and selected payload
 
[40.513][user]-[Info]-[DjiTest_LiveviewRunSample:166) Storing camera h264 stream, second: 1. 
[41.513][user]-[Info]-[DjiTest_LiveviewRunSample:166) Storing camera h264 stream, second: 2. 
[42.513][user]-[Info]-[DjiTest_LiveviewRunSample:166) Storing camera h264 stream, second: 3. 
[43.513][user]-[Info]-[DjiTest_LiveviewRunSample:166) Storing camera h264 stream, second: 4. 
[44.513][user]-[Info]-[DjiTest_LiveviewRunSample:166) Storing camera h264 stream, second: 5. 
[45.513][user]-[Info]-[DjiTest_LiveviewRunSample:166) Storing camera h264 stream, second: 6. 
[46.514][user]-[Info]-[DjiTest_LiveviewRunSample:166) Storing camera h264 stream, second: 7. 
[47.514][user]-[Info]-[DjiTest_LiveviewRunSample:166) Storing camera h264 stream, second: 8. 
[48.514][user]-[Info]-[DjiTest_LiveviewRunSample:166) Storing camera h264 stream, second: 9. 
[49.514][user]-[Info]-[DjiTest_LiveviewRunSample:166) Storing camera h264 stream, second: 10. 
[50.514][user]-[Info]-[DjiTest_LiveviewRunSample:166) Storing camera h264 stream, second: 11. 
[51.514][user]-[Info]-[DjiTest_LiveviewRunSample:166) Storing camera h264 stream, second: 12. 
[52.514][user]-[Info]-[DjiTest_LiveviewRunSample:166) Storing camera h264 stream, second: 13. 
[53.514][user]-[Info]-[DjiTest_LiveviewRunSample:166) Storing camera h264 stream, second: 14. 
[54.514][user]-[Info]-[DjiTest_LiveviewRunSample:166) Storing camera h264 stream, second: 15. 
[55.515][user]-[Info]-[DjiTest_LiveviewRunSample:166) Storing camera h264 stream, second: 16. 
[56.515][user]-[Info]-[DjiTest_LiveviewRunSample:166) Storing camera h264 stream, second: 17. 
[57.515][user]-[Info]-[DjiTest_LiveviewRunSample:166) Storing camera h264 stream, second: 18. 
[58.515][user]-[Info]-[DjiTest_LiveviewRunSample:166) Storing camera h264 stream, second: 19. 
[59.515][user]-[Info]-[DjiTest_LiveviewRunSample:166) Storing camera h264 stream, second: 20. 
[61.028][user]-[Info]-[DjiTest_LiveviewRunSample:178) Fpv stream is saved to file:  
[61.028][user]-[Info]-[DjiTest_LiveviewRunSample:179) Payload1 stream is saved to file: payload1_ir_stream_20240704_15-59-17.h264
 
[61.028][user]-[Info]-[DjiTest_LiveviewRunSample:181) --> Step 4: Deinit liveview module 
[61.028][user]-[Info]-[DjiTest_LiveviewRunSample:190) Liveview sample end 

The print statements in the callbacks are not being displayed. Thus, it is confirmed now that the USB Bulk link has some flaw. Could you please look into the procedure that I have followed as explained in the previous comment to see if I made some mistake while setting up the USB Bulk link? The tutorial provided in PSDK documentation offers the suggestions for Jetson Nano, but since I am using Orin Nano I had to make some changes as I have indicated with ###### comments.

@dji-dev
Copy link
Contributor

dji-dev commented Jul 5, 2024

Agent comment from Leon in Zendesk ticket #111143:

Dear Developer,

Greetings and thank you for reaching out to DJI Innovations.

We appreciate the steps and validation conclusions you provided. We have carefully reviewed your validation on the M30T model. Firstly, there is no necessary connection between BULK and NETWORK. The NETWORK link you used should be based on RNDIS for communication, which should not be affected by whether your BULK is configured correctly. Additionally, you mentioned that even when switching to BULK, the M30T still cannot retrieve data properly.

We also noticed that there is no information printed from the callback function in your log, indicating that your bulk or PSDK's hal_usb_bulk.h file is still not configured correctly.

Perhaps you can locate the nv-l4t-usb-device-mode-start.sh file in your development board and add the following code snippet at the end (please adjust the paths accordingly):

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/dji/Desktop/startup_bulk/startup_bulk /dev/usb-ffs/bulk1 & /home/sutpc/Downloads/UAV/usb-bulk-configuration-reference/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/dji/Desktop/startup_bulk/startup_bulk /dev/usb-ffs/bulk2 & /home/sutpc/Downloads/UAV/usb-bulk-configuration-reference/startup_bulk /dev/usb-ffs/bulk2 & sleep 3 fi

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

Best Regards,

DJI Innovations SDK Technical Support

°°°

@kkishore9891
Copy link
Author

Hello,

This is the original nv-l4t-usb-device-mode-start.sh code that I took a backup of:

#!/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

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

As you suggested I added the lines to this code. Adding at the end doesn't work however. So I added it in the middle and now the code is:

#!/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/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

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

My hal_usb_bulk.h file is:

/**
 ********************************************************************
 * @file    hal_usb_bulk.h
 * @brief   This is the header file for "hal_usb_bulk.c", defining the structure and
 * (exported) function prototypes.
 *
 * @copyright (c) 2021 DJI. All rights reserved.
 *
 * All information contained herein is, and remains, the property of DJI.
 * The intellectual and technical concepts contained herein are proprietary
 * to DJI and may be covered by U.S. and foreign patents, patents in process,
 * and protected by trade secret or copyright law.  Dissemination of this
 * information, including but not limited to data and other proprietary
 * material(s) incorporated within the information, in any form, is strictly
 * prohibited without the express written consent of DJI.
 *
 * If you receive this source code without DJI’s authorization, you may not
 * further disseminate the information, and you must immediately remove the
 * source code and notify DJI of its removal. DJI reserves the right to pursue
 * legal actions against you for any loss(es) or damage(s) caused by your
 * failure to do so.
 *
 *********************************************************************
 */

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef HAL_USB_BULK_H
#define HAL_USB_BULK_H

/* Includes ------------------------------------------------------------------*/
#include "stdint.h"
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#ifdef LIBUSB_INSTALLED

#include <libusb-1.0/libusb.h>

#endif

#include "dji_platform.h"

#ifdef __cplusplus
extern "C" {
#endif

/* Exported constants --------------------------------------------------------*/
#define LINUX_USB_BULK1_EP_OUT_FD               "/dev/usb-ffs/bulk1/ep1"
#define LINUX_USB_BULK1_EP_IN_FD                "/dev/usb-ffs/bulk1/ep2"

#define LINUX_USB_BULK1_INTERFACE_NUM           (2)
#define LINUX_USB_BULK1_END_POINT_IN            (0x83)
#define LINUX_USB_BULK1_END_POINT_OUT           (2)

#define LINUX_USB_BULK2_EP_OUT_FD               "/dev/usb-ffs/bulk2/ep1"
#define LINUX_USB_BULK2_EP_IN_FD                "/dev/usb-ffs/bulk2/ep2"

#define LINUX_USB_BULK2_INTERFACE_NUM           (3)
#define LINUX_USB_BULK2_END_POINT_IN            (0x84)
#define LINUX_USB_BULK2_END_POINT_OUT           (3)

#ifdef PLATFORM_ARCH_x86_64
#define LINUX_USB_VID                         (0x0B95)
#define LINUX_USB_PID                         (0x1790)
#else
#define LINUX_USB_VID                         (0x0955)
#define LINUX_USB_PID                         (0x7020)
#endif

/* Exported types ------------------------------------------------------------*/

/* Exported functions --------------------------------------------------------*/
T_DjiReturnCode HalUsbBulk_Init(T_DjiHalUsbBulkInfo usbBulkInfo, T_DjiUsbBulkHandle *usbBulkHandle);
T_DjiReturnCode HalUsbBulk_DeInit(T_DjiUsbBulkHandle usbBulkHandle);
T_DjiReturnCode HalUsbBulk_WriteData(T_DjiUsbBulkHandle usbBulkHandle, const uint8_t *buf, uint32_t len,
                                     uint32_t *realLen);
T_DjiReturnCode HalUsbBulk_ReadData(T_DjiUsbBulkHandle usbBulkHandle, uint8_t *buf, uint32_t len, uint32_t *realLen);
T_DjiReturnCode HalUsbBulk_GetDeviceInfo(T_DjiHalUsbBulkDeviceInfo *deviceInfo);

#ifdef __cplusplus
}
#endif

#endif // HAL_USB_BULK_H
/************************ (C) COPYRIGHT DJI Innovations *******END OF FILE******/

But the image subscription still doesn't work.

The bulk_device.c program to test everything doesn't work either:

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

@dji-dev
Copy link
Contributor

dji-dev commented Jul 8, 2024

Agent comment from Leon in Zendesk ticket #111143:

Dear kkishore9891,

Greetings. We appreciate your contact with DJI Innovations.

Please incorporate the modifications provided in our previous response to the end of your current source file. Run your script with the updated path, and refrain from executing any other commands for now. Afterwards, you can observe any error messages that may appear.

You can download the script nv-l4t-usb-device-mode-start.sh here.

Thank you for your support of DJI products! We wish you every success.

Best Regards,

DJI Innovations SDK Technical Support

°°°

@casper9429-kth
Copy link

Agent comment from Leon in Zendesk ticket #111143:Dear kkishore9891,

Greetings. We appreciate your contact with DJI Innovations.

Please incorporate the modifications provided in our previous response to the end of your current source file. Run your script with the updated path, and refrain from executing any other commands for now. Afterwards, you can observe any error messages that may appear.

You can download the script nv-l4t-usb-device-mode-start.sh here.

Thank you for your support of DJI products! We wish you every success.

Best Regards,

DJI Innovations SDK Technical Support

°°°

Hi dji-dev!

I am working on this problem together with @kkishore9891.

We added:

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

To the end of /opt/nvidia/l4t-usb-device-mode/nv-l4t-usb-device-mode-start.sh.

We get the following errors:

nvidia@nvidia:/opt/nvidia/l4t-usb-device-mode$ sudo journalctl -fu nv-l4t-usb-device-mode.service 
Jul 08 17:31:30 nvidia systemd[1]: Starting Configure USB flashing port for device mode...
Jan 01 01:00:29 nvidia nv-l4t-usb-device-mode-start.sh[547]: /
Jan 01 01:00:31 nvidia nv-l4t-usb-device-mode-start.sh[1199]: /sys/devices/platform/bus@0/3520000.padctl/usb2-0/usb_role/usb2-0-role-switch
Jan 01 01:00:31 nvidia nv-l4t-usb-device-mode-start.sh[1397]: ln: failed to create symbolic link 'configs/c.1': No such file or directory
Jan 01 01:00:31 nvidia systemd[1]: nv-l4t-usb-device-mode.service: Main process exited, code=exited, status=1/FAILURE
Jan 01 01:00:34 nvidia nv-l4t-usb-device-mode-stop.sh[1958]: rmdir: failed to remove 'l4t/functions/ecm.usb0/': No such file or directory
Jan 01 01:00:36 nvidia systemd[1]: nv-l4t-usb-device-mode.service: Failed with result 'exit-code'.
Jan 01 01:00:36 nvidia systemd[1]: Failed to start Configure USB flashing port for device mode.

We are really thankful for all the help!

Background
We are both working at the company FLOX robotics AB, and trying to make a jetson Orin to work together with the DJI M3TD through PSDK. And we are a bit on a tight deadline, if you over business to business support, please contact us on [email protected].

Best, Casper

@casper9429-kth
Copy link

Additional information @dji-dev . The usb_gadget c.1 and additional files gets created if we add the code you gave us to somewhere in the middle of the /opt/nvidia/l4t-usb-device-mode/nv-l4t-usb-device-mode-start.sh corresponding to the file psdk-usb-configure.sh given in the guide Jetson Nano Quick Start. They do not get created if we add the line you gave us to the end off nv-l4t-usb-device-mode-start.sh.

When we connect the Jetson Orin to itself from the gadget usb to an arbitrary usb port on the same jetson orin we get this information when typing lsusb -d 0955:7020 -v

nvidia@nvidia:~$ lsusb -d 0955:7020 -v

Bus 001 Device 008: ID 0955:7020 NVIDIA Corp. L4T (Linux for Tegra) running on Tegra
Couldn't open device, some information will be missing
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.10
  bDeviceClass          239 Miscellaneous Device
  bDeviceSubClass         2 
  bDeviceProtocol         1 Interface Association
  bMaxPacketSize0        64
  idVendor           0x0955 NVIDIA Corp.
  idProduct          0x7020 L4T (Linux for Tegra) running on Tegra
  bcdDevice            0.02
  iManufacturer           1 NVIDIA
  iProduct                2 Linux for Tegra
  iSerial                 3 1420524216468
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x0127
    bNumInterfaces          9
    bConfigurationValue     1
    iConfiguration          4 
    bmAttributes         0xe0
      Self Powered
      Remote Wakeup
    MaxPower                2mA
    Interface Association:
      bLength                 8
      bDescriptorType        11
      bFirstInterface         0
      bInterfaceCount         2
      bFunctionClass          2 Communications
      bFunctionSubClass       6 Ethernet Networking
      bFunctionProtocol       0 
      iFunction               7 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         2 Communications
      bInterfaceSubClass      2 Abstract (modem)
      bInterfaceProtocol    255 Vendor Specific (MSFT RNDIS?)
      iInterface              5 
      CDC Header:
        bcdCDC               1.10
      CDC Call Management:
        bmCapabilities       0x00
        bDataInterface          1
      CDC ACM:
        bmCapabilities       0x00
      CDC Union:
        bMasterInterface        0
        bSlaveInterface         1 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval              32
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass        10 CDC Data
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              6 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
    Interface Association:
      bLength                 8
      bDescriptorType        11
      bFirstInterface         2
      bInterfaceCount         2
      bFunctionClass          2 Communications
      bFunctionSubClass       2 Abstract (modem)
      bFunctionProtocol       1 AT-commands (v.25ter)
      iFunction              11 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         2 Communications
      bInterfaceSubClass      2 Abstract (modem)
      bInterfaceProtocol      1 AT-commands (v.25ter)
      iInterface              9 
      CDC Header:
        bcdCDC               1.10
      CDC Call Management:
        bmCapabilities       0x00
        bDataInterface          3
      CDC ACM:
        bmCapabilities       0x02
          line coding and serial state
      CDC Union:
        bMasterInterface        2
        bSlaveInterface         3 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x84  EP 4 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x000a  1x 10 bytes
        bInterval              32
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        3
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass        10 CDC Data
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface             10 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        4
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass         8 Mass Storage
      bInterfaceSubClass      6 SCSI
      bInterfaceProtocol     80 Bulk-Only
      iInterface             13 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x85  EP 5 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x03  EP 3 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
    Interface Association:
      bLength                 8
      bDescriptorType        11
      bFirstInterface         5
      bInterfaceCount         2
      bFunctionClass          2 Communications
      bFunctionSubClass      13 
      bFunctionProtocol       0 
      iFunction              18 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        5
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         2 Communications
      bInterfaceSubClass     13 
      bInterfaceProtocol      0 
      iInterface             15 
      CDC Header:
        bcdCDC               1.10
      CDC Union:
        bMasterInterface        5
        bSlaveInterface         6 
      CDC Ethernet:
        iMacAddress                     16 (??)
        bmEthernetStatistics    0x00000000
        wMaxSegmentSize               1514
        wNumberMCFilters            0x0000
        bNumberPowerFilters              0
      CDC NCM:
        bcdNcmVersion        1.00
        bmNetworkCapabilities 0x11
          crc mode
          packet filter
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x87  EP 7 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0010  1x 16 bytes
        bInterval              32
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        6
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass        10 CDC Data
      bInterfaceSubClass      0 
      bInterfaceProtocol      1 
      iInterface             17 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        6
      bAlternateSetting       1
      bNumEndpoints           2
      bInterfaceClass        10 CDC Data
      bInterfaceSubClass      0 
      bInterfaceProtocol      1 
      iInterface             17 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x86  EP 6 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x04  EP 4 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        7
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface             20 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x88  EP 8 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0000  1x 0 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x05  EP 5 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0000  1x 0 bytes
        bInterval               0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        8
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface             21 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x89  EP 9 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0000  1x 0 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x06  EP 6 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0000  1x 0 bytes
        bInterval               0

Thank you again for all the help!

Best, Casper

@casper9429-kth
Copy link

Hi again!

We solved the problem!

Following this guide 树莓派4B配置USB device RNDIS 和 BULK
, we recompiled the startup_bulk.c
And added

/******************** Little Endian Handling ********************************/

/*
* cpu_to_le16/32 are used when initializing structures, a context where a
* function call is not allowed. To solve this, we code cpu_to_le16/32 in a way
* that allows them to be used when initializing structures.
*/

#if __BYTE_ORDER == __LITTLE_ENDIAN
#define cpu_to_le16(x) (x)
#define cpu_to_le32(x) (x)
#else
#define cpu_to_le16(x) ((((x) >> 8) & 0xffu) | (((x) & 0xffu) << 8))
#define cpu_to_le32(x) \
((((x) & 0xff000000u) >> 24) | (((x) & 0x00ff0000u) >> 8) | \
(((x) & 0x0000ff00u) << 8) | (((x) & 0x000000ffu) << 24))
#endif

#define le32_to_cpu(x) le32toh(x)
#define le16_to_cpu(x) le16toh(x)

and replaced:

htole32  --> cpu_to_le32()

htole16 --> cpu_to_le16()

We also downgraded and install these dependencies:

/* Update software repository */
sudo apt-get update
sudo apt-get upgrade   
sudo apt-get install automake
sudo apt-get install libaio-dev
/* Download opus-1.3.1 source code from https://opus-codec.org/ and install */
tar -xzvf opus-1.3.1.tar.gz
cd opus-1.3.1/
autoreconf  -f  -i
./configure
make -j16
sudo make install
/* Download and install FFmpeg 4.3 source code from GitHub */
tar -zxvf ffmpeg-4.3.2.tar.gz
./configure --enable-shared
make && make install
/* Verify OpenCV installation */
opencv_version
/* Install libusb */
sudo apt-get install libusb-1.0-0-dev

We added the line @dji-dev gave us, but in the middle of the file corresponding to where it is in files given in the jetson quick start tutorial.

In PSDK, hal_usb_bulk.h we also used these settings.

#define LINUX_USB_BULK1_EP_OUT_FD               "/dev/usb-ffs/bulk1/ep1"
#define LINUX_USB_BULK1_EP_IN_FD                "/dev/usb-ffs/bulk1/ep2"

#define LINUX_USB_BULK1_INTERFACE_NUM           (7)
#define LINUX_USB_BULK1_END_POINT_IN            (0x88)
#define LINUX_USB_BULK1_END_POINT_OUT           (5)

#define LINUX_USB_BULK2_EP_OUT_FD               "/dev/usb-ffs/bulk2/ep1"
#define LINUX_USB_BULK2_EP_IN_FD                "/dev/usb-ffs/bulk2/ep2"

#define LINUX_USB_BULK2_INTERFACE_NUM           (8)
#define LINUX_USB_BULK2_END_POINT_IN            (0x89)
#define LINUX_USB_BULK2_END_POINT_OUT           (6)

And now it works!

@dji-dev
Copy link
Contributor

dji-dev commented Jul 10, 2024

Agent comment from Leon in Zendesk ticket #111143:

Dear kkishore9891,

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

We apologize for the delayed response due to the high volume of inquiries recently.

We are pleased to hear that your issue has been resolved. It appears that you have successfully resolved it by referring to an article in our knowledge base. We have noticed that you have also downgraded some dependencies. Could you please confirm if these actions were necessary? We can supplement our documentation to provide developers with more references.

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

Best Regards,

DJI - Da-Jiang Innovations SDK Technical Support

°°°

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants