linux/drivers/usb/gadget/legacy/inode.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * inode.c -- user mode filesystem api for usb gadget controllers
 *
 * Copyright (C) 2003-2004 David Brownell
 * Copyright (C) 2003 Agilent Technologies
 */


/* #define VERBOSE_DEBUG */

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/fs_context.h>
#include <linux/pagemap.h>
#include <linux/uts.h>
#include <linux/wait.h>
#include <linux/compiler.h>
#include <linux/uaccess.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/kthread.h>
#include <linux/aio.h>
#include <linux/uio.h>
#include <linux/refcount.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/moduleparam.h>

#include <linux/usb/gadgetfs.h>
#include <linux/usb/gadget.h>
#include <linux/usb/composite.h> /* for USB_GADGET_DELAYED_STATUS */

/* Undef helpers from linux/usb/composite.h as gadgetfs redefines them */
#undef DBG
#undef ERROR
#undef INFO


/*
 * The gadgetfs API maps each endpoint to a file descriptor so that you
 * can use standard synchronous read/write calls for I/O.  There's some
 * O_NONBLOCK and O_ASYNC/FASYNC style i/o support.  Example usermode
 * drivers show how this works in practice.  You can also use AIO to
 * eliminate I/O gaps between requests, to help when streaming data.
 *
 * Key parts that must be USB-specific are protocols defining how the
 * read/write operations relate to the hardware state machines.  There
 * are two types of files.  One type is for the device, implementing ep0.
 * The other type is for each IN or OUT endpoint.  In both cases, the
 * user mode driver must configure the hardware before using it.
 *
 * - First, dev_config() is called when /dev/gadget/$CHIP is configured
 *   (by writing configuration and device descriptors).  Afterwards it
 *   may serve as a source of device events, used to handle all control
 *   requests other than basic enumeration.
 *
 * - Then, after a SET_CONFIGURATION control request, ep_config() is
 *   called when each /dev/gadget/ep* file is configured (by writing
 *   endpoint descriptors).  Afterwards these files are used to write()
 *   IN data or to read() OUT data.  To halt the endpoint, a "wrong
 *   direction" request is issued (like reading an IN endpoint).
 *
 * Unlike "usbfs" the only ioctl()s are for things that are rare, and maybe
 * not possible on all hardware.  For example, precise fault handling with
 * respect to data left in endpoint fifos after aborted operations; or
 * selective clearing of endpoint halts, to implement SET_INTERFACE.
 */

#define DRIVER_DESC
#define DRIVER_VERSION

static const char driver_desc [] =;
static const char shortname [] =;

MODULE_DESCRIPTION();
MODULE_AUTHOR();
MODULE_LICENSE();

static int ep_open(struct inode *, struct file *);


/*----------------------------------------------------------------------*/

#define GADGETFS_MAGIC

/* /dev/gadget/$CHIP represents ep0 and the whole device */
enum ep0_state {};

/* enough for the whole queue: most events invalidate others */
#define N_EVENT

#define RBUF_SIZE

struct dev_data {};

static inline void get_dev (struct dev_data *data)
{}

static void put_dev (struct dev_data *data)
{}

static struct dev_data *dev_new (void)
{}

/*----------------------------------------------------------------------*/

/* other /dev/gadget/$ENDPOINT files represent endpoints */
enum ep_state {};

struct ep_data {};

static inline void get_ep (struct ep_data *data)
{}

static void put_ep (struct ep_data *data)
{}

/*----------------------------------------------------------------------*/

/* most "how to use the hardware" policy choices are in userspace:
 * mapping endpoint roles (which the driver needs) to the capabilities
 * which the usb controller has.  most of those capabilities are exposed
 * implicitly, starting with the driver name and then endpoint names.
 */

static const char *CHIP;
static DEFINE_MUTEX(sb_mutex);		/* Serialize superblock operations */

/*----------------------------------------------------------------------*/

/* NOTE:  don't use dev_printk calls before binding to the gadget
 * at the end of ep0 configuration, or after unbind.
 */

/* too wordy: dev_printk(level , &(d)->gadget->dev , fmt , ## args) */
#define xprintk(d,level,fmt,args...)

