Last time, I was initially exposed to the mounting problem of Android USB client, so I wrote the first article about the feelings. There are still some problems in many places, some of which are not clear enough, so I want to continue writing.
First, the last verification shows that the device can be mounted, but only one storage device can be mounted at a time.
Secondly, what I said last time about the driver of the device node, there is also a problem, in fact itself there is a tegra-udc.c created such a node in the/sys/devices/platform/tegra-udc.0/lun0, therefore, you do not need to create any mass-storage nodes.
========================================================== ==========================================
(1) first, let's take a look at the first question. How can one device be mounted at a time?
1. vold will first read the configuration content in the vold. conf file (the linked list inserted at the end) to store the necessary information of the storage device (as mentioned last time, partition 4 of emmc)
Then, the system reads the information of the dynamically inserted storage device through uevent, inserts the linked list in the header, and combines the first linked list with the Linked List (auto_add_volume function ), the dynamic storage device is at the head of the linked list, while the static storage device is at the end of the linked list. This order is correct in my environment, because some of my dynamic storage devices are mounted on partition 4. Anyone who has used a mobile phone or has some experience in mounting and detaching a part of the system knows that if you want to unmount partition 4 smoothly, You Need To unmount the directory in it. Otherwise, partition 4 always displays busy and cannot be unmounted. Why do you need to uninstall the storage device and then stop it? This is because both sides are prevented from simultaneously operating.
If you want the dynamic storage device to pass ums_path detection, You need to specify a directory under ums_path in the auto_add_volume function so that the dynamic storage device can be correctly mounted.
2. When the client is successfully uninstalled, it needs to be mounted to the host. I tracked it all the way and found that the volmgr. C code of vold played a role.
Static void _ cb_volstopped_for_ums_enable (volume_t * V, void * Arg) <br/>{< br/> int RC; <br/> char * devdir_path; <br/> # If debug_volmgr <br/> log_vol ("_ cb_volstopped_for_ums_enable (% s):", V-> mount_point ); <br/> # endif <br/> // check Dev-> disk whether is null <br/> If (V-> Dev-> disk) <br/> devdir_path = blkdev_get_devpath (V-> Dev-> disk); <br/> else <br/> devdir_path = blkdev_get_devpath (V-> Dev ); </P> <p> If (rc = ums_enable (devdir_path, V-> ums_path) <0) {// key <br/> free (devdir_path ); <br/> LogE ("error enabling UMS (% d)", RC); <br/> return; <br/>}< br/> free (devdir_path ); <br/> volume_setstate (v, volstate_ums); <br/> pthread_mutex_unlock (mutex); <br/>}
The most important thing is ums_enable (). In this case, mount the device to the host and continue with the subsequent steps.
In the UMS. C code in the same directory
Int ums_enable (char * dev_fspath, char * lun_syspath) <br/>{< br/> log_vol ("ums_enable (% s, % s):", dev_fspath, lun_syspath ); <br/> int FD; <br/> char filename [255]; <br/> sprintf (filename, "/sys/% S/file", lun_syspath ); <br/> If (FD = open (filename, o_wronly) <0) {<br/> LogE ("unable to open '% s' (% s )", filename, strerror (errno); <br/> return-errno; <br/>}< br/> If (write (FD, dev_fspath, strlen (dev_fspath )) <0) {<br/> LogE ("unable to write to ums lunfile (% s)", strerror (errno); <br/> close (FD ); <br/> return-errno; <br/>}</P> <p> close (FD); <br/> return 0; <br/>}
Open a "/sys/devices/platform/tegra-udc.0/lun0/file" File
Then, write a "/dev/block/vold/major: Minor" path to the file, which corresponds to each storage device.
I tried to write different paths to the file (such as Echo "/dev/block/vold/179 written through ADB: 0 ">/sys/devices/platform/tegra-udc.0/lun0/file ).
Each time you write a path, a corresponding storage device will be mounted to the host, but when you mount the next device, you must echo ""> file, the current device can be mounted only when the previous device is unmounted from the host.
Continue to trace the code to kernenl and find that/driver/USB/gadget/f_mass_storage.c has performed some actions and mounted the device.
Static ssize_t store_file (struct device * Dev, struct device_attribute * ATTR, <br/> const char * Buf, size_t count) <br/> {<br/> struct Lun * curlun = dev_to_lun (Dev); <br/> struct fsg_dev * FSG = dev_get_drvdata (Dev ); <br/> intrc = 0; <br/> dbg (FSG, "store_file:/" % S/"/N", Buf ); <br/> # If 0 <br/>/* disabled because we need to allow closing the backing file if the media was removed */<br/> If (curlun-> prevent _ Medium_removal & backing_file_is_open (curlun) {<br/> ldbg (curlun, "eject attempt prevented/N"); <br/> return-ebusy; /* "door is locked" */<br/>}< br/> # endif <br/>/* remove a trailing newline */<br/> If (count> 0 & Buf [count-1] = '/N ') <br/> (char *) BUF) [count-1] = 0; <br/>/* eject current medium */<br/> down_write (& FSG-> filesem); <br/> If (backing_file_is_open (curlun )) {<br/> close_backing_fi Le (FSG, curlun); <br/> curlun-> unit_attention_data = ss_medium_not_present; </P> <p >}< br/>/* load new medium */<br/> If (count> 0 & Buf [0]) {<br/> rc = open_backing_file (FSG, curlun, Buf); <br/> If (rc = 0) <br/> curlun-> unit_attention_data = <br/> ss_not_ready_to_ready_transition; </P> <p >}< br/> up_write (& FSG-> filesem ); <br/> return (RC <0? RC: Count); <br/>}
Anyone who knows the principles of sysfs knows static device_attr (file, 0444, show_file, store_file); is responsible for reading (CAT/read) or direct writing (echo/write) the Macro of the device property file. The specific implementation is the above sentence (write ).
It seems that it is mainly the function of open_backing_file. I haven't learned much about it yet. I only know that it must have played a role. It opened the device node under the vold directory and initialized some things. It can be seen that the host only recognizes the mounting of different partitions of a single device, but does not recognize simultaneous mounting of multiple storage devices.
I don't know what the problem is, so that all devices are mounted to only one device node (conflict), rather than the previous/dev/SDB SDC SDE.
Hope to learn and solve
========================================================== ====================================
(2) The second problem is actually nothing, but the UDC (USB device controller) driver goes down first. I didn't pay attention to it at that time.
I don't know if the Android mobile phone driver has such restrictions on mounting a single storage device, at least for now. It is normal to think about it. Generally, a mobile phone has only one SD slot, and its memory is limited. It is understandable that an SD storage device is mounted...
Hope is the problem of your own code, and you are still working on it. Hope you can have experts who have studied it and share your experience in this area. Thank you. I guess I will write it soon (3). I am still trying to solve this problem when I write the next article.