Analysis on the process of mounting the kernel driver layer to android4.0 USB (I)
1. supported_functions
static struct android_usb_function *supported_functions[] = {&rmnet_smd_function,&rmnet_sdio_function,&rmnet_smd_sdio_function,&rmnet_function,&diag_function,&serial_function,&adb_function,&ccid_function,//&acm_function,&mtp_function,&ptp_function,&rndis_function,&mass_storage_function,&accessory_function,NULL};
Since it is the analysis of the USB Mount process, it does not look at other functions, directly jump to mass_storage_function.
2. mass_storage_function
static struct android_usb_function mass_storage_function = {.name= "mass_storage",.init= mass_storage_function_init,.cleanup= mass_storage_function_cleanup,.bind_config= mass_storage_function_bind_config,.attributes= mass_storage_function_attributes,};
Including function name, initialization, cleanup, binding configuration, and attributes.
About android_usb_function struct:
Struct android_usb_function {char * Name; // "mass_storage" Void * config; struct device * dev; char * dev_name; struct device_attribute ** attributes; /* For android_dev.enabled_functions */struct list_head enabled_list;/* Optional: initialization during gadget bind * // initialization (optional) int (* init) when the device driver is bound) (struct android_usb_function *, struct usb_composite_dev *);/* Optional: cleanup during gadget unbind * // cleanup when the device is unbound (optional) void (* cleanup) (struct android_usb_function *); int (* bind_config) (struct android_usb_function *, struct usb_configuration *); // configuration when binding/* Optional: called when the configuration is removed * // optional when the configuration is removed (* unbind_config) (struct android_usb_function *, struct usb_configuration *);/* Optional: handle CTRL requests before the device is configured * // if there is any request before the device is configured, run this function (optional) int (* ctrlrequest) (struct android_usb_function *, struct usb_composite_dev *, const struct usb_ctrlrequest *);};
Init function: mass_storage_function_init
Before analyzing the mass_storage_function_init function, you must first understand a very important struct:
struct fsg_config {unsigned nluns;struct fsg_lun_config {const char *filename;char ro;char removable;char cdrom;char nofua;} luns[FSG_MAX_LUNS];const char*lun_name_format;const char*thread_name;/* Callback functions. */const struct fsg_operations*ops;/* Gadget's private data. */void*private_data;const char *vendor_name;/* 8 characters or less */const char *product_name;/* 16 characters or less */u16 release;charcan_stall;};
The above struct is in f_mass_storage.c. The struct is described in detail at the beginning of the C file:
Maximum number of Luns supported by nluns (Lun: logical units)
The parameters of each Lun in Luns are as follows:
--> Filename: The Lun name. This parameter is not required if it is not detachable.
--> Ro false (true), set read-only, if it is a CD-ROM, it cannot be mounted to R/W
--> Removable true (false) indicates that the Lun can be removed.
--> CDROM false (true), whether this Lun is a CD-ROM
--> Nofua false (true). Can this Lun be ignored?
We also recommend that you use Lun % d For lun_name_format. If it is not just a Lun, you can use % d for guidance. It must be an integer. If it does not match, unexpected errors may occur.
Thread_name is named "file_storage" by default. It should be called the kernel thread name.
After learning about this struct, see the mass_storage_function_init function:
Static int mass_storage_function_init (struct android_usb_function * F, struct usb_composite_dev * cdev) {struct mass_storage_function_config * config; struct fsg_common * Common; int err; int I; config = kzarloc (sizeof (struct mass_storage_function_config), gfp_kernel); If (! Config) Return-enomem;/* Support multi Luns and Ro of ench Lun is set to 0 to allow * opening "FILENAME" in R/W mode. if the file is read-only, * the RO will be set to 1 automatically. */config-> FSG. nluns = usb_max_luns; // usb_max_luns = 3. Three storage devices are supported. For (I = 0; I <usb_max_luns; I ++) {// all three devices can be removed, which can be ignored and attached as R/W, none is CD-ROM config-> FSG. luns [I]. removable = 1; config-> FSG. luns [I]. nofua = 1;} common = fsg_common_init (null, cdev, & config-> FSG); // submit it to fsg_common_init to create a device based on the configuration, in f_mass_storage.c, if (is_err (common) {kfree (config); Return ptr_err (common );} /* Create a symlink for each Lun */for (I = 0; I <usb_max_luns; I ++) {err = sysfs_create_link (& F-> Dev-> kobj, & Common-> Luns [I]. dev. kobj, dev_name (& Common-> Luns [I]. dev); // create a device link if (ERR) {fsg_common_release (& Common-> ref); kfree (config); Return err ;}} config-> common = common; f-> Config = config; return 0 ;}
Now the basic structure is initialized. Configuration is very important and must not be wrong. We will analyze android_bind tomorrow.