drivers/usb/gadget/function/f_fs.c
Source file repositories/reference/linux-study-clean/drivers/usb/gadget/function/f_fs.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/usb/gadget/function/f_fs.c- Extension
.c- Size
- 106352 bytes
- Lines
- 4367
- Domain
- Driver Families
- Bucket
- drivers/usb
- Inferred role
- Driver Families: operation-table or driver-model contract
- Status
- pattern 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.
- 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.
- Defines an operation table; this is where Linux turns generic core objects into subsystem-specific behavior.
- Touches user memory; correctness depends on fault-safe copying and privilege boundary handling.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/blkdev.hlinux/dma-buf.hlinux/dma-fence.hlinux/dma-resv.hlinux/pagemap.hlinux/export.hlinux/fs_parser.hlinux/hid.hlinux/mm.hlinux/module.hlinux/scatterlist.hlinux/sched/signal.hlinux/uio.hlinux/vmalloc.hlinux/unaligned.hlinux/usb/ccid.hlinux/usb/composite.hlinux/usb/functionfs.hlinux/usb/func_utils.hlinux/aio.hlinux/kthread.hlinux/poll.hlinux/eventfd.hu_fs.hu_os_desc.hconfigfs.h
Detected Declarations
struct ffs_epstruct ffs_functionstruct ffs_epstruct ffs_dmabuf_privstruct ffs_dma_fencestruct ffs_epfilestruct ffs_bufferstruct ffs_io_datastruct ffs_desc_helperstruct ffs_sb_fill_dataenum ffs_entity_typeenum ffs_os_desc_typefunction ffs_setup_state_clear_cancelledfunction ffs_ep0_completefunction __ffs_ep0_queue_waitfunction __ffs_ep0_stallfunction ffs_ep0_writefunction __ffs_ep0_read_eventsfunction ffs_ep0_readfunction ffs_ep0_openfunction ffs_ep0_releasefunction ffs_ep0_ioctlfunction ffs_ep0_pollfunction ffs_epfile_io_completefunction ffs_copy_to_iterfunction ffs_free_bufferfunction ffs_user_copy_workerfunction ffs_epfile_async_io_completefunction __ffs_epfile_read_buffer_freefunction __ffs_epfile_read_bufferedfunction __ffs_epfile_read_datafunction ffs_epfile_iofunction ffs_epfile_openfunction ffs_aio_cancelfunction ffs_epfile_write_iterfunction ffs_epfile_read_iterfunction ffs_dmabuf_releasefunction ffs_dmabuf_getfunction ffs_dmabuf_putfunction ffs_epfile_releasefunction ffs_dmabuf_cleanupfunction ffs_dmabuf_signal_donefunction ffs_epfile_dmabuf_io_completefunction ffs_dmabuf_fence_releasefunction ffs_dma_resv_lockfunction ffs_dmabuf_find_attachmentfunction list_for_each_entryfunction ffs_dmabuf_attach
Annotated Snippet
void *data, const struct file_operations *fops);
/* Devices management *******************************************************/
DEFINE_MUTEX(ffs_lock);
EXPORT_SYMBOL_GPL(ffs_lock);
static struct ffs_dev *_ffs_find_dev(const char *name);
static struct ffs_dev *_ffs_alloc_dev(void);
static void _ffs_free_dev(struct ffs_dev *dev);
static int ffs_acquire_dev(const char *dev_name, struct ffs_data *ffs_data);
static void ffs_release_dev(struct ffs_dev *ffs_dev);
static int ffs_ready(struct ffs_data *ffs);
static void ffs_closed(struct ffs_data *ffs);
/* Misc helper functions ****************************************************/
static int ffs_mutex_lock(struct mutex *mutex, unsigned nonblock)
__attribute__((warn_unused_result, nonnull));
static char *ffs_prepare_buffer(const char __user *buf, size_t len)
__attribute__((warn_unused_result, nonnull));
/* Control file aka ep0 *****************************************************/
static void ffs_ep0_complete(struct usb_ep *ep, struct usb_request *req)
{
struct ffs_data *ffs = req->context;
complete(&ffs->ep0req_completion);
}
static int __ffs_ep0_queue_wait(struct ffs_data *ffs, char *data, size_t len)
__releases(&ffs->ev.waitq.lock)
{
struct usb_request *req = ffs->ep0req;
int ret;
if (!req) {
spin_unlock_irq(&ffs->ev.waitq.lock);
return -EINVAL;
}
req->zero = len < le16_to_cpu(ffs->ev.setup.wLength);
spin_unlock_irq(&ffs->ev.waitq.lock);
req->buf = data;
req->length = len;
/*
* UDC layer requires to provide a buffer even for ZLP, but should
* not use it at all. Let's provide some poisoned pointer to catch
* possible bug in the driver.
*/
if (req->buf == NULL)
req->buf = (void *)0xDEADBABE;
reinit_completion(&ffs->ep0req_completion);
ret = usb_ep_queue(ffs->gadget->ep0, req, GFP_ATOMIC);
if (ret < 0)
return ret;
ret = wait_for_completion_interruptible(&ffs->ep0req_completion);
if (ret) {
usb_ep_dequeue(ffs->gadget->ep0, req);
return -EINTR;
}
ffs->setup_state = FFS_NO_SETUP;
return req->status ? req->status : req->actual;
}
static int __ffs_ep0_stall(struct ffs_data *ffs)
{
if (ffs->ev.can_stall) {
pr_vdebug("ep0 stall\n");
usb_ep_set_halt(ffs->gadget->ep0);
ffs->setup_state = FFS_NO_SETUP;
return -EL2HLT;
} else {
pr_debug("bogus ep0 stall!\n");
return -ESRCH;
}
}
static ssize_t ffs_ep0_write(struct file *file, const char __user *buf,
size_t len, loff_t *ptr)
{
Annotation
- Immediate include surface: `linux/blkdev.h`, `linux/dma-buf.h`, `linux/dma-fence.h`, `linux/dma-resv.h`, `linux/pagemap.h`, `linux/export.h`, `linux/fs_parser.h`, `linux/hid.h`.
- Detected declarations: `struct ffs_ep`, `struct ffs_function`, `struct ffs_ep`, `struct ffs_dmabuf_priv`, `struct ffs_dma_fence`, `struct ffs_epfile`, `struct ffs_buffer`, `struct ffs_io_data`, `struct ffs_desc_helper`, `struct ffs_sb_fill_data`.
- Atlas domain: Driver Families / drivers/usb.
- Implementation status: pattern implementation candidate.
- This snippet crosses the user/kernel memory boundary; validate fault handling and access checks before translating the pattern.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.