Jetson Tx2 with JetPack 4.2[32.1R] as USB Mass Storage Device

Hey,

I am trying to do the following using Jetson tx2 and Host PC:

  • I am running the sample script given in /opt/nvidia/l4t-usb-device-mode/nv-l4t-usb-device-mode.sh and the (system.img size was 2.1GB)
  • I am able to see the partition of 2.1GB at /dev/loop0.But the partition is not write-able only read access is there for Jetson Tx2.When Tx2 is connected to Host PC running windows, the application in windows is able to read and write.
  • Expected Behaviour that I am trying to achieve is: the host will copy some files to Tx2 then Tx2 will process those files and write the output on 2.1GB partition which will be again used by Windows PC application.
  • PS : I have Commented the “read-only” line in nv-l4t-usb-device-mode.sh

    Thanks.

    This is very similar to another thread:
    https://devtalk.nvidia.com/default/topic/1056904/enable-read-write-access-on-tx2-as-a-device-flashed-with-jp-4-2/

    Whatever file you are using to replace the sample filesystem.img, make sure the file itself is writable by all. There may be other requirements, but that would be a good test to start with if you know the loopback is not read-only. You might want to combine your thread into that other thread if you believe they are the same topic.

    @Linuxdev Thanks for your reply.
    The filesystem.img has read permission only. Even if I change it via sudo chmod 0777 … Result is the same. Is it that during creation of filesystem.img the owner hast to set the permission read and write for all?
    Because filesystem.img was obtained from different user.

    I have not actually sat down and tried to set this to read-write. However, the first permission is the file itself must be writable. Most likely this is run as root, and thus this would not actually be a problem if “group” and “other” have no write permission…but for testing it is good to leave this open to anyone. Keep in mind that individuals cannot normally mount devices, but can cover devices with loopback. Once the device is mounted, if the file itself were not writable, then the files couldn’t change. The mount options themselves will need permissions for users.

    Before you do any of the experiments below, make sure you run this to stop the current mount:

    sudo /opt/nvidia/l4t-usb-device-mode/nv-l4t-usb-device-mode-stop.sh
    

    As a test, I will suggest now that the mount command explicitly give options. If you were to look at the man page for “fstab”, then you’ll see the options in the fourth field. The “-o” options of mount correspond to this. So you could use defaults like this as a test, but adjust as needed since I’m only giving examples:

    <b>sudo -s</b>
    cd /opt/nvidia/l4t-usb-device-mode
    mount <b>-o loop</b>,rw,suid,dev,exec,auto,nouser,async <b>filesystem.img</b> /mnt
    ls /mnt
    touch /mnt/deleteme
    rm /mnt/deleteme
    exit
    

    The “-o loop” is equivalent to covering with a loopback device (which is what the script does) and then mounting the loop device instead of the file name. If the file is no longer mounted, and if you disconnect any loop device associated with the file with “sudo losetup -D” (detach), then you could simulate this intermediate step on command line and see if writing is still supported. Here is an edit of the first example, and this assumes when you run this it shows “/dev/loop0” is the first device available (if the “nv-l4t-usb-device-mode-stop.sh” script was run and the file is not mounted this will most likely be loop0…if it is loop1, then loop0 is still being used, and that’s ok so long as it isn’t associated with the file you are interested in):

    <b>sudo -s</b>
    cd /opt/nvidia/l4t-usb-device-mode
    losetup -f --list ./filesystem.img
    # Note: No "-o loop":
    mount -o rw,suid,dev,exec,auto,nouser,async <b>/dev/loop0</b> /mnt
    ls /mnt
    touch /mnt/deleteme
    rm /mnt/deleteme
    losetup -D
    exit
    

    Does this work for you? If this works, then you know that loopback itself, and permissions are ok if you use root for the writes. You can instead try to do the touch operation from another user (mount with sudo, but don’t use sudo for “touch”), but you’d need to chmod the directory of the image for that user (e.g., “sudo mkdir /mnt/testing; sudo chown ubuntu /mnt/testing; …do stuff as user ubuntu in /mnt/testing…”). If you can create other directories and change ownership to a regular user, then the only thing left is to figure out why the “usb gadget interface” has made the device read-only.

    Both the code snippets given by you executes. But, still the partition created is not writable by Tx2 only its writable by Windows Host PC.

    The process I follow to create partition on Tx2 is as follows:

    Below Code is for creating Partition

    #!/bin/sh
       echo "Mount Partition Called" 
       #create a separate partition
       dd if=/dev/zero of=/opt/nvidia/l4t-usb-device-mode/filesystem.img bs=10M count=1k
       mkfs.vfat /opt/nvidia/l4t-usb-device-mode/filesystem.img
    
       echo /opt/nvidia/l4t-usb-device-mode/filesystem.img > /sys/kernel/config/usb_gadget/l4t/functions/mass_storage.0/lun.0/file
       
       mkdir -p /mnt/mountpoint
    
       #mount the partition
       mount -t vfat /opt/nvidia/l4t-usb-device-mode/filesystem.img /mnt/mountpoint
    
       mkdir -p /mnt/mountpoint/Input
       mkdir -p /mnt/mountpoint/Output
    
       umount /mnt/mountpoint
    

    Below code is for Mounting:

    #!/bin/sh
    echo "Mount Partition Called" 
    
    #mount the partition
    mount -t vfat /opt/nvidia/l4t-usb-device-mode/filesystem.img /mnt/mountpoint
    
    rm -r /mnt/mountpoint/Output/*
       
    echo "Output folder cleared"
    

    I was thinking you were having issues writing to the Jetson from the USB connection. To clarify, are you looking to write to the partition from both the Jetson and the USB bulk storage? If so, there may be some issue with a partition being owned and mounted simultaneously by two different computers, but gadget does allow for exporting a directory tree of the Jetson which is a normal directory so far as the Jetson is concerned, and yet appearing as a partition to the remote system. The difference is that the gadget setup would name a chroot location on the Jetson rather than naming a partition or a loopback mounted virtual partition. Is this what you want to do? If so, what directory do you want to export?

    Below is Detailed functionality I am trying to achieve :

    • A partition on Jetson TX2 needs to be created where jetson can write images after doing some processing on the image captured by it.
    • The written images by Jetson in the partition of Tx2 is read by a PC application(HOST) and also Host should be able to write some images back on to the partition on TX2.
    • So for above cases to be implemented both the TX2 and Host should have permission to read and write onto to the partition of TX2.

    Current Problem I am facing:

    • I am able to create partition which but TX2 cannot write onto that partition only windows application is able to read and write on that partition

    This functionality was working with jetpack 3.3 when I ran the scripts in previous reply of mine. Is there some issue with jetpack 4.2.?

    Can you suggest me solution to get around this problem.

    Thanks

    Gadget is just a framework in the Linux kernel (this is not related to NVIDIA hardware, nor NVIDIA drivers), and what is present is a sample implementation using that framework (one sample is mass storage, the other is virtual ethernet). Gadget itself can be studied in the kernel source and used as a basis for writing custom USB drivers which implement standard USB classes…the mass storage class is just one example.

    The gadget framework itself imposes the need for a backing file (which I will refer to as a partition, but it tends to be a loopback emulated partition), and the Linux kernel (not caring about USB in any way) will refuse to dual mount a partition. Should both the TX2 and USB remote be set up to force write with two different operating systems managing the filesystem, then you will get failures (and possibly corruption or crash…rules can be broken when two different operating systems both think they are the masters). If the partition is read-only, then you can expose the partition to more than one reader.

    When I experimented with mounting at both the TX2 and USB in read-write I found updates did not correctly propagate from one system to the other, and this is to be expected. For your case I don’t know if this actually worked as you expected, but if it did, then there would probably be some failures in the future. The Ubuntu kernel has probably changed (along with the rest of the o/s) when going from 16.04 to 18.04, so differences are unlikely to be fault so much as it is a reflection of the operating system evolving.

    An alternative would be the NFS distributed filesystem (or any distributed filesystem). The NFS export could be the mount point of a partition which is read-write for all parties, although there would be some performance loss to locking in some situations. I’m uncertain about it, but there is a possibility a distributed filesystem could be used with the gadget framework mass storage and simultaneously mounted on the TX2. If the user which mounts the USB drive if Linux, then odds go up it would work…if the other end is Windows, then odds go down. I don’t know what Windows does for distributed filesystems other than network neighborhood (you could use Samba instead, but Samba over USB sounds like a bad idea).

    If this does not work, then the problem is basically one of writing kernel code from scratch with gadget as a starting example. Regardless of how you do this, if you absolutely must let two different operating systems mount this as a drive and allow random simultaneous read-write, then you cannot use ext4 or VFAT since they do not allow multiple mounts (sending multiple write commands through a single host/driver is quite different than having two drivers collide from two independent computers…the two systems have no concept of locking).

    If you are interested in examining this, then here are some places you can look, and this explains why I am saying simultaneous mount on both host and USB sides with read-write is problematic:
    https://www.kernel.org/doc/Documentation/usb/mass-storage.txt
    https://www.emcraft.com/stm32f769i-discovery-board/stm32f7-usb-storage

    Thanks a lot.

    I am thinking is there a way to have a secondary device like a USB or sd card connected to TX2 act as shared storage between the PC and TX2. As per your previous reply this might not work since read-write is done by two operating systems. I’m just confirming if it’s possible?

    And I also have a doubt regarding the “device mode” in TX2. What exactly it does and is it the whole TX2 going into slave and PC being master or it’s just the partition we create using the sample script going into " device mode". Is there a detailed documentation regarding the same?

    I was also wondering is it possible to give read and write access as per demand of program running. What I mean to say is there is not need for both HOST and TX2 to write simultaneously. While TX2 is writing on to the partition Host need not have permission to write and while Host is writing TX2 need not have permission to write.

    But at certain point in my application I want both TX2 and HOST to write on the partition though not at the same time

    Read and write from two operating systems is the realm of distributed filesystems. What I’ve never done is to add this to gadget USB, but if both operating systems are Linux, then you stand a good chance of this working. VFAT, ext4, and NTFS would fail.

    “device mode” is just a naming convention for USB. One end is a device, the other end is a host. Example devices: Mouse, keyboard. The host is anything which can use those. USB3 complicates wiring, but if you get past that, then it is true for all USB versions that a port cannot be simultaneously a host and a device. In the case of USB2 or earlier device and host modes are enforced by the connectors and cables. For USB3 there is just some trickery with extra wires which make this appear to be “symmetric”, but there is still a host and a device at each end. The micro-OTG socket accepts either a micro-A (host) connector or a micro-B (device) connector, but an ID pin detects which it is at the moment.

    Sometimes a port is dedicated as a host. Sometimes a port is dedicated as a device. In the case of OTG (“on the go”) it is possible for the port to switch between host and device, but only if it is programmed to do so and is aware of the ID pin.

    The gadget framework puts a port capable of device mode into that mode and emulates the standard class device.

    When the TX2 is in recovery mode that port becomes a device, but unlike gadget, the device is custom and not a standard class. Only the custom driver understands that recovery mode device.

    In the case of not needing simultaneous read and write, then the port could have some sort of script written that when the ID pin is detected the filesystem is unmounted from the TX2 (and a prerequisite is killing any process trying to write to the partition), followed by what is essentially the content of the gadget mode start script. Unplugging the pin could then automatically remount on the TX2 so the TX2 can then write.

    Note that mount has many options, and one would be to remount read-only without stopping the entire mount, or doing the reverse of remounting read-only as read-write.

    I’m not sure what you would have to do for this to work well, but most likely it would revolve around writing a kernel module which understands the ID pin for detecting changes in the type of connector touching the micro-OTG port. From there most of the code is already in place and this would just be a module to direct use of existing code.