drivers/usb/gadget/legacy/g_ffs.c

Source file repositories/reference/linux-study-clean/drivers/usb/gadget/legacy/g_ffs.c

File Facts

System
Linux kernel
Corpus path
drivers/usb/gadget/legacy/g_ffs.c
Extension
.c
Size
13236 bytes
Lines
575
Domain
Driver Families
Bucket
drivers/usb
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

module_init(gfs_init);

static void __exit gfs_exit(void)
{
	int i;

	if (gfs_registered)
		usb_composite_unregister(&gfs_driver);
	gfs_registered = false;

	kfree(f_ffs[0]);

	for (i = 0; i < func_num; i++)
		usb_put_function_instance(fi_ffs[i]);

	kfree(fi_ffs);
}
module_exit(gfs_exit);

static void *functionfs_acquire_dev(struct ffs_dev *dev)
{
	if (!try_module_get(THIS_MODULE))
		return ERR_PTR(-ENOENT);

	return NULL;
}

static void functionfs_release_dev(struct ffs_dev *dev)
{
	module_put(THIS_MODULE);
}

/*
 * The caller of this function takes ffs_lock
 */
static int functionfs_ready_callback(struct ffs_data *ffs)
{
	int ret = 0;

	if (--missing_funcs)
		return 0;

	if (gfs_registered)
		return -EBUSY;

	gfs_registered = true;

	ret = usb_composite_probe(&gfs_driver);
	if (unlikely(ret < 0)) {
		++missing_funcs;
		gfs_registered = false;
	}

	return ret;
}

/*
 * The caller of this function takes ffs_lock
 */
static void functionfs_closed_callback(struct ffs_data *ffs)
{
	missing_funcs++;

	if (gfs_registered)
		usb_composite_unregister(&gfs_driver);
	gfs_registered = false;
}

/*
 * It is assumed that gfs_bind is called from a context where ffs_lock is held
 */
static int gfs_bind(struct usb_composite_dev *cdev)
{
#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
	struct net_device *net;
#endif
	int ret, i;

	if (missing_funcs)
		return -ENODEV;
#if defined CONFIG_USB_FUNCTIONFS_ETH
	if (can_support_ecm(cdev->gadget)) {
		struct f_ecm_opts *ecm_opts;

		fi_ecm = usb_get_function_instance("ecm");
		if (IS_ERR(fi_ecm))
			return PTR_ERR(fi_ecm);
		ecm_opts = container_of(fi_ecm, struct f_ecm_opts, func_inst);
		net = ecm_opts->net;
	} else {

Annotation

Implementation Notes