#ifdef DEBUG
#define DBG(dev,fmt,args...)
#else
#define DBG
#endif /* DEBUG */

#ifdef VERBOSE_DEBUG
#define VDEBUG
#else
#define VDEBUG
#endif /* DEBUG */

#define ERROR(dev,fmt,args...)
#define INFO(dev,fmt,args...)


/*----------------------------------------------------------------------*/

/* SYNCHRONOUS ENDPOINT OPERATIONS (bulk/intr/iso)
 *
 * After opening, configure non-control endpoints.  Then use normal
 * stream read() and write() requests; and maybe ioctl() to get more
 * precise FIFO status when recovering from cancellation.
 */

static void epio_complete (struct usb_ep *ep, struct usb_request *req)
{}

/* tasklock endpoint, returning when it's connected.
 * still need dev->lock to use epdata->ep.
 */
static int
get_ready_ep (unsigned f_flags, struct ep_data *epdata, bool is_write)
{}

static ssize_t
ep_io (struct ep_data *epdata, void *buf, unsigned len)
{}

static int
ep_release (struct inode *inode, struct file *fd)
{}

static long ep_ioctl(struct file *fd, unsigned code, unsigned long value)
{}

/*----------------------------------------------------------------------*/

/* ASYNCHRONOUS ENDPOINT I/O OPERATIONS (bulk/intr/iso) */

struct kiocb_priv {};

static int ep_aio_cancel(struct kiocb *iocb)
{}

static void ep_user_copy_worker(struct work_struct *work)
{}

static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
{}

static ssize_t ep_aio(struct kiocb *iocb,
		      struct kiocb_priv *priv,
		      struct ep_data *epdata,
		      char *buf,
		      size_t len)
{}

static ssize_t
ep_read_iter(struct kiocb *iocb, struct iov_iter *to)
{}

static ssize_t ep_config(struct ep_data *, const char *, size_t);

static ssize_t
ep_write_iter(struct kiocb *iocb, struct iov_iter *from)
{}

/*----------------------------------------------------------------------*/

/* used after endpoint configuration */
static const struct file_operations ep_io_operations =;

/* ENDPOINT INITIALIZATION
 *
 *     fd = open ("/dev/gadget/$ENDPOINT", O_RDWR)
 *     status = write (fd, descriptors, sizeof descriptors)
 *
 * That write establishes the endpoint configuration, configuring
 * the controller to process bulk, interrupt, or isochronous transfers
 * at the right maxpacket size, and so on.
 *
 * The descriptors are message type 1, identified by a host order u32
 * at the beginning of what's written.  Descriptor order is: full/low
 * speed descriptor, then optional high speed descriptor.
 */
static ssize_t
ep_config (struct ep_data *data, const char *buf, size_t len)
{}

static int
ep_open (struct inode *inode, struct file *fd)
{}

/*----------------------------------------------------------------------*/

/* EP0 IMPLEMENTATION can be partly in userspace.
 *
 * Drivers that use this facility receive various events, including
 * control requests the kernel doesn't handle.  Drivers that don't
 * use this facility may be too simple-minded for real applications.
 */

static inline void ep0_readable (struct dev_data *dev)
{}

static void clean_req (struct usb_ep *ep, struct usb_request *req)
{}

static void ep0_complete (struct usb_ep *ep, struct usb_request *req)
{}

static int setup_req (struct usb_ep *ep, struct usb_request *req, u16 len)
{}

static ssize_t
ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr)
{}

static struct usb_gadgetfs_event *
next_event (struct dev_data *dev, enum usb_gadgetfs_event_type type)
{}

static ssize_t
ep0_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
{}

static int
ep0_fasync (int f, struct file *fd, int on)
{}

static struct usb_gadget_driver gadgetfs_driver;

static int
dev_release (struct inode *inode, struct file *fd)
{}

static __poll_t
ep0_poll (struct file *fd, poll_table *wait)
{}

static long gadget_dev_ioctl (struct file *fd, unsigned code, unsigned long value)
{}

/*----------------------------------------------------------------------*/

