Describing how OTG works might help. This usually is not what people think it is.
USB always has a “host” end, and a “device” end. The connection is never two-way. USB-C only looks to be bidirectional, but in reality it has extra wires and ways to identify a host versus a device. The OTG port can accept either a type-A (host mode) connector, or a type-B (device mode) connector; an ID pin tells the Jetson which mode. The micro-B OTG cable used for flashing and serial console tells the Jetson to use device mode. Everything which follows is about device mode.
Many consumer devices, such as music players or smart phones, will appear as a storage device when connected to a type-B connector (charger cables are type-B, but generally have very low quality…literally they might have 2 strands of very thin copper cable, or worse). This is not a definition of “device mode”. The “device” which appears is a matter of programming. It just happens that those consumer devices are almost always programmed to appear as disk storage. They could be something custom, e.g., a USB network adapter would probably need a non-standard driver. A microphone is a “device”, and it might be “standard”, but it won’t appear as a disk.
Device mode can in fact appear as several devices at once on the same cable. The devices would share bandwidth. Jetsons tend to do this whereby they appear as a virtual network device and provide the address of
192.168.55.1 for the Jetson, and the host PC would get address
192.168.55.100. Simultaneously, there is usually a mass storage device also visible, and that is set up as read-only, and only has a README file. This latter is a demonstration of something the Linux kernel makes available as a kind of shortcut “framework”. That is called the USB Gadget API for Linux.
USB itself is just a pipe for data, although USB also provides information about whatever device is connecting. The devihttp://www.linux-usb.org/gadget/ce itself needs its own driver, and USB is not responsible for that. However, there are a number of USB device classes which were created as a means of making a lot of standardized and common devices available without a custom driver for every device. USB Mass Storage is one such class, and USB does provide a driver for that, but this is a convenience, and the Mass Storage driver itself is not a “USB” driver…the “pipe” is a USB driver, the mass storage driver attaches to the disk itself, and is not necessarily aware that this is going through a USB data pipe. See also:
A camera vendor might use the standard USB Video Class (“UVC” device). However, quite often a camera vendor would also implement some sort of control function for that camera, and that function is itself not standard; thus a second device would show up, and that would report itself to the “hot plug” layer, and no standard driver would know how to work with that, and so no driver would load; but if you have the manufacturer’s custom driver, and USB reports this device to all drivers, then the custom driver would know it works with that and would assume ownership to the control side.
There are other standard USB classes, including HID (Human Interface Device). You’re interested in the standard Mass Storage device.
The Gadget framework is essentially a template for the standard device classes. You have to fill in the details before it works to become any given device. The disk behind this within the Linux system actually has its own driver. It’s up to the Gadget software to basically pipe that through to USB. This works if and only if you’ve set up both the disk and the Gadget correctly. Multiple virtual devices exist on Linux for Tegra (L4T, which is Ubuntu plus NVIDIA drivers), and their content can be examined at:
(these are human readable files, and can be manually run, but those files, by default, run as a “service” through
systemd, so there are both
systemd setup files and Gadget setup there)
The sample gadget mass storage device partition is actually the file “
/opt/nvidia/l4t-usb-device-mode/filesystem.img”. The file is not directly used; instead, loopback is used (via “
losetup”) to “cover” the file and allow “pretending” that the loopback device is a disk partition.
There are a number of security and other issues related to exposing a system disk to USB mass storage. Before going into the details, consider that every partition is formatted for some particular filesystem type. Linux tends to use
ext4. Desktop Windows tends to use NTFS, but removable media on Windows tends to use VFAT (this is a superset of FAT16/FAT32, so on…they are non-journaled filesystems). Understand that no Windows filesystem type has any ability to understand Linux permissions. You can export
ext4 through a mechanism which translates to Windows permissions, but it is basically stripping out a lot of information. For example, Windows has shortcuts, but not symbolic links; the user/group/other permissions exist in full in
ext4, but much of that is stripped out for Windows.
The example mass storage is formatted as VFAT. If you run your Jetson, and use this command it shows the block devices, their mount point, and the filesystem type:
Many of those partitions are not mounted (they are used as binary data and are not formatted for mount). Some of those partitions exist in RAM and are not real hard drives. One of those will be “
/dev/loop0”, and this is the demo file with the virtual software (the loopback) pretending it is a hard disk partition. That loop device is VFAT. This is what you’d use if you want Windows to be able to use it. If you want full use, and you want to use this strictly with Linux, then you’d be better off with
ext4. If this is passing through an actual Windows partition, then it would be best as type NTFS. All of these have different security concerns (except that
ext4 can do anything Linux does; you could even enable SElinux labels, and device special files would work).
The simplest case is if you have an actual partition (such as an SSD), and that partition is not used for Linux, but is instead just a “data” partition. You could format that partition with NTFS or VFAT or
ext4, and then export this read/write without much concern (you’d set up the partition, and then adjust the Gadget to point at that partition rather than to loopback).
In the case where you share part of the actual Jetson’s root filesystem, it gets to be a lot more complicated. First of all, the rootfs is normally
ext4. No Windows system will understand that. If you put rootfs on VFAT, then Linux won’t work right (as soon as
sudo or any SUID/GUID program runs, it’ll fail; security will drop dramatically for what works). Often one will export only a subdirectory for the case of exporting within the operating system. For example, it’d be bad to export “
/boot” and give the outside world the ability to damage or alter the kernel or boot content. More likely one would create something like “
/exports” and put exported content there. Or maybe export a home directory of a particular user (that user might be in name only, and simply be a placeholder for security reasons).
Better yet, to add to the previous example with a placeholder user’s home directory, one would mount a VFAT partition to that home location. Then only that directory would be exposed, and the directory would be understood by both Windows and Linux (but permissions would be cut down). One could create a partition on the SSD and mount it there after formatting it as VFAT, and Gadget could describe that.
If for some reason you were to export the whole rootfs, then you’d better make it read-only. You wouldn’t want to give write access to things like the user password files (including shadow files). It’s rather unnerving thinking about giving someone full access to clone your whole system.
So consider what it is you want to appear as an export. Consider what filesystem type you want, although you’re stuck with
ext4 if it is the whole running operating system. Consider what actual content you want to export, e.g., just music or something that isn’t the actual Linux operating system, versus a subset such as a home directory, versus “everything”.
Then explore the sample gadget setup. You can disable the existing mass storage without altering the virtual network. You could create and edit what is otherwise a clone of that, and even make a service such that it leaves alone the original example setup.
Note that if you run the command “
lsusb”, that this provides an “ID”. An example ID might be “
0x0955 is NVIDIA’s USB registry ID;
0x7e19 is one device ID within NVIDIA’s registry). Using that example ID, one can get a much more verbose listing of a single device, and that listing has most of what you’d need (but more) for a Gadget template:
sudo lsusb -d 0955:7e19 -vvv
Then examine the gadget setup and compare it what you see from a verbose device listing (plug in an external USB disk and see what shows up for a verbose
lsusb on that disk). Go from there.