Friday, February 11, 2011

USB File Storage Gadget

Today I have enabled the USB gadget support for file storage. The intention is to be able to export files via the USB device interface to a PC.

The file storage gadget must be enabled at the kernel config menu:
USB support -> Support for USB gadgets -> File-backed storage gadget

Note that only one USB gadget may be enabled at the same time. If multiple gadgets must be supported, all of them must be configured as modules, so I had to remove built-in support for ethernet gadget from the kernel. Switching the USB function requires removing and installing the proper modules.

The module for file storage is g_file_storage.o and is installed this way:
insmod g_file_storage.o file=/results.bin stall=0

The 'stall' argument is necessary for the USB disk to be properly detected by windows. Linux does not require this argument and the drive can be mounted without problem. If 'stall' is not set to zero and the gadget is connected to a windows PC, the following messages appear:
g_file_storage pxa2xx_udc: full speed config #1
udc: pxa2xx_ep_disable, ep1in-bulk not enabled
udc: pxa2xx_ep_disable, ep2out-bulk not enabled
udc: USB reset
udc: USB reset

repeating every few seconds.

For the 'stall' option to be available, it is necessary to enable the 'file-backed storage gadget in test mode' option in the kernel configuration.

Multiple files may be specified when the gadget module is installed, thus creating multiple drives visible to the remote host.


Any volume size may be created but it seems that Windows assigns floppy drive letters if the volume size is similar to a floppy device size. I have tested 720KB and 1440KB only.

The volume may be declared as read-only by using the "ro=1" parameter at the insmod.

The backend file may be either a disk partition or a file image.
An initial filesystem image can be created this way:

# dd if=/dev/zero of=results.bin bs=512 count=2880
# mkdosfs results.bin

Then, loop-mount the image file and populate the filsystem. Here is where problems came: if a process writes a new file to the loop filesystem, the host side of the USB connection (where the file browser runs) does not see the new file, even if the file browser is refreshed. The only workaround is to unplug/plug again the USB cable. This happens even if a 'sync' command is run on the tester device.



Also, some inconsistences happen if the USB host side writes to the device. The device doesn't see the new files, and vice-versa.


In conclusion, it is quite a good method to export only file from a Linux device, but with some limitations on "live" filesystems.




10 comments:

MarcosMaa said...

Hi!!! How do you do?

I need some help with g_file_storage. I have some doubts about it. Could you help please?

a) Is it possible to emulate more than 1 USB mass storage in the same computer box?
My computer box has 6 USB 2.0 ports. In each port, I will connect 1 DVD player through a USB in port. Each USB port could be recognized as a different USB mass storage, containing different files?

b) After the DVD player become connect to 1 of the USB mass storage from my computer box, how could I update the files in the directory used as the mass storage? Is it possible to unmount gadgetfs, update files and re-mount it again?


Thanks and regards
Marcos

pela-suros said...

Hi Marcos,

No, g_file_storage only can emulate one mass storage device.

However, I think this is not the point.

I am not sure if I understand what you try to do. A PC has a USB *host* interface, so it is not possible to run g_file_storage on the PC side, because this module is intended for USB slave/device interfaces only.

About (b) you wouldn't need to unmount so that the files are refreshed. Just add the file to the exported directory and the new files should be visible. But, this is possible only between a USB host and a USB device, where the files reside on the USB device.

hope this helps

Regards
Jordi

DJ said...

Hello Jordi,
I need help, in my application, I need two gadget devices active at a time one for internal modem and other exposed externally for USB communication. I have these working individually but i can not enable both of then at time. is there workaround for this.

thanks
Dhanraj

Unknown said...

Hi Jordi, your answer is incorrect.

g_file_storage will happily emulate many mass storage devices (or, to be exact, multiple LUNs on one device, which has the same effect). Just try e.g. "file=storage1,storage2"

pela-suros said...

Your're right, however, when I tried this I did it in a 2.6.22 kernel which didn't suppoort this multi-file feature.

Thanks for your input.

Andz said...

How to do this multiple LUN? I tried using g_file_storage g_mass_storage and g_multi cannot make the 2 drives appear in Windows 7 and Windows XP. What else to do for this multiple LUN to work? Does it not work with the generic driver from Microsoft?

Nerd Progre said...

Thanks for this document Jordi. It comes handy.

I wonder, is there a way for FSG to emulate a specific device, ie pass the right USB vendor id and product ID? (VID, PID) pairs?.

Specifically I´d like to emulate a certain floppy adapter, that the host system expects to be present, and it has to be THAT one not any other.

Thanks,
FC

Nerd Progre said...

Jordi,

Another question... if I load a USB Sniffer, and I plug a pen drive (flash drive) and a USB Floppy I see the following differences (other than vendor id and product id):

USB Pen drive shows:
USB Class 08
USB Subclass 06
USB Protocol 50

USB Floppy shows:
USB Class 08
USB Subclass 04
USB Protocol 00

Could you please shed some light as to if FSG allows to emulate these settings too?
FC

Damien Wei said...

Hi,
I need some helps on inserting two usb gadget modules.

Can I insert two USB gadget modules simultaneously? for example, running command "sudo insmod g_hid.ko" then followed with "sudo insmod g_ether.ko".

Any helps would be much appreciated.
Thanks

mahasiswa teladan said...

Thanks for providing such a great article, it was excellent and very informative.
as a first time visitor to your blog I am very impressed.
thank you :)