/* The in-kernel gadget driver handles most ep0 issues, in particular
 * enumerating the single configuration (as provided from user space).
 *
 * Unrecognized ep0 requests may be handled in user space.
 */

static void make_qualifier (struct dev_data *dev)
{}

static int
config_buf (struct dev_data *dev, u8 type, unsigned index)
{}

static int
gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
{}

static void destroy_ep_files (struct dev_data *dev)
{}


static struct dentry *
gadgetfs_create_file (struct super_block *sb, char const *name,
		void *data, const struct file_operations *fops);

static int activate_ep_files (struct dev_data *dev)
{}

static void
gadgetfs_unbind (struct usb_gadget *gadget)
{}

static struct dev_data		*the_device;

static int gadgetfs_bind(struct usb_gadget *gadget,
		struct usb_gadget_driver *driver)
{}

static void
gadgetfs_disconnect (struct usb_gadget *gadget)
{}

static void
gadgetfs_suspend (struct usb_gadget *gadget)
{}

static struct usb_gadget_driver gadgetfs_driver =;

/*----------------------------------------------------------------------*/
/* DEVICE INITIALIZATION
 *
 *     fd = open ("/dev/gadget/$CHIP", O_RDWR)
 *     status = write (fd, descriptors, sizeof descriptors)
 *
 * That write establishes the device configuration, so the kernel can
 * bind to the controller ... guaranteeing it can handle enumeration
 * at all necessary speeds.  Descriptor order is:
 *
 * . message tag (u32, host order) ... for now, must be zero; it
 *	would change to support features like multi-config devices
 * . full/low speed config ... all wTotalLength bytes (with interface,
 *	class, altsetting, endpoint, and other descriptors)
 * . high speed config ... all descriptors, for high speed operation;
 *	this one's optional except for high-speed hardware
 * . device descriptor
 *
 * Endpoints are not yet enabled. Drivers must wait until device
 * configuration and interface altsetting changes create
 * the need to configure (or unconfigure) them.
 *
 * After initialization, the device stays active for as long as that
 * $CHIP file is open.  Events must then be read from that descriptor,
 * such as configuration notifications.
 */

static int is_valid_config(struct usb_config_descriptor *config,
		unsigned int total)
{}

static ssize_t
dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
{}

static int
gadget_dev_open (struct inode *inode, struct file *fd)
{}

static const struct file_operations ep0_operations =;

/*----------------------------------------------------------------------*/

/* FILESYSTEM AND SUPERBLOCK OPERATIONS
 *
 * Mounting the filesystem creates a controller file, used first for
 * device configuration then later for event monitoring.
 */


/* FIXME PAM etc could set this security policy without mount options
 * if epfiles inherited ownership and permissons from ep0 ...
 */

static unsigned default_uid;
static unsigned default_gid;
static unsigned default_perm =;

module_param (default_uid, uint, 0644);
module_param (default_gid, uint, 0644);
module_param (default_perm, uint, 0644);


static struct inode *
gadgetfs_make_inode (struct super_block *sb,
		void *data, const struct file_operations *fops,
		int mode)
{}

/* creates in fs root directory, so non-renamable and non-linkable.
 * so inode and dentry are paired, until device reconfig.
 */
static struct dentry *
gadgetfs_create_file (struct super_block *sb, char const *name,
		void *data, const struct file_operations *fops)
{}

static const struct super_operations gadget_fs_operations =;

static int
gadgetfs_fill_super (struct super_block *sb, struct fs_context *fc)
{}

/* "mount -t gadgetfs path /dev/gadget" ends up here */
static int gadgetfs_get_tree(struct fs_context *fc)
{}

static const struct fs_context_operations gadgetfs_context_ops =;

static int gadgetfs_init_fs_context(struct fs_context *fc)
{}

static void
gadgetfs_kill_sb (struct super_block *sb)
{}

/*----------------------------------------------------------------------*/

static struct file_system_type gadgetfs_type =;
MODULE_ALIAS_FS();

/*----------------------------------------------------------------------*/

static int __init gadgetfs_init (void)
{}
module_init();

static void __exit gadgetfs_cleanup (void)
{}
module_exit (gadgetfs_cleanup);