4470 lines · 106.7 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0+/* * f_fs.c -- user mode file system API for USB composite function controllers * * Copyright (C) 2010 Samsung Electronics * Author: Michal Nazarewicz <mina86@mina86.com> * * Based on inode.c (GadgetFS) which was: * Copyright (C) 2003-2004 David Brownell * Copyright (C) 2003 Agilent Technologies */  /* #define DEBUG *//* #define VERBOSE_DEBUG */ #include <linux/blkdev.h>#include <linux/dma-buf.h>#include <linux/dma-fence.h>#include <linux/dma-resv.h>#include <linux/pagemap.h>#include <linux/export.h>#include <linux/fs_parser.h>#include <linux/hid.h>#include <linux/mm.h>#include <linux/module.h>#include <linux/scatterlist.h>#include <linux/sched/signal.h>#include <linux/uio.h>#include <linux/vmalloc.h>#include <linux/unaligned.h> #include <linux/usb/ccid.h>#include <linux/usb/composite.h>#include <linux/usb/functionfs.h>#include <linux/usb/func_utils.h> #include <linux/aio.h>#include <linux/kthread.h>#include <linux/poll.h>#include <linux/eventfd.h> #include "u_fs.h"#include "u_os_desc.h"#include "configfs.h" #define FUNCTIONFS_MAGIC	0xa647361 /* Chosen by a honest dice roll ;) */#define MAX_ALT_SETTINGS	2		  /* Allow up to 2 alt settings to be set. */ #define DMABUF_ENQUEUE_TIMEOUT_MS 5000 MODULE_IMPORT_NS("DMA_BUF"); /* Reference counter handling */static void ffs_data_get(struct ffs_data *ffs);static void ffs_data_put(struct ffs_data *ffs);/* Creates new ffs_data object. */static struct ffs_data *__must_check ffs_data_new(const char *dev_name)	__attribute__((malloc)); /* Opened counter handling. */static void ffs_data_closed(struct ffs_data *ffs); /* Called with ffs->mutex held; take over ownership of data. */static int __must_check__ffs_data_got_descs(struct ffs_data *ffs, char *data, size_t len);static int __must_check__ffs_data_got_strings(struct ffs_data *ffs, char *data, size_t len);  /* The function structure ***************************************************/ struct ffs_ep; struct ffs_function {	struct usb_configuration	*conf;	struct usb_gadget		*gadget;	struct ffs_data			*ffs; 	struct ffs_ep			*eps;	u8				eps_revmap[16];	short				*interfaces_nums; 	struct usb_function		function;	int				cur_alt[MAX_CONFIG_INTERFACES];};  static struct ffs_function *ffs_func_from_usb(struct usb_function *f){	return container_of(f, struct ffs_function, function);}  static inline enum ffs_setup_stateffs_setup_state_clear_cancelled(struct ffs_data *ffs){	return (enum ffs_setup_state)		cmpxchg(&ffs->setup_state, FFS_SETUP_CANCELLED, FFS_NO_SETUP);}  static void ffs_func_eps_disable(struct ffs_function *func);static int __must_check ffs_func_eps_enable(struct ffs_function *func); static int ffs_func_bind(struct usb_configuration *,			 struct usb_function *);static int ffs_func_set_alt(struct usb_function *, unsigned, unsigned);static int ffs_func_get_alt(struct usb_function *f, unsigned int intf);static void ffs_func_disable(struct usb_function *);static int ffs_func_setup(struct usb_function *,			  const struct usb_ctrlrequest *);static bool ffs_func_req_match(struct usb_function *,			       const struct usb_ctrlrequest *,			       bool config0);static void ffs_func_suspend(struct usb_function *);static void ffs_func_resume(struct usb_function *);  static int ffs_func_revmap_ep(struct ffs_function *func, u8 num);static int ffs_func_revmap_intf(struct ffs_function *func, u8 intf);  /* The endpoints structures *************************************************/ struct ffs_ep {	struct usb_ep			*ep;	/* P: ffs->eps_lock */	struct usb_request		*req;	/* P: epfile->mutex */ 	/* [0]: full speed, [1]: high speed, [2]: super speed */	struct usb_endpoint_descriptor	*descs[3]; 	u8				num;}; struct ffs_dmabuf_priv {	struct list_head entry;	struct kref ref;	struct ffs_data *ffs;	struct dma_buf_attachment *attach;	struct sg_table *sgt;	enum dma_data_direction dir;	spinlock_t lock;	u64 context;	struct usb_request *req;	/* P: ffs->eps_lock */	struct usb_ep *ep;		/* P: ffs->eps_lock */}; struct ffs_dma_fence {	struct dma_fence base;	struct ffs_dmabuf_priv *priv;	struct work_struct work;	struct usb_ep *ep;	struct usb_request *req;}; struct ffs_epfile {	/* Protects ep->ep and ep->req. */	struct mutex			mutex; 	struct ffs_data			*ffs;	struct ffs_ep			*ep;		/* P: ffs->eps_lock */	struct ffs_epfile		*epfile_in;	/* P: ffs->eps_lock */	struct ffs_epfile		*epfile_out;	/* P: ffs->eps_lock */ 	/*	 * Buffer for holding data from partial reads which may happen since	 * we’re rounding user read requests to a multiple of a max packet size.	 *	 * The pointer is initialised with NULL value and may be set by	 * __ffs_epfile_read_data function to point to a temporary buffer.	 *	 * In normal operation, calls to __ffs_epfile_read_buffered will consume	 * data from said buffer and eventually free it.  Importantly, while the	 * function is using the buffer, it sets the pointer to NULL.  This is	 * all right since __ffs_epfile_read_data and __ffs_epfile_read_buffered	 * can never run concurrently (they are synchronised by epfile->mutex)	 * so the latter will not assign a new value to the pointer.	 *	 * Meanwhile ffs_func_eps_disable frees the buffer (if the pointer is	 * valid) and sets the pointer to READ_BUFFER_DROP value.  This special	 * value is crux of the synchronisation between ffs_func_eps_disable and	 * __ffs_epfile_read_data.	 *	 * Once __ffs_epfile_read_data is about to finish it will try to set the	 * pointer back to its old value (as described above), but seeing as the	 * pointer is not-NULL (namely READ_BUFFER_DROP) it will instead free	 * the buffer.	 *	 * == State transitions ==	 *	 * • ptr == NULL:  (initial state)	 *   ◦ __ffs_epfile_read_buffer_free: go to ptr == DROP	 *   ◦ __ffs_epfile_read_buffered:    nop	 *   ◦ __ffs_epfile_read_data allocates temp buffer: go to ptr == buf	 *   ◦ reading finishes:              n/a, not in ‘and reading’ state	 * • ptr == DROP:	 *   ◦ __ffs_epfile_read_buffer_free: nop	 *   ◦ __ffs_epfile_read_buffered:    go to ptr == NULL	 *   ◦ __ffs_epfile_read_data allocates temp buffer: free buf, nop	 *   ◦ reading finishes:              n/a, not in ‘and reading’ state	 * • ptr == buf:	 *   ◦ __ffs_epfile_read_buffer_free: free buf, go to ptr == DROP	 *   ◦ __ffs_epfile_read_buffered:    go to ptr == NULL and reading	 *   ◦ __ffs_epfile_read_data:        n/a, __ffs_epfile_read_buffered	 *                                    is always called first	 *   ◦ reading finishes:              n/a, not in ‘and reading’ state	 * • ptr == NULL and reading:	 *   ◦ __ffs_epfile_read_buffer_free: go to ptr == DROP and reading	 *   ◦ __ffs_epfile_read_buffered:    n/a, mutex is held	 *   ◦ __ffs_epfile_read_data:        n/a, mutex is held	 *   ◦ reading finishes and …	 *     … all data read:               free buf, go to ptr == NULL	 *     … otherwise:                   go to ptr == buf and reading	 * • ptr == DROP and reading:	 *   ◦ __ffs_epfile_read_buffer_free: nop	 *   ◦ __ffs_epfile_read_buffered:    n/a, mutex is held	 *   ◦ __ffs_epfile_read_data:        n/a, mutex is held	 *   ◦ reading finishes:              free buf, go to ptr == DROP	 */	struct ffs_buffer		*read_buffer;#define READ_BUFFER_DROP ((struct ffs_buffer *)ERR_PTR(-ESHUTDOWN)) 	char				name[8]; 	unsigned char			in;	/* P: ffs->eps_lock */	unsigned char			isoc;	/* P: ffs->eps_lock */ 	u8				zlp_enabled; /* P: ffs->eps_lock */	bool				is_rw_proxy; 	/* Protects dmabufs */	struct mutex			dmabufs_mutex;	struct list_head		dmabufs; /* P: dmabufs_mutex */	atomic_t			seqno;}; struct ffs_buffer {	size_t length;	char *data;	char storage[] __counted_by(length);}; /*  ffs_io_data structure ***************************************************/ struct ffs_io_data {	bool aio;	bool read; 	struct kiocb *kiocb;	struct iov_iter data;	const void *to_free;	char *buf; 	struct mm_struct *mm;	struct work_struct work; 	struct usb_ep *ep;	struct usb_request *req;	struct sg_table sgt;	bool use_sg; 	struct ffs_data *ffs; 	int status;	struct completion done;}; struct ffs_desc_helper {	struct ffs_data *ffs;	unsigned interfaces_count;	unsigned eps_count;}; static int  __must_check ffs_epfiles_create(struct ffs_data *ffs);static void ffs_epfiles_destroy(struct super_block *sb,				struct ffs_epfile *epfiles, unsigned count); static int ffs_sb_create_file(struct super_block *sb, const char *name,			      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);static void ffs_reset_work(struct work_struct *work); /* 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){	struct ffs_data *ffs = file->private_data;	ssize_t ret;	char *data; 	/* Fast check if setup was canceled */	if (ffs_setup_state_clear_cancelled(ffs) == FFS_SETUP_CANCELLED)		return -EIDRM; 	/* Acquire mutex */	ret = ffs_mutex_lock(&ffs->mutex, file->f_flags & O_NONBLOCK);	if (ret < 0)		return ret; 	/* Check state */	switch (ffs->state) {	case FFS_READ_DESCRIPTORS:	case FFS_READ_STRINGS:		/* Copy data */		if (len < 16) {			ret = -EINVAL;			break;		} 		data = ffs_prepare_buffer(buf, len);		if (IS_ERR(data)) {			ret = PTR_ERR(data);			break;		} 		/* Handle data */		if (ffs->state == FFS_READ_DESCRIPTORS) {			pr_info("read descriptors\n");			ret = __ffs_data_got_descs(ffs, data, len);			if (ret < 0)				break; 			ffs->state = FFS_READ_STRINGS;			ret = len;		} else {			pr_info("read strings\n");			ret = __ffs_data_got_strings(ffs, data, len);			if (ret < 0)				break; 			ret = ffs_epfiles_create(ffs);			if (ret) {				ffs->state = FFS_CLOSING;				break;			} 			ffs->state = FFS_ACTIVE;			mutex_unlock(&ffs->mutex); 			ret = ffs_ready(ffs);			if (ret < 0) {				ffs->state = FFS_CLOSING;				return ret;			} 			return len;		}		break; 	case FFS_ACTIVE:		data = NULL;		/*		 * We're called from user space, we can use _irq		 * rather then _irqsave		 */		spin_lock_irq(&ffs->ev.waitq.lock);		switch (ffs_setup_state_clear_cancelled(ffs)) {		case FFS_SETUP_CANCELLED:			ret = -EIDRM;			goto done_spin; 		case FFS_NO_SETUP:			ret = -ESRCH;			goto done_spin; 		case FFS_SETUP_PENDING:			break;		} 		/* FFS_SETUP_PENDING */		if (!(ffs->ev.setup.bRequestType & USB_DIR_IN)) {			spin_unlock_irq(&ffs->ev.waitq.lock);			ret = __ffs_ep0_stall(ffs);			break;		} 		/* FFS_SETUP_PENDING and not stall */		len = min_t(size_t, len, le16_to_cpu(ffs->ev.setup.wLength)); 		spin_unlock_irq(&ffs->ev.waitq.lock); 		data = ffs_prepare_buffer(buf, len);		if (IS_ERR(data)) {			ret = PTR_ERR(data);			break;		} 		spin_lock_irq(&ffs->ev.waitq.lock); 		/*		 * We are guaranteed to be still in FFS_ACTIVE state		 * but the state of setup could have changed from		 * FFS_SETUP_PENDING to FFS_SETUP_CANCELLED so we need		 * to check for that.  If that happened we copied data		 * from user space in vain but it's unlikely.		 *		 * For sure we are not in FFS_NO_SETUP since this is		 * the only place FFS_SETUP_PENDING -> FFS_NO_SETUP		 * transition can be performed and it's protected by		 * mutex.		 */		if (ffs_setup_state_clear_cancelled(ffs) ==		    FFS_SETUP_CANCELLED) {			ret = -EIDRM;done_spin:			spin_unlock_irq(&ffs->ev.waitq.lock);		} else {			/* unlocks spinlock */			ret = __ffs_ep0_queue_wait(ffs, data, len);		}		kfree(data);		break; 	default:		ret = -EBADFD;		break;

Lines 1–500 of 4470.