USB 2.0 Port as Mass Storage Device

The documentation indicates that the USB OTG port can be used as USB Mass Storage (similar to USB memory stick).

I am not able to format this drive since it is read-only. Is there a way to format this drive so that it can be used similar to a USB memory stick?

From the documentation:

Using USB Mass Storage

Linux for Tegra implements a USB Mass Storage device, known as a USB disk or
USB memory stick, that is natively supported by all operating systems. The USB
disk automatically appears in the graphical filesystem browser such as:

  • Linux desktop
  • Windows Explorer
  • Mac Finder

On Linux or Mac, you can manually mount the disk from the command line, just
like a USB storage device.

The USB storage device is read-only and contains various driver files and Linux
for Tegra documentation.

What you see implemented is just sample code to demonstrate the most basic version of this. If you look at “/opt/nvidia/l4t-usb-device-mode/” you will see a human readable script which produces this (and some virtual network devices): “nv-l4t-usb-device-mode.sh”.

Within this the script sets up read-only access to a loopback (“fake”) partition contained in file “filesystem.img”. Changing the file, and changing various options, would make this available as read-write if desired, and could make some alternate mount device also become the partition instead of this file. Overall, you should be able to find information on the internet about the linux kernel’s “gadget” interface, although most will be at a lower level than what is here. Take what is here, and edit. Maybe look for examples on the internet which might be more of what you want this to be.

Before you start realize that you can’t manipulate the filesystem.img if it is currently mounted and in use. You can (temporarily) disable this service with (assumes you are in the above listed directory):

sudo nv-l4t-usb-device-mode-stop.sh

You can restart this with:

sudo nv-l4t-usb-device-mode.sh

The part of the start script which is for the storage is the only part you need to change (though you could have fun with virtual network device edits as well). If you search for “filesystem.img”, then you’ll find this is how the file is named (but through a more significant edit this could be a partition or other media):

# The disk image to export as a USB Mass Storage device
fs_img="${script_dir}/filesystem.img"

If you search for “fs_img”, then you can see where this is used. Much of it is just setting it up to “pretend” it is an actual disk partition.

The size of storage depends on the size of that file. If you were to correctly enlarge the file and loopback format it to your preferred filesystem, then the device would become that size and use that filesystem. I see on the TX2 version the file size is “16777216” bytes, which you will note is evenly divisible by the block size of 512. This could be any multiple of the block size (and in reality block size itself could be changed to various multiples of the power of two). The actual unformatted size is “16777216 / (1024*1024) = 16MiB”. After formatting the actual space is a bit less.

If the filesystem.img is itself read/write, and you use the correct options, then you can make this not just readable, but also writable.

There are many ways to alter that file to become bigger. This is just one example, and it deletes the original file (you could copy the file to a new name instead of destroying it if you really want this). Here is one example which changes name to “filesystem2.img” and leaves the original alone (and then you’d change the fs_img in the script) but sets size to 128MiB (“12810241024 == 134217728” is the same as “1281024512*2”…and “134217728/512 == 262144”…the block size of 512 * 262144 count is 128MiB):

sudo dd if=/dev/zero of=filesystem2.img bs=512 count=262144

Now to loopback format this as ext4 or VFAT (you could make it VFAT for non-Linux systems, but you probably need to add package “dosfstools” for “mkfs.vfat” to substitute for “mkfs.ext4”:

# Find the first unused loop device...sudo also creates it:
sudo losetup -f
# Assumes you see "/dev/loop1", but it could be different...this covers that device and echos verification of the particular device:
sudo losetup --show -f ./filesystem2.img
# Format the loopback device which pretends to be a partition:
sudo mkfs.vfat /dev/loop1

You could then then test this filesystem2.img in place of filesystem.img. Notice in that script that “losetup” is used there too. See this line:

/sbin/losetup -f -r "${fs_img}"

It is the “-r” option which makes it read-only. Comment this line out and add your own version without “-r” to make it read-write. There may be other permission changes needed (not sure, didn’t actually mount this), but that is the basic way it works. The loopback device can be substituted for an actual formatted partition without loopback.

1 Like

Thanks for the detailed information @linuxdev. I was able to follow your instructions (with some modifications) to configure the USB 2.0 Port as Mass Storage Device.

To create my new script, I first copied the original “nv-l4t-usb-device-mode.sh” content. Then I removed all of the content that was not related to mass storage. Then I updated fs_img in the script to the location of a FAT32 partition that I created on the Jetson Nano’s SD Card.

# The disk image to export as a USB Mass Storage device
fs_img="/dev/mmcblk0p13"

Next, I removed the following line that makes the disk read-only

# Prevent users from corrupting the disk image; make it read-only
echo 1 > "${func}/lun.0/ro"

Finally, I updated the vendor and product ID’s, as suggested in the comments.

When I attached the Jetson Nano to my Windows PC via USB 2.0 OTG, the partition was automatically recognized and I was able to read/ write files.

By the way, I also stopped the original demo service from running on the Nano, and setup my new script to run as service at startup.

Thanks!

2 Likes