162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * f_fs.c -- user mode file system API for USB composite function controllers
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2010 Samsung Electronics
662306a36Sopenharmony_ci * Author: Michal Nazarewicz <mina86@mina86.com>
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * Based on inode.c (GadgetFS) which was:
962306a36Sopenharmony_ci * Copyright (C) 2003-2004 David Brownell
1062306a36Sopenharmony_ci * Copyright (C) 2003 Agilent Technologies
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci/* #define DEBUG */
1562306a36Sopenharmony_ci/* #define VERBOSE_DEBUG */
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#include <linux/blkdev.h>
1862306a36Sopenharmony_ci#include <linux/pagemap.h>
1962306a36Sopenharmony_ci#include <linux/export.h>
2062306a36Sopenharmony_ci#include <linux/fs_parser.h>
2162306a36Sopenharmony_ci#include <linux/hid.h>
2262306a36Sopenharmony_ci#include <linux/mm.h>
2362306a36Sopenharmony_ci#include <linux/module.h>
2462306a36Sopenharmony_ci#include <linux/scatterlist.h>
2562306a36Sopenharmony_ci#include <linux/sched/signal.h>
2662306a36Sopenharmony_ci#include <linux/uio.h>
2762306a36Sopenharmony_ci#include <linux/vmalloc.h>
2862306a36Sopenharmony_ci#include <asm/unaligned.h>
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#include <linux/usb/ccid.h>
3162306a36Sopenharmony_ci#include <linux/usb/composite.h>
3262306a36Sopenharmony_ci#include <linux/usb/functionfs.h>
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#include <linux/aio.h>
3562306a36Sopenharmony_ci#include <linux/kthread.h>
3662306a36Sopenharmony_ci#include <linux/poll.h>
3762306a36Sopenharmony_ci#include <linux/eventfd.h>
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci#include "u_fs.h"
4062306a36Sopenharmony_ci#include "u_f.h"
4162306a36Sopenharmony_ci#include "u_os_desc.h"
4262306a36Sopenharmony_ci#include "configfs.h"
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci#define FUNCTIONFS_MAGIC	0xa647361 /* Chosen by a honest dice roll ;) */
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci/* Reference counter handling */
4762306a36Sopenharmony_cistatic void ffs_data_get(struct ffs_data *ffs);
4862306a36Sopenharmony_cistatic void ffs_data_put(struct ffs_data *ffs);
4962306a36Sopenharmony_ci/* Creates new ffs_data object. */
5062306a36Sopenharmony_cistatic struct ffs_data *__must_check ffs_data_new(const char *dev_name)
5162306a36Sopenharmony_ci	__attribute__((malloc));
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci/* Opened counter handling. */
5462306a36Sopenharmony_cistatic void ffs_data_opened(struct ffs_data *ffs);
5562306a36Sopenharmony_cistatic void ffs_data_closed(struct ffs_data *ffs);
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci/* Called with ffs->mutex held; take over ownership of data. */
5862306a36Sopenharmony_cistatic int __must_check
5962306a36Sopenharmony_ci__ffs_data_got_descs(struct ffs_data *ffs, char *data, size_t len);
6062306a36Sopenharmony_cistatic int __must_check
6162306a36Sopenharmony_ci__ffs_data_got_strings(struct ffs_data *ffs, char *data, size_t len);
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci/* The function structure ***************************************************/
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_cistruct ffs_ep;
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_cistruct ffs_function {
6962306a36Sopenharmony_ci	struct usb_configuration	*conf;
7062306a36Sopenharmony_ci	struct usb_gadget		*gadget;
7162306a36Sopenharmony_ci	struct ffs_data			*ffs;
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	struct ffs_ep			*eps;
7462306a36Sopenharmony_ci	u8				eps_revmap[16];
7562306a36Sopenharmony_ci	short				*interfaces_nums;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	struct usb_function		function;
7862306a36Sopenharmony_ci};
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_cistatic struct ffs_function *ffs_func_from_usb(struct usb_function *f)
8262306a36Sopenharmony_ci{
8362306a36Sopenharmony_ci	return container_of(f, struct ffs_function, function);
8462306a36Sopenharmony_ci}
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_cistatic inline enum ffs_setup_state
8862306a36Sopenharmony_ciffs_setup_state_clear_cancelled(struct ffs_data *ffs)
8962306a36Sopenharmony_ci{
9062306a36Sopenharmony_ci	return (enum ffs_setup_state)
9162306a36Sopenharmony_ci		cmpxchg(&ffs->setup_state, FFS_SETUP_CANCELLED, FFS_NO_SETUP);
9262306a36Sopenharmony_ci}
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_cistatic void ffs_func_eps_disable(struct ffs_function *func);
9662306a36Sopenharmony_cistatic int __must_check ffs_func_eps_enable(struct ffs_function *func);
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_cistatic int ffs_func_bind(struct usb_configuration *,
9962306a36Sopenharmony_ci			 struct usb_function *);
10062306a36Sopenharmony_cistatic int ffs_func_set_alt(struct usb_function *, unsigned, unsigned);
10162306a36Sopenharmony_cistatic void ffs_func_disable(struct usb_function *);
10262306a36Sopenharmony_cistatic int ffs_func_setup(struct usb_function *,
10362306a36Sopenharmony_ci			  const struct usb_ctrlrequest *);
10462306a36Sopenharmony_cistatic bool ffs_func_req_match(struct usb_function *,
10562306a36Sopenharmony_ci			       const struct usb_ctrlrequest *,
10662306a36Sopenharmony_ci			       bool config0);
10762306a36Sopenharmony_cistatic void ffs_func_suspend(struct usb_function *);
10862306a36Sopenharmony_cistatic void ffs_func_resume(struct usb_function *);
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_cistatic int ffs_func_revmap_ep(struct ffs_function *func, u8 num);
11262306a36Sopenharmony_cistatic int ffs_func_revmap_intf(struct ffs_function *func, u8 intf);
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci/* The endpoints structures *************************************************/
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_cistruct ffs_ep {
11862306a36Sopenharmony_ci	struct usb_ep			*ep;	/* P: ffs->eps_lock */
11962306a36Sopenharmony_ci	struct usb_request		*req;	/* P: epfile->mutex */
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	/* [0]: full speed, [1]: high speed, [2]: super speed */
12262306a36Sopenharmony_ci	struct usb_endpoint_descriptor	*descs[3];
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	u8				num;
12562306a36Sopenharmony_ci};
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_cistruct ffs_epfile {
12862306a36Sopenharmony_ci	/* Protects ep->ep and ep->req. */
12962306a36Sopenharmony_ci	struct mutex			mutex;
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	struct ffs_data			*ffs;
13262306a36Sopenharmony_ci	struct ffs_ep			*ep;	/* P: ffs->eps_lock */
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	struct dentry			*dentry;
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci	/*
13762306a36Sopenharmony_ci	 * Buffer for holding data from partial reads which may happen since
13862306a36Sopenharmony_ci	 * we’re rounding user read requests to a multiple of a max packet size.
13962306a36Sopenharmony_ci	 *
14062306a36Sopenharmony_ci	 * The pointer is initialised with NULL value and may be set by
14162306a36Sopenharmony_ci	 * __ffs_epfile_read_data function to point to a temporary buffer.
14262306a36Sopenharmony_ci	 *
14362306a36Sopenharmony_ci	 * In normal operation, calls to __ffs_epfile_read_buffered will consume
14462306a36Sopenharmony_ci	 * data from said buffer and eventually free it.  Importantly, while the
14562306a36Sopenharmony_ci	 * function is using the buffer, it sets the pointer to NULL.  This is
14662306a36Sopenharmony_ci	 * all right since __ffs_epfile_read_data and __ffs_epfile_read_buffered
14762306a36Sopenharmony_ci	 * can never run concurrently (they are synchronised by epfile->mutex)
14862306a36Sopenharmony_ci	 * so the latter will not assign a new value to the pointer.
14962306a36Sopenharmony_ci	 *
15062306a36Sopenharmony_ci	 * Meanwhile ffs_func_eps_disable frees the buffer (if the pointer is
15162306a36Sopenharmony_ci	 * valid) and sets the pointer to READ_BUFFER_DROP value.  This special
15262306a36Sopenharmony_ci	 * value is crux of the synchronisation between ffs_func_eps_disable and
15362306a36Sopenharmony_ci	 * __ffs_epfile_read_data.
15462306a36Sopenharmony_ci	 *
15562306a36Sopenharmony_ci	 * Once __ffs_epfile_read_data is about to finish it will try to set the
15662306a36Sopenharmony_ci	 * pointer back to its old value (as described above), but seeing as the
15762306a36Sopenharmony_ci	 * pointer is not-NULL (namely READ_BUFFER_DROP) it will instead free
15862306a36Sopenharmony_ci	 * the buffer.
15962306a36Sopenharmony_ci	 *
16062306a36Sopenharmony_ci	 * == State transitions ==
16162306a36Sopenharmony_ci	 *
16262306a36Sopenharmony_ci	 * • ptr == NULL:  (initial state)
16362306a36Sopenharmony_ci	 *   ◦ __ffs_epfile_read_buffer_free: go to ptr == DROP
16462306a36Sopenharmony_ci	 *   ◦ __ffs_epfile_read_buffered:    nop
16562306a36Sopenharmony_ci	 *   ◦ __ffs_epfile_read_data allocates temp buffer: go to ptr == buf
16662306a36Sopenharmony_ci	 *   ◦ reading finishes:              n/a, not in ‘and reading’ state
16762306a36Sopenharmony_ci	 * • ptr == DROP:
16862306a36Sopenharmony_ci	 *   ◦ __ffs_epfile_read_buffer_free: nop
16962306a36Sopenharmony_ci	 *   ◦ __ffs_epfile_read_buffered:    go to ptr == NULL
17062306a36Sopenharmony_ci	 *   ◦ __ffs_epfile_read_data allocates temp buffer: free buf, nop
17162306a36Sopenharmony_ci	 *   ◦ reading finishes:              n/a, not in ‘and reading’ state
17262306a36Sopenharmony_ci	 * • ptr == buf:
17362306a36Sopenharmony_ci	 *   ◦ __ffs_epfile_read_buffer_free: free buf, go to ptr == DROP
17462306a36Sopenharmony_ci	 *   ◦ __ffs_epfile_read_buffered:    go to ptr == NULL and reading
17562306a36Sopenharmony_ci	 *   ◦ __ffs_epfile_read_data:        n/a, __ffs_epfile_read_buffered
17662306a36Sopenharmony_ci	 *                                    is always called first
17762306a36Sopenharmony_ci	 *   ◦ reading finishes:              n/a, not in ‘and reading’ state
17862306a36Sopenharmony_ci	 * • ptr == NULL and reading:
17962306a36Sopenharmony_ci	 *   ◦ __ffs_epfile_read_buffer_free: go to ptr == DROP and reading
18062306a36Sopenharmony_ci	 *   ◦ __ffs_epfile_read_buffered:    n/a, mutex is held
18162306a36Sopenharmony_ci	 *   ◦ __ffs_epfile_read_data:        n/a, mutex is held
18262306a36Sopenharmony_ci	 *   ◦ reading finishes and …
18362306a36Sopenharmony_ci	 *     … all data read:               free buf, go to ptr == NULL
18462306a36Sopenharmony_ci	 *     … otherwise:                   go to ptr == buf and reading
18562306a36Sopenharmony_ci	 * • ptr == DROP and reading:
18662306a36Sopenharmony_ci	 *   ◦ __ffs_epfile_read_buffer_free: nop
18762306a36Sopenharmony_ci	 *   ◦ __ffs_epfile_read_buffered:    n/a, mutex is held
18862306a36Sopenharmony_ci	 *   ◦ __ffs_epfile_read_data:        n/a, mutex is held
18962306a36Sopenharmony_ci	 *   ◦ reading finishes:              free buf, go to ptr == DROP
19062306a36Sopenharmony_ci	 */
19162306a36Sopenharmony_ci	struct ffs_buffer		*read_buffer;
19262306a36Sopenharmony_ci#define READ_BUFFER_DROP ((struct ffs_buffer *)ERR_PTR(-ESHUTDOWN))
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci	char				name[5];
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	unsigned char			in;	/* P: ffs->eps_lock */
19762306a36Sopenharmony_ci	unsigned char			isoc;	/* P: ffs->eps_lock */
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci	unsigned char			_pad;
20062306a36Sopenharmony_ci};
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_cistruct ffs_buffer {
20362306a36Sopenharmony_ci	size_t length;
20462306a36Sopenharmony_ci	char *data;
20562306a36Sopenharmony_ci	char storage[];
20662306a36Sopenharmony_ci};
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci/*  ffs_io_data structure ***************************************************/
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_cistruct ffs_io_data {
21162306a36Sopenharmony_ci	bool aio;
21262306a36Sopenharmony_ci	bool read;
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	struct kiocb *kiocb;
21562306a36Sopenharmony_ci	struct iov_iter data;
21662306a36Sopenharmony_ci	const void *to_free;
21762306a36Sopenharmony_ci	char *buf;
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci	struct mm_struct *mm;
22062306a36Sopenharmony_ci	struct work_struct work;
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci	struct usb_ep *ep;
22362306a36Sopenharmony_ci	struct usb_request *req;
22462306a36Sopenharmony_ci	struct sg_table sgt;
22562306a36Sopenharmony_ci	bool use_sg;
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	struct ffs_data *ffs;
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci	int status;
23062306a36Sopenharmony_ci	struct completion done;
23162306a36Sopenharmony_ci};
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_cistruct ffs_desc_helper {
23462306a36Sopenharmony_ci	struct ffs_data *ffs;
23562306a36Sopenharmony_ci	unsigned interfaces_count;
23662306a36Sopenharmony_ci	unsigned eps_count;
23762306a36Sopenharmony_ci};
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_cistatic int  __must_check ffs_epfiles_create(struct ffs_data *ffs);
24062306a36Sopenharmony_cistatic void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count);
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_cistatic struct dentry *
24362306a36Sopenharmony_ciffs_sb_create_file(struct super_block *sb, const char *name, void *data,
24462306a36Sopenharmony_ci		   const struct file_operations *fops);
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci/* Devices management *******************************************************/
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ciDEFINE_MUTEX(ffs_lock);
24962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ffs_lock);
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_cistatic struct ffs_dev *_ffs_find_dev(const char *name);
25262306a36Sopenharmony_cistatic struct ffs_dev *_ffs_alloc_dev(void);
25362306a36Sopenharmony_cistatic void _ffs_free_dev(struct ffs_dev *dev);
25462306a36Sopenharmony_cistatic int ffs_acquire_dev(const char *dev_name, struct ffs_data *ffs_data);
25562306a36Sopenharmony_cistatic void ffs_release_dev(struct ffs_dev *ffs_dev);
25662306a36Sopenharmony_cistatic int ffs_ready(struct ffs_data *ffs);
25762306a36Sopenharmony_cistatic void ffs_closed(struct ffs_data *ffs);
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci/* Misc helper functions ****************************************************/
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_cistatic int ffs_mutex_lock(struct mutex *mutex, unsigned nonblock)
26262306a36Sopenharmony_ci	__attribute__((warn_unused_result, nonnull));
26362306a36Sopenharmony_cistatic char *ffs_prepare_buffer(const char __user *buf, size_t len)
26462306a36Sopenharmony_ci	__attribute__((warn_unused_result, nonnull));
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci/* Control file aka ep0 *****************************************************/
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_cistatic void ffs_ep0_complete(struct usb_ep *ep, struct usb_request *req)
27062306a36Sopenharmony_ci{
27162306a36Sopenharmony_ci	struct ffs_data *ffs = req->context;
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	complete(&ffs->ep0req_completion);
27462306a36Sopenharmony_ci}
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_cistatic int __ffs_ep0_queue_wait(struct ffs_data *ffs, char *data, size_t len)
27762306a36Sopenharmony_ci	__releases(&ffs->ev.waitq.lock)
27862306a36Sopenharmony_ci{
27962306a36Sopenharmony_ci	struct usb_request *req = ffs->ep0req;
28062306a36Sopenharmony_ci	int ret;
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci	if (!req) {
28362306a36Sopenharmony_ci		spin_unlock_irq(&ffs->ev.waitq.lock);
28462306a36Sopenharmony_ci		return -EINVAL;
28562306a36Sopenharmony_ci	}
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	req->zero     = len < le16_to_cpu(ffs->ev.setup.wLength);
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci	spin_unlock_irq(&ffs->ev.waitq.lock);
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	req->buf      = data;
29262306a36Sopenharmony_ci	req->length   = len;
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	/*
29562306a36Sopenharmony_ci	 * UDC layer requires to provide a buffer even for ZLP, but should
29662306a36Sopenharmony_ci	 * not use it at all. Let's provide some poisoned pointer to catch
29762306a36Sopenharmony_ci	 * possible bug in the driver.
29862306a36Sopenharmony_ci	 */
29962306a36Sopenharmony_ci	if (req->buf == NULL)
30062306a36Sopenharmony_ci		req->buf = (void *)0xDEADBABE;
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	reinit_completion(&ffs->ep0req_completion);
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci	ret = usb_ep_queue(ffs->gadget->ep0, req, GFP_ATOMIC);
30562306a36Sopenharmony_ci	if (ret < 0)
30662306a36Sopenharmony_ci		return ret;
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	ret = wait_for_completion_interruptible(&ffs->ep0req_completion);
30962306a36Sopenharmony_ci	if (ret) {
31062306a36Sopenharmony_ci		usb_ep_dequeue(ffs->gadget->ep0, req);
31162306a36Sopenharmony_ci		return -EINTR;
31262306a36Sopenharmony_ci	}
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci	ffs->setup_state = FFS_NO_SETUP;
31562306a36Sopenharmony_ci	return req->status ? req->status : req->actual;
31662306a36Sopenharmony_ci}
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_cistatic int __ffs_ep0_stall(struct ffs_data *ffs)
31962306a36Sopenharmony_ci{
32062306a36Sopenharmony_ci	if (ffs->ev.can_stall) {
32162306a36Sopenharmony_ci		pr_vdebug("ep0 stall\n");
32262306a36Sopenharmony_ci		usb_ep_set_halt(ffs->gadget->ep0);
32362306a36Sopenharmony_ci		ffs->setup_state = FFS_NO_SETUP;
32462306a36Sopenharmony_ci		return -EL2HLT;
32562306a36Sopenharmony_ci	} else {
32662306a36Sopenharmony_ci		pr_debug("bogus ep0 stall!\n");
32762306a36Sopenharmony_ci		return -ESRCH;
32862306a36Sopenharmony_ci	}
32962306a36Sopenharmony_ci}
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_cistatic ssize_t ffs_ep0_write(struct file *file, const char __user *buf,
33262306a36Sopenharmony_ci			     size_t len, loff_t *ptr)
33362306a36Sopenharmony_ci{
33462306a36Sopenharmony_ci	struct ffs_data *ffs = file->private_data;
33562306a36Sopenharmony_ci	ssize_t ret;
33662306a36Sopenharmony_ci	char *data;
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci	/* Fast check if setup was canceled */
33962306a36Sopenharmony_ci	if (ffs_setup_state_clear_cancelled(ffs) == FFS_SETUP_CANCELLED)
34062306a36Sopenharmony_ci		return -EIDRM;
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci	/* Acquire mutex */
34362306a36Sopenharmony_ci	ret = ffs_mutex_lock(&ffs->mutex, file->f_flags & O_NONBLOCK);
34462306a36Sopenharmony_ci	if (ret < 0)
34562306a36Sopenharmony_ci		return ret;
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	/* Check state */
34862306a36Sopenharmony_ci	switch (ffs->state) {
34962306a36Sopenharmony_ci	case FFS_READ_DESCRIPTORS:
35062306a36Sopenharmony_ci	case FFS_READ_STRINGS:
35162306a36Sopenharmony_ci		/* Copy data */
35262306a36Sopenharmony_ci		if (len < 16) {
35362306a36Sopenharmony_ci			ret = -EINVAL;
35462306a36Sopenharmony_ci			break;
35562306a36Sopenharmony_ci		}
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci		data = ffs_prepare_buffer(buf, len);
35862306a36Sopenharmony_ci		if (IS_ERR(data)) {
35962306a36Sopenharmony_ci			ret = PTR_ERR(data);
36062306a36Sopenharmony_ci			break;
36162306a36Sopenharmony_ci		}
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci		/* Handle data */
36462306a36Sopenharmony_ci		if (ffs->state == FFS_READ_DESCRIPTORS) {
36562306a36Sopenharmony_ci			pr_info("read descriptors\n");
36662306a36Sopenharmony_ci			ret = __ffs_data_got_descs(ffs, data, len);
36762306a36Sopenharmony_ci			if (ret < 0)
36862306a36Sopenharmony_ci				break;
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci			ffs->state = FFS_READ_STRINGS;
37162306a36Sopenharmony_ci			ret = len;
37262306a36Sopenharmony_ci		} else {
37362306a36Sopenharmony_ci			pr_info("read strings\n");
37462306a36Sopenharmony_ci			ret = __ffs_data_got_strings(ffs, data, len);
37562306a36Sopenharmony_ci			if (ret < 0)
37662306a36Sopenharmony_ci				break;
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci			ret = ffs_epfiles_create(ffs);
37962306a36Sopenharmony_ci			if (ret) {
38062306a36Sopenharmony_ci				ffs->state = FFS_CLOSING;
38162306a36Sopenharmony_ci				break;
38262306a36Sopenharmony_ci			}
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_ci			ffs->state = FFS_ACTIVE;
38562306a36Sopenharmony_ci			mutex_unlock(&ffs->mutex);
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci			ret = ffs_ready(ffs);
38862306a36Sopenharmony_ci			if (ret < 0) {
38962306a36Sopenharmony_ci				ffs->state = FFS_CLOSING;
39062306a36Sopenharmony_ci				return ret;
39162306a36Sopenharmony_ci			}
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci			return len;
39462306a36Sopenharmony_ci		}
39562306a36Sopenharmony_ci		break;
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci	case FFS_ACTIVE:
39862306a36Sopenharmony_ci		data = NULL;
39962306a36Sopenharmony_ci		/*
40062306a36Sopenharmony_ci		 * We're called from user space, we can use _irq
40162306a36Sopenharmony_ci		 * rather then _irqsave
40262306a36Sopenharmony_ci		 */
40362306a36Sopenharmony_ci		spin_lock_irq(&ffs->ev.waitq.lock);
40462306a36Sopenharmony_ci		switch (ffs_setup_state_clear_cancelled(ffs)) {
40562306a36Sopenharmony_ci		case FFS_SETUP_CANCELLED:
40662306a36Sopenharmony_ci			ret = -EIDRM;
40762306a36Sopenharmony_ci			goto done_spin;
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci		case FFS_NO_SETUP:
41062306a36Sopenharmony_ci			ret = -ESRCH;
41162306a36Sopenharmony_ci			goto done_spin;
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci		case FFS_SETUP_PENDING:
41462306a36Sopenharmony_ci			break;
41562306a36Sopenharmony_ci		}
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci		/* FFS_SETUP_PENDING */
41862306a36Sopenharmony_ci		if (!(ffs->ev.setup.bRequestType & USB_DIR_IN)) {
41962306a36Sopenharmony_ci			spin_unlock_irq(&ffs->ev.waitq.lock);
42062306a36Sopenharmony_ci			ret = __ffs_ep0_stall(ffs);
42162306a36Sopenharmony_ci			break;
42262306a36Sopenharmony_ci		}
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci		/* FFS_SETUP_PENDING and not stall */
42562306a36Sopenharmony_ci		len = min(len, (size_t)le16_to_cpu(ffs->ev.setup.wLength));
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci		spin_unlock_irq(&ffs->ev.waitq.lock);
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci		data = ffs_prepare_buffer(buf, len);
43062306a36Sopenharmony_ci		if (IS_ERR(data)) {
43162306a36Sopenharmony_ci			ret = PTR_ERR(data);
43262306a36Sopenharmony_ci			break;
43362306a36Sopenharmony_ci		}
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci		spin_lock_irq(&ffs->ev.waitq.lock);
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci		/*
43862306a36Sopenharmony_ci		 * We are guaranteed to be still in FFS_ACTIVE state
43962306a36Sopenharmony_ci		 * but the state of setup could have changed from
44062306a36Sopenharmony_ci		 * FFS_SETUP_PENDING to FFS_SETUP_CANCELLED so we need
44162306a36Sopenharmony_ci		 * to check for that.  If that happened we copied data
44262306a36Sopenharmony_ci		 * from user space in vain but it's unlikely.
44362306a36Sopenharmony_ci		 *
44462306a36Sopenharmony_ci		 * For sure we are not in FFS_NO_SETUP since this is
44562306a36Sopenharmony_ci		 * the only place FFS_SETUP_PENDING -> FFS_NO_SETUP
44662306a36Sopenharmony_ci		 * transition can be performed and it's protected by
44762306a36Sopenharmony_ci		 * mutex.
44862306a36Sopenharmony_ci		 */
44962306a36Sopenharmony_ci		if (ffs_setup_state_clear_cancelled(ffs) ==
45062306a36Sopenharmony_ci		    FFS_SETUP_CANCELLED) {
45162306a36Sopenharmony_ci			ret = -EIDRM;
45262306a36Sopenharmony_cidone_spin:
45362306a36Sopenharmony_ci			spin_unlock_irq(&ffs->ev.waitq.lock);
45462306a36Sopenharmony_ci		} else {
45562306a36Sopenharmony_ci			/* unlocks spinlock */
45662306a36Sopenharmony_ci			ret = __ffs_ep0_queue_wait(ffs, data, len);
45762306a36Sopenharmony_ci		}
45862306a36Sopenharmony_ci		kfree(data);
45962306a36Sopenharmony_ci		break;
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci	default:
46262306a36Sopenharmony_ci		ret = -EBADFD;
46362306a36Sopenharmony_ci		break;
46462306a36Sopenharmony_ci	}
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	mutex_unlock(&ffs->mutex);
46762306a36Sopenharmony_ci	return ret;
46862306a36Sopenharmony_ci}
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci/* Called with ffs->ev.waitq.lock and ffs->mutex held, both released on exit. */
47162306a36Sopenharmony_cistatic ssize_t __ffs_ep0_read_events(struct ffs_data *ffs, char __user *buf,
47262306a36Sopenharmony_ci				     size_t n)
47362306a36Sopenharmony_ci	__releases(&ffs->ev.waitq.lock)
47462306a36Sopenharmony_ci{
47562306a36Sopenharmony_ci	/*
47662306a36Sopenharmony_ci	 * n cannot be bigger than ffs->ev.count, which cannot be bigger than
47762306a36Sopenharmony_ci	 * size of ffs->ev.types array (which is four) so that's how much space
47862306a36Sopenharmony_ci	 * we reserve.
47962306a36Sopenharmony_ci	 */
48062306a36Sopenharmony_ci	struct usb_functionfs_event events[ARRAY_SIZE(ffs->ev.types)];
48162306a36Sopenharmony_ci	const size_t size = n * sizeof *events;
48262306a36Sopenharmony_ci	unsigned i = 0;
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci	memset(events, 0, size);
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_ci	do {
48762306a36Sopenharmony_ci		events[i].type = ffs->ev.types[i];
48862306a36Sopenharmony_ci		if (events[i].type == FUNCTIONFS_SETUP) {
48962306a36Sopenharmony_ci			events[i].u.setup = ffs->ev.setup;
49062306a36Sopenharmony_ci			ffs->setup_state = FFS_SETUP_PENDING;
49162306a36Sopenharmony_ci		}
49262306a36Sopenharmony_ci	} while (++i < n);
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci	ffs->ev.count -= n;
49562306a36Sopenharmony_ci	if (ffs->ev.count)
49662306a36Sopenharmony_ci		memmove(ffs->ev.types, ffs->ev.types + n,
49762306a36Sopenharmony_ci			ffs->ev.count * sizeof *ffs->ev.types);
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci	spin_unlock_irq(&ffs->ev.waitq.lock);
50062306a36Sopenharmony_ci	mutex_unlock(&ffs->mutex);
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci	return copy_to_user(buf, events, size) ? -EFAULT : size;
50362306a36Sopenharmony_ci}
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_cistatic ssize_t ffs_ep0_read(struct file *file, char __user *buf,
50662306a36Sopenharmony_ci			    size_t len, loff_t *ptr)
50762306a36Sopenharmony_ci{
50862306a36Sopenharmony_ci	struct ffs_data *ffs = file->private_data;
50962306a36Sopenharmony_ci	char *data = NULL;
51062306a36Sopenharmony_ci	size_t n;
51162306a36Sopenharmony_ci	int ret;
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci	/* Fast check if setup was canceled */
51462306a36Sopenharmony_ci	if (ffs_setup_state_clear_cancelled(ffs) == FFS_SETUP_CANCELLED)
51562306a36Sopenharmony_ci		return -EIDRM;
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci	/* Acquire mutex */
51862306a36Sopenharmony_ci	ret = ffs_mutex_lock(&ffs->mutex, file->f_flags & O_NONBLOCK);
51962306a36Sopenharmony_ci	if (ret < 0)
52062306a36Sopenharmony_ci		return ret;
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci	/* Check state */
52362306a36Sopenharmony_ci	if (ffs->state != FFS_ACTIVE) {
52462306a36Sopenharmony_ci		ret = -EBADFD;
52562306a36Sopenharmony_ci		goto done_mutex;
52662306a36Sopenharmony_ci	}
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci	/*
52962306a36Sopenharmony_ci	 * We're called from user space, we can use _irq rather then
53062306a36Sopenharmony_ci	 * _irqsave
53162306a36Sopenharmony_ci	 */
53262306a36Sopenharmony_ci	spin_lock_irq(&ffs->ev.waitq.lock);
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci	switch (ffs_setup_state_clear_cancelled(ffs)) {
53562306a36Sopenharmony_ci	case FFS_SETUP_CANCELLED:
53662306a36Sopenharmony_ci		ret = -EIDRM;
53762306a36Sopenharmony_ci		break;
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci	case FFS_NO_SETUP:
54062306a36Sopenharmony_ci		n = len / sizeof(struct usb_functionfs_event);
54162306a36Sopenharmony_ci		if (!n) {
54262306a36Sopenharmony_ci			ret = -EINVAL;
54362306a36Sopenharmony_ci			break;
54462306a36Sopenharmony_ci		}
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci		if ((file->f_flags & O_NONBLOCK) && !ffs->ev.count) {
54762306a36Sopenharmony_ci			ret = -EAGAIN;
54862306a36Sopenharmony_ci			break;
54962306a36Sopenharmony_ci		}
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci		if (wait_event_interruptible_exclusive_locked_irq(ffs->ev.waitq,
55262306a36Sopenharmony_ci							ffs->ev.count)) {
55362306a36Sopenharmony_ci			ret = -EINTR;
55462306a36Sopenharmony_ci			break;
55562306a36Sopenharmony_ci		}
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci		/* unlocks spinlock */
55862306a36Sopenharmony_ci		return __ffs_ep0_read_events(ffs, buf,
55962306a36Sopenharmony_ci					     min(n, (size_t)ffs->ev.count));
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_ci	case FFS_SETUP_PENDING:
56262306a36Sopenharmony_ci		if (ffs->ev.setup.bRequestType & USB_DIR_IN) {
56362306a36Sopenharmony_ci			spin_unlock_irq(&ffs->ev.waitq.lock);
56462306a36Sopenharmony_ci			ret = __ffs_ep0_stall(ffs);
56562306a36Sopenharmony_ci			goto done_mutex;
56662306a36Sopenharmony_ci		}
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_ci		len = min(len, (size_t)le16_to_cpu(ffs->ev.setup.wLength));
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ci		spin_unlock_irq(&ffs->ev.waitq.lock);
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ci		if (len) {
57362306a36Sopenharmony_ci			data = kmalloc(len, GFP_KERNEL);
57462306a36Sopenharmony_ci			if (!data) {
57562306a36Sopenharmony_ci				ret = -ENOMEM;
57662306a36Sopenharmony_ci				goto done_mutex;
57762306a36Sopenharmony_ci			}
57862306a36Sopenharmony_ci		}
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci		spin_lock_irq(&ffs->ev.waitq.lock);
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci		/* See ffs_ep0_write() */
58362306a36Sopenharmony_ci		if (ffs_setup_state_clear_cancelled(ffs) ==
58462306a36Sopenharmony_ci		    FFS_SETUP_CANCELLED) {
58562306a36Sopenharmony_ci			ret = -EIDRM;
58662306a36Sopenharmony_ci			break;
58762306a36Sopenharmony_ci		}
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci		/* unlocks spinlock */
59062306a36Sopenharmony_ci		ret = __ffs_ep0_queue_wait(ffs, data, len);
59162306a36Sopenharmony_ci		if ((ret > 0) && (copy_to_user(buf, data, len)))
59262306a36Sopenharmony_ci			ret = -EFAULT;
59362306a36Sopenharmony_ci		goto done_mutex;
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_ci	default:
59662306a36Sopenharmony_ci		ret = -EBADFD;
59762306a36Sopenharmony_ci		break;
59862306a36Sopenharmony_ci	}
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	spin_unlock_irq(&ffs->ev.waitq.lock);
60162306a36Sopenharmony_cidone_mutex:
60262306a36Sopenharmony_ci	mutex_unlock(&ffs->mutex);
60362306a36Sopenharmony_ci	kfree(data);
60462306a36Sopenharmony_ci	return ret;
60562306a36Sopenharmony_ci}
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_cistatic int ffs_ep0_open(struct inode *inode, struct file *file)
60862306a36Sopenharmony_ci{
60962306a36Sopenharmony_ci	struct ffs_data *ffs = inode->i_private;
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_ci	if (ffs->state == FFS_CLOSING)
61262306a36Sopenharmony_ci		return -EBUSY;
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci	file->private_data = ffs;
61562306a36Sopenharmony_ci	ffs_data_opened(ffs);
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci	return stream_open(inode, file);
61862306a36Sopenharmony_ci}
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_cistatic int ffs_ep0_release(struct inode *inode, struct file *file)
62162306a36Sopenharmony_ci{
62262306a36Sopenharmony_ci	struct ffs_data *ffs = file->private_data;
62362306a36Sopenharmony_ci
62462306a36Sopenharmony_ci	ffs_data_closed(ffs);
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci	return 0;
62762306a36Sopenharmony_ci}
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_cistatic long ffs_ep0_ioctl(struct file *file, unsigned code, unsigned long value)
63062306a36Sopenharmony_ci{
63162306a36Sopenharmony_ci	struct ffs_data *ffs = file->private_data;
63262306a36Sopenharmony_ci	struct usb_gadget *gadget = ffs->gadget;
63362306a36Sopenharmony_ci	long ret;
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci	if (code == FUNCTIONFS_INTERFACE_REVMAP) {
63662306a36Sopenharmony_ci		struct ffs_function *func = ffs->func;
63762306a36Sopenharmony_ci		ret = func ? ffs_func_revmap_intf(func, value) : -ENODEV;
63862306a36Sopenharmony_ci	} else if (gadget && gadget->ops->ioctl) {
63962306a36Sopenharmony_ci		ret = gadget->ops->ioctl(gadget, code, value);
64062306a36Sopenharmony_ci	} else {
64162306a36Sopenharmony_ci		ret = -ENOTTY;
64262306a36Sopenharmony_ci	}
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	return ret;
64562306a36Sopenharmony_ci}
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_cistatic __poll_t ffs_ep0_poll(struct file *file, poll_table *wait)
64862306a36Sopenharmony_ci{
64962306a36Sopenharmony_ci	struct ffs_data *ffs = file->private_data;
65062306a36Sopenharmony_ci	__poll_t mask = EPOLLWRNORM;
65162306a36Sopenharmony_ci	int ret;
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_ci	poll_wait(file, &ffs->ev.waitq, wait);
65462306a36Sopenharmony_ci
65562306a36Sopenharmony_ci	ret = ffs_mutex_lock(&ffs->mutex, file->f_flags & O_NONBLOCK);
65662306a36Sopenharmony_ci	if (ret < 0)
65762306a36Sopenharmony_ci		return mask;
65862306a36Sopenharmony_ci
65962306a36Sopenharmony_ci	switch (ffs->state) {
66062306a36Sopenharmony_ci	case FFS_READ_DESCRIPTORS:
66162306a36Sopenharmony_ci	case FFS_READ_STRINGS:
66262306a36Sopenharmony_ci		mask |= EPOLLOUT;
66362306a36Sopenharmony_ci		break;
66462306a36Sopenharmony_ci
66562306a36Sopenharmony_ci	case FFS_ACTIVE:
66662306a36Sopenharmony_ci		switch (ffs->setup_state) {
66762306a36Sopenharmony_ci		case FFS_NO_SETUP:
66862306a36Sopenharmony_ci			if (ffs->ev.count)
66962306a36Sopenharmony_ci				mask |= EPOLLIN;
67062306a36Sopenharmony_ci			break;
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci		case FFS_SETUP_PENDING:
67362306a36Sopenharmony_ci		case FFS_SETUP_CANCELLED:
67462306a36Sopenharmony_ci			mask |= (EPOLLIN | EPOLLOUT);
67562306a36Sopenharmony_ci			break;
67662306a36Sopenharmony_ci		}
67762306a36Sopenharmony_ci		break;
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_ci	case FFS_CLOSING:
68062306a36Sopenharmony_ci		break;
68162306a36Sopenharmony_ci	case FFS_DEACTIVATED:
68262306a36Sopenharmony_ci		break;
68362306a36Sopenharmony_ci	}
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_ci	mutex_unlock(&ffs->mutex);
68662306a36Sopenharmony_ci
68762306a36Sopenharmony_ci	return mask;
68862306a36Sopenharmony_ci}
68962306a36Sopenharmony_ci
69062306a36Sopenharmony_cistatic const struct file_operations ffs_ep0_operations = {
69162306a36Sopenharmony_ci	.llseek =	no_llseek,
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci	.open =		ffs_ep0_open,
69462306a36Sopenharmony_ci	.write =	ffs_ep0_write,
69562306a36Sopenharmony_ci	.read =		ffs_ep0_read,
69662306a36Sopenharmony_ci	.release =	ffs_ep0_release,
69762306a36Sopenharmony_ci	.unlocked_ioctl =	ffs_ep0_ioctl,
69862306a36Sopenharmony_ci	.poll =		ffs_ep0_poll,
69962306a36Sopenharmony_ci};
70062306a36Sopenharmony_ci
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_ci/* "Normal" endpoints operations ********************************************/
70362306a36Sopenharmony_ci
70462306a36Sopenharmony_cistatic void ffs_epfile_io_complete(struct usb_ep *_ep, struct usb_request *req)
70562306a36Sopenharmony_ci{
70662306a36Sopenharmony_ci	struct ffs_io_data *io_data = req->context;
70762306a36Sopenharmony_ci
70862306a36Sopenharmony_ci	if (req->status)
70962306a36Sopenharmony_ci		io_data->status = req->status;
71062306a36Sopenharmony_ci	else
71162306a36Sopenharmony_ci		io_data->status = req->actual;
71262306a36Sopenharmony_ci
71362306a36Sopenharmony_ci	complete(&io_data->done);
71462306a36Sopenharmony_ci}
71562306a36Sopenharmony_ci
71662306a36Sopenharmony_cistatic ssize_t ffs_copy_to_iter(void *data, int data_len, struct iov_iter *iter)
71762306a36Sopenharmony_ci{
71862306a36Sopenharmony_ci	ssize_t ret = copy_to_iter(data, data_len, iter);
71962306a36Sopenharmony_ci	if (ret == data_len)
72062306a36Sopenharmony_ci		return ret;
72162306a36Sopenharmony_ci
72262306a36Sopenharmony_ci	if (iov_iter_count(iter))
72362306a36Sopenharmony_ci		return -EFAULT;
72462306a36Sopenharmony_ci
72562306a36Sopenharmony_ci	/*
72662306a36Sopenharmony_ci	 * Dear user space developer!
72762306a36Sopenharmony_ci	 *
72862306a36Sopenharmony_ci	 * TL;DR: To stop getting below error message in your kernel log, change
72962306a36Sopenharmony_ci	 * user space code using functionfs to align read buffers to a max
73062306a36Sopenharmony_ci	 * packet size.
73162306a36Sopenharmony_ci	 *
73262306a36Sopenharmony_ci	 * Some UDCs (e.g. dwc3) require request sizes to be a multiple of a max
73362306a36Sopenharmony_ci	 * packet size.  When unaligned buffer is passed to functionfs, it
73462306a36Sopenharmony_ci	 * internally uses a larger, aligned buffer so that such UDCs are happy.
73562306a36Sopenharmony_ci	 *
73662306a36Sopenharmony_ci	 * Unfortunately, this means that host may send more data than was
73762306a36Sopenharmony_ci	 * requested in read(2) system call.  f_fs doesn’t know what to do with
73862306a36Sopenharmony_ci	 * that excess data so it simply drops it.
73962306a36Sopenharmony_ci	 *
74062306a36Sopenharmony_ci	 * Was the buffer aligned in the first place, no such problem would
74162306a36Sopenharmony_ci	 * happen.
74262306a36Sopenharmony_ci	 *
74362306a36Sopenharmony_ci	 * Data may be dropped only in AIO reads.  Synchronous reads are handled
74462306a36Sopenharmony_ci	 * by splitting a request into multiple parts.  This splitting may still
74562306a36Sopenharmony_ci	 * be a problem though so it’s likely best to align the buffer
74662306a36Sopenharmony_ci	 * regardless of it being AIO or not..
74762306a36Sopenharmony_ci	 *
74862306a36Sopenharmony_ci	 * This only affects OUT endpoints, i.e. reading data with a read(2),
74962306a36Sopenharmony_ci	 * aio_read(2) etc. system calls.  Writing data to an IN endpoint is not
75062306a36Sopenharmony_ci	 * affected.
75162306a36Sopenharmony_ci	 */
75262306a36Sopenharmony_ci	pr_err("functionfs read size %d > requested size %zd, dropping excess data. "
75362306a36Sopenharmony_ci	       "Align read buffer size to max packet size to avoid the problem.\n",
75462306a36Sopenharmony_ci	       data_len, ret);
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_ci	return ret;
75762306a36Sopenharmony_ci}
75862306a36Sopenharmony_ci
75962306a36Sopenharmony_ci/*
76062306a36Sopenharmony_ci * allocate a virtually contiguous buffer and create a scatterlist describing it
76162306a36Sopenharmony_ci * @sg_table	- pointer to a place to be filled with sg_table contents
76262306a36Sopenharmony_ci * @size	- required buffer size
76362306a36Sopenharmony_ci */
76462306a36Sopenharmony_cistatic void *ffs_build_sg_list(struct sg_table *sgt, size_t sz)
76562306a36Sopenharmony_ci{
76662306a36Sopenharmony_ci	struct page **pages;
76762306a36Sopenharmony_ci	void *vaddr, *ptr;
76862306a36Sopenharmony_ci	unsigned int n_pages;
76962306a36Sopenharmony_ci	int i;
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ci	vaddr = vmalloc(sz);
77262306a36Sopenharmony_ci	if (!vaddr)
77362306a36Sopenharmony_ci		return NULL;
77462306a36Sopenharmony_ci
77562306a36Sopenharmony_ci	n_pages = PAGE_ALIGN(sz) >> PAGE_SHIFT;
77662306a36Sopenharmony_ci	pages = kvmalloc_array(n_pages, sizeof(struct page *), GFP_KERNEL);
77762306a36Sopenharmony_ci	if (!pages) {
77862306a36Sopenharmony_ci		vfree(vaddr);
77962306a36Sopenharmony_ci
78062306a36Sopenharmony_ci		return NULL;
78162306a36Sopenharmony_ci	}
78262306a36Sopenharmony_ci	for (i = 0, ptr = vaddr; i < n_pages; ++i, ptr += PAGE_SIZE)
78362306a36Sopenharmony_ci		pages[i] = vmalloc_to_page(ptr);
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_ci	if (sg_alloc_table_from_pages(sgt, pages, n_pages, 0, sz, GFP_KERNEL)) {
78662306a36Sopenharmony_ci		kvfree(pages);
78762306a36Sopenharmony_ci		vfree(vaddr);
78862306a36Sopenharmony_ci
78962306a36Sopenharmony_ci		return NULL;
79062306a36Sopenharmony_ci	}
79162306a36Sopenharmony_ci	kvfree(pages);
79262306a36Sopenharmony_ci
79362306a36Sopenharmony_ci	return vaddr;
79462306a36Sopenharmony_ci}
79562306a36Sopenharmony_ci
79662306a36Sopenharmony_cistatic inline void *ffs_alloc_buffer(struct ffs_io_data *io_data,
79762306a36Sopenharmony_ci	size_t data_len)
79862306a36Sopenharmony_ci{
79962306a36Sopenharmony_ci	if (io_data->use_sg)
80062306a36Sopenharmony_ci		return ffs_build_sg_list(&io_data->sgt, data_len);
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_ci	return kmalloc(data_len, GFP_KERNEL);
80362306a36Sopenharmony_ci}
80462306a36Sopenharmony_ci
80562306a36Sopenharmony_cistatic inline void ffs_free_buffer(struct ffs_io_data *io_data)
80662306a36Sopenharmony_ci{
80762306a36Sopenharmony_ci	if (!io_data->buf)
80862306a36Sopenharmony_ci		return;
80962306a36Sopenharmony_ci
81062306a36Sopenharmony_ci	if (io_data->use_sg) {
81162306a36Sopenharmony_ci		sg_free_table(&io_data->sgt);
81262306a36Sopenharmony_ci		vfree(io_data->buf);
81362306a36Sopenharmony_ci	} else {
81462306a36Sopenharmony_ci		kfree(io_data->buf);
81562306a36Sopenharmony_ci	}
81662306a36Sopenharmony_ci}
81762306a36Sopenharmony_ci
81862306a36Sopenharmony_cistatic void ffs_user_copy_worker(struct work_struct *work)
81962306a36Sopenharmony_ci{
82062306a36Sopenharmony_ci	struct ffs_io_data *io_data = container_of(work, struct ffs_io_data,
82162306a36Sopenharmony_ci						   work);
82262306a36Sopenharmony_ci	int ret = io_data->status;
82362306a36Sopenharmony_ci	bool kiocb_has_eventfd = io_data->kiocb->ki_flags & IOCB_EVENTFD;
82462306a36Sopenharmony_ci
82562306a36Sopenharmony_ci	if (io_data->read && ret > 0) {
82662306a36Sopenharmony_ci		kthread_use_mm(io_data->mm);
82762306a36Sopenharmony_ci		ret = ffs_copy_to_iter(io_data->buf, ret, &io_data->data);
82862306a36Sopenharmony_ci		kthread_unuse_mm(io_data->mm);
82962306a36Sopenharmony_ci	}
83062306a36Sopenharmony_ci
83162306a36Sopenharmony_ci	io_data->kiocb->ki_complete(io_data->kiocb, ret);
83262306a36Sopenharmony_ci
83362306a36Sopenharmony_ci	if (io_data->ffs->ffs_eventfd && !kiocb_has_eventfd)
83462306a36Sopenharmony_ci		eventfd_signal(io_data->ffs->ffs_eventfd, 1);
83562306a36Sopenharmony_ci
83662306a36Sopenharmony_ci	if (io_data->read)
83762306a36Sopenharmony_ci		kfree(io_data->to_free);
83862306a36Sopenharmony_ci	ffs_free_buffer(io_data);
83962306a36Sopenharmony_ci	kfree(io_data);
84062306a36Sopenharmony_ci}
84162306a36Sopenharmony_ci
84262306a36Sopenharmony_cistatic void ffs_epfile_async_io_complete(struct usb_ep *_ep,
84362306a36Sopenharmony_ci					 struct usb_request *req)
84462306a36Sopenharmony_ci{
84562306a36Sopenharmony_ci	struct ffs_io_data *io_data = req->context;
84662306a36Sopenharmony_ci	struct ffs_data *ffs = io_data->ffs;
84762306a36Sopenharmony_ci
84862306a36Sopenharmony_ci	io_data->status = req->status ? req->status : req->actual;
84962306a36Sopenharmony_ci	usb_ep_free_request(_ep, req);
85062306a36Sopenharmony_ci
85162306a36Sopenharmony_ci	INIT_WORK(&io_data->work, ffs_user_copy_worker);
85262306a36Sopenharmony_ci	queue_work(ffs->io_completion_wq, &io_data->work);
85362306a36Sopenharmony_ci}
85462306a36Sopenharmony_ci
85562306a36Sopenharmony_cistatic void __ffs_epfile_read_buffer_free(struct ffs_epfile *epfile)
85662306a36Sopenharmony_ci{
85762306a36Sopenharmony_ci	/*
85862306a36Sopenharmony_ci	 * See comment in struct ffs_epfile for full read_buffer pointer
85962306a36Sopenharmony_ci	 * synchronisation story.
86062306a36Sopenharmony_ci	 */
86162306a36Sopenharmony_ci	struct ffs_buffer *buf = xchg(&epfile->read_buffer, READ_BUFFER_DROP);
86262306a36Sopenharmony_ci	if (buf && buf != READ_BUFFER_DROP)
86362306a36Sopenharmony_ci		kfree(buf);
86462306a36Sopenharmony_ci}
86562306a36Sopenharmony_ci
86662306a36Sopenharmony_ci/* Assumes epfile->mutex is held. */
86762306a36Sopenharmony_cistatic ssize_t __ffs_epfile_read_buffered(struct ffs_epfile *epfile,
86862306a36Sopenharmony_ci					  struct iov_iter *iter)
86962306a36Sopenharmony_ci{
87062306a36Sopenharmony_ci	/*
87162306a36Sopenharmony_ci	 * Null out epfile->read_buffer so ffs_func_eps_disable does not free
87262306a36Sopenharmony_ci	 * the buffer while we are using it.  See comment in struct ffs_epfile
87362306a36Sopenharmony_ci	 * for full read_buffer pointer synchronisation story.
87462306a36Sopenharmony_ci	 */
87562306a36Sopenharmony_ci	struct ffs_buffer *buf = xchg(&epfile->read_buffer, NULL);
87662306a36Sopenharmony_ci	ssize_t ret;
87762306a36Sopenharmony_ci	if (!buf || buf == READ_BUFFER_DROP)
87862306a36Sopenharmony_ci		return 0;
87962306a36Sopenharmony_ci
88062306a36Sopenharmony_ci	ret = copy_to_iter(buf->data, buf->length, iter);
88162306a36Sopenharmony_ci	if (buf->length == ret) {
88262306a36Sopenharmony_ci		kfree(buf);
88362306a36Sopenharmony_ci		return ret;
88462306a36Sopenharmony_ci	}
88562306a36Sopenharmony_ci
88662306a36Sopenharmony_ci	if (iov_iter_count(iter)) {
88762306a36Sopenharmony_ci		ret = -EFAULT;
88862306a36Sopenharmony_ci	} else {
88962306a36Sopenharmony_ci		buf->length -= ret;
89062306a36Sopenharmony_ci		buf->data += ret;
89162306a36Sopenharmony_ci	}
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_ci	if (cmpxchg(&epfile->read_buffer, NULL, buf))
89462306a36Sopenharmony_ci		kfree(buf);
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_ci	return ret;
89762306a36Sopenharmony_ci}
89862306a36Sopenharmony_ci
89962306a36Sopenharmony_ci/* Assumes epfile->mutex is held. */
90062306a36Sopenharmony_cistatic ssize_t __ffs_epfile_read_data(struct ffs_epfile *epfile,
90162306a36Sopenharmony_ci				      void *data, int data_len,
90262306a36Sopenharmony_ci				      struct iov_iter *iter)
90362306a36Sopenharmony_ci{
90462306a36Sopenharmony_ci	struct ffs_buffer *buf;
90562306a36Sopenharmony_ci
90662306a36Sopenharmony_ci	ssize_t ret = copy_to_iter(data, data_len, iter);
90762306a36Sopenharmony_ci	if (data_len == ret)
90862306a36Sopenharmony_ci		return ret;
90962306a36Sopenharmony_ci
91062306a36Sopenharmony_ci	if (iov_iter_count(iter))
91162306a36Sopenharmony_ci		return -EFAULT;
91262306a36Sopenharmony_ci
91362306a36Sopenharmony_ci	/* See ffs_copy_to_iter for more context. */
91462306a36Sopenharmony_ci	pr_warn("functionfs read size %d > requested size %zd, splitting request into multiple reads.",
91562306a36Sopenharmony_ci		data_len, ret);
91662306a36Sopenharmony_ci
91762306a36Sopenharmony_ci	data_len -= ret;
91862306a36Sopenharmony_ci	buf = kmalloc(struct_size(buf, storage, data_len), GFP_KERNEL);
91962306a36Sopenharmony_ci	if (!buf)
92062306a36Sopenharmony_ci		return -ENOMEM;
92162306a36Sopenharmony_ci	buf->length = data_len;
92262306a36Sopenharmony_ci	buf->data = buf->storage;
92362306a36Sopenharmony_ci	memcpy(buf->storage, data + ret, flex_array_size(buf, storage, data_len));
92462306a36Sopenharmony_ci
92562306a36Sopenharmony_ci	/*
92662306a36Sopenharmony_ci	 * At this point read_buffer is NULL or READ_BUFFER_DROP (if
92762306a36Sopenharmony_ci	 * ffs_func_eps_disable has been called in the meanwhile).  See comment
92862306a36Sopenharmony_ci	 * in struct ffs_epfile for full read_buffer pointer synchronisation
92962306a36Sopenharmony_ci	 * story.
93062306a36Sopenharmony_ci	 */
93162306a36Sopenharmony_ci	if (cmpxchg(&epfile->read_buffer, NULL, buf))
93262306a36Sopenharmony_ci		kfree(buf);
93362306a36Sopenharmony_ci
93462306a36Sopenharmony_ci	return ret;
93562306a36Sopenharmony_ci}
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_cistatic ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
93862306a36Sopenharmony_ci{
93962306a36Sopenharmony_ci	struct ffs_epfile *epfile = file->private_data;
94062306a36Sopenharmony_ci	struct usb_request *req;
94162306a36Sopenharmony_ci	struct ffs_ep *ep;
94262306a36Sopenharmony_ci	char *data = NULL;
94362306a36Sopenharmony_ci	ssize_t ret, data_len = -EINVAL;
94462306a36Sopenharmony_ci	int halt;
94562306a36Sopenharmony_ci
94662306a36Sopenharmony_ci	/* Are we still active? */
94762306a36Sopenharmony_ci	if (WARN_ON(epfile->ffs->state != FFS_ACTIVE))
94862306a36Sopenharmony_ci		return -ENODEV;
94962306a36Sopenharmony_ci
95062306a36Sopenharmony_ci	/* Wait for endpoint to be enabled */
95162306a36Sopenharmony_ci	ep = epfile->ep;
95262306a36Sopenharmony_ci	if (!ep) {
95362306a36Sopenharmony_ci		if (file->f_flags & O_NONBLOCK)
95462306a36Sopenharmony_ci			return -EAGAIN;
95562306a36Sopenharmony_ci
95662306a36Sopenharmony_ci		ret = wait_event_interruptible(
95762306a36Sopenharmony_ci				epfile->ffs->wait, (ep = epfile->ep));
95862306a36Sopenharmony_ci		if (ret)
95962306a36Sopenharmony_ci			return -EINTR;
96062306a36Sopenharmony_ci	}
96162306a36Sopenharmony_ci
96262306a36Sopenharmony_ci	/* Do we halt? */
96362306a36Sopenharmony_ci	halt = (!io_data->read == !epfile->in);
96462306a36Sopenharmony_ci	if (halt && epfile->isoc)
96562306a36Sopenharmony_ci		return -EINVAL;
96662306a36Sopenharmony_ci
96762306a36Sopenharmony_ci	/* We will be using request and read_buffer */
96862306a36Sopenharmony_ci	ret = ffs_mutex_lock(&epfile->mutex, file->f_flags & O_NONBLOCK);
96962306a36Sopenharmony_ci	if (ret)
97062306a36Sopenharmony_ci		goto error;
97162306a36Sopenharmony_ci
97262306a36Sopenharmony_ci	/* Allocate & copy */
97362306a36Sopenharmony_ci	if (!halt) {
97462306a36Sopenharmony_ci		struct usb_gadget *gadget;
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_ci		/*
97762306a36Sopenharmony_ci		 * Do we have buffered data from previous partial read?  Check
97862306a36Sopenharmony_ci		 * that for synchronous case only because we do not have
97962306a36Sopenharmony_ci		 * facility to ‘wake up’ a pending asynchronous read and push
98062306a36Sopenharmony_ci		 * buffered data to it which we would need to make things behave
98162306a36Sopenharmony_ci		 * consistently.
98262306a36Sopenharmony_ci		 */
98362306a36Sopenharmony_ci		if (!io_data->aio && io_data->read) {
98462306a36Sopenharmony_ci			ret = __ffs_epfile_read_buffered(epfile, &io_data->data);
98562306a36Sopenharmony_ci			if (ret)
98662306a36Sopenharmony_ci				goto error_mutex;
98762306a36Sopenharmony_ci		}
98862306a36Sopenharmony_ci
98962306a36Sopenharmony_ci		/*
99062306a36Sopenharmony_ci		 * if we _do_ wait above, the epfile->ffs->gadget might be NULL
99162306a36Sopenharmony_ci		 * before the waiting completes, so do not assign to 'gadget'
99262306a36Sopenharmony_ci		 * earlier
99362306a36Sopenharmony_ci		 */
99462306a36Sopenharmony_ci		gadget = epfile->ffs->gadget;
99562306a36Sopenharmony_ci
99662306a36Sopenharmony_ci		spin_lock_irq(&epfile->ffs->eps_lock);
99762306a36Sopenharmony_ci		/* In the meantime, endpoint got disabled or changed. */
99862306a36Sopenharmony_ci		if (epfile->ep != ep) {
99962306a36Sopenharmony_ci			ret = -ESHUTDOWN;
100062306a36Sopenharmony_ci			goto error_lock;
100162306a36Sopenharmony_ci		}
100262306a36Sopenharmony_ci		data_len = iov_iter_count(&io_data->data);
100362306a36Sopenharmony_ci		/*
100462306a36Sopenharmony_ci		 * Controller may require buffer size to be aligned to
100562306a36Sopenharmony_ci		 * maxpacketsize of an out endpoint.
100662306a36Sopenharmony_ci		 */
100762306a36Sopenharmony_ci		if (io_data->read)
100862306a36Sopenharmony_ci			data_len = usb_ep_align_maybe(gadget, ep->ep, data_len);
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ci		io_data->use_sg = gadget->sg_supported && data_len > PAGE_SIZE;
101162306a36Sopenharmony_ci		spin_unlock_irq(&epfile->ffs->eps_lock);
101262306a36Sopenharmony_ci
101362306a36Sopenharmony_ci		data = ffs_alloc_buffer(io_data, data_len);
101462306a36Sopenharmony_ci		if (!data) {
101562306a36Sopenharmony_ci			ret = -ENOMEM;
101662306a36Sopenharmony_ci			goto error_mutex;
101762306a36Sopenharmony_ci		}
101862306a36Sopenharmony_ci		if (!io_data->read &&
101962306a36Sopenharmony_ci		    !copy_from_iter_full(data, data_len, &io_data->data)) {
102062306a36Sopenharmony_ci			ret = -EFAULT;
102162306a36Sopenharmony_ci			goto error_mutex;
102262306a36Sopenharmony_ci		}
102362306a36Sopenharmony_ci	}
102462306a36Sopenharmony_ci
102562306a36Sopenharmony_ci	spin_lock_irq(&epfile->ffs->eps_lock);
102662306a36Sopenharmony_ci
102762306a36Sopenharmony_ci	if (epfile->ep != ep) {
102862306a36Sopenharmony_ci		/* In the meantime, endpoint got disabled or changed. */
102962306a36Sopenharmony_ci		ret = -ESHUTDOWN;
103062306a36Sopenharmony_ci	} else if (halt) {
103162306a36Sopenharmony_ci		ret = usb_ep_set_halt(ep->ep);
103262306a36Sopenharmony_ci		if (!ret)
103362306a36Sopenharmony_ci			ret = -EBADMSG;
103462306a36Sopenharmony_ci	} else if (data_len == -EINVAL) {
103562306a36Sopenharmony_ci		/*
103662306a36Sopenharmony_ci		 * Sanity Check: even though data_len can't be used
103762306a36Sopenharmony_ci		 * uninitialized at the time I write this comment, some
103862306a36Sopenharmony_ci		 * compilers complain about this situation.
103962306a36Sopenharmony_ci		 * In order to keep the code clean from warnings, data_len is
104062306a36Sopenharmony_ci		 * being initialized to -EINVAL during its declaration, which
104162306a36Sopenharmony_ci		 * means we can't rely on compiler anymore to warn no future
104262306a36Sopenharmony_ci		 * changes won't result in data_len being used uninitialized.
104362306a36Sopenharmony_ci		 * For such reason, we're adding this redundant sanity check
104462306a36Sopenharmony_ci		 * here.
104562306a36Sopenharmony_ci		 */
104662306a36Sopenharmony_ci		WARN(1, "%s: data_len == -EINVAL\n", __func__);
104762306a36Sopenharmony_ci		ret = -EINVAL;
104862306a36Sopenharmony_ci	} else if (!io_data->aio) {
104962306a36Sopenharmony_ci		bool interrupted = false;
105062306a36Sopenharmony_ci
105162306a36Sopenharmony_ci		req = ep->req;
105262306a36Sopenharmony_ci		if (io_data->use_sg) {
105362306a36Sopenharmony_ci			req->buf = NULL;
105462306a36Sopenharmony_ci			req->sg	= io_data->sgt.sgl;
105562306a36Sopenharmony_ci			req->num_sgs = io_data->sgt.nents;
105662306a36Sopenharmony_ci		} else {
105762306a36Sopenharmony_ci			req->buf = data;
105862306a36Sopenharmony_ci			req->num_sgs = 0;
105962306a36Sopenharmony_ci		}
106062306a36Sopenharmony_ci		req->length = data_len;
106162306a36Sopenharmony_ci
106262306a36Sopenharmony_ci		io_data->buf = data;
106362306a36Sopenharmony_ci
106462306a36Sopenharmony_ci		init_completion(&io_data->done);
106562306a36Sopenharmony_ci		req->context  = io_data;
106662306a36Sopenharmony_ci		req->complete = ffs_epfile_io_complete;
106762306a36Sopenharmony_ci
106862306a36Sopenharmony_ci		ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC);
106962306a36Sopenharmony_ci		if (ret < 0)
107062306a36Sopenharmony_ci			goto error_lock;
107162306a36Sopenharmony_ci
107262306a36Sopenharmony_ci		spin_unlock_irq(&epfile->ffs->eps_lock);
107362306a36Sopenharmony_ci
107462306a36Sopenharmony_ci		if (wait_for_completion_interruptible(&io_data->done)) {
107562306a36Sopenharmony_ci			spin_lock_irq(&epfile->ffs->eps_lock);
107662306a36Sopenharmony_ci			if (epfile->ep != ep) {
107762306a36Sopenharmony_ci				ret = -ESHUTDOWN;
107862306a36Sopenharmony_ci				goto error_lock;
107962306a36Sopenharmony_ci			}
108062306a36Sopenharmony_ci			/*
108162306a36Sopenharmony_ci			 * To avoid race condition with ffs_epfile_io_complete,
108262306a36Sopenharmony_ci			 * dequeue the request first then check
108362306a36Sopenharmony_ci			 * status. usb_ep_dequeue API should guarantee no race
108462306a36Sopenharmony_ci			 * condition with req->complete callback.
108562306a36Sopenharmony_ci			 */
108662306a36Sopenharmony_ci			usb_ep_dequeue(ep->ep, req);
108762306a36Sopenharmony_ci			spin_unlock_irq(&epfile->ffs->eps_lock);
108862306a36Sopenharmony_ci			wait_for_completion(&io_data->done);
108962306a36Sopenharmony_ci			interrupted = io_data->status < 0;
109062306a36Sopenharmony_ci		}
109162306a36Sopenharmony_ci
109262306a36Sopenharmony_ci		if (interrupted)
109362306a36Sopenharmony_ci			ret = -EINTR;
109462306a36Sopenharmony_ci		else if (io_data->read && io_data->status > 0)
109562306a36Sopenharmony_ci			ret = __ffs_epfile_read_data(epfile, data, io_data->status,
109662306a36Sopenharmony_ci						     &io_data->data);
109762306a36Sopenharmony_ci		else
109862306a36Sopenharmony_ci			ret = io_data->status;
109962306a36Sopenharmony_ci		goto error_mutex;
110062306a36Sopenharmony_ci	} else if (!(req = usb_ep_alloc_request(ep->ep, GFP_ATOMIC))) {
110162306a36Sopenharmony_ci		ret = -ENOMEM;
110262306a36Sopenharmony_ci	} else {
110362306a36Sopenharmony_ci		if (io_data->use_sg) {
110462306a36Sopenharmony_ci			req->buf = NULL;
110562306a36Sopenharmony_ci			req->sg	= io_data->sgt.sgl;
110662306a36Sopenharmony_ci			req->num_sgs = io_data->sgt.nents;
110762306a36Sopenharmony_ci		} else {
110862306a36Sopenharmony_ci			req->buf = data;
110962306a36Sopenharmony_ci			req->num_sgs = 0;
111062306a36Sopenharmony_ci		}
111162306a36Sopenharmony_ci		req->length = data_len;
111262306a36Sopenharmony_ci
111362306a36Sopenharmony_ci		io_data->buf = data;
111462306a36Sopenharmony_ci		io_data->ep = ep->ep;
111562306a36Sopenharmony_ci		io_data->req = req;
111662306a36Sopenharmony_ci		io_data->ffs = epfile->ffs;
111762306a36Sopenharmony_ci
111862306a36Sopenharmony_ci		req->context  = io_data;
111962306a36Sopenharmony_ci		req->complete = ffs_epfile_async_io_complete;
112062306a36Sopenharmony_ci
112162306a36Sopenharmony_ci		ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC);
112262306a36Sopenharmony_ci		if (ret) {
112362306a36Sopenharmony_ci			io_data->req = NULL;
112462306a36Sopenharmony_ci			usb_ep_free_request(ep->ep, req);
112562306a36Sopenharmony_ci			goto error_lock;
112662306a36Sopenharmony_ci		}
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_ci		ret = -EIOCBQUEUED;
112962306a36Sopenharmony_ci		/*
113062306a36Sopenharmony_ci		 * Do not kfree the buffer in this function.  It will be freed
113162306a36Sopenharmony_ci		 * by ffs_user_copy_worker.
113262306a36Sopenharmony_ci		 */
113362306a36Sopenharmony_ci		data = NULL;
113462306a36Sopenharmony_ci	}
113562306a36Sopenharmony_ci
113662306a36Sopenharmony_cierror_lock:
113762306a36Sopenharmony_ci	spin_unlock_irq(&epfile->ffs->eps_lock);
113862306a36Sopenharmony_cierror_mutex:
113962306a36Sopenharmony_ci	mutex_unlock(&epfile->mutex);
114062306a36Sopenharmony_cierror:
114162306a36Sopenharmony_ci	if (ret != -EIOCBQUEUED) /* don't free if there is iocb queued */
114262306a36Sopenharmony_ci		ffs_free_buffer(io_data);
114362306a36Sopenharmony_ci	return ret;
114462306a36Sopenharmony_ci}
114562306a36Sopenharmony_ci
114662306a36Sopenharmony_cistatic int
114762306a36Sopenharmony_ciffs_epfile_open(struct inode *inode, struct file *file)
114862306a36Sopenharmony_ci{
114962306a36Sopenharmony_ci	struct ffs_epfile *epfile = inode->i_private;
115062306a36Sopenharmony_ci
115162306a36Sopenharmony_ci	if (WARN_ON(epfile->ffs->state != FFS_ACTIVE))
115262306a36Sopenharmony_ci		return -ENODEV;
115362306a36Sopenharmony_ci
115462306a36Sopenharmony_ci	file->private_data = epfile;
115562306a36Sopenharmony_ci	ffs_data_opened(epfile->ffs);
115662306a36Sopenharmony_ci
115762306a36Sopenharmony_ci	return stream_open(inode, file);
115862306a36Sopenharmony_ci}
115962306a36Sopenharmony_ci
116062306a36Sopenharmony_cistatic int ffs_aio_cancel(struct kiocb *kiocb)
116162306a36Sopenharmony_ci{
116262306a36Sopenharmony_ci	struct ffs_io_data *io_data = kiocb->private;
116362306a36Sopenharmony_ci	struct ffs_epfile *epfile = kiocb->ki_filp->private_data;
116462306a36Sopenharmony_ci	unsigned long flags;
116562306a36Sopenharmony_ci	int value;
116662306a36Sopenharmony_ci
116762306a36Sopenharmony_ci	spin_lock_irqsave(&epfile->ffs->eps_lock, flags);
116862306a36Sopenharmony_ci
116962306a36Sopenharmony_ci	if (io_data && io_data->ep && io_data->req)
117062306a36Sopenharmony_ci		value = usb_ep_dequeue(io_data->ep, io_data->req);
117162306a36Sopenharmony_ci	else
117262306a36Sopenharmony_ci		value = -EINVAL;
117362306a36Sopenharmony_ci
117462306a36Sopenharmony_ci	spin_unlock_irqrestore(&epfile->ffs->eps_lock, flags);
117562306a36Sopenharmony_ci
117662306a36Sopenharmony_ci	return value;
117762306a36Sopenharmony_ci}
117862306a36Sopenharmony_ci
117962306a36Sopenharmony_cistatic ssize_t ffs_epfile_write_iter(struct kiocb *kiocb, struct iov_iter *from)
118062306a36Sopenharmony_ci{
118162306a36Sopenharmony_ci	struct ffs_io_data io_data, *p = &io_data;
118262306a36Sopenharmony_ci	ssize_t res;
118362306a36Sopenharmony_ci
118462306a36Sopenharmony_ci	if (!is_sync_kiocb(kiocb)) {
118562306a36Sopenharmony_ci		p = kzalloc(sizeof(io_data), GFP_KERNEL);
118662306a36Sopenharmony_ci		if (!p)
118762306a36Sopenharmony_ci			return -ENOMEM;
118862306a36Sopenharmony_ci		p->aio = true;
118962306a36Sopenharmony_ci	} else {
119062306a36Sopenharmony_ci		memset(p, 0, sizeof(*p));
119162306a36Sopenharmony_ci		p->aio = false;
119262306a36Sopenharmony_ci	}
119362306a36Sopenharmony_ci
119462306a36Sopenharmony_ci	p->read = false;
119562306a36Sopenharmony_ci	p->kiocb = kiocb;
119662306a36Sopenharmony_ci	p->data = *from;
119762306a36Sopenharmony_ci	p->mm = current->mm;
119862306a36Sopenharmony_ci
119962306a36Sopenharmony_ci	kiocb->private = p;
120062306a36Sopenharmony_ci
120162306a36Sopenharmony_ci	if (p->aio)
120262306a36Sopenharmony_ci		kiocb_set_cancel_fn(kiocb, ffs_aio_cancel);
120362306a36Sopenharmony_ci
120462306a36Sopenharmony_ci	res = ffs_epfile_io(kiocb->ki_filp, p);
120562306a36Sopenharmony_ci	if (res == -EIOCBQUEUED)
120662306a36Sopenharmony_ci		return res;
120762306a36Sopenharmony_ci	if (p->aio)
120862306a36Sopenharmony_ci		kfree(p);
120962306a36Sopenharmony_ci	else
121062306a36Sopenharmony_ci		*from = p->data;
121162306a36Sopenharmony_ci	return res;
121262306a36Sopenharmony_ci}
121362306a36Sopenharmony_ci
121462306a36Sopenharmony_cistatic ssize_t ffs_epfile_read_iter(struct kiocb *kiocb, struct iov_iter *to)
121562306a36Sopenharmony_ci{
121662306a36Sopenharmony_ci	struct ffs_io_data io_data, *p = &io_data;
121762306a36Sopenharmony_ci	ssize_t res;
121862306a36Sopenharmony_ci
121962306a36Sopenharmony_ci	if (!is_sync_kiocb(kiocb)) {
122062306a36Sopenharmony_ci		p = kzalloc(sizeof(io_data), GFP_KERNEL);
122162306a36Sopenharmony_ci		if (!p)
122262306a36Sopenharmony_ci			return -ENOMEM;
122362306a36Sopenharmony_ci		p->aio = true;
122462306a36Sopenharmony_ci	} else {
122562306a36Sopenharmony_ci		memset(p, 0, sizeof(*p));
122662306a36Sopenharmony_ci		p->aio = false;
122762306a36Sopenharmony_ci	}
122862306a36Sopenharmony_ci
122962306a36Sopenharmony_ci	p->read = true;
123062306a36Sopenharmony_ci	p->kiocb = kiocb;
123162306a36Sopenharmony_ci	if (p->aio) {
123262306a36Sopenharmony_ci		p->to_free = dup_iter(&p->data, to, GFP_KERNEL);
123362306a36Sopenharmony_ci		if (!iter_is_ubuf(&p->data) && !p->to_free) {
123462306a36Sopenharmony_ci			kfree(p);
123562306a36Sopenharmony_ci			return -ENOMEM;
123662306a36Sopenharmony_ci		}
123762306a36Sopenharmony_ci	} else {
123862306a36Sopenharmony_ci		p->data = *to;
123962306a36Sopenharmony_ci		p->to_free = NULL;
124062306a36Sopenharmony_ci	}
124162306a36Sopenharmony_ci	p->mm = current->mm;
124262306a36Sopenharmony_ci
124362306a36Sopenharmony_ci	kiocb->private = p;
124462306a36Sopenharmony_ci
124562306a36Sopenharmony_ci	if (p->aio)
124662306a36Sopenharmony_ci		kiocb_set_cancel_fn(kiocb, ffs_aio_cancel);
124762306a36Sopenharmony_ci
124862306a36Sopenharmony_ci	res = ffs_epfile_io(kiocb->ki_filp, p);
124962306a36Sopenharmony_ci	if (res == -EIOCBQUEUED)
125062306a36Sopenharmony_ci		return res;
125162306a36Sopenharmony_ci
125262306a36Sopenharmony_ci	if (p->aio) {
125362306a36Sopenharmony_ci		kfree(p->to_free);
125462306a36Sopenharmony_ci		kfree(p);
125562306a36Sopenharmony_ci	} else {
125662306a36Sopenharmony_ci		*to = p->data;
125762306a36Sopenharmony_ci	}
125862306a36Sopenharmony_ci	return res;
125962306a36Sopenharmony_ci}
126062306a36Sopenharmony_ci
126162306a36Sopenharmony_cistatic int
126262306a36Sopenharmony_ciffs_epfile_release(struct inode *inode, struct file *file)
126362306a36Sopenharmony_ci{
126462306a36Sopenharmony_ci	struct ffs_epfile *epfile = inode->i_private;
126562306a36Sopenharmony_ci
126662306a36Sopenharmony_ci	__ffs_epfile_read_buffer_free(epfile);
126762306a36Sopenharmony_ci	ffs_data_closed(epfile->ffs);
126862306a36Sopenharmony_ci
126962306a36Sopenharmony_ci	return 0;
127062306a36Sopenharmony_ci}
127162306a36Sopenharmony_ci
127262306a36Sopenharmony_cistatic long ffs_epfile_ioctl(struct file *file, unsigned code,
127362306a36Sopenharmony_ci			     unsigned long value)
127462306a36Sopenharmony_ci{
127562306a36Sopenharmony_ci	struct ffs_epfile *epfile = file->private_data;
127662306a36Sopenharmony_ci	struct ffs_ep *ep;
127762306a36Sopenharmony_ci	int ret;
127862306a36Sopenharmony_ci
127962306a36Sopenharmony_ci	if (WARN_ON(epfile->ffs->state != FFS_ACTIVE))
128062306a36Sopenharmony_ci		return -ENODEV;
128162306a36Sopenharmony_ci
128262306a36Sopenharmony_ci	/* Wait for endpoint to be enabled */
128362306a36Sopenharmony_ci	ep = epfile->ep;
128462306a36Sopenharmony_ci	if (!ep) {
128562306a36Sopenharmony_ci		if (file->f_flags & O_NONBLOCK)
128662306a36Sopenharmony_ci			return -EAGAIN;
128762306a36Sopenharmony_ci
128862306a36Sopenharmony_ci		ret = wait_event_interruptible(
128962306a36Sopenharmony_ci				epfile->ffs->wait, (ep = epfile->ep));
129062306a36Sopenharmony_ci		if (ret)
129162306a36Sopenharmony_ci			return -EINTR;
129262306a36Sopenharmony_ci	}
129362306a36Sopenharmony_ci
129462306a36Sopenharmony_ci	spin_lock_irq(&epfile->ffs->eps_lock);
129562306a36Sopenharmony_ci
129662306a36Sopenharmony_ci	/* In the meantime, endpoint got disabled or changed. */
129762306a36Sopenharmony_ci	if (epfile->ep != ep) {
129862306a36Sopenharmony_ci		spin_unlock_irq(&epfile->ffs->eps_lock);
129962306a36Sopenharmony_ci		return -ESHUTDOWN;
130062306a36Sopenharmony_ci	}
130162306a36Sopenharmony_ci
130262306a36Sopenharmony_ci	switch (code) {
130362306a36Sopenharmony_ci	case FUNCTIONFS_FIFO_STATUS:
130462306a36Sopenharmony_ci		ret = usb_ep_fifo_status(epfile->ep->ep);
130562306a36Sopenharmony_ci		break;
130662306a36Sopenharmony_ci	case FUNCTIONFS_FIFO_FLUSH:
130762306a36Sopenharmony_ci		usb_ep_fifo_flush(epfile->ep->ep);
130862306a36Sopenharmony_ci		ret = 0;
130962306a36Sopenharmony_ci		break;
131062306a36Sopenharmony_ci	case FUNCTIONFS_CLEAR_HALT:
131162306a36Sopenharmony_ci		ret = usb_ep_clear_halt(epfile->ep->ep);
131262306a36Sopenharmony_ci		break;
131362306a36Sopenharmony_ci	case FUNCTIONFS_ENDPOINT_REVMAP:
131462306a36Sopenharmony_ci		ret = epfile->ep->num;
131562306a36Sopenharmony_ci		break;
131662306a36Sopenharmony_ci	case FUNCTIONFS_ENDPOINT_DESC:
131762306a36Sopenharmony_ci	{
131862306a36Sopenharmony_ci		int desc_idx;
131962306a36Sopenharmony_ci		struct usb_endpoint_descriptor desc1, *desc;
132062306a36Sopenharmony_ci
132162306a36Sopenharmony_ci		switch (epfile->ffs->gadget->speed) {
132262306a36Sopenharmony_ci		case USB_SPEED_SUPER:
132362306a36Sopenharmony_ci		case USB_SPEED_SUPER_PLUS:
132462306a36Sopenharmony_ci			desc_idx = 2;
132562306a36Sopenharmony_ci			break;
132662306a36Sopenharmony_ci		case USB_SPEED_HIGH:
132762306a36Sopenharmony_ci			desc_idx = 1;
132862306a36Sopenharmony_ci			break;
132962306a36Sopenharmony_ci		default:
133062306a36Sopenharmony_ci			desc_idx = 0;
133162306a36Sopenharmony_ci		}
133262306a36Sopenharmony_ci
133362306a36Sopenharmony_ci		desc = epfile->ep->descs[desc_idx];
133462306a36Sopenharmony_ci		memcpy(&desc1, desc, desc->bLength);
133562306a36Sopenharmony_ci
133662306a36Sopenharmony_ci		spin_unlock_irq(&epfile->ffs->eps_lock);
133762306a36Sopenharmony_ci		ret = copy_to_user((void __user *)value, &desc1, desc1.bLength);
133862306a36Sopenharmony_ci		if (ret)
133962306a36Sopenharmony_ci			ret = -EFAULT;
134062306a36Sopenharmony_ci		return ret;
134162306a36Sopenharmony_ci	}
134262306a36Sopenharmony_ci	default:
134362306a36Sopenharmony_ci		ret = -ENOTTY;
134462306a36Sopenharmony_ci	}
134562306a36Sopenharmony_ci	spin_unlock_irq(&epfile->ffs->eps_lock);
134662306a36Sopenharmony_ci
134762306a36Sopenharmony_ci	return ret;
134862306a36Sopenharmony_ci}
134962306a36Sopenharmony_ci
135062306a36Sopenharmony_cistatic const struct file_operations ffs_epfile_operations = {
135162306a36Sopenharmony_ci	.llseek =	no_llseek,
135262306a36Sopenharmony_ci
135362306a36Sopenharmony_ci	.open =		ffs_epfile_open,
135462306a36Sopenharmony_ci	.write_iter =	ffs_epfile_write_iter,
135562306a36Sopenharmony_ci	.read_iter =	ffs_epfile_read_iter,
135662306a36Sopenharmony_ci	.release =	ffs_epfile_release,
135762306a36Sopenharmony_ci	.unlocked_ioctl =	ffs_epfile_ioctl,
135862306a36Sopenharmony_ci	.compat_ioctl = compat_ptr_ioctl,
135962306a36Sopenharmony_ci};
136062306a36Sopenharmony_ci
136162306a36Sopenharmony_ci
136262306a36Sopenharmony_ci/* File system and super block operations ***********************************/
136362306a36Sopenharmony_ci
136462306a36Sopenharmony_ci/*
136562306a36Sopenharmony_ci * Mounting the file system creates a controller file, used first for
136662306a36Sopenharmony_ci * function configuration then later for event monitoring.
136762306a36Sopenharmony_ci */
136862306a36Sopenharmony_ci
136962306a36Sopenharmony_cistatic struct inode *__must_check
137062306a36Sopenharmony_ciffs_sb_make_inode(struct super_block *sb, void *data,
137162306a36Sopenharmony_ci		  const struct file_operations *fops,
137262306a36Sopenharmony_ci		  const struct inode_operations *iops,
137362306a36Sopenharmony_ci		  struct ffs_file_perms *perms)
137462306a36Sopenharmony_ci{
137562306a36Sopenharmony_ci	struct inode *inode;
137662306a36Sopenharmony_ci
137762306a36Sopenharmony_ci	inode = new_inode(sb);
137862306a36Sopenharmony_ci
137962306a36Sopenharmony_ci	if (inode) {
138062306a36Sopenharmony_ci		struct timespec64 ts = inode_set_ctime_current(inode);
138162306a36Sopenharmony_ci
138262306a36Sopenharmony_ci		inode->i_ino	 = get_next_ino();
138362306a36Sopenharmony_ci		inode->i_mode    = perms->mode;
138462306a36Sopenharmony_ci		inode->i_uid     = perms->uid;
138562306a36Sopenharmony_ci		inode->i_gid     = perms->gid;
138662306a36Sopenharmony_ci		inode->i_atime   = ts;
138762306a36Sopenharmony_ci		inode->i_mtime   = ts;
138862306a36Sopenharmony_ci		inode->i_private = data;
138962306a36Sopenharmony_ci		if (fops)
139062306a36Sopenharmony_ci			inode->i_fop = fops;
139162306a36Sopenharmony_ci		if (iops)
139262306a36Sopenharmony_ci			inode->i_op  = iops;
139362306a36Sopenharmony_ci	}
139462306a36Sopenharmony_ci
139562306a36Sopenharmony_ci	return inode;
139662306a36Sopenharmony_ci}
139762306a36Sopenharmony_ci
139862306a36Sopenharmony_ci/* Create "regular" file */
139962306a36Sopenharmony_cistatic struct dentry *ffs_sb_create_file(struct super_block *sb,
140062306a36Sopenharmony_ci					const char *name, void *data,
140162306a36Sopenharmony_ci					const struct file_operations *fops)
140262306a36Sopenharmony_ci{
140362306a36Sopenharmony_ci	struct ffs_data	*ffs = sb->s_fs_info;
140462306a36Sopenharmony_ci	struct dentry	*dentry;
140562306a36Sopenharmony_ci	struct inode	*inode;
140662306a36Sopenharmony_ci
140762306a36Sopenharmony_ci	dentry = d_alloc_name(sb->s_root, name);
140862306a36Sopenharmony_ci	if (!dentry)
140962306a36Sopenharmony_ci		return NULL;
141062306a36Sopenharmony_ci
141162306a36Sopenharmony_ci	inode = ffs_sb_make_inode(sb, data, fops, NULL, &ffs->file_perms);
141262306a36Sopenharmony_ci	if (!inode) {
141362306a36Sopenharmony_ci		dput(dentry);
141462306a36Sopenharmony_ci		return NULL;
141562306a36Sopenharmony_ci	}
141662306a36Sopenharmony_ci
141762306a36Sopenharmony_ci	d_add(dentry, inode);
141862306a36Sopenharmony_ci	return dentry;
141962306a36Sopenharmony_ci}
142062306a36Sopenharmony_ci
142162306a36Sopenharmony_ci/* Super block */
142262306a36Sopenharmony_cistatic const struct super_operations ffs_sb_operations = {
142362306a36Sopenharmony_ci	.statfs =	simple_statfs,
142462306a36Sopenharmony_ci	.drop_inode =	generic_delete_inode,
142562306a36Sopenharmony_ci};
142662306a36Sopenharmony_ci
142762306a36Sopenharmony_cistruct ffs_sb_fill_data {
142862306a36Sopenharmony_ci	struct ffs_file_perms perms;
142962306a36Sopenharmony_ci	umode_t root_mode;
143062306a36Sopenharmony_ci	const char *dev_name;
143162306a36Sopenharmony_ci	bool no_disconnect;
143262306a36Sopenharmony_ci	struct ffs_data *ffs_data;
143362306a36Sopenharmony_ci};
143462306a36Sopenharmony_ci
143562306a36Sopenharmony_cistatic int ffs_sb_fill(struct super_block *sb, struct fs_context *fc)
143662306a36Sopenharmony_ci{
143762306a36Sopenharmony_ci	struct ffs_sb_fill_data *data = fc->fs_private;
143862306a36Sopenharmony_ci	struct inode	*inode;
143962306a36Sopenharmony_ci	struct ffs_data	*ffs = data->ffs_data;
144062306a36Sopenharmony_ci
144162306a36Sopenharmony_ci	ffs->sb              = sb;
144262306a36Sopenharmony_ci	data->ffs_data       = NULL;
144362306a36Sopenharmony_ci	sb->s_fs_info        = ffs;
144462306a36Sopenharmony_ci	sb->s_blocksize      = PAGE_SIZE;
144562306a36Sopenharmony_ci	sb->s_blocksize_bits = PAGE_SHIFT;
144662306a36Sopenharmony_ci	sb->s_magic          = FUNCTIONFS_MAGIC;
144762306a36Sopenharmony_ci	sb->s_op             = &ffs_sb_operations;
144862306a36Sopenharmony_ci	sb->s_time_gran      = 1;
144962306a36Sopenharmony_ci
145062306a36Sopenharmony_ci	/* Root inode */
145162306a36Sopenharmony_ci	data->perms.mode = data->root_mode;
145262306a36Sopenharmony_ci	inode = ffs_sb_make_inode(sb, NULL,
145362306a36Sopenharmony_ci				  &simple_dir_operations,
145462306a36Sopenharmony_ci				  &simple_dir_inode_operations,
145562306a36Sopenharmony_ci				  &data->perms);
145662306a36Sopenharmony_ci	sb->s_root = d_make_root(inode);
145762306a36Sopenharmony_ci	if (!sb->s_root)
145862306a36Sopenharmony_ci		return -ENOMEM;
145962306a36Sopenharmony_ci
146062306a36Sopenharmony_ci	/* EP0 file */
146162306a36Sopenharmony_ci	if (!ffs_sb_create_file(sb, "ep0", ffs, &ffs_ep0_operations))
146262306a36Sopenharmony_ci		return -ENOMEM;
146362306a36Sopenharmony_ci
146462306a36Sopenharmony_ci	return 0;
146562306a36Sopenharmony_ci}
146662306a36Sopenharmony_ci
146762306a36Sopenharmony_cienum {
146862306a36Sopenharmony_ci	Opt_no_disconnect,
146962306a36Sopenharmony_ci	Opt_rmode,
147062306a36Sopenharmony_ci	Opt_fmode,
147162306a36Sopenharmony_ci	Opt_mode,
147262306a36Sopenharmony_ci	Opt_uid,
147362306a36Sopenharmony_ci	Opt_gid,
147462306a36Sopenharmony_ci};
147562306a36Sopenharmony_ci
147662306a36Sopenharmony_cistatic const struct fs_parameter_spec ffs_fs_fs_parameters[] = {
147762306a36Sopenharmony_ci	fsparam_bool	("no_disconnect",	Opt_no_disconnect),
147862306a36Sopenharmony_ci	fsparam_u32	("rmode",		Opt_rmode),
147962306a36Sopenharmony_ci	fsparam_u32	("fmode",		Opt_fmode),
148062306a36Sopenharmony_ci	fsparam_u32	("mode",		Opt_mode),
148162306a36Sopenharmony_ci	fsparam_u32	("uid",			Opt_uid),
148262306a36Sopenharmony_ci	fsparam_u32	("gid",			Opt_gid),
148362306a36Sopenharmony_ci	{}
148462306a36Sopenharmony_ci};
148562306a36Sopenharmony_ci
148662306a36Sopenharmony_cistatic int ffs_fs_parse_param(struct fs_context *fc, struct fs_parameter *param)
148762306a36Sopenharmony_ci{
148862306a36Sopenharmony_ci	struct ffs_sb_fill_data *data = fc->fs_private;
148962306a36Sopenharmony_ci	struct fs_parse_result result;
149062306a36Sopenharmony_ci	int opt;
149162306a36Sopenharmony_ci
149262306a36Sopenharmony_ci	opt = fs_parse(fc, ffs_fs_fs_parameters, param, &result);
149362306a36Sopenharmony_ci	if (opt < 0)
149462306a36Sopenharmony_ci		return opt;
149562306a36Sopenharmony_ci
149662306a36Sopenharmony_ci	switch (opt) {
149762306a36Sopenharmony_ci	case Opt_no_disconnect:
149862306a36Sopenharmony_ci		data->no_disconnect = result.boolean;
149962306a36Sopenharmony_ci		break;
150062306a36Sopenharmony_ci	case Opt_rmode:
150162306a36Sopenharmony_ci		data->root_mode  = (result.uint_32 & 0555) | S_IFDIR;
150262306a36Sopenharmony_ci		break;
150362306a36Sopenharmony_ci	case Opt_fmode:
150462306a36Sopenharmony_ci		data->perms.mode = (result.uint_32 & 0666) | S_IFREG;
150562306a36Sopenharmony_ci		break;
150662306a36Sopenharmony_ci	case Opt_mode:
150762306a36Sopenharmony_ci		data->root_mode  = (result.uint_32 & 0555) | S_IFDIR;
150862306a36Sopenharmony_ci		data->perms.mode = (result.uint_32 & 0666) | S_IFREG;
150962306a36Sopenharmony_ci		break;
151062306a36Sopenharmony_ci
151162306a36Sopenharmony_ci	case Opt_uid:
151262306a36Sopenharmony_ci		data->perms.uid = make_kuid(current_user_ns(), result.uint_32);
151362306a36Sopenharmony_ci		if (!uid_valid(data->perms.uid))
151462306a36Sopenharmony_ci			goto unmapped_value;
151562306a36Sopenharmony_ci		break;
151662306a36Sopenharmony_ci	case Opt_gid:
151762306a36Sopenharmony_ci		data->perms.gid = make_kgid(current_user_ns(), result.uint_32);
151862306a36Sopenharmony_ci		if (!gid_valid(data->perms.gid))
151962306a36Sopenharmony_ci			goto unmapped_value;
152062306a36Sopenharmony_ci		break;
152162306a36Sopenharmony_ci
152262306a36Sopenharmony_ci	default:
152362306a36Sopenharmony_ci		return -ENOPARAM;
152462306a36Sopenharmony_ci	}
152562306a36Sopenharmony_ci
152662306a36Sopenharmony_ci	return 0;
152762306a36Sopenharmony_ci
152862306a36Sopenharmony_ciunmapped_value:
152962306a36Sopenharmony_ci	return invalf(fc, "%s: unmapped value: %u", param->key, result.uint_32);
153062306a36Sopenharmony_ci}
153162306a36Sopenharmony_ci
153262306a36Sopenharmony_ci/*
153362306a36Sopenharmony_ci * Set up the superblock for a mount.
153462306a36Sopenharmony_ci */
153562306a36Sopenharmony_cistatic int ffs_fs_get_tree(struct fs_context *fc)
153662306a36Sopenharmony_ci{
153762306a36Sopenharmony_ci	struct ffs_sb_fill_data *ctx = fc->fs_private;
153862306a36Sopenharmony_ci	struct ffs_data	*ffs;
153962306a36Sopenharmony_ci	int ret;
154062306a36Sopenharmony_ci
154162306a36Sopenharmony_ci	if (!fc->source)
154262306a36Sopenharmony_ci		return invalf(fc, "No source specified");
154362306a36Sopenharmony_ci
154462306a36Sopenharmony_ci	ffs = ffs_data_new(fc->source);
154562306a36Sopenharmony_ci	if (!ffs)
154662306a36Sopenharmony_ci		return -ENOMEM;
154762306a36Sopenharmony_ci	ffs->file_perms = ctx->perms;
154862306a36Sopenharmony_ci	ffs->no_disconnect = ctx->no_disconnect;
154962306a36Sopenharmony_ci
155062306a36Sopenharmony_ci	ffs->dev_name = kstrdup(fc->source, GFP_KERNEL);
155162306a36Sopenharmony_ci	if (!ffs->dev_name) {
155262306a36Sopenharmony_ci		ffs_data_put(ffs);
155362306a36Sopenharmony_ci		return -ENOMEM;
155462306a36Sopenharmony_ci	}
155562306a36Sopenharmony_ci
155662306a36Sopenharmony_ci	ret = ffs_acquire_dev(ffs->dev_name, ffs);
155762306a36Sopenharmony_ci	if (ret) {
155862306a36Sopenharmony_ci		ffs_data_put(ffs);
155962306a36Sopenharmony_ci		return ret;
156062306a36Sopenharmony_ci	}
156162306a36Sopenharmony_ci
156262306a36Sopenharmony_ci	ctx->ffs_data = ffs;
156362306a36Sopenharmony_ci	return get_tree_nodev(fc, ffs_sb_fill);
156462306a36Sopenharmony_ci}
156562306a36Sopenharmony_ci
156662306a36Sopenharmony_cistatic void ffs_fs_free_fc(struct fs_context *fc)
156762306a36Sopenharmony_ci{
156862306a36Sopenharmony_ci	struct ffs_sb_fill_data *ctx = fc->fs_private;
156962306a36Sopenharmony_ci
157062306a36Sopenharmony_ci	if (ctx) {
157162306a36Sopenharmony_ci		if (ctx->ffs_data) {
157262306a36Sopenharmony_ci			ffs_data_put(ctx->ffs_data);
157362306a36Sopenharmony_ci		}
157462306a36Sopenharmony_ci
157562306a36Sopenharmony_ci		kfree(ctx);
157662306a36Sopenharmony_ci	}
157762306a36Sopenharmony_ci}
157862306a36Sopenharmony_ci
157962306a36Sopenharmony_cistatic const struct fs_context_operations ffs_fs_context_ops = {
158062306a36Sopenharmony_ci	.free		= ffs_fs_free_fc,
158162306a36Sopenharmony_ci	.parse_param	= ffs_fs_parse_param,
158262306a36Sopenharmony_ci	.get_tree	= ffs_fs_get_tree,
158362306a36Sopenharmony_ci};
158462306a36Sopenharmony_ci
158562306a36Sopenharmony_cistatic int ffs_fs_init_fs_context(struct fs_context *fc)
158662306a36Sopenharmony_ci{
158762306a36Sopenharmony_ci	struct ffs_sb_fill_data *ctx;
158862306a36Sopenharmony_ci
158962306a36Sopenharmony_ci	ctx = kzalloc(sizeof(struct ffs_sb_fill_data), GFP_KERNEL);
159062306a36Sopenharmony_ci	if (!ctx)
159162306a36Sopenharmony_ci		return -ENOMEM;
159262306a36Sopenharmony_ci
159362306a36Sopenharmony_ci	ctx->perms.mode = S_IFREG | 0600;
159462306a36Sopenharmony_ci	ctx->perms.uid = GLOBAL_ROOT_UID;
159562306a36Sopenharmony_ci	ctx->perms.gid = GLOBAL_ROOT_GID;
159662306a36Sopenharmony_ci	ctx->root_mode = S_IFDIR | 0500;
159762306a36Sopenharmony_ci	ctx->no_disconnect = false;
159862306a36Sopenharmony_ci
159962306a36Sopenharmony_ci	fc->fs_private = ctx;
160062306a36Sopenharmony_ci	fc->ops = &ffs_fs_context_ops;
160162306a36Sopenharmony_ci	return 0;
160262306a36Sopenharmony_ci}
160362306a36Sopenharmony_ci
160462306a36Sopenharmony_cistatic void
160562306a36Sopenharmony_ciffs_fs_kill_sb(struct super_block *sb)
160662306a36Sopenharmony_ci{
160762306a36Sopenharmony_ci	kill_litter_super(sb);
160862306a36Sopenharmony_ci	if (sb->s_fs_info)
160962306a36Sopenharmony_ci		ffs_data_closed(sb->s_fs_info);
161062306a36Sopenharmony_ci}
161162306a36Sopenharmony_ci
161262306a36Sopenharmony_cistatic struct file_system_type ffs_fs_type = {
161362306a36Sopenharmony_ci	.owner		= THIS_MODULE,
161462306a36Sopenharmony_ci	.name		= "functionfs",
161562306a36Sopenharmony_ci	.init_fs_context = ffs_fs_init_fs_context,
161662306a36Sopenharmony_ci	.parameters	= ffs_fs_fs_parameters,
161762306a36Sopenharmony_ci	.kill_sb	= ffs_fs_kill_sb,
161862306a36Sopenharmony_ci};
161962306a36Sopenharmony_ciMODULE_ALIAS_FS("functionfs");
162062306a36Sopenharmony_ci
162162306a36Sopenharmony_ci
162262306a36Sopenharmony_ci/* Driver's main init/cleanup functions *************************************/
162362306a36Sopenharmony_ci
162462306a36Sopenharmony_cistatic int functionfs_init(void)
162562306a36Sopenharmony_ci{
162662306a36Sopenharmony_ci	int ret;
162762306a36Sopenharmony_ci
162862306a36Sopenharmony_ci	ret = register_filesystem(&ffs_fs_type);
162962306a36Sopenharmony_ci	if (!ret)
163062306a36Sopenharmony_ci		pr_info("file system registered\n");
163162306a36Sopenharmony_ci	else
163262306a36Sopenharmony_ci		pr_err("failed registering file system (%d)\n", ret);
163362306a36Sopenharmony_ci
163462306a36Sopenharmony_ci	return ret;
163562306a36Sopenharmony_ci}
163662306a36Sopenharmony_ci
163762306a36Sopenharmony_cistatic void functionfs_cleanup(void)
163862306a36Sopenharmony_ci{
163962306a36Sopenharmony_ci	pr_info("unloading\n");
164062306a36Sopenharmony_ci	unregister_filesystem(&ffs_fs_type);
164162306a36Sopenharmony_ci}
164262306a36Sopenharmony_ci
164362306a36Sopenharmony_ci
164462306a36Sopenharmony_ci/* ffs_data and ffs_function construction and destruction code **************/
164562306a36Sopenharmony_ci
164662306a36Sopenharmony_cistatic void ffs_data_clear(struct ffs_data *ffs);
164762306a36Sopenharmony_cistatic void ffs_data_reset(struct ffs_data *ffs);
164862306a36Sopenharmony_ci
164962306a36Sopenharmony_cistatic void ffs_data_get(struct ffs_data *ffs)
165062306a36Sopenharmony_ci{
165162306a36Sopenharmony_ci	refcount_inc(&ffs->ref);
165262306a36Sopenharmony_ci}
165362306a36Sopenharmony_ci
165462306a36Sopenharmony_cistatic void ffs_data_opened(struct ffs_data *ffs)
165562306a36Sopenharmony_ci{
165662306a36Sopenharmony_ci	refcount_inc(&ffs->ref);
165762306a36Sopenharmony_ci	if (atomic_add_return(1, &ffs->opened) == 1 &&
165862306a36Sopenharmony_ci			ffs->state == FFS_DEACTIVATED) {
165962306a36Sopenharmony_ci		ffs->state = FFS_CLOSING;
166062306a36Sopenharmony_ci		ffs_data_reset(ffs);
166162306a36Sopenharmony_ci	}
166262306a36Sopenharmony_ci}
166362306a36Sopenharmony_ci
166462306a36Sopenharmony_cistatic void ffs_data_put(struct ffs_data *ffs)
166562306a36Sopenharmony_ci{
166662306a36Sopenharmony_ci	if (refcount_dec_and_test(&ffs->ref)) {
166762306a36Sopenharmony_ci		pr_info("%s(): freeing\n", __func__);
166862306a36Sopenharmony_ci		ffs_data_clear(ffs);
166962306a36Sopenharmony_ci		ffs_release_dev(ffs->private_data);
167062306a36Sopenharmony_ci		BUG_ON(waitqueue_active(&ffs->ev.waitq) ||
167162306a36Sopenharmony_ci		       swait_active(&ffs->ep0req_completion.wait) ||
167262306a36Sopenharmony_ci		       waitqueue_active(&ffs->wait));
167362306a36Sopenharmony_ci		destroy_workqueue(ffs->io_completion_wq);
167462306a36Sopenharmony_ci		kfree(ffs->dev_name);
167562306a36Sopenharmony_ci		kfree(ffs);
167662306a36Sopenharmony_ci	}
167762306a36Sopenharmony_ci}
167862306a36Sopenharmony_ci
167962306a36Sopenharmony_cistatic void ffs_data_closed(struct ffs_data *ffs)
168062306a36Sopenharmony_ci{
168162306a36Sopenharmony_ci	struct ffs_epfile *epfiles;
168262306a36Sopenharmony_ci	unsigned long flags;
168362306a36Sopenharmony_ci
168462306a36Sopenharmony_ci	if (atomic_dec_and_test(&ffs->opened)) {
168562306a36Sopenharmony_ci		if (ffs->no_disconnect) {
168662306a36Sopenharmony_ci			ffs->state = FFS_DEACTIVATED;
168762306a36Sopenharmony_ci			spin_lock_irqsave(&ffs->eps_lock, flags);
168862306a36Sopenharmony_ci			epfiles = ffs->epfiles;
168962306a36Sopenharmony_ci			ffs->epfiles = NULL;
169062306a36Sopenharmony_ci			spin_unlock_irqrestore(&ffs->eps_lock,
169162306a36Sopenharmony_ci							flags);
169262306a36Sopenharmony_ci
169362306a36Sopenharmony_ci			if (epfiles)
169462306a36Sopenharmony_ci				ffs_epfiles_destroy(epfiles,
169562306a36Sopenharmony_ci						 ffs->eps_count);
169662306a36Sopenharmony_ci
169762306a36Sopenharmony_ci			if (ffs->setup_state == FFS_SETUP_PENDING)
169862306a36Sopenharmony_ci				__ffs_ep0_stall(ffs);
169962306a36Sopenharmony_ci		} else {
170062306a36Sopenharmony_ci			ffs->state = FFS_CLOSING;
170162306a36Sopenharmony_ci			ffs_data_reset(ffs);
170262306a36Sopenharmony_ci		}
170362306a36Sopenharmony_ci	}
170462306a36Sopenharmony_ci	if (atomic_read(&ffs->opened) < 0) {
170562306a36Sopenharmony_ci		ffs->state = FFS_CLOSING;
170662306a36Sopenharmony_ci		ffs_data_reset(ffs);
170762306a36Sopenharmony_ci	}
170862306a36Sopenharmony_ci
170962306a36Sopenharmony_ci	ffs_data_put(ffs);
171062306a36Sopenharmony_ci}
171162306a36Sopenharmony_ci
171262306a36Sopenharmony_cistatic struct ffs_data *ffs_data_new(const char *dev_name)
171362306a36Sopenharmony_ci{
171462306a36Sopenharmony_ci	struct ffs_data *ffs = kzalloc(sizeof *ffs, GFP_KERNEL);
171562306a36Sopenharmony_ci	if (!ffs)
171662306a36Sopenharmony_ci		return NULL;
171762306a36Sopenharmony_ci
171862306a36Sopenharmony_ci	ffs->io_completion_wq = alloc_ordered_workqueue("%s", 0, dev_name);
171962306a36Sopenharmony_ci	if (!ffs->io_completion_wq) {
172062306a36Sopenharmony_ci		kfree(ffs);
172162306a36Sopenharmony_ci		return NULL;
172262306a36Sopenharmony_ci	}
172362306a36Sopenharmony_ci
172462306a36Sopenharmony_ci	refcount_set(&ffs->ref, 1);
172562306a36Sopenharmony_ci	atomic_set(&ffs->opened, 0);
172662306a36Sopenharmony_ci	ffs->state = FFS_READ_DESCRIPTORS;
172762306a36Sopenharmony_ci	mutex_init(&ffs->mutex);
172862306a36Sopenharmony_ci	spin_lock_init(&ffs->eps_lock);
172962306a36Sopenharmony_ci	init_waitqueue_head(&ffs->ev.waitq);
173062306a36Sopenharmony_ci	init_waitqueue_head(&ffs->wait);
173162306a36Sopenharmony_ci	init_completion(&ffs->ep0req_completion);
173262306a36Sopenharmony_ci
173362306a36Sopenharmony_ci	/* XXX REVISIT need to update it in some places, or do we? */
173462306a36Sopenharmony_ci	ffs->ev.can_stall = 1;
173562306a36Sopenharmony_ci
173662306a36Sopenharmony_ci	return ffs;
173762306a36Sopenharmony_ci}
173862306a36Sopenharmony_ci
173962306a36Sopenharmony_cistatic void ffs_data_clear(struct ffs_data *ffs)
174062306a36Sopenharmony_ci{
174162306a36Sopenharmony_ci	struct ffs_epfile *epfiles;
174262306a36Sopenharmony_ci	unsigned long flags;
174362306a36Sopenharmony_ci
174462306a36Sopenharmony_ci	ffs_closed(ffs);
174562306a36Sopenharmony_ci
174662306a36Sopenharmony_ci	BUG_ON(ffs->gadget);
174762306a36Sopenharmony_ci
174862306a36Sopenharmony_ci	spin_lock_irqsave(&ffs->eps_lock, flags);
174962306a36Sopenharmony_ci	epfiles = ffs->epfiles;
175062306a36Sopenharmony_ci	ffs->epfiles = NULL;
175162306a36Sopenharmony_ci	spin_unlock_irqrestore(&ffs->eps_lock, flags);
175262306a36Sopenharmony_ci
175362306a36Sopenharmony_ci	/*
175462306a36Sopenharmony_ci	 * potential race possible between ffs_func_eps_disable
175562306a36Sopenharmony_ci	 * & ffs_epfile_release therefore maintaining a local
175662306a36Sopenharmony_ci	 * copy of epfile will save us from use-after-free.
175762306a36Sopenharmony_ci	 */
175862306a36Sopenharmony_ci	if (epfiles) {
175962306a36Sopenharmony_ci		ffs_epfiles_destroy(epfiles, ffs->eps_count);
176062306a36Sopenharmony_ci		ffs->epfiles = NULL;
176162306a36Sopenharmony_ci	}
176262306a36Sopenharmony_ci
176362306a36Sopenharmony_ci	if (ffs->ffs_eventfd) {
176462306a36Sopenharmony_ci		eventfd_ctx_put(ffs->ffs_eventfd);
176562306a36Sopenharmony_ci		ffs->ffs_eventfd = NULL;
176662306a36Sopenharmony_ci	}
176762306a36Sopenharmony_ci
176862306a36Sopenharmony_ci	kfree(ffs->raw_descs_data);
176962306a36Sopenharmony_ci	kfree(ffs->raw_strings);
177062306a36Sopenharmony_ci	kfree(ffs->stringtabs);
177162306a36Sopenharmony_ci}
177262306a36Sopenharmony_ci
177362306a36Sopenharmony_cistatic void ffs_data_reset(struct ffs_data *ffs)
177462306a36Sopenharmony_ci{
177562306a36Sopenharmony_ci	ffs_data_clear(ffs);
177662306a36Sopenharmony_ci
177762306a36Sopenharmony_ci	ffs->raw_descs_data = NULL;
177862306a36Sopenharmony_ci	ffs->raw_descs = NULL;
177962306a36Sopenharmony_ci	ffs->raw_strings = NULL;
178062306a36Sopenharmony_ci	ffs->stringtabs = NULL;
178162306a36Sopenharmony_ci
178262306a36Sopenharmony_ci	ffs->raw_descs_length = 0;
178362306a36Sopenharmony_ci	ffs->fs_descs_count = 0;
178462306a36Sopenharmony_ci	ffs->hs_descs_count = 0;
178562306a36Sopenharmony_ci	ffs->ss_descs_count = 0;
178662306a36Sopenharmony_ci
178762306a36Sopenharmony_ci	ffs->strings_count = 0;
178862306a36Sopenharmony_ci	ffs->interfaces_count = 0;
178962306a36Sopenharmony_ci	ffs->eps_count = 0;
179062306a36Sopenharmony_ci
179162306a36Sopenharmony_ci	ffs->ev.count = 0;
179262306a36Sopenharmony_ci
179362306a36Sopenharmony_ci	ffs->state = FFS_READ_DESCRIPTORS;
179462306a36Sopenharmony_ci	ffs->setup_state = FFS_NO_SETUP;
179562306a36Sopenharmony_ci	ffs->flags = 0;
179662306a36Sopenharmony_ci
179762306a36Sopenharmony_ci	ffs->ms_os_descs_ext_prop_count = 0;
179862306a36Sopenharmony_ci	ffs->ms_os_descs_ext_prop_name_len = 0;
179962306a36Sopenharmony_ci	ffs->ms_os_descs_ext_prop_data_len = 0;
180062306a36Sopenharmony_ci}
180162306a36Sopenharmony_ci
180262306a36Sopenharmony_ci
180362306a36Sopenharmony_cistatic int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev)
180462306a36Sopenharmony_ci{
180562306a36Sopenharmony_ci	struct usb_gadget_strings **lang;
180662306a36Sopenharmony_ci	int first_id;
180762306a36Sopenharmony_ci
180862306a36Sopenharmony_ci	if (WARN_ON(ffs->state != FFS_ACTIVE
180962306a36Sopenharmony_ci		 || test_and_set_bit(FFS_FL_BOUND, &ffs->flags)))
181062306a36Sopenharmony_ci		return -EBADFD;
181162306a36Sopenharmony_ci
181262306a36Sopenharmony_ci	first_id = usb_string_ids_n(cdev, ffs->strings_count);
181362306a36Sopenharmony_ci	if (first_id < 0)
181462306a36Sopenharmony_ci		return first_id;
181562306a36Sopenharmony_ci
181662306a36Sopenharmony_ci	ffs->ep0req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL);
181762306a36Sopenharmony_ci	if (!ffs->ep0req)
181862306a36Sopenharmony_ci		return -ENOMEM;
181962306a36Sopenharmony_ci	ffs->ep0req->complete = ffs_ep0_complete;
182062306a36Sopenharmony_ci	ffs->ep0req->context = ffs;
182162306a36Sopenharmony_ci
182262306a36Sopenharmony_ci	lang = ffs->stringtabs;
182362306a36Sopenharmony_ci	if (lang) {
182462306a36Sopenharmony_ci		for (; *lang; ++lang) {
182562306a36Sopenharmony_ci			struct usb_string *str = (*lang)->strings;
182662306a36Sopenharmony_ci			int id = first_id;
182762306a36Sopenharmony_ci			for (; str->s; ++id, ++str)
182862306a36Sopenharmony_ci				str->id = id;
182962306a36Sopenharmony_ci		}
183062306a36Sopenharmony_ci	}
183162306a36Sopenharmony_ci
183262306a36Sopenharmony_ci	ffs->gadget = cdev->gadget;
183362306a36Sopenharmony_ci	ffs_data_get(ffs);
183462306a36Sopenharmony_ci	return 0;
183562306a36Sopenharmony_ci}
183662306a36Sopenharmony_ci
183762306a36Sopenharmony_cistatic void functionfs_unbind(struct ffs_data *ffs)
183862306a36Sopenharmony_ci{
183962306a36Sopenharmony_ci	if (!WARN_ON(!ffs->gadget)) {
184062306a36Sopenharmony_ci		/* dequeue before freeing ep0req */
184162306a36Sopenharmony_ci		usb_ep_dequeue(ffs->gadget->ep0, ffs->ep0req);
184262306a36Sopenharmony_ci		mutex_lock(&ffs->mutex);
184362306a36Sopenharmony_ci		usb_ep_free_request(ffs->gadget->ep0, ffs->ep0req);
184462306a36Sopenharmony_ci		ffs->ep0req = NULL;
184562306a36Sopenharmony_ci		ffs->gadget = NULL;
184662306a36Sopenharmony_ci		clear_bit(FFS_FL_BOUND, &ffs->flags);
184762306a36Sopenharmony_ci		mutex_unlock(&ffs->mutex);
184862306a36Sopenharmony_ci		ffs_data_put(ffs);
184962306a36Sopenharmony_ci	}
185062306a36Sopenharmony_ci}
185162306a36Sopenharmony_ci
185262306a36Sopenharmony_cistatic int ffs_epfiles_create(struct ffs_data *ffs)
185362306a36Sopenharmony_ci{
185462306a36Sopenharmony_ci	struct ffs_epfile *epfile, *epfiles;
185562306a36Sopenharmony_ci	unsigned i, count;
185662306a36Sopenharmony_ci
185762306a36Sopenharmony_ci	count = ffs->eps_count;
185862306a36Sopenharmony_ci	epfiles = kcalloc(count, sizeof(*epfiles), GFP_KERNEL);
185962306a36Sopenharmony_ci	if (!epfiles)
186062306a36Sopenharmony_ci		return -ENOMEM;
186162306a36Sopenharmony_ci
186262306a36Sopenharmony_ci	epfile = epfiles;
186362306a36Sopenharmony_ci	for (i = 1; i <= count; ++i, ++epfile) {
186462306a36Sopenharmony_ci		epfile->ffs = ffs;
186562306a36Sopenharmony_ci		mutex_init(&epfile->mutex);
186662306a36Sopenharmony_ci		if (ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR)
186762306a36Sopenharmony_ci			sprintf(epfile->name, "ep%02x", ffs->eps_addrmap[i]);
186862306a36Sopenharmony_ci		else
186962306a36Sopenharmony_ci			sprintf(epfile->name, "ep%u", i);
187062306a36Sopenharmony_ci		epfile->dentry = ffs_sb_create_file(ffs->sb, epfile->name,
187162306a36Sopenharmony_ci						 epfile,
187262306a36Sopenharmony_ci						 &ffs_epfile_operations);
187362306a36Sopenharmony_ci		if (!epfile->dentry) {
187462306a36Sopenharmony_ci			ffs_epfiles_destroy(epfiles, i - 1);
187562306a36Sopenharmony_ci			return -ENOMEM;
187662306a36Sopenharmony_ci		}
187762306a36Sopenharmony_ci	}
187862306a36Sopenharmony_ci
187962306a36Sopenharmony_ci	ffs->epfiles = epfiles;
188062306a36Sopenharmony_ci	return 0;
188162306a36Sopenharmony_ci}
188262306a36Sopenharmony_ci
188362306a36Sopenharmony_cistatic void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count)
188462306a36Sopenharmony_ci{
188562306a36Sopenharmony_ci	struct ffs_epfile *epfile = epfiles;
188662306a36Sopenharmony_ci
188762306a36Sopenharmony_ci	for (; count; --count, ++epfile) {
188862306a36Sopenharmony_ci		BUG_ON(mutex_is_locked(&epfile->mutex));
188962306a36Sopenharmony_ci		if (epfile->dentry) {
189062306a36Sopenharmony_ci			d_delete(epfile->dentry);
189162306a36Sopenharmony_ci			dput(epfile->dentry);
189262306a36Sopenharmony_ci			epfile->dentry = NULL;
189362306a36Sopenharmony_ci		}
189462306a36Sopenharmony_ci	}
189562306a36Sopenharmony_ci
189662306a36Sopenharmony_ci	kfree(epfiles);
189762306a36Sopenharmony_ci}
189862306a36Sopenharmony_ci
189962306a36Sopenharmony_cistatic void ffs_func_eps_disable(struct ffs_function *func)
190062306a36Sopenharmony_ci{
190162306a36Sopenharmony_ci	struct ffs_ep *ep;
190262306a36Sopenharmony_ci	struct ffs_epfile *epfile;
190362306a36Sopenharmony_ci	unsigned short count;
190462306a36Sopenharmony_ci	unsigned long flags;
190562306a36Sopenharmony_ci
190662306a36Sopenharmony_ci	spin_lock_irqsave(&func->ffs->eps_lock, flags);
190762306a36Sopenharmony_ci	count = func->ffs->eps_count;
190862306a36Sopenharmony_ci	epfile = func->ffs->epfiles;
190962306a36Sopenharmony_ci	ep = func->eps;
191062306a36Sopenharmony_ci	while (count--) {
191162306a36Sopenharmony_ci		/* pending requests get nuked */
191262306a36Sopenharmony_ci		if (ep->ep)
191362306a36Sopenharmony_ci			usb_ep_disable(ep->ep);
191462306a36Sopenharmony_ci		++ep;
191562306a36Sopenharmony_ci
191662306a36Sopenharmony_ci		if (epfile) {
191762306a36Sopenharmony_ci			epfile->ep = NULL;
191862306a36Sopenharmony_ci			__ffs_epfile_read_buffer_free(epfile);
191962306a36Sopenharmony_ci			++epfile;
192062306a36Sopenharmony_ci		}
192162306a36Sopenharmony_ci	}
192262306a36Sopenharmony_ci	spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
192362306a36Sopenharmony_ci}
192462306a36Sopenharmony_ci
192562306a36Sopenharmony_cistatic int ffs_func_eps_enable(struct ffs_function *func)
192662306a36Sopenharmony_ci{
192762306a36Sopenharmony_ci	struct ffs_data *ffs;
192862306a36Sopenharmony_ci	struct ffs_ep *ep;
192962306a36Sopenharmony_ci	struct ffs_epfile *epfile;
193062306a36Sopenharmony_ci	unsigned short count;
193162306a36Sopenharmony_ci	unsigned long flags;
193262306a36Sopenharmony_ci	int ret = 0;
193362306a36Sopenharmony_ci
193462306a36Sopenharmony_ci	spin_lock_irqsave(&func->ffs->eps_lock, flags);
193562306a36Sopenharmony_ci	ffs = func->ffs;
193662306a36Sopenharmony_ci	ep = func->eps;
193762306a36Sopenharmony_ci	epfile = ffs->epfiles;
193862306a36Sopenharmony_ci	count = ffs->eps_count;
193962306a36Sopenharmony_ci	while(count--) {
194062306a36Sopenharmony_ci		ep->ep->driver_data = ep;
194162306a36Sopenharmony_ci
194262306a36Sopenharmony_ci		ret = config_ep_by_speed(func->gadget, &func->function, ep->ep);
194362306a36Sopenharmony_ci		if (ret) {
194462306a36Sopenharmony_ci			pr_err("%s: config_ep_by_speed(%s) returned %d\n",
194562306a36Sopenharmony_ci					__func__, ep->ep->name, ret);
194662306a36Sopenharmony_ci			break;
194762306a36Sopenharmony_ci		}
194862306a36Sopenharmony_ci
194962306a36Sopenharmony_ci		ret = usb_ep_enable(ep->ep);
195062306a36Sopenharmony_ci		if (!ret) {
195162306a36Sopenharmony_ci			epfile->ep = ep;
195262306a36Sopenharmony_ci			epfile->in = usb_endpoint_dir_in(ep->ep->desc);
195362306a36Sopenharmony_ci			epfile->isoc = usb_endpoint_xfer_isoc(ep->ep->desc);
195462306a36Sopenharmony_ci		} else {
195562306a36Sopenharmony_ci			break;
195662306a36Sopenharmony_ci		}
195762306a36Sopenharmony_ci
195862306a36Sopenharmony_ci		++ep;
195962306a36Sopenharmony_ci		++epfile;
196062306a36Sopenharmony_ci	}
196162306a36Sopenharmony_ci
196262306a36Sopenharmony_ci	wake_up_interruptible(&ffs->wait);
196362306a36Sopenharmony_ci	spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
196462306a36Sopenharmony_ci
196562306a36Sopenharmony_ci	return ret;
196662306a36Sopenharmony_ci}
196762306a36Sopenharmony_ci
196862306a36Sopenharmony_ci
196962306a36Sopenharmony_ci/* Parsing and building descriptors and strings *****************************/
197062306a36Sopenharmony_ci
197162306a36Sopenharmony_ci/*
197262306a36Sopenharmony_ci * This validates if data pointed by data is a valid USB descriptor as
197362306a36Sopenharmony_ci * well as record how many interfaces, endpoints and strings are
197462306a36Sopenharmony_ci * required by given configuration.  Returns address after the
197562306a36Sopenharmony_ci * descriptor or NULL if data is invalid.
197662306a36Sopenharmony_ci */
197762306a36Sopenharmony_ci
197862306a36Sopenharmony_cienum ffs_entity_type {
197962306a36Sopenharmony_ci	FFS_DESCRIPTOR, FFS_INTERFACE, FFS_STRING, FFS_ENDPOINT
198062306a36Sopenharmony_ci};
198162306a36Sopenharmony_ci
198262306a36Sopenharmony_cienum ffs_os_desc_type {
198362306a36Sopenharmony_ci	FFS_OS_DESC, FFS_OS_DESC_EXT_COMPAT, FFS_OS_DESC_EXT_PROP
198462306a36Sopenharmony_ci};
198562306a36Sopenharmony_ci
198662306a36Sopenharmony_citypedef int (*ffs_entity_callback)(enum ffs_entity_type entity,
198762306a36Sopenharmony_ci				   u8 *valuep,
198862306a36Sopenharmony_ci				   struct usb_descriptor_header *desc,
198962306a36Sopenharmony_ci				   void *priv);
199062306a36Sopenharmony_ci
199162306a36Sopenharmony_citypedef int (*ffs_os_desc_callback)(enum ffs_os_desc_type entity,
199262306a36Sopenharmony_ci				    struct usb_os_desc_header *h, void *data,
199362306a36Sopenharmony_ci				    unsigned len, void *priv);
199462306a36Sopenharmony_ci
199562306a36Sopenharmony_cistatic int __must_check ffs_do_single_desc(char *data, unsigned len,
199662306a36Sopenharmony_ci					   ffs_entity_callback entity,
199762306a36Sopenharmony_ci					   void *priv, int *current_class)
199862306a36Sopenharmony_ci{
199962306a36Sopenharmony_ci	struct usb_descriptor_header *_ds = (void *)data;
200062306a36Sopenharmony_ci	u8 length;
200162306a36Sopenharmony_ci	int ret;
200262306a36Sopenharmony_ci
200362306a36Sopenharmony_ci	/* At least two bytes are required: length and type */
200462306a36Sopenharmony_ci	if (len < 2) {
200562306a36Sopenharmony_ci		pr_vdebug("descriptor too short\n");
200662306a36Sopenharmony_ci		return -EINVAL;
200762306a36Sopenharmony_ci	}
200862306a36Sopenharmony_ci
200962306a36Sopenharmony_ci	/* If we have at least as many bytes as the descriptor takes? */
201062306a36Sopenharmony_ci	length = _ds->bLength;
201162306a36Sopenharmony_ci	if (len < length) {
201262306a36Sopenharmony_ci		pr_vdebug("descriptor longer then available data\n");
201362306a36Sopenharmony_ci		return -EINVAL;
201462306a36Sopenharmony_ci	}
201562306a36Sopenharmony_ci
201662306a36Sopenharmony_ci#define __entity_check_INTERFACE(val)  1
201762306a36Sopenharmony_ci#define __entity_check_STRING(val)     (val)
201862306a36Sopenharmony_ci#define __entity_check_ENDPOINT(val)   ((val) & USB_ENDPOINT_NUMBER_MASK)
201962306a36Sopenharmony_ci#define __entity(type, val) do {					\
202062306a36Sopenharmony_ci		pr_vdebug("entity " #type "(%02x)\n", (val));		\
202162306a36Sopenharmony_ci		if (!__entity_check_ ##type(val)) {			\
202262306a36Sopenharmony_ci			pr_vdebug("invalid entity's value\n");		\
202362306a36Sopenharmony_ci			return -EINVAL;					\
202462306a36Sopenharmony_ci		}							\
202562306a36Sopenharmony_ci		ret = entity(FFS_ ##type, &val, _ds, priv);		\
202662306a36Sopenharmony_ci		if (ret < 0) {						\
202762306a36Sopenharmony_ci			pr_debug("entity " #type "(%02x); ret = %d\n",	\
202862306a36Sopenharmony_ci				 (val), ret);				\
202962306a36Sopenharmony_ci			return ret;					\
203062306a36Sopenharmony_ci		}							\
203162306a36Sopenharmony_ci	} while (0)
203262306a36Sopenharmony_ci
203362306a36Sopenharmony_ci	/* Parse descriptor depending on type. */
203462306a36Sopenharmony_ci	switch (_ds->bDescriptorType) {
203562306a36Sopenharmony_ci	case USB_DT_DEVICE:
203662306a36Sopenharmony_ci	case USB_DT_CONFIG:
203762306a36Sopenharmony_ci	case USB_DT_STRING:
203862306a36Sopenharmony_ci	case USB_DT_DEVICE_QUALIFIER:
203962306a36Sopenharmony_ci		/* function can't have any of those */
204062306a36Sopenharmony_ci		pr_vdebug("descriptor reserved for gadget: %d\n",
204162306a36Sopenharmony_ci		      _ds->bDescriptorType);
204262306a36Sopenharmony_ci		return -EINVAL;
204362306a36Sopenharmony_ci
204462306a36Sopenharmony_ci	case USB_DT_INTERFACE: {
204562306a36Sopenharmony_ci		struct usb_interface_descriptor *ds = (void *)_ds;
204662306a36Sopenharmony_ci		pr_vdebug("interface descriptor\n");
204762306a36Sopenharmony_ci		if (length != sizeof *ds)
204862306a36Sopenharmony_ci			goto inv_length;
204962306a36Sopenharmony_ci
205062306a36Sopenharmony_ci		__entity(INTERFACE, ds->bInterfaceNumber);
205162306a36Sopenharmony_ci		if (ds->iInterface)
205262306a36Sopenharmony_ci			__entity(STRING, ds->iInterface);
205362306a36Sopenharmony_ci		*current_class = ds->bInterfaceClass;
205462306a36Sopenharmony_ci	}
205562306a36Sopenharmony_ci		break;
205662306a36Sopenharmony_ci
205762306a36Sopenharmony_ci	case USB_DT_ENDPOINT: {
205862306a36Sopenharmony_ci		struct usb_endpoint_descriptor *ds = (void *)_ds;
205962306a36Sopenharmony_ci		pr_vdebug("endpoint descriptor\n");
206062306a36Sopenharmony_ci		if (length != USB_DT_ENDPOINT_SIZE &&
206162306a36Sopenharmony_ci		    length != USB_DT_ENDPOINT_AUDIO_SIZE)
206262306a36Sopenharmony_ci			goto inv_length;
206362306a36Sopenharmony_ci		__entity(ENDPOINT, ds->bEndpointAddress);
206462306a36Sopenharmony_ci	}
206562306a36Sopenharmony_ci		break;
206662306a36Sopenharmony_ci
206762306a36Sopenharmony_ci	case USB_TYPE_CLASS | 0x01:
206862306a36Sopenharmony_ci		if (*current_class == USB_INTERFACE_CLASS_HID) {
206962306a36Sopenharmony_ci			pr_vdebug("hid descriptor\n");
207062306a36Sopenharmony_ci			if (length != sizeof(struct hid_descriptor))
207162306a36Sopenharmony_ci				goto inv_length;
207262306a36Sopenharmony_ci			break;
207362306a36Sopenharmony_ci		} else if (*current_class == USB_INTERFACE_CLASS_CCID) {
207462306a36Sopenharmony_ci			pr_vdebug("ccid descriptor\n");
207562306a36Sopenharmony_ci			if (length != sizeof(struct ccid_descriptor))
207662306a36Sopenharmony_ci				goto inv_length;
207762306a36Sopenharmony_ci			break;
207862306a36Sopenharmony_ci		} else {
207962306a36Sopenharmony_ci			pr_vdebug("unknown descriptor: %d for class %d\n",
208062306a36Sopenharmony_ci			      _ds->bDescriptorType, *current_class);
208162306a36Sopenharmony_ci			return -EINVAL;
208262306a36Sopenharmony_ci		}
208362306a36Sopenharmony_ci
208462306a36Sopenharmony_ci	case USB_DT_OTG:
208562306a36Sopenharmony_ci		if (length != sizeof(struct usb_otg_descriptor))
208662306a36Sopenharmony_ci			goto inv_length;
208762306a36Sopenharmony_ci		break;
208862306a36Sopenharmony_ci
208962306a36Sopenharmony_ci	case USB_DT_INTERFACE_ASSOCIATION: {
209062306a36Sopenharmony_ci		struct usb_interface_assoc_descriptor *ds = (void *)_ds;
209162306a36Sopenharmony_ci		pr_vdebug("interface association descriptor\n");
209262306a36Sopenharmony_ci		if (length != sizeof *ds)
209362306a36Sopenharmony_ci			goto inv_length;
209462306a36Sopenharmony_ci		if (ds->iFunction)
209562306a36Sopenharmony_ci			__entity(STRING, ds->iFunction);
209662306a36Sopenharmony_ci	}
209762306a36Sopenharmony_ci		break;
209862306a36Sopenharmony_ci
209962306a36Sopenharmony_ci	case USB_DT_SS_ENDPOINT_COMP:
210062306a36Sopenharmony_ci		pr_vdebug("EP SS companion descriptor\n");
210162306a36Sopenharmony_ci		if (length != sizeof(struct usb_ss_ep_comp_descriptor))
210262306a36Sopenharmony_ci			goto inv_length;
210362306a36Sopenharmony_ci		break;
210462306a36Sopenharmony_ci
210562306a36Sopenharmony_ci	case USB_DT_OTHER_SPEED_CONFIG:
210662306a36Sopenharmony_ci	case USB_DT_INTERFACE_POWER:
210762306a36Sopenharmony_ci	case USB_DT_DEBUG:
210862306a36Sopenharmony_ci	case USB_DT_SECURITY:
210962306a36Sopenharmony_ci	case USB_DT_CS_RADIO_CONTROL:
211062306a36Sopenharmony_ci		/* TODO */
211162306a36Sopenharmony_ci		pr_vdebug("unimplemented descriptor: %d\n", _ds->bDescriptorType);
211262306a36Sopenharmony_ci		return -EINVAL;
211362306a36Sopenharmony_ci
211462306a36Sopenharmony_ci	default:
211562306a36Sopenharmony_ci		/* We should never be here */
211662306a36Sopenharmony_ci		pr_vdebug("unknown descriptor: %d\n", _ds->bDescriptorType);
211762306a36Sopenharmony_ci		return -EINVAL;
211862306a36Sopenharmony_ci
211962306a36Sopenharmony_ciinv_length:
212062306a36Sopenharmony_ci		pr_vdebug("invalid length: %d (descriptor %d)\n",
212162306a36Sopenharmony_ci			  _ds->bLength, _ds->bDescriptorType);
212262306a36Sopenharmony_ci		return -EINVAL;
212362306a36Sopenharmony_ci	}
212462306a36Sopenharmony_ci
212562306a36Sopenharmony_ci#undef __entity
212662306a36Sopenharmony_ci#undef __entity_check_DESCRIPTOR
212762306a36Sopenharmony_ci#undef __entity_check_INTERFACE
212862306a36Sopenharmony_ci#undef __entity_check_STRING
212962306a36Sopenharmony_ci#undef __entity_check_ENDPOINT
213062306a36Sopenharmony_ci
213162306a36Sopenharmony_ci	return length;
213262306a36Sopenharmony_ci}
213362306a36Sopenharmony_ci
213462306a36Sopenharmony_cistatic int __must_check ffs_do_descs(unsigned count, char *data, unsigned len,
213562306a36Sopenharmony_ci				     ffs_entity_callback entity, void *priv)
213662306a36Sopenharmony_ci{
213762306a36Sopenharmony_ci	const unsigned _len = len;
213862306a36Sopenharmony_ci	unsigned long num = 0;
213962306a36Sopenharmony_ci	int current_class = -1;
214062306a36Sopenharmony_ci
214162306a36Sopenharmony_ci	for (;;) {
214262306a36Sopenharmony_ci		int ret;
214362306a36Sopenharmony_ci
214462306a36Sopenharmony_ci		if (num == count)
214562306a36Sopenharmony_ci			data = NULL;
214662306a36Sopenharmony_ci
214762306a36Sopenharmony_ci		/* Record "descriptor" entity */
214862306a36Sopenharmony_ci		ret = entity(FFS_DESCRIPTOR, (u8 *)num, (void *)data, priv);
214962306a36Sopenharmony_ci		if (ret < 0) {
215062306a36Sopenharmony_ci			pr_debug("entity DESCRIPTOR(%02lx); ret = %d\n",
215162306a36Sopenharmony_ci				 num, ret);
215262306a36Sopenharmony_ci			return ret;
215362306a36Sopenharmony_ci		}
215462306a36Sopenharmony_ci
215562306a36Sopenharmony_ci		if (!data)
215662306a36Sopenharmony_ci			return _len - len;
215762306a36Sopenharmony_ci
215862306a36Sopenharmony_ci		ret = ffs_do_single_desc(data, len, entity, priv,
215962306a36Sopenharmony_ci			&current_class);
216062306a36Sopenharmony_ci		if (ret < 0) {
216162306a36Sopenharmony_ci			pr_debug("%s returns %d\n", __func__, ret);
216262306a36Sopenharmony_ci			return ret;
216362306a36Sopenharmony_ci		}
216462306a36Sopenharmony_ci
216562306a36Sopenharmony_ci		len -= ret;
216662306a36Sopenharmony_ci		data += ret;
216762306a36Sopenharmony_ci		++num;
216862306a36Sopenharmony_ci	}
216962306a36Sopenharmony_ci}
217062306a36Sopenharmony_ci
217162306a36Sopenharmony_cistatic int __ffs_data_do_entity(enum ffs_entity_type type,
217262306a36Sopenharmony_ci				u8 *valuep, struct usb_descriptor_header *desc,
217362306a36Sopenharmony_ci				void *priv)
217462306a36Sopenharmony_ci{
217562306a36Sopenharmony_ci	struct ffs_desc_helper *helper = priv;
217662306a36Sopenharmony_ci	struct usb_endpoint_descriptor *d;
217762306a36Sopenharmony_ci
217862306a36Sopenharmony_ci	switch (type) {
217962306a36Sopenharmony_ci	case FFS_DESCRIPTOR:
218062306a36Sopenharmony_ci		break;
218162306a36Sopenharmony_ci
218262306a36Sopenharmony_ci	case FFS_INTERFACE:
218362306a36Sopenharmony_ci		/*
218462306a36Sopenharmony_ci		 * Interfaces are indexed from zero so if we
218562306a36Sopenharmony_ci		 * encountered interface "n" then there are at least
218662306a36Sopenharmony_ci		 * "n+1" interfaces.
218762306a36Sopenharmony_ci		 */
218862306a36Sopenharmony_ci		if (*valuep >= helper->interfaces_count)
218962306a36Sopenharmony_ci			helper->interfaces_count = *valuep + 1;
219062306a36Sopenharmony_ci		break;
219162306a36Sopenharmony_ci
219262306a36Sopenharmony_ci	case FFS_STRING:
219362306a36Sopenharmony_ci		/*
219462306a36Sopenharmony_ci		 * Strings are indexed from 1 (0 is reserved
219562306a36Sopenharmony_ci		 * for languages list)
219662306a36Sopenharmony_ci		 */
219762306a36Sopenharmony_ci		if (*valuep > helper->ffs->strings_count)
219862306a36Sopenharmony_ci			helper->ffs->strings_count = *valuep;
219962306a36Sopenharmony_ci		break;
220062306a36Sopenharmony_ci
220162306a36Sopenharmony_ci	case FFS_ENDPOINT:
220262306a36Sopenharmony_ci		d = (void *)desc;
220362306a36Sopenharmony_ci		helper->eps_count++;
220462306a36Sopenharmony_ci		if (helper->eps_count >= FFS_MAX_EPS_COUNT)
220562306a36Sopenharmony_ci			return -EINVAL;
220662306a36Sopenharmony_ci		/* Check if descriptors for any speed were already parsed */
220762306a36Sopenharmony_ci		if (!helper->ffs->eps_count && !helper->ffs->interfaces_count)
220862306a36Sopenharmony_ci			helper->ffs->eps_addrmap[helper->eps_count] =
220962306a36Sopenharmony_ci				d->bEndpointAddress;
221062306a36Sopenharmony_ci		else if (helper->ffs->eps_addrmap[helper->eps_count] !=
221162306a36Sopenharmony_ci				d->bEndpointAddress)
221262306a36Sopenharmony_ci			return -EINVAL;
221362306a36Sopenharmony_ci		break;
221462306a36Sopenharmony_ci	}
221562306a36Sopenharmony_ci
221662306a36Sopenharmony_ci	return 0;
221762306a36Sopenharmony_ci}
221862306a36Sopenharmony_ci
221962306a36Sopenharmony_cistatic int __ffs_do_os_desc_header(enum ffs_os_desc_type *next_type,
222062306a36Sopenharmony_ci				   struct usb_os_desc_header *desc)
222162306a36Sopenharmony_ci{
222262306a36Sopenharmony_ci	u16 bcd_version = le16_to_cpu(desc->bcdVersion);
222362306a36Sopenharmony_ci	u16 w_index = le16_to_cpu(desc->wIndex);
222462306a36Sopenharmony_ci
222562306a36Sopenharmony_ci	if (bcd_version == 0x1) {
222662306a36Sopenharmony_ci		pr_warn("bcdVersion must be 0x0100, stored in Little Endian order. "
222762306a36Sopenharmony_ci			"Userspace driver should be fixed, accepting 0x0001 for compatibility.\n");
222862306a36Sopenharmony_ci	} else if (bcd_version != 0x100) {
222962306a36Sopenharmony_ci		pr_vdebug("unsupported os descriptors version: 0x%x\n",
223062306a36Sopenharmony_ci			  bcd_version);
223162306a36Sopenharmony_ci		return -EINVAL;
223262306a36Sopenharmony_ci	}
223362306a36Sopenharmony_ci	switch (w_index) {
223462306a36Sopenharmony_ci	case 0x4:
223562306a36Sopenharmony_ci		*next_type = FFS_OS_DESC_EXT_COMPAT;
223662306a36Sopenharmony_ci		break;
223762306a36Sopenharmony_ci	case 0x5:
223862306a36Sopenharmony_ci		*next_type = FFS_OS_DESC_EXT_PROP;
223962306a36Sopenharmony_ci		break;
224062306a36Sopenharmony_ci	default:
224162306a36Sopenharmony_ci		pr_vdebug("unsupported os descriptor type: %d", w_index);
224262306a36Sopenharmony_ci		return -EINVAL;
224362306a36Sopenharmony_ci	}
224462306a36Sopenharmony_ci
224562306a36Sopenharmony_ci	return sizeof(*desc);
224662306a36Sopenharmony_ci}
224762306a36Sopenharmony_ci
224862306a36Sopenharmony_ci/*
224962306a36Sopenharmony_ci * Process all extended compatibility/extended property descriptors
225062306a36Sopenharmony_ci * of a feature descriptor
225162306a36Sopenharmony_ci */
225262306a36Sopenharmony_cistatic int __must_check ffs_do_single_os_desc(char *data, unsigned len,
225362306a36Sopenharmony_ci					      enum ffs_os_desc_type type,
225462306a36Sopenharmony_ci					      u16 feature_count,
225562306a36Sopenharmony_ci					      ffs_os_desc_callback entity,
225662306a36Sopenharmony_ci					      void *priv,
225762306a36Sopenharmony_ci					      struct usb_os_desc_header *h)
225862306a36Sopenharmony_ci{
225962306a36Sopenharmony_ci	int ret;
226062306a36Sopenharmony_ci	const unsigned _len = len;
226162306a36Sopenharmony_ci
226262306a36Sopenharmony_ci	/* loop over all ext compat/ext prop descriptors */
226362306a36Sopenharmony_ci	while (feature_count--) {
226462306a36Sopenharmony_ci		ret = entity(type, h, data, len, priv);
226562306a36Sopenharmony_ci		if (ret < 0) {
226662306a36Sopenharmony_ci			pr_debug("bad OS descriptor, type: %d\n", type);
226762306a36Sopenharmony_ci			return ret;
226862306a36Sopenharmony_ci		}
226962306a36Sopenharmony_ci		data += ret;
227062306a36Sopenharmony_ci		len -= ret;
227162306a36Sopenharmony_ci	}
227262306a36Sopenharmony_ci	return _len - len;
227362306a36Sopenharmony_ci}
227462306a36Sopenharmony_ci
227562306a36Sopenharmony_ci/* Process a number of complete Feature Descriptors (Ext Compat or Ext Prop) */
227662306a36Sopenharmony_cistatic int __must_check ffs_do_os_descs(unsigned count,
227762306a36Sopenharmony_ci					char *data, unsigned len,
227862306a36Sopenharmony_ci					ffs_os_desc_callback entity, void *priv)
227962306a36Sopenharmony_ci{
228062306a36Sopenharmony_ci	const unsigned _len = len;
228162306a36Sopenharmony_ci	unsigned long num = 0;
228262306a36Sopenharmony_ci
228362306a36Sopenharmony_ci	for (num = 0; num < count; ++num) {
228462306a36Sopenharmony_ci		int ret;
228562306a36Sopenharmony_ci		enum ffs_os_desc_type type;
228662306a36Sopenharmony_ci		u16 feature_count;
228762306a36Sopenharmony_ci		struct usb_os_desc_header *desc = (void *)data;
228862306a36Sopenharmony_ci
228962306a36Sopenharmony_ci		if (len < sizeof(*desc))
229062306a36Sopenharmony_ci			return -EINVAL;
229162306a36Sopenharmony_ci
229262306a36Sopenharmony_ci		/*
229362306a36Sopenharmony_ci		 * Record "descriptor" entity.
229462306a36Sopenharmony_ci		 * Process dwLength, bcdVersion, wIndex, get b/wCount.
229562306a36Sopenharmony_ci		 * Move the data pointer to the beginning of extended
229662306a36Sopenharmony_ci		 * compatibilities proper or extended properties proper
229762306a36Sopenharmony_ci		 * portions of the data
229862306a36Sopenharmony_ci		 */
229962306a36Sopenharmony_ci		if (le32_to_cpu(desc->dwLength) > len)
230062306a36Sopenharmony_ci			return -EINVAL;
230162306a36Sopenharmony_ci
230262306a36Sopenharmony_ci		ret = __ffs_do_os_desc_header(&type, desc);
230362306a36Sopenharmony_ci		if (ret < 0) {
230462306a36Sopenharmony_ci			pr_debug("entity OS_DESCRIPTOR(%02lx); ret = %d\n",
230562306a36Sopenharmony_ci				 num, ret);
230662306a36Sopenharmony_ci			return ret;
230762306a36Sopenharmony_ci		}
230862306a36Sopenharmony_ci		/*
230962306a36Sopenharmony_ci		 * 16-bit hex "?? 00" Little Endian looks like 8-bit hex "??"
231062306a36Sopenharmony_ci		 */
231162306a36Sopenharmony_ci		feature_count = le16_to_cpu(desc->wCount);
231262306a36Sopenharmony_ci		if (type == FFS_OS_DESC_EXT_COMPAT &&
231362306a36Sopenharmony_ci		    (feature_count > 255 || desc->Reserved))
231462306a36Sopenharmony_ci				return -EINVAL;
231562306a36Sopenharmony_ci		len -= ret;
231662306a36Sopenharmony_ci		data += ret;
231762306a36Sopenharmony_ci
231862306a36Sopenharmony_ci		/*
231962306a36Sopenharmony_ci		 * Process all function/property descriptors
232062306a36Sopenharmony_ci		 * of this Feature Descriptor
232162306a36Sopenharmony_ci		 */
232262306a36Sopenharmony_ci		ret = ffs_do_single_os_desc(data, len, type,
232362306a36Sopenharmony_ci					    feature_count, entity, priv, desc);
232462306a36Sopenharmony_ci		if (ret < 0) {
232562306a36Sopenharmony_ci			pr_debug("%s returns %d\n", __func__, ret);
232662306a36Sopenharmony_ci			return ret;
232762306a36Sopenharmony_ci		}
232862306a36Sopenharmony_ci
232962306a36Sopenharmony_ci		len -= ret;
233062306a36Sopenharmony_ci		data += ret;
233162306a36Sopenharmony_ci	}
233262306a36Sopenharmony_ci	return _len - len;
233362306a36Sopenharmony_ci}
233462306a36Sopenharmony_ci
233562306a36Sopenharmony_ci/*
233662306a36Sopenharmony_ci * Validate contents of the buffer from userspace related to OS descriptors.
233762306a36Sopenharmony_ci */
233862306a36Sopenharmony_cistatic int __ffs_data_do_os_desc(enum ffs_os_desc_type type,
233962306a36Sopenharmony_ci				 struct usb_os_desc_header *h, void *data,
234062306a36Sopenharmony_ci				 unsigned len, void *priv)
234162306a36Sopenharmony_ci{
234262306a36Sopenharmony_ci	struct ffs_data *ffs = priv;
234362306a36Sopenharmony_ci	u8 length;
234462306a36Sopenharmony_ci
234562306a36Sopenharmony_ci	switch (type) {
234662306a36Sopenharmony_ci	case FFS_OS_DESC_EXT_COMPAT: {
234762306a36Sopenharmony_ci		struct usb_ext_compat_desc *d = data;
234862306a36Sopenharmony_ci		int i;
234962306a36Sopenharmony_ci
235062306a36Sopenharmony_ci		if (len < sizeof(*d) ||
235162306a36Sopenharmony_ci		    d->bFirstInterfaceNumber >= ffs->interfaces_count)
235262306a36Sopenharmony_ci			return -EINVAL;
235362306a36Sopenharmony_ci		if (d->Reserved1 != 1) {
235462306a36Sopenharmony_ci			/*
235562306a36Sopenharmony_ci			 * According to the spec, Reserved1 must be set to 1
235662306a36Sopenharmony_ci			 * but older kernels incorrectly rejected non-zero
235762306a36Sopenharmony_ci			 * values.  We fix it here to avoid returning EINVAL
235862306a36Sopenharmony_ci			 * in response to values we used to accept.
235962306a36Sopenharmony_ci			 */
236062306a36Sopenharmony_ci			pr_debug("usb_ext_compat_desc::Reserved1 forced to 1\n");
236162306a36Sopenharmony_ci			d->Reserved1 = 1;
236262306a36Sopenharmony_ci		}
236362306a36Sopenharmony_ci		for (i = 0; i < ARRAY_SIZE(d->Reserved2); ++i)
236462306a36Sopenharmony_ci			if (d->Reserved2[i])
236562306a36Sopenharmony_ci				return -EINVAL;
236662306a36Sopenharmony_ci
236762306a36Sopenharmony_ci		length = sizeof(struct usb_ext_compat_desc);
236862306a36Sopenharmony_ci	}
236962306a36Sopenharmony_ci		break;
237062306a36Sopenharmony_ci	case FFS_OS_DESC_EXT_PROP: {
237162306a36Sopenharmony_ci		struct usb_ext_prop_desc *d = data;
237262306a36Sopenharmony_ci		u32 type, pdl;
237362306a36Sopenharmony_ci		u16 pnl;
237462306a36Sopenharmony_ci
237562306a36Sopenharmony_ci		if (len < sizeof(*d) || h->interface >= ffs->interfaces_count)
237662306a36Sopenharmony_ci			return -EINVAL;
237762306a36Sopenharmony_ci		length = le32_to_cpu(d->dwSize);
237862306a36Sopenharmony_ci		if (len < length)
237962306a36Sopenharmony_ci			return -EINVAL;
238062306a36Sopenharmony_ci		type = le32_to_cpu(d->dwPropertyDataType);
238162306a36Sopenharmony_ci		if (type < USB_EXT_PROP_UNICODE ||
238262306a36Sopenharmony_ci		    type > USB_EXT_PROP_UNICODE_MULTI) {
238362306a36Sopenharmony_ci			pr_vdebug("unsupported os descriptor property type: %d",
238462306a36Sopenharmony_ci				  type);
238562306a36Sopenharmony_ci			return -EINVAL;
238662306a36Sopenharmony_ci		}
238762306a36Sopenharmony_ci		pnl = le16_to_cpu(d->wPropertyNameLength);
238862306a36Sopenharmony_ci		if (length < 14 + pnl) {
238962306a36Sopenharmony_ci			pr_vdebug("invalid os descriptor length: %d pnl:%d (descriptor %d)\n",
239062306a36Sopenharmony_ci				  length, pnl, type);
239162306a36Sopenharmony_ci			return -EINVAL;
239262306a36Sopenharmony_ci		}
239362306a36Sopenharmony_ci		pdl = le32_to_cpu(*(__le32 *)((u8 *)data + 10 + pnl));
239462306a36Sopenharmony_ci		if (length != 14 + pnl + pdl) {
239562306a36Sopenharmony_ci			pr_vdebug("invalid os descriptor length: %d pnl:%d pdl:%d (descriptor %d)\n",
239662306a36Sopenharmony_ci				  length, pnl, pdl, type);
239762306a36Sopenharmony_ci			return -EINVAL;
239862306a36Sopenharmony_ci		}
239962306a36Sopenharmony_ci		++ffs->ms_os_descs_ext_prop_count;
240062306a36Sopenharmony_ci		/* property name reported to the host as "WCHAR"s */
240162306a36Sopenharmony_ci		ffs->ms_os_descs_ext_prop_name_len += pnl * 2;
240262306a36Sopenharmony_ci		ffs->ms_os_descs_ext_prop_data_len += pdl;
240362306a36Sopenharmony_ci	}
240462306a36Sopenharmony_ci		break;
240562306a36Sopenharmony_ci	default:
240662306a36Sopenharmony_ci		pr_vdebug("unknown descriptor: %d\n", type);
240762306a36Sopenharmony_ci		return -EINVAL;
240862306a36Sopenharmony_ci	}
240962306a36Sopenharmony_ci	return length;
241062306a36Sopenharmony_ci}
241162306a36Sopenharmony_ci
241262306a36Sopenharmony_cistatic int __ffs_data_got_descs(struct ffs_data *ffs,
241362306a36Sopenharmony_ci				char *const _data, size_t len)
241462306a36Sopenharmony_ci{
241562306a36Sopenharmony_ci	char *data = _data, *raw_descs;
241662306a36Sopenharmony_ci	unsigned os_descs_count = 0, counts[3], flags;
241762306a36Sopenharmony_ci	int ret = -EINVAL, i;
241862306a36Sopenharmony_ci	struct ffs_desc_helper helper;
241962306a36Sopenharmony_ci
242062306a36Sopenharmony_ci	if (get_unaligned_le32(data + 4) != len)
242162306a36Sopenharmony_ci		goto error;
242262306a36Sopenharmony_ci
242362306a36Sopenharmony_ci	switch (get_unaligned_le32(data)) {
242462306a36Sopenharmony_ci	case FUNCTIONFS_DESCRIPTORS_MAGIC:
242562306a36Sopenharmony_ci		flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC;
242662306a36Sopenharmony_ci		data += 8;
242762306a36Sopenharmony_ci		len  -= 8;
242862306a36Sopenharmony_ci		break;
242962306a36Sopenharmony_ci	case FUNCTIONFS_DESCRIPTORS_MAGIC_V2:
243062306a36Sopenharmony_ci		flags = get_unaligned_le32(data + 8);
243162306a36Sopenharmony_ci		ffs->user_flags = flags;
243262306a36Sopenharmony_ci		if (flags & ~(FUNCTIONFS_HAS_FS_DESC |
243362306a36Sopenharmony_ci			      FUNCTIONFS_HAS_HS_DESC |
243462306a36Sopenharmony_ci			      FUNCTIONFS_HAS_SS_DESC |
243562306a36Sopenharmony_ci			      FUNCTIONFS_HAS_MS_OS_DESC |
243662306a36Sopenharmony_ci			      FUNCTIONFS_VIRTUAL_ADDR |
243762306a36Sopenharmony_ci			      FUNCTIONFS_EVENTFD |
243862306a36Sopenharmony_ci			      FUNCTIONFS_ALL_CTRL_RECIP |
243962306a36Sopenharmony_ci			      FUNCTIONFS_CONFIG0_SETUP)) {
244062306a36Sopenharmony_ci			ret = -ENOSYS;
244162306a36Sopenharmony_ci			goto error;
244262306a36Sopenharmony_ci		}
244362306a36Sopenharmony_ci		data += 12;
244462306a36Sopenharmony_ci		len  -= 12;
244562306a36Sopenharmony_ci		break;
244662306a36Sopenharmony_ci	default:
244762306a36Sopenharmony_ci		goto error;
244862306a36Sopenharmony_ci	}
244962306a36Sopenharmony_ci
245062306a36Sopenharmony_ci	if (flags & FUNCTIONFS_EVENTFD) {
245162306a36Sopenharmony_ci		if (len < 4)
245262306a36Sopenharmony_ci			goto error;
245362306a36Sopenharmony_ci		ffs->ffs_eventfd =
245462306a36Sopenharmony_ci			eventfd_ctx_fdget((int)get_unaligned_le32(data));
245562306a36Sopenharmony_ci		if (IS_ERR(ffs->ffs_eventfd)) {
245662306a36Sopenharmony_ci			ret = PTR_ERR(ffs->ffs_eventfd);
245762306a36Sopenharmony_ci			ffs->ffs_eventfd = NULL;
245862306a36Sopenharmony_ci			goto error;
245962306a36Sopenharmony_ci		}
246062306a36Sopenharmony_ci		data += 4;
246162306a36Sopenharmony_ci		len  -= 4;
246262306a36Sopenharmony_ci	}
246362306a36Sopenharmony_ci
246462306a36Sopenharmony_ci	/* Read fs_count, hs_count and ss_count (if present) */
246562306a36Sopenharmony_ci	for (i = 0; i < 3; ++i) {
246662306a36Sopenharmony_ci		if (!(flags & (1 << i))) {
246762306a36Sopenharmony_ci			counts[i] = 0;
246862306a36Sopenharmony_ci		} else if (len < 4) {
246962306a36Sopenharmony_ci			goto error;
247062306a36Sopenharmony_ci		} else {
247162306a36Sopenharmony_ci			counts[i] = get_unaligned_le32(data);
247262306a36Sopenharmony_ci			data += 4;
247362306a36Sopenharmony_ci			len  -= 4;
247462306a36Sopenharmony_ci		}
247562306a36Sopenharmony_ci	}
247662306a36Sopenharmony_ci	if (flags & (1 << i)) {
247762306a36Sopenharmony_ci		if (len < 4) {
247862306a36Sopenharmony_ci			goto error;
247962306a36Sopenharmony_ci		}
248062306a36Sopenharmony_ci		os_descs_count = get_unaligned_le32(data);
248162306a36Sopenharmony_ci		data += 4;
248262306a36Sopenharmony_ci		len -= 4;
248362306a36Sopenharmony_ci	}
248462306a36Sopenharmony_ci
248562306a36Sopenharmony_ci	/* Read descriptors */
248662306a36Sopenharmony_ci	raw_descs = data;
248762306a36Sopenharmony_ci	helper.ffs = ffs;
248862306a36Sopenharmony_ci	for (i = 0; i < 3; ++i) {
248962306a36Sopenharmony_ci		if (!counts[i])
249062306a36Sopenharmony_ci			continue;
249162306a36Sopenharmony_ci		helper.interfaces_count = 0;
249262306a36Sopenharmony_ci		helper.eps_count = 0;
249362306a36Sopenharmony_ci		ret = ffs_do_descs(counts[i], data, len,
249462306a36Sopenharmony_ci				   __ffs_data_do_entity, &helper);
249562306a36Sopenharmony_ci		if (ret < 0)
249662306a36Sopenharmony_ci			goto error;
249762306a36Sopenharmony_ci		if (!ffs->eps_count && !ffs->interfaces_count) {
249862306a36Sopenharmony_ci			ffs->eps_count = helper.eps_count;
249962306a36Sopenharmony_ci			ffs->interfaces_count = helper.interfaces_count;
250062306a36Sopenharmony_ci		} else {
250162306a36Sopenharmony_ci			if (ffs->eps_count != helper.eps_count) {
250262306a36Sopenharmony_ci				ret = -EINVAL;
250362306a36Sopenharmony_ci				goto error;
250462306a36Sopenharmony_ci			}
250562306a36Sopenharmony_ci			if (ffs->interfaces_count != helper.interfaces_count) {
250662306a36Sopenharmony_ci				ret = -EINVAL;
250762306a36Sopenharmony_ci				goto error;
250862306a36Sopenharmony_ci			}
250962306a36Sopenharmony_ci		}
251062306a36Sopenharmony_ci		data += ret;
251162306a36Sopenharmony_ci		len  -= ret;
251262306a36Sopenharmony_ci	}
251362306a36Sopenharmony_ci	if (os_descs_count) {
251462306a36Sopenharmony_ci		ret = ffs_do_os_descs(os_descs_count, data, len,
251562306a36Sopenharmony_ci				      __ffs_data_do_os_desc, ffs);
251662306a36Sopenharmony_ci		if (ret < 0)
251762306a36Sopenharmony_ci			goto error;
251862306a36Sopenharmony_ci		data += ret;
251962306a36Sopenharmony_ci		len -= ret;
252062306a36Sopenharmony_ci	}
252162306a36Sopenharmony_ci
252262306a36Sopenharmony_ci	if (raw_descs == data || len) {
252362306a36Sopenharmony_ci		ret = -EINVAL;
252462306a36Sopenharmony_ci		goto error;
252562306a36Sopenharmony_ci	}
252662306a36Sopenharmony_ci
252762306a36Sopenharmony_ci	ffs->raw_descs_data	= _data;
252862306a36Sopenharmony_ci	ffs->raw_descs		= raw_descs;
252962306a36Sopenharmony_ci	ffs->raw_descs_length	= data - raw_descs;
253062306a36Sopenharmony_ci	ffs->fs_descs_count	= counts[0];
253162306a36Sopenharmony_ci	ffs->hs_descs_count	= counts[1];
253262306a36Sopenharmony_ci	ffs->ss_descs_count	= counts[2];
253362306a36Sopenharmony_ci	ffs->ms_os_descs_count	= os_descs_count;
253462306a36Sopenharmony_ci
253562306a36Sopenharmony_ci	return 0;
253662306a36Sopenharmony_ci
253762306a36Sopenharmony_cierror:
253862306a36Sopenharmony_ci	kfree(_data);
253962306a36Sopenharmony_ci	return ret;
254062306a36Sopenharmony_ci}
254162306a36Sopenharmony_ci
254262306a36Sopenharmony_cistatic int __ffs_data_got_strings(struct ffs_data *ffs,
254362306a36Sopenharmony_ci				  char *const _data, size_t len)
254462306a36Sopenharmony_ci{
254562306a36Sopenharmony_ci	u32 str_count, needed_count, lang_count;
254662306a36Sopenharmony_ci	struct usb_gadget_strings **stringtabs, *t;
254762306a36Sopenharmony_ci	const char *data = _data;
254862306a36Sopenharmony_ci	struct usb_string *s;
254962306a36Sopenharmony_ci
255062306a36Sopenharmony_ci	if (len < 16 ||
255162306a36Sopenharmony_ci	    get_unaligned_le32(data) != FUNCTIONFS_STRINGS_MAGIC ||
255262306a36Sopenharmony_ci	    get_unaligned_le32(data + 4) != len)
255362306a36Sopenharmony_ci		goto error;
255462306a36Sopenharmony_ci	str_count  = get_unaligned_le32(data + 8);
255562306a36Sopenharmony_ci	lang_count = get_unaligned_le32(data + 12);
255662306a36Sopenharmony_ci
255762306a36Sopenharmony_ci	/* if one is zero the other must be zero */
255862306a36Sopenharmony_ci	if (!str_count != !lang_count)
255962306a36Sopenharmony_ci		goto error;
256062306a36Sopenharmony_ci
256162306a36Sopenharmony_ci	/* Do we have at least as many strings as descriptors need? */
256262306a36Sopenharmony_ci	needed_count = ffs->strings_count;
256362306a36Sopenharmony_ci	if (str_count < needed_count)
256462306a36Sopenharmony_ci		goto error;
256562306a36Sopenharmony_ci
256662306a36Sopenharmony_ci	/*
256762306a36Sopenharmony_ci	 * If we don't need any strings just return and free all
256862306a36Sopenharmony_ci	 * memory.
256962306a36Sopenharmony_ci	 */
257062306a36Sopenharmony_ci	if (!needed_count) {
257162306a36Sopenharmony_ci		kfree(_data);
257262306a36Sopenharmony_ci		return 0;
257362306a36Sopenharmony_ci	}
257462306a36Sopenharmony_ci
257562306a36Sopenharmony_ci	/* Allocate everything in one chunk so there's less maintenance. */
257662306a36Sopenharmony_ci	{
257762306a36Sopenharmony_ci		unsigned i = 0;
257862306a36Sopenharmony_ci		vla_group(d);
257962306a36Sopenharmony_ci		vla_item(d, struct usb_gadget_strings *, stringtabs,
258062306a36Sopenharmony_ci			size_add(lang_count, 1));
258162306a36Sopenharmony_ci		vla_item(d, struct usb_gadget_strings, stringtab, lang_count);
258262306a36Sopenharmony_ci		vla_item(d, struct usb_string, strings,
258362306a36Sopenharmony_ci			size_mul(lang_count, (needed_count + 1)));
258462306a36Sopenharmony_ci
258562306a36Sopenharmony_ci		char *vlabuf = kmalloc(vla_group_size(d), GFP_KERNEL);
258662306a36Sopenharmony_ci
258762306a36Sopenharmony_ci		if (!vlabuf) {
258862306a36Sopenharmony_ci			kfree(_data);
258962306a36Sopenharmony_ci			return -ENOMEM;
259062306a36Sopenharmony_ci		}
259162306a36Sopenharmony_ci
259262306a36Sopenharmony_ci		/* Initialize the VLA pointers */
259362306a36Sopenharmony_ci		stringtabs = vla_ptr(vlabuf, d, stringtabs);
259462306a36Sopenharmony_ci		t = vla_ptr(vlabuf, d, stringtab);
259562306a36Sopenharmony_ci		i = lang_count;
259662306a36Sopenharmony_ci		do {
259762306a36Sopenharmony_ci			*stringtabs++ = t++;
259862306a36Sopenharmony_ci		} while (--i);
259962306a36Sopenharmony_ci		*stringtabs = NULL;
260062306a36Sopenharmony_ci
260162306a36Sopenharmony_ci		/* stringtabs = vlabuf = d_stringtabs for later kfree */
260262306a36Sopenharmony_ci		stringtabs = vla_ptr(vlabuf, d, stringtabs);
260362306a36Sopenharmony_ci		t = vla_ptr(vlabuf, d, stringtab);
260462306a36Sopenharmony_ci		s = vla_ptr(vlabuf, d, strings);
260562306a36Sopenharmony_ci	}
260662306a36Sopenharmony_ci
260762306a36Sopenharmony_ci	/* For each language */
260862306a36Sopenharmony_ci	data += 16;
260962306a36Sopenharmony_ci	len -= 16;
261062306a36Sopenharmony_ci
261162306a36Sopenharmony_ci	do { /* lang_count > 0 so we can use do-while */
261262306a36Sopenharmony_ci		unsigned needed = needed_count;
261362306a36Sopenharmony_ci		u32 str_per_lang = str_count;
261462306a36Sopenharmony_ci
261562306a36Sopenharmony_ci		if (len < 3)
261662306a36Sopenharmony_ci			goto error_free;
261762306a36Sopenharmony_ci		t->language = get_unaligned_le16(data);
261862306a36Sopenharmony_ci		t->strings  = s;
261962306a36Sopenharmony_ci		++t;
262062306a36Sopenharmony_ci
262162306a36Sopenharmony_ci		data += 2;
262262306a36Sopenharmony_ci		len -= 2;
262362306a36Sopenharmony_ci
262462306a36Sopenharmony_ci		/* For each string */
262562306a36Sopenharmony_ci		do { /* str_count > 0 so we can use do-while */
262662306a36Sopenharmony_ci			size_t length = strnlen(data, len);
262762306a36Sopenharmony_ci
262862306a36Sopenharmony_ci			if (length == len)
262962306a36Sopenharmony_ci				goto error_free;
263062306a36Sopenharmony_ci
263162306a36Sopenharmony_ci			/*
263262306a36Sopenharmony_ci			 * User may provide more strings then we need,
263362306a36Sopenharmony_ci			 * if that's the case we simply ignore the
263462306a36Sopenharmony_ci			 * rest
263562306a36Sopenharmony_ci			 */
263662306a36Sopenharmony_ci			if (needed) {
263762306a36Sopenharmony_ci				/*
263862306a36Sopenharmony_ci				 * s->id will be set while adding
263962306a36Sopenharmony_ci				 * function to configuration so for
264062306a36Sopenharmony_ci				 * now just leave garbage here.
264162306a36Sopenharmony_ci				 */
264262306a36Sopenharmony_ci				s->s = data;
264362306a36Sopenharmony_ci				--needed;
264462306a36Sopenharmony_ci				++s;
264562306a36Sopenharmony_ci			}
264662306a36Sopenharmony_ci
264762306a36Sopenharmony_ci			data += length + 1;
264862306a36Sopenharmony_ci			len -= length + 1;
264962306a36Sopenharmony_ci		} while (--str_per_lang);
265062306a36Sopenharmony_ci
265162306a36Sopenharmony_ci		s->id = 0;   /* terminator */
265262306a36Sopenharmony_ci		s->s = NULL;
265362306a36Sopenharmony_ci		++s;
265462306a36Sopenharmony_ci
265562306a36Sopenharmony_ci	} while (--lang_count);
265662306a36Sopenharmony_ci
265762306a36Sopenharmony_ci	/* Some garbage left? */
265862306a36Sopenharmony_ci	if (len)
265962306a36Sopenharmony_ci		goto error_free;
266062306a36Sopenharmony_ci
266162306a36Sopenharmony_ci	/* Done! */
266262306a36Sopenharmony_ci	ffs->stringtabs = stringtabs;
266362306a36Sopenharmony_ci	ffs->raw_strings = _data;
266462306a36Sopenharmony_ci
266562306a36Sopenharmony_ci	return 0;
266662306a36Sopenharmony_ci
266762306a36Sopenharmony_cierror_free:
266862306a36Sopenharmony_ci	kfree(stringtabs);
266962306a36Sopenharmony_cierror:
267062306a36Sopenharmony_ci	kfree(_data);
267162306a36Sopenharmony_ci	return -EINVAL;
267262306a36Sopenharmony_ci}
267362306a36Sopenharmony_ci
267462306a36Sopenharmony_ci
267562306a36Sopenharmony_ci/* Events handling and management *******************************************/
267662306a36Sopenharmony_ci
267762306a36Sopenharmony_cistatic void __ffs_event_add(struct ffs_data *ffs,
267862306a36Sopenharmony_ci			    enum usb_functionfs_event_type type)
267962306a36Sopenharmony_ci{
268062306a36Sopenharmony_ci	enum usb_functionfs_event_type rem_type1, rem_type2 = type;
268162306a36Sopenharmony_ci	int neg = 0;
268262306a36Sopenharmony_ci
268362306a36Sopenharmony_ci	/*
268462306a36Sopenharmony_ci	 * Abort any unhandled setup
268562306a36Sopenharmony_ci	 *
268662306a36Sopenharmony_ci	 * We do not need to worry about some cmpxchg() changing value
268762306a36Sopenharmony_ci	 * of ffs->setup_state without holding the lock because when
268862306a36Sopenharmony_ci	 * state is FFS_SETUP_PENDING cmpxchg() in several places in
268962306a36Sopenharmony_ci	 * the source does nothing.
269062306a36Sopenharmony_ci	 */
269162306a36Sopenharmony_ci	if (ffs->setup_state == FFS_SETUP_PENDING)
269262306a36Sopenharmony_ci		ffs->setup_state = FFS_SETUP_CANCELLED;
269362306a36Sopenharmony_ci
269462306a36Sopenharmony_ci	/*
269562306a36Sopenharmony_ci	 * Logic of this function guarantees that there are at most four pending
269662306a36Sopenharmony_ci	 * evens on ffs->ev.types queue.  This is important because the queue
269762306a36Sopenharmony_ci	 * has space for four elements only and __ffs_ep0_read_events function
269862306a36Sopenharmony_ci	 * depends on that limit as well.  If more event types are added, those
269962306a36Sopenharmony_ci	 * limits have to be revisited or guaranteed to still hold.
270062306a36Sopenharmony_ci	 */
270162306a36Sopenharmony_ci	switch (type) {
270262306a36Sopenharmony_ci	case FUNCTIONFS_RESUME:
270362306a36Sopenharmony_ci		rem_type2 = FUNCTIONFS_SUSPEND;
270462306a36Sopenharmony_ci		fallthrough;
270562306a36Sopenharmony_ci	case FUNCTIONFS_SUSPEND:
270662306a36Sopenharmony_ci	case FUNCTIONFS_SETUP:
270762306a36Sopenharmony_ci		rem_type1 = type;
270862306a36Sopenharmony_ci		/* Discard all similar events */
270962306a36Sopenharmony_ci		break;
271062306a36Sopenharmony_ci
271162306a36Sopenharmony_ci	case FUNCTIONFS_BIND:
271262306a36Sopenharmony_ci	case FUNCTIONFS_UNBIND:
271362306a36Sopenharmony_ci	case FUNCTIONFS_DISABLE:
271462306a36Sopenharmony_ci	case FUNCTIONFS_ENABLE:
271562306a36Sopenharmony_ci		/* Discard everything other then power management. */
271662306a36Sopenharmony_ci		rem_type1 = FUNCTIONFS_SUSPEND;
271762306a36Sopenharmony_ci		rem_type2 = FUNCTIONFS_RESUME;
271862306a36Sopenharmony_ci		neg = 1;
271962306a36Sopenharmony_ci		break;
272062306a36Sopenharmony_ci
272162306a36Sopenharmony_ci	default:
272262306a36Sopenharmony_ci		WARN(1, "%d: unknown event, this should not happen\n", type);
272362306a36Sopenharmony_ci		return;
272462306a36Sopenharmony_ci	}
272562306a36Sopenharmony_ci
272662306a36Sopenharmony_ci	{
272762306a36Sopenharmony_ci		u8 *ev  = ffs->ev.types, *out = ev;
272862306a36Sopenharmony_ci		unsigned n = ffs->ev.count;
272962306a36Sopenharmony_ci		for (; n; --n, ++ev)
273062306a36Sopenharmony_ci			if ((*ev == rem_type1 || *ev == rem_type2) == neg)
273162306a36Sopenharmony_ci				*out++ = *ev;
273262306a36Sopenharmony_ci			else
273362306a36Sopenharmony_ci				pr_vdebug("purging event %d\n", *ev);
273462306a36Sopenharmony_ci		ffs->ev.count = out - ffs->ev.types;
273562306a36Sopenharmony_ci	}
273662306a36Sopenharmony_ci
273762306a36Sopenharmony_ci	pr_vdebug("adding event %d\n", type);
273862306a36Sopenharmony_ci	ffs->ev.types[ffs->ev.count++] = type;
273962306a36Sopenharmony_ci	wake_up_locked(&ffs->ev.waitq);
274062306a36Sopenharmony_ci	if (ffs->ffs_eventfd)
274162306a36Sopenharmony_ci		eventfd_signal(ffs->ffs_eventfd, 1);
274262306a36Sopenharmony_ci}
274362306a36Sopenharmony_ci
274462306a36Sopenharmony_cistatic void ffs_event_add(struct ffs_data *ffs,
274562306a36Sopenharmony_ci			  enum usb_functionfs_event_type type)
274662306a36Sopenharmony_ci{
274762306a36Sopenharmony_ci	unsigned long flags;
274862306a36Sopenharmony_ci	spin_lock_irqsave(&ffs->ev.waitq.lock, flags);
274962306a36Sopenharmony_ci	__ffs_event_add(ffs, type);
275062306a36Sopenharmony_ci	spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags);
275162306a36Sopenharmony_ci}
275262306a36Sopenharmony_ci
275362306a36Sopenharmony_ci/* Bind/unbind USB function hooks *******************************************/
275462306a36Sopenharmony_ci
275562306a36Sopenharmony_cistatic int ffs_ep_addr2idx(struct ffs_data *ffs, u8 endpoint_address)
275662306a36Sopenharmony_ci{
275762306a36Sopenharmony_ci	int i;
275862306a36Sopenharmony_ci
275962306a36Sopenharmony_ci	for (i = 1; i < ARRAY_SIZE(ffs->eps_addrmap); ++i)
276062306a36Sopenharmony_ci		if (ffs->eps_addrmap[i] == endpoint_address)
276162306a36Sopenharmony_ci			return i;
276262306a36Sopenharmony_ci	return -ENOENT;
276362306a36Sopenharmony_ci}
276462306a36Sopenharmony_ci
276562306a36Sopenharmony_cistatic int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
276662306a36Sopenharmony_ci				    struct usb_descriptor_header *desc,
276762306a36Sopenharmony_ci				    void *priv)
276862306a36Sopenharmony_ci{
276962306a36Sopenharmony_ci	struct usb_endpoint_descriptor *ds = (void *)desc;
277062306a36Sopenharmony_ci	struct ffs_function *func = priv;
277162306a36Sopenharmony_ci	struct ffs_ep *ffs_ep;
277262306a36Sopenharmony_ci	unsigned ep_desc_id;
277362306a36Sopenharmony_ci	int idx;
277462306a36Sopenharmony_ci	static const char *speed_names[] = { "full", "high", "super" };
277562306a36Sopenharmony_ci
277662306a36Sopenharmony_ci	if (type != FFS_DESCRIPTOR)
277762306a36Sopenharmony_ci		return 0;
277862306a36Sopenharmony_ci
277962306a36Sopenharmony_ci	/*
278062306a36Sopenharmony_ci	 * If ss_descriptors is not NULL, we are reading super speed
278162306a36Sopenharmony_ci	 * descriptors; if hs_descriptors is not NULL, we are reading high
278262306a36Sopenharmony_ci	 * speed descriptors; otherwise, we are reading full speed
278362306a36Sopenharmony_ci	 * descriptors.
278462306a36Sopenharmony_ci	 */
278562306a36Sopenharmony_ci	if (func->function.ss_descriptors) {
278662306a36Sopenharmony_ci		ep_desc_id = 2;
278762306a36Sopenharmony_ci		func->function.ss_descriptors[(long)valuep] = desc;
278862306a36Sopenharmony_ci	} else if (func->function.hs_descriptors) {
278962306a36Sopenharmony_ci		ep_desc_id = 1;
279062306a36Sopenharmony_ci		func->function.hs_descriptors[(long)valuep] = desc;
279162306a36Sopenharmony_ci	} else {
279262306a36Sopenharmony_ci		ep_desc_id = 0;
279362306a36Sopenharmony_ci		func->function.fs_descriptors[(long)valuep]    = desc;
279462306a36Sopenharmony_ci	}
279562306a36Sopenharmony_ci
279662306a36Sopenharmony_ci	if (!desc || desc->bDescriptorType != USB_DT_ENDPOINT)
279762306a36Sopenharmony_ci		return 0;
279862306a36Sopenharmony_ci
279962306a36Sopenharmony_ci	idx = ffs_ep_addr2idx(func->ffs, ds->bEndpointAddress) - 1;
280062306a36Sopenharmony_ci	if (idx < 0)
280162306a36Sopenharmony_ci		return idx;
280262306a36Sopenharmony_ci
280362306a36Sopenharmony_ci	ffs_ep = func->eps + idx;
280462306a36Sopenharmony_ci
280562306a36Sopenharmony_ci	if (ffs_ep->descs[ep_desc_id]) {
280662306a36Sopenharmony_ci		pr_err("two %sspeed descriptors for EP %d\n",
280762306a36Sopenharmony_ci			  speed_names[ep_desc_id],
280862306a36Sopenharmony_ci			  ds->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
280962306a36Sopenharmony_ci		return -EINVAL;
281062306a36Sopenharmony_ci	}
281162306a36Sopenharmony_ci	ffs_ep->descs[ep_desc_id] = ds;
281262306a36Sopenharmony_ci
281362306a36Sopenharmony_ci	ffs_dump_mem(": Original  ep desc", ds, ds->bLength);
281462306a36Sopenharmony_ci	if (ffs_ep->ep) {
281562306a36Sopenharmony_ci		ds->bEndpointAddress = ffs_ep->descs[0]->bEndpointAddress;
281662306a36Sopenharmony_ci		if (!ds->wMaxPacketSize)
281762306a36Sopenharmony_ci			ds->wMaxPacketSize = ffs_ep->descs[0]->wMaxPacketSize;
281862306a36Sopenharmony_ci	} else {
281962306a36Sopenharmony_ci		struct usb_request *req;
282062306a36Sopenharmony_ci		struct usb_ep *ep;
282162306a36Sopenharmony_ci		u8 bEndpointAddress;
282262306a36Sopenharmony_ci		u16 wMaxPacketSize;
282362306a36Sopenharmony_ci
282462306a36Sopenharmony_ci		/*
282562306a36Sopenharmony_ci		 * We back up bEndpointAddress because autoconfig overwrites
282662306a36Sopenharmony_ci		 * it with physical endpoint address.
282762306a36Sopenharmony_ci		 */
282862306a36Sopenharmony_ci		bEndpointAddress = ds->bEndpointAddress;
282962306a36Sopenharmony_ci		/*
283062306a36Sopenharmony_ci		 * We back up wMaxPacketSize because autoconfig treats
283162306a36Sopenharmony_ci		 * endpoint descriptors as if they were full speed.
283262306a36Sopenharmony_ci		 */
283362306a36Sopenharmony_ci		wMaxPacketSize = ds->wMaxPacketSize;
283462306a36Sopenharmony_ci		pr_vdebug("autoconfig\n");
283562306a36Sopenharmony_ci		ep = usb_ep_autoconfig(func->gadget, ds);
283662306a36Sopenharmony_ci		if (!ep)
283762306a36Sopenharmony_ci			return -ENOTSUPP;
283862306a36Sopenharmony_ci		ep->driver_data = func->eps + idx;
283962306a36Sopenharmony_ci
284062306a36Sopenharmony_ci		req = usb_ep_alloc_request(ep, GFP_KERNEL);
284162306a36Sopenharmony_ci		if (!req)
284262306a36Sopenharmony_ci			return -ENOMEM;
284362306a36Sopenharmony_ci
284462306a36Sopenharmony_ci		ffs_ep->ep  = ep;
284562306a36Sopenharmony_ci		ffs_ep->req = req;
284662306a36Sopenharmony_ci		func->eps_revmap[ds->bEndpointAddress &
284762306a36Sopenharmony_ci				 USB_ENDPOINT_NUMBER_MASK] = idx + 1;
284862306a36Sopenharmony_ci		/*
284962306a36Sopenharmony_ci		 * If we use virtual address mapping, we restore
285062306a36Sopenharmony_ci		 * original bEndpointAddress value.
285162306a36Sopenharmony_ci		 */
285262306a36Sopenharmony_ci		if (func->ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR)
285362306a36Sopenharmony_ci			ds->bEndpointAddress = bEndpointAddress;
285462306a36Sopenharmony_ci		/*
285562306a36Sopenharmony_ci		 * Restore wMaxPacketSize which was potentially
285662306a36Sopenharmony_ci		 * overwritten by autoconfig.
285762306a36Sopenharmony_ci		 */
285862306a36Sopenharmony_ci		ds->wMaxPacketSize = wMaxPacketSize;
285962306a36Sopenharmony_ci	}
286062306a36Sopenharmony_ci	ffs_dump_mem(": Rewritten ep desc", ds, ds->bLength);
286162306a36Sopenharmony_ci
286262306a36Sopenharmony_ci	return 0;
286362306a36Sopenharmony_ci}
286462306a36Sopenharmony_ci
286562306a36Sopenharmony_cistatic int __ffs_func_bind_do_nums(enum ffs_entity_type type, u8 *valuep,
286662306a36Sopenharmony_ci				   struct usb_descriptor_header *desc,
286762306a36Sopenharmony_ci				   void *priv)
286862306a36Sopenharmony_ci{
286962306a36Sopenharmony_ci	struct ffs_function *func = priv;
287062306a36Sopenharmony_ci	unsigned idx;
287162306a36Sopenharmony_ci	u8 newValue;
287262306a36Sopenharmony_ci
287362306a36Sopenharmony_ci	switch (type) {
287462306a36Sopenharmony_ci	default:
287562306a36Sopenharmony_ci	case FFS_DESCRIPTOR:
287662306a36Sopenharmony_ci		/* Handled in previous pass by __ffs_func_bind_do_descs() */
287762306a36Sopenharmony_ci		return 0;
287862306a36Sopenharmony_ci
287962306a36Sopenharmony_ci	case FFS_INTERFACE:
288062306a36Sopenharmony_ci		idx = *valuep;
288162306a36Sopenharmony_ci		if (func->interfaces_nums[idx] < 0) {
288262306a36Sopenharmony_ci			int id = usb_interface_id(func->conf, &func->function);
288362306a36Sopenharmony_ci			if (id < 0)
288462306a36Sopenharmony_ci				return id;
288562306a36Sopenharmony_ci			func->interfaces_nums[idx] = id;
288662306a36Sopenharmony_ci		}
288762306a36Sopenharmony_ci		newValue = func->interfaces_nums[idx];
288862306a36Sopenharmony_ci		break;
288962306a36Sopenharmony_ci
289062306a36Sopenharmony_ci	case FFS_STRING:
289162306a36Sopenharmony_ci		/* String' IDs are allocated when fsf_data is bound to cdev */
289262306a36Sopenharmony_ci		newValue = func->ffs->stringtabs[0]->strings[*valuep - 1].id;
289362306a36Sopenharmony_ci		break;
289462306a36Sopenharmony_ci
289562306a36Sopenharmony_ci	case FFS_ENDPOINT:
289662306a36Sopenharmony_ci		/*
289762306a36Sopenharmony_ci		 * USB_DT_ENDPOINT are handled in
289862306a36Sopenharmony_ci		 * __ffs_func_bind_do_descs().
289962306a36Sopenharmony_ci		 */
290062306a36Sopenharmony_ci		if (desc->bDescriptorType == USB_DT_ENDPOINT)
290162306a36Sopenharmony_ci			return 0;
290262306a36Sopenharmony_ci
290362306a36Sopenharmony_ci		idx = (*valuep & USB_ENDPOINT_NUMBER_MASK) - 1;
290462306a36Sopenharmony_ci		if (!func->eps[idx].ep)
290562306a36Sopenharmony_ci			return -EINVAL;
290662306a36Sopenharmony_ci
290762306a36Sopenharmony_ci		{
290862306a36Sopenharmony_ci			struct usb_endpoint_descriptor **descs;
290962306a36Sopenharmony_ci			descs = func->eps[idx].descs;
291062306a36Sopenharmony_ci			newValue = descs[descs[0] ? 0 : 1]->bEndpointAddress;
291162306a36Sopenharmony_ci		}
291262306a36Sopenharmony_ci		break;
291362306a36Sopenharmony_ci	}
291462306a36Sopenharmony_ci
291562306a36Sopenharmony_ci	pr_vdebug("%02x -> %02x\n", *valuep, newValue);
291662306a36Sopenharmony_ci	*valuep = newValue;
291762306a36Sopenharmony_ci	return 0;
291862306a36Sopenharmony_ci}
291962306a36Sopenharmony_ci
292062306a36Sopenharmony_cistatic int __ffs_func_bind_do_os_desc(enum ffs_os_desc_type type,
292162306a36Sopenharmony_ci				      struct usb_os_desc_header *h, void *data,
292262306a36Sopenharmony_ci				      unsigned len, void *priv)
292362306a36Sopenharmony_ci{
292462306a36Sopenharmony_ci	struct ffs_function *func = priv;
292562306a36Sopenharmony_ci	u8 length = 0;
292662306a36Sopenharmony_ci
292762306a36Sopenharmony_ci	switch (type) {
292862306a36Sopenharmony_ci	case FFS_OS_DESC_EXT_COMPAT: {
292962306a36Sopenharmony_ci		struct usb_ext_compat_desc *desc = data;
293062306a36Sopenharmony_ci		struct usb_os_desc_table *t;
293162306a36Sopenharmony_ci
293262306a36Sopenharmony_ci		t = &func->function.os_desc_table[desc->bFirstInterfaceNumber];
293362306a36Sopenharmony_ci		t->if_id = func->interfaces_nums[desc->bFirstInterfaceNumber];
293462306a36Sopenharmony_ci		memcpy(t->os_desc->ext_compat_id, &desc->CompatibleID,
293562306a36Sopenharmony_ci		       ARRAY_SIZE(desc->CompatibleID) +
293662306a36Sopenharmony_ci		       ARRAY_SIZE(desc->SubCompatibleID));
293762306a36Sopenharmony_ci		length = sizeof(*desc);
293862306a36Sopenharmony_ci	}
293962306a36Sopenharmony_ci		break;
294062306a36Sopenharmony_ci	case FFS_OS_DESC_EXT_PROP: {
294162306a36Sopenharmony_ci		struct usb_ext_prop_desc *desc = data;
294262306a36Sopenharmony_ci		struct usb_os_desc_table *t;
294362306a36Sopenharmony_ci		struct usb_os_desc_ext_prop *ext_prop;
294462306a36Sopenharmony_ci		char *ext_prop_name;
294562306a36Sopenharmony_ci		char *ext_prop_data;
294662306a36Sopenharmony_ci
294762306a36Sopenharmony_ci		t = &func->function.os_desc_table[h->interface];
294862306a36Sopenharmony_ci		t->if_id = func->interfaces_nums[h->interface];
294962306a36Sopenharmony_ci
295062306a36Sopenharmony_ci		ext_prop = func->ffs->ms_os_descs_ext_prop_avail;
295162306a36Sopenharmony_ci		func->ffs->ms_os_descs_ext_prop_avail += sizeof(*ext_prop);
295262306a36Sopenharmony_ci
295362306a36Sopenharmony_ci		ext_prop->type = le32_to_cpu(desc->dwPropertyDataType);
295462306a36Sopenharmony_ci		ext_prop->name_len = le16_to_cpu(desc->wPropertyNameLength);
295562306a36Sopenharmony_ci		ext_prop->data_len = le32_to_cpu(*(__le32 *)
295662306a36Sopenharmony_ci			usb_ext_prop_data_len_ptr(data, ext_prop->name_len));
295762306a36Sopenharmony_ci		length = ext_prop->name_len + ext_prop->data_len + 14;
295862306a36Sopenharmony_ci
295962306a36Sopenharmony_ci		ext_prop_name = func->ffs->ms_os_descs_ext_prop_name_avail;
296062306a36Sopenharmony_ci		func->ffs->ms_os_descs_ext_prop_name_avail +=
296162306a36Sopenharmony_ci			ext_prop->name_len;
296262306a36Sopenharmony_ci
296362306a36Sopenharmony_ci		ext_prop_data = func->ffs->ms_os_descs_ext_prop_data_avail;
296462306a36Sopenharmony_ci		func->ffs->ms_os_descs_ext_prop_data_avail +=
296562306a36Sopenharmony_ci			ext_prop->data_len;
296662306a36Sopenharmony_ci		memcpy(ext_prop_data,
296762306a36Sopenharmony_ci		       usb_ext_prop_data_ptr(data, ext_prop->name_len),
296862306a36Sopenharmony_ci		       ext_prop->data_len);
296962306a36Sopenharmony_ci		/* unicode data reported to the host as "WCHAR"s */
297062306a36Sopenharmony_ci		switch (ext_prop->type) {
297162306a36Sopenharmony_ci		case USB_EXT_PROP_UNICODE:
297262306a36Sopenharmony_ci		case USB_EXT_PROP_UNICODE_ENV:
297362306a36Sopenharmony_ci		case USB_EXT_PROP_UNICODE_LINK:
297462306a36Sopenharmony_ci		case USB_EXT_PROP_UNICODE_MULTI:
297562306a36Sopenharmony_ci			ext_prop->data_len *= 2;
297662306a36Sopenharmony_ci			break;
297762306a36Sopenharmony_ci		}
297862306a36Sopenharmony_ci		ext_prop->data = ext_prop_data;
297962306a36Sopenharmony_ci
298062306a36Sopenharmony_ci		memcpy(ext_prop_name, usb_ext_prop_name_ptr(data),
298162306a36Sopenharmony_ci		       ext_prop->name_len);
298262306a36Sopenharmony_ci		/* property name reported to the host as "WCHAR"s */
298362306a36Sopenharmony_ci		ext_prop->name_len *= 2;
298462306a36Sopenharmony_ci		ext_prop->name = ext_prop_name;
298562306a36Sopenharmony_ci
298662306a36Sopenharmony_ci		t->os_desc->ext_prop_len +=
298762306a36Sopenharmony_ci			ext_prop->name_len + ext_prop->data_len + 14;
298862306a36Sopenharmony_ci		++t->os_desc->ext_prop_count;
298962306a36Sopenharmony_ci		list_add_tail(&ext_prop->entry, &t->os_desc->ext_prop);
299062306a36Sopenharmony_ci	}
299162306a36Sopenharmony_ci		break;
299262306a36Sopenharmony_ci	default:
299362306a36Sopenharmony_ci		pr_vdebug("unknown descriptor: %d\n", type);
299462306a36Sopenharmony_ci	}
299562306a36Sopenharmony_ci
299662306a36Sopenharmony_ci	return length;
299762306a36Sopenharmony_ci}
299862306a36Sopenharmony_ci
299962306a36Sopenharmony_cistatic inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f,
300062306a36Sopenharmony_ci						struct usb_configuration *c)
300162306a36Sopenharmony_ci{
300262306a36Sopenharmony_ci	struct ffs_function *func = ffs_func_from_usb(f);
300362306a36Sopenharmony_ci	struct f_fs_opts *ffs_opts =
300462306a36Sopenharmony_ci		container_of(f->fi, struct f_fs_opts, func_inst);
300562306a36Sopenharmony_ci	struct ffs_data *ffs_data;
300662306a36Sopenharmony_ci	int ret;
300762306a36Sopenharmony_ci
300862306a36Sopenharmony_ci	/*
300962306a36Sopenharmony_ci	 * Legacy gadget triggers binding in functionfs_ready_callback,
301062306a36Sopenharmony_ci	 * which already uses locking; taking the same lock here would
301162306a36Sopenharmony_ci	 * cause a deadlock.
301262306a36Sopenharmony_ci	 *
301362306a36Sopenharmony_ci	 * Configfs-enabled gadgets however do need ffs_dev_lock.
301462306a36Sopenharmony_ci	 */
301562306a36Sopenharmony_ci	if (!ffs_opts->no_configfs)
301662306a36Sopenharmony_ci		ffs_dev_lock();
301762306a36Sopenharmony_ci	ret = ffs_opts->dev->desc_ready ? 0 : -ENODEV;
301862306a36Sopenharmony_ci	ffs_data = ffs_opts->dev->ffs_data;
301962306a36Sopenharmony_ci	if (!ffs_opts->no_configfs)
302062306a36Sopenharmony_ci		ffs_dev_unlock();
302162306a36Sopenharmony_ci	if (ret)
302262306a36Sopenharmony_ci		return ERR_PTR(ret);
302362306a36Sopenharmony_ci
302462306a36Sopenharmony_ci	func->ffs = ffs_data;
302562306a36Sopenharmony_ci	func->conf = c;
302662306a36Sopenharmony_ci	func->gadget = c->cdev->gadget;
302762306a36Sopenharmony_ci
302862306a36Sopenharmony_ci	/*
302962306a36Sopenharmony_ci	 * in drivers/usb/gadget/configfs.c:configfs_composite_bind()
303062306a36Sopenharmony_ci	 * configurations are bound in sequence with list_for_each_entry,
303162306a36Sopenharmony_ci	 * in each configuration its functions are bound in sequence
303262306a36Sopenharmony_ci	 * with list_for_each_entry, so we assume no race condition
303362306a36Sopenharmony_ci	 * with regard to ffs_opts->bound access
303462306a36Sopenharmony_ci	 */
303562306a36Sopenharmony_ci	if (!ffs_opts->refcnt) {
303662306a36Sopenharmony_ci		ret = functionfs_bind(func->ffs, c->cdev);
303762306a36Sopenharmony_ci		if (ret)
303862306a36Sopenharmony_ci			return ERR_PTR(ret);
303962306a36Sopenharmony_ci	}
304062306a36Sopenharmony_ci	ffs_opts->refcnt++;
304162306a36Sopenharmony_ci	func->function.strings = func->ffs->stringtabs;
304262306a36Sopenharmony_ci
304362306a36Sopenharmony_ci	return ffs_opts;
304462306a36Sopenharmony_ci}
304562306a36Sopenharmony_ci
304662306a36Sopenharmony_cistatic int _ffs_func_bind(struct usb_configuration *c,
304762306a36Sopenharmony_ci			  struct usb_function *f)
304862306a36Sopenharmony_ci{
304962306a36Sopenharmony_ci	struct ffs_function *func = ffs_func_from_usb(f);
305062306a36Sopenharmony_ci	struct ffs_data *ffs = func->ffs;
305162306a36Sopenharmony_ci
305262306a36Sopenharmony_ci	const int full = !!func->ffs->fs_descs_count;
305362306a36Sopenharmony_ci	const int high = !!func->ffs->hs_descs_count;
305462306a36Sopenharmony_ci	const int super = !!func->ffs->ss_descs_count;
305562306a36Sopenharmony_ci
305662306a36Sopenharmony_ci	int fs_len, hs_len, ss_len, ret, i;
305762306a36Sopenharmony_ci	struct ffs_ep *eps_ptr;
305862306a36Sopenharmony_ci
305962306a36Sopenharmony_ci	/* Make it a single chunk, less management later on */
306062306a36Sopenharmony_ci	vla_group(d);
306162306a36Sopenharmony_ci	vla_item_with_sz(d, struct ffs_ep, eps, ffs->eps_count);
306262306a36Sopenharmony_ci	vla_item_with_sz(d, struct usb_descriptor_header *, fs_descs,
306362306a36Sopenharmony_ci		full ? ffs->fs_descs_count + 1 : 0);
306462306a36Sopenharmony_ci	vla_item_with_sz(d, struct usb_descriptor_header *, hs_descs,
306562306a36Sopenharmony_ci		high ? ffs->hs_descs_count + 1 : 0);
306662306a36Sopenharmony_ci	vla_item_with_sz(d, struct usb_descriptor_header *, ss_descs,
306762306a36Sopenharmony_ci		super ? ffs->ss_descs_count + 1 : 0);
306862306a36Sopenharmony_ci	vla_item_with_sz(d, short, inums, ffs->interfaces_count);
306962306a36Sopenharmony_ci	vla_item_with_sz(d, struct usb_os_desc_table, os_desc_table,
307062306a36Sopenharmony_ci			 c->cdev->use_os_string ? ffs->interfaces_count : 0);
307162306a36Sopenharmony_ci	vla_item_with_sz(d, char[16], ext_compat,
307262306a36Sopenharmony_ci			 c->cdev->use_os_string ? ffs->interfaces_count : 0);
307362306a36Sopenharmony_ci	vla_item_with_sz(d, struct usb_os_desc, os_desc,
307462306a36Sopenharmony_ci			 c->cdev->use_os_string ? ffs->interfaces_count : 0);
307562306a36Sopenharmony_ci	vla_item_with_sz(d, struct usb_os_desc_ext_prop, ext_prop,
307662306a36Sopenharmony_ci			 ffs->ms_os_descs_ext_prop_count);
307762306a36Sopenharmony_ci	vla_item_with_sz(d, char, ext_prop_name,
307862306a36Sopenharmony_ci			 ffs->ms_os_descs_ext_prop_name_len);
307962306a36Sopenharmony_ci	vla_item_with_sz(d, char, ext_prop_data,
308062306a36Sopenharmony_ci			 ffs->ms_os_descs_ext_prop_data_len);
308162306a36Sopenharmony_ci	vla_item_with_sz(d, char, raw_descs, ffs->raw_descs_length);
308262306a36Sopenharmony_ci	char *vlabuf;
308362306a36Sopenharmony_ci
308462306a36Sopenharmony_ci	/* Has descriptors only for speeds gadget does not support */
308562306a36Sopenharmony_ci	if (!(full | high | super))
308662306a36Sopenharmony_ci		return -ENOTSUPP;
308762306a36Sopenharmony_ci
308862306a36Sopenharmony_ci	/* Allocate a single chunk, less management later on */
308962306a36Sopenharmony_ci	vlabuf = kzalloc(vla_group_size(d), GFP_KERNEL);
309062306a36Sopenharmony_ci	if (!vlabuf)
309162306a36Sopenharmony_ci		return -ENOMEM;
309262306a36Sopenharmony_ci
309362306a36Sopenharmony_ci	ffs->ms_os_descs_ext_prop_avail = vla_ptr(vlabuf, d, ext_prop);
309462306a36Sopenharmony_ci	ffs->ms_os_descs_ext_prop_name_avail =
309562306a36Sopenharmony_ci		vla_ptr(vlabuf, d, ext_prop_name);
309662306a36Sopenharmony_ci	ffs->ms_os_descs_ext_prop_data_avail =
309762306a36Sopenharmony_ci		vla_ptr(vlabuf, d, ext_prop_data);
309862306a36Sopenharmony_ci
309962306a36Sopenharmony_ci	/* Copy descriptors  */
310062306a36Sopenharmony_ci	memcpy(vla_ptr(vlabuf, d, raw_descs), ffs->raw_descs,
310162306a36Sopenharmony_ci	       ffs->raw_descs_length);
310262306a36Sopenharmony_ci
310362306a36Sopenharmony_ci	memset(vla_ptr(vlabuf, d, inums), 0xff, d_inums__sz);
310462306a36Sopenharmony_ci	eps_ptr = vla_ptr(vlabuf, d, eps);
310562306a36Sopenharmony_ci	for (i = 0; i < ffs->eps_count; i++)
310662306a36Sopenharmony_ci		eps_ptr[i].num = -1;
310762306a36Sopenharmony_ci
310862306a36Sopenharmony_ci	/* Save pointers
310962306a36Sopenharmony_ci	 * d_eps == vlabuf, func->eps used to kfree vlabuf later
311062306a36Sopenharmony_ci	*/
311162306a36Sopenharmony_ci	func->eps             = vla_ptr(vlabuf, d, eps);
311262306a36Sopenharmony_ci	func->interfaces_nums = vla_ptr(vlabuf, d, inums);
311362306a36Sopenharmony_ci
311462306a36Sopenharmony_ci	/*
311562306a36Sopenharmony_ci	 * Go through all the endpoint descriptors and allocate
311662306a36Sopenharmony_ci	 * endpoints first, so that later we can rewrite the endpoint
311762306a36Sopenharmony_ci	 * numbers without worrying that it may be described later on.
311862306a36Sopenharmony_ci	 */
311962306a36Sopenharmony_ci	if (full) {
312062306a36Sopenharmony_ci		func->function.fs_descriptors = vla_ptr(vlabuf, d, fs_descs);
312162306a36Sopenharmony_ci		fs_len = ffs_do_descs(ffs->fs_descs_count,
312262306a36Sopenharmony_ci				      vla_ptr(vlabuf, d, raw_descs),
312362306a36Sopenharmony_ci				      d_raw_descs__sz,
312462306a36Sopenharmony_ci				      __ffs_func_bind_do_descs, func);
312562306a36Sopenharmony_ci		if (fs_len < 0) {
312662306a36Sopenharmony_ci			ret = fs_len;
312762306a36Sopenharmony_ci			goto error;
312862306a36Sopenharmony_ci		}
312962306a36Sopenharmony_ci	} else {
313062306a36Sopenharmony_ci		fs_len = 0;
313162306a36Sopenharmony_ci	}
313262306a36Sopenharmony_ci
313362306a36Sopenharmony_ci	if (high) {
313462306a36Sopenharmony_ci		func->function.hs_descriptors = vla_ptr(vlabuf, d, hs_descs);
313562306a36Sopenharmony_ci		hs_len = ffs_do_descs(ffs->hs_descs_count,
313662306a36Sopenharmony_ci				      vla_ptr(vlabuf, d, raw_descs) + fs_len,
313762306a36Sopenharmony_ci				      d_raw_descs__sz - fs_len,
313862306a36Sopenharmony_ci				      __ffs_func_bind_do_descs, func);
313962306a36Sopenharmony_ci		if (hs_len < 0) {
314062306a36Sopenharmony_ci			ret = hs_len;
314162306a36Sopenharmony_ci			goto error;
314262306a36Sopenharmony_ci		}
314362306a36Sopenharmony_ci	} else {
314462306a36Sopenharmony_ci		hs_len = 0;
314562306a36Sopenharmony_ci	}
314662306a36Sopenharmony_ci
314762306a36Sopenharmony_ci	if (super) {
314862306a36Sopenharmony_ci		func->function.ss_descriptors = func->function.ssp_descriptors =
314962306a36Sopenharmony_ci			vla_ptr(vlabuf, d, ss_descs);
315062306a36Sopenharmony_ci		ss_len = ffs_do_descs(ffs->ss_descs_count,
315162306a36Sopenharmony_ci				vla_ptr(vlabuf, d, raw_descs) + fs_len + hs_len,
315262306a36Sopenharmony_ci				d_raw_descs__sz - fs_len - hs_len,
315362306a36Sopenharmony_ci				__ffs_func_bind_do_descs, func);
315462306a36Sopenharmony_ci		if (ss_len < 0) {
315562306a36Sopenharmony_ci			ret = ss_len;
315662306a36Sopenharmony_ci			goto error;
315762306a36Sopenharmony_ci		}
315862306a36Sopenharmony_ci	} else {
315962306a36Sopenharmony_ci		ss_len = 0;
316062306a36Sopenharmony_ci	}
316162306a36Sopenharmony_ci
316262306a36Sopenharmony_ci	/*
316362306a36Sopenharmony_ci	 * Now handle interface numbers allocation and interface and
316462306a36Sopenharmony_ci	 * endpoint numbers rewriting.  We can do that in one go
316562306a36Sopenharmony_ci	 * now.
316662306a36Sopenharmony_ci	 */
316762306a36Sopenharmony_ci	ret = ffs_do_descs(ffs->fs_descs_count +
316862306a36Sopenharmony_ci			   (high ? ffs->hs_descs_count : 0) +
316962306a36Sopenharmony_ci			   (super ? ffs->ss_descs_count : 0),
317062306a36Sopenharmony_ci			   vla_ptr(vlabuf, d, raw_descs), d_raw_descs__sz,
317162306a36Sopenharmony_ci			   __ffs_func_bind_do_nums, func);
317262306a36Sopenharmony_ci	if (ret < 0)
317362306a36Sopenharmony_ci		goto error;
317462306a36Sopenharmony_ci
317562306a36Sopenharmony_ci	func->function.os_desc_table = vla_ptr(vlabuf, d, os_desc_table);
317662306a36Sopenharmony_ci	if (c->cdev->use_os_string) {
317762306a36Sopenharmony_ci		for (i = 0; i < ffs->interfaces_count; ++i) {
317862306a36Sopenharmony_ci			struct usb_os_desc *desc;
317962306a36Sopenharmony_ci
318062306a36Sopenharmony_ci			desc = func->function.os_desc_table[i].os_desc =
318162306a36Sopenharmony_ci				vla_ptr(vlabuf, d, os_desc) +
318262306a36Sopenharmony_ci				i * sizeof(struct usb_os_desc);
318362306a36Sopenharmony_ci			desc->ext_compat_id =
318462306a36Sopenharmony_ci				vla_ptr(vlabuf, d, ext_compat) + i * 16;
318562306a36Sopenharmony_ci			INIT_LIST_HEAD(&desc->ext_prop);
318662306a36Sopenharmony_ci		}
318762306a36Sopenharmony_ci		ret = ffs_do_os_descs(ffs->ms_os_descs_count,
318862306a36Sopenharmony_ci				      vla_ptr(vlabuf, d, raw_descs) +
318962306a36Sopenharmony_ci				      fs_len + hs_len + ss_len,
319062306a36Sopenharmony_ci				      d_raw_descs__sz - fs_len - hs_len -
319162306a36Sopenharmony_ci				      ss_len,
319262306a36Sopenharmony_ci				      __ffs_func_bind_do_os_desc, func);
319362306a36Sopenharmony_ci		if (ret < 0)
319462306a36Sopenharmony_ci			goto error;
319562306a36Sopenharmony_ci	}
319662306a36Sopenharmony_ci	func->function.os_desc_n =
319762306a36Sopenharmony_ci		c->cdev->use_os_string ? ffs->interfaces_count : 0;
319862306a36Sopenharmony_ci
319962306a36Sopenharmony_ci	/* And we're done */
320062306a36Sopenharmony_ci	ffs_event_add(ffs, FUNCTIONFS_BIND);
320162306a36Sopenharmony_ci	return 0;
320262306a36Sopenharmony_ci
320362306a36Sopenharmony_cierror:
320462306a36Sopenharmony_ci	/* XXX Do we need to release all claimed endpoints here? */
320562306a36Sopenharmony_ci	return ret;
320662306a36Sopenharmony_ci}
320762306a36Sopenharmony_ci
320862306a36Sopenharmony_cistatic int ffs_func_bind(struct usb_configuration *c,
320962306a36Sopenharmony_ci			 struct usb_function *f)
321062306a36Sopenharmony_ci{
321162306a36Sopenharmony_ci	struct f_fs_opts *ffs_opts = ffs_do_functionfs_bind(f, c);
321262306a36Sopenharmony_ci	struct ffs_function *func = ffs_func_from_usb(f);
321362306a36Sopenharmony_ci	int ret;
321462306a36Sopenharmony_ci
321562306a36Sopenharmony_ci	if (IS_ERR(ffs_opts))
321662306a36Sopenharmony_ci		return PTR_ERR(ffs_opts);
321762306a36Sopenharmony_ci
321862306a36Sopenharmony_ci	ret = _ffs_func_bind(c, f);
321962306a36Sopenharmony_ci	if (ret && !--ffs_opts->refcnt)
322062306a36Sopenharmony_ci		functionfs_unbind(func->ffs);
322162306a36Sopenharmony_ci
322262306a36Sopenharmony_ci	return ret;
322362306a36Sopenharmony_ci}
322462306a36Sopenharmony_ci
322562306a36Sopenharmony_ci
322662306a36Sopenharmony_ci/* Other USB function hooks *************************************************/
322762306a36Sopenharmony_ci
322862306a36Sopenharmony_cistatic void ffs_reset_work(struct work_struct *work)
322962306a36Sopenharmony_ci{
323062306a36Sopenharmony_ci	struct ffs_data *ffs = container_of(work,
323162306a36Sopenharmony_ci		struct ffs_data, reset_work);
323262306a36Sopenharmony_ci	ffs_data_reset(ffs);
323362306a36Sopenharmony_ci}
323462306a36Sopenharmony_ci
323562306a36Sopenharmony_cistatic int ffs_func_set_alt(struct usb_function *f,
323662306a36Sopenharmony_ci			    unsigned interface, unsigned alt)
323762306a36Sopenharmony_ci{
323862306a36Sopenharmony_ci	struct ffs_function *func = ffs_func_from_usb(f);
323962306a36Sopenharmony_ci	struct ffs_data *ffs = func->ffs;
324062306a36Sopenharmony_ci	int ret = 0, intf;
324162306a36Sopenharmony_ci
324262306a36Sopenharmony_ci	if (alt != (unsigned)-1) {
324362306a36Sopenharmony_ci		intf = ffs_func_revmap_intf(func, interface);
324462306a36Sopenharmony_ci		if (intf < 0)
324562306a36Sopenharmony_ci			return intf;
324662306a36Sopenharmony_ci	}
324762306a36Sopenharmony_ci
324862306a36Sopenharmony_ci	if (ffs->func)
324962306a36Sopenharmony_ci		ffs_func_eps_disable(ffs->func);
325062306a36Sopenharmony_ci
325162306a36Sopenharmony_ci	if (ffs->state == FFS_DEACTIVATED) {
325262306a36Sopenharmony_ci		ffs->state = FFS_CLOSING;
325362306a36Sopenharmony_ci		INIT_WORK(&ffs->reset_work, ffs_reset_work);
325462306a36Sopenharmony_ci		schedule_work(&ffs->reset_work);
325562306a36Sopenharmony_ci		return -ENODEV;
325662306a36Sopenharmony_ci	}
325762306a36Sopenharmony_ci
325862306a36Sopenharmony_ci	if (ffs->state != FFS_ACTIVE)
325962306a36Sopenharmony_ci		return -ENODEV;
326062306a36Sopenharmony_ci
326162306a36Sopenharmony_ci	if (alt == (unsigned)-1) {
326262306a36Sopenharmony_ci		ffs->func = NULL;
326362306a36Sopenharmony_ci		ffs_event_add(ffs, FUNCTIONFS_DISABLE);
326462306a36Sopenharmony_ci		return 0;
326562306a36Sopenharmony_ci	}
326662306a36Sopenharmony_ci
326762306a36Sopenharmony_ci	ffs->func = func;
326862306a36Sopenharmony_ci	ret = ffs_func_eps_enable(func);
326962306a36Sopenharmony_ci	if (ret >= 0)
327062306a36Sopenharmony_ci		ffs_event_add(ffs, FUNCTIONFS_ENABLE);
327162306a36Sopenharmony_ci	return ret;
327262306a36Sopenharmony_ci}
327362306a36Sopenharmony_ci
327462306a36Sopenharmony_cistatic void ffs_func_disable(struct usb_function *f)
327562306a36Sopenharmony_ci{
327662306a36Sopenharmony_ci	ffs_func_set_alt(f, 0, (unsigned)-1);
327762306a36Sopenharmony_ci}
327862306a36Sopenharmony_ci
327962306a36Sopenharmony_cistatic int ffs_func_setup(struct usb_function *f,
328062306a36Sopenharmony_ci			  const struct usb_ctrlrequest *creq)
328162306a36Sopenharmony_ci{
328262306a36Sopenharmony_ci	struct ffs_function *func = ffs_func_from_usb(f);
328362306a36Sopenharmony_ci	struct ffs_data *ffs = func->ffs;
328462306a36Sopenharmony_ci	unsigned long flags;
328562306a36Sopenharmony_ci	int ret;
328662306a36Sopenharmony_ci
328762306a36Sopenharmony_ci	pr_vdebug("creq->bRequestType = %02x\n", creq->bRequestType);
328862306a36Sopenharmony_ci	pr_vdebug("creq->bRequest     = %02x\n", creq->bRequest);
328962306a36Sopenharmony_ci	pr_vdebug("creq->wValue       = %04x\n", le16_to_cpu(creq->wValue));
329062306a36Sopenharmony_ci	pr_vdebug("creq->wIndex       = %04x\n", le16_to_cpu(creq->wIndex));
329162306a36Sopenharmony_ci	pr_vdebug("creq->wLength      = %04x\n", le16_to_cpu(creq->wLength));
329262306a36Sopenharmony_ci
329362306a36Sopenharmony_ci	/*
329462306a36Sopenharmony_ci	 * Most requests directed to interface go through here
329562306a36Sopenharmony_ci	 * (notable exceptions are set/get interface) so we need to
329662306a36Sopenharmony_ci	 * handle them.  All other either handled by composite or
329762306a36Sopenharmony_ci	 * passed to usb_configuration->setup() (if one is set).  No
329862306a36Sopenharmony_ci	 * matter, we will handle requests directed to endpoint here
329962306a36Sopenharmony_ci	 * as well (as it's straightforward).  Other request recipient
330062306a36Sopenharmony_ci	 * types are only handled when the user flag FUNCTIONFS_ALL_CTRL_RECIP
330162306a36Sopenharmony_ci	 * is being used.
330262306a36Sopenharmony_ci	 */
330362306a36Sopenharmony_ci	if (ffs->state != FFS_ACTIVE)
330462306a36Sopenharmony_ci		return -ENODEV;
330562306a36Sopenharmony_ci
330662306a36Sopenharmony_ci	switch (creq->bRequestType & USB_RECIP_MASK) {
330762306a36Sopenharmony_ci	case USB_RECIP_INTERFACE:
330862306a36Sopenharmony_ci		ret = ffs_func_revmap_intf(func, le16_to_cpu(creq->wIndex));
330962306a36Sopenharmony_ci		if (ret < 0)
331062306a36Sopenharmony_ci			return ret;
331162306a36Sopenharmony_ci		break;
331262306a36Sopenharmony_ci
331362306a36Sopenharmony_ci	case USB_RECIP_ENDPOINT:
331462306a36Sopenharmony_ci		ret = ffs_func_revmap_ep(func, le16_to_cpu(creq->wIndex));
331562306a36Sopenharmony_ci		if (ret < 0)
331662306a36Sopenharmony_ci			return ret;
331762306a36Sopenharmony_ci		if (func->ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR)
331862306a36Sopenharmony_ci			ret = func->ffs->eps_addrmap[ret];
331962306a36Sopenharmony_ci		break;
332062306a36Sopenharmony_ci
332162306a36Sopenharmony_ci	default:
332262306a36Sopenharmony_ci		if (func->ffs->user_flags & FUNCTIONFS_ALL_CTRL_RECIP)
332362306a36Sopenharmony_ci			ret = le16_to_cpu(creq->wIndex);
332462306a36Sopenharmony_ci		else
332562306a36Sopenharmony_ci			return -EOPNOTSUPP;
332662306a36Sopenharmony_ci	}
332762306a36Sopenharmony_ci
332862306a36Sopenharmony_ci	spin_lock_irqsave(&ffs->ev.waitq.lock, flags);
332962306a36Sopenharmony_ci	ffs->ev.setup = *creq;
333062306a36Sopenharmony_ci	ffs->ev.setup.wIndex = cpu_to_le16(ret);
333162306a36Sopenharmony_ci	__ffs_event_add(ffs, FUNCTIONFS_SETUP);
333262306a36Sopenharmony_ci	spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags);
333362306a36Sopenharmony_ci
333462306a36Sopenharmony_ci	return creq->wLength == 0 ? USB_GADGET_DELAYED_STATUS : 0;
333562306a36Sopenharmony_ci}
333662306a36Sopenharmony_ci
333762306a36Sopenharmony_cistatic bool ffs_func_req_match(struct usb_function *f,
333862306a36Sopenharmony_ci			       const struct usb_ctrlrequest *creq,
333962306a36Sopenharmony_ci			       bool config0)
334062306a36Sopenharmony_ci{
334162306a36Sopenharmony_ci	struct ffs_function *func = ffs_func_from_usb(f);
334262306a36Sopenharmony_ci
334362306a36Sopenharmony_ci	if (config0 && !(func->ffs->user_flags & FUNCTIONFS_CONFIG0_SETUP))
334462306a36Sopenharmony_ci		return false;
334562306a36Sopenharmony_ci
334662306a36Sopenharmony_ci	switch (creq->bRequestType & USB_RECIP_MASK) {
334762306a36Sopenharmony_ci	case USB_RECIP_INTERFACE:
334862306a36Sopenharmony_ci		return (ffs_func_revmap_intf(func,
334962306a36Sopenharmony_ci					     le16_to_cpu(creq->wIndex)) >= 0);
335062306a36Sopenharmony_ci	case USB_RECIP_ENDPOINT:
335162306a36Sopenharmony_ci		return (ffs_func_revmap_ep(func,
335262306a36Sopenharmony_ci					   le16_to_cpu(creq->wIndex)) >= 0);
335362306a36Sopenharmony_ci	default:
335462306a36Sopenharmony_ci		return (bool) (func->ffs->user_flags &
335562306a36Sopenharmony_ci			       FUNCTIONFS_ALL_CTRL_RECIP);
335662306a36Sopenharmony_ci	}
335762306a36Sopenharmony_ci}
335862306a36Sopenharmony_ci
335962306a36Sopenharmony_cistatic void ffs_func_suspend(struct usb_function *f)
336062306a36Sopenharmony_ci{
336162306a36Sopenharmony_ci	ffs_event_add(ffs_func_from_usb(f)->ffs, FUNCTIONFS_SUSPEND);
336262306a36Sopenharmony_ci}
336362306a36Sopenharmony_ci
336462306a36Sopenharmony_cistatic void ffs_func_resume(struct usb_function *f)
336562306a36Sopenharmony_ci{
336662306a36Sopenharmony_ci	ffs_event_add(ffs_func_from_usb(f)->ffs, FUNCTIONFS_RESUME);
336762306a36Sopenharmony_ci}
336862306a36Sopenharmony_ci
336962306a36Sopenharmony_ci
337062306a36Sopenharmony_ci/* Endpoint and interface numbers reverse mapping ***************************/
337162306a36Sopenharmony_ci
337262306a36Sopenharmony_cistatic int ffs_func_revmap_ep(struct ffs_function *func, u8 num)
337362306a36Sopenharmony_ci{
337462306a36Sopenharmony_ci	num = func->eps_revmap[num & USB_ENDPOINT_NUMBER_MASK];
337562306a36Sopenharmony_ci	return num ? num : -EDOM;
337662306a36Sopenharmony_ci}
337762306a36Sopenharmony_ci
337862306a36Sopenharmony_cistatic int ffs_func_revmap_intf(struct ffs_function *func, u8 intf)
337962306a36Sopenharmony_ci{
338062306a36Sopenharmony_ci	short *nums = func->interfaces_nums;
338162306a36Sopenharmony_ci	unsigned count = func->ffs->interfaces_count;
338262306a36Sopenharmony_ci
338362306a36Sopenharmony_ci	for (; count; --count, ++nums) {
338462306a36Sopenharmony_ci		if (*nums >= 0 && *nums == intf)
338562306a36Sopenharmony_ci			return nums - func->interfaces_nums;
338662306a36Sopenharmony_ci	}
338762306a36Sopenharmony_ci
338862306a36Sopenharmony_ci	return -EDOM;
338962306a36Sopenharmony_ci}
339062306a36Sopenharmony_ci
339162306a36Sopenharmony_ci
339262306a36Sopenharmony_ci/* Devices management *******************************************************/
339362306a36Sopenharmony_ci
339462306a36Sopenharmony_cistatic LIST_HEAD(ffs_devices);
339562306a36Sopenharmony_ci
339662306a36Sopenharmony_cistatic struct ffs_dev *_ffs_do_find_dev(const char *name)
339762306a36Sopenharmony_ci{
339862306a36Sopenharmony_ci	struct ffs_dev *dev;
339962306a36Sopenharmony_ci
340062306a36Sopenharmony_ci	if (!name)
340162306a36Sopenharmony_ci		return NULL;
340262306a36Sopenharmony_ci
340362306a36Sopenharmony_ci	list_for_each_entry(dev, &ffs_devices, entry) {
340462306a36Sopenharmony_ci		if (strcmp(dev->name, name) == 0)
340562306a36Sopenharmony_ci			return dev;
340662306a36Sopenharmony_ci	}
340762306a36Sopenharmony_ci
340862306a36Sopenharmony_ci	return NULL;
340962306a36Sopenharmony_ci}
341062306a36Sopenharmony_ci
341162306a36Sopenharmony_ci/*
341262306a36Sopenharmony_ci * ffs_lock must be taken by the caller of this function
341362306a36Sopenharmony_ci */
341462306a36Sopenharmony_cistatic struct ffs_dev *_ffs_get_single_dev(void)
341562306a36Sopenharmony_ci{
341662306a36Sopenharmony_ci	struct ffs_dev *dev;
341762306a36Sopenharmony_ci
341862306a36Sopenharmony_ci	if (list_is_singular(&ffs_devices)) {
341962306a36Sopenharmony_ci		dev = list_first_entry(&ffs_devices, struct ffs_dev, entry);
342062306a36Sopenharmony_ci		if (dev->single)
342162306a36Sopenharmony_ci			return dev;
342262306a36Sopenharmony_ci	}
342362306a36Sopenharmony_ci
342462306a36Sopenharmony_ci	return NULL;
342562306a36Sopenharmony_ci}
342662306a36Sopenharmony_ci
342762306a36Sopenharmony_ci/*
342862306a36Sopenharmony_ci * ffs_lock must be taken by the caller of this function
342962306a36Sopenharmony_ci */
343062306a36Sopenharmony_cistatic struct ffs_dev *_ffs_find_dev(const char *name)
343162306a36Sopenharmony_ci{
343262306a36Sopenharmony_ci	struct ffs_dev *dev;
343362306a36Sopenharmony_ci
343462306a36Sopenharmony_ci	dev = _ffs_get_single_dev();
343562306a36Sopenharmony_ci	if (dev)
343662306a36Sopenharmony_ci		return dev;
343762306a36Sopenharmony_ci
343862306a36Sopenharmony_ci	return _ffs_do_find_dev(name);
343962306a36Sopenharmony_ci}
344062306a36Sopenharmony_ci
344162306a36Sopenharmony_ci/* Configfs support *********************************************************/
344262306a36Sopenharmony_ci
344362306a36Sopenharmony_cistatic inline struct f_fs_opts *to_ffs_opts(struct config_item *item)
344462306a36Sopenharmony_ci{
344562306a36Sopenharmony_ci	return container_of(to_config_group(item), struct f_fs_opts,
344662306a36Sopenharmony_ci			    func_inst.group);
344762306a36Sopenharmony_ci}
344862306a36Sopenharmony_ci
344962306a36Sopenharmony_cistatic void ffs_attr_release(struct config_item *item)
345062306a36Sopenharmony_ci{
345162306a36Sopenharmony_ci	struct f_fs_opts *opts = to_ffs_opts(item);
345262306a36Sopenharmony_ci
345362306a36Sopenharmony_ci	usb_put_function_instance(&opts->func_inst);
345462306a36Sopenharmony_ci}
345562306a36Sopenharmony_ci
345662306a36Sopenharmony_cistatic struct configfs_item_operations ffs_item_ops = {
345762306a36Sopenharmony_ci	.release	= ffs_attr_release,
345862306a36Sopenharmony_ci};
345962306a36Sopenharmony_ci
346062306a36Sopenharmony_cistatic const struct config_item_type ffs_func_type = {
346162306a36Sopenharmony_ci	.ct_item_ops	= &ffs_item_ops,
346262306a36Sopenharmony_ci	.ct_owner	= THIS_MODULE,
346362306a36Sopenharmony_ci};
346462306a36Sopenharmony_ci
346562306a36Sopenharmony_ci
346662306a36Sopenharmony_ci/* Function registration interface ******************************************/
346762306a36Sopenharmony_ci
346862306a36Sopenharmony_cistatic void ffs_free_inst(struct usb_function_instance *f)
346962306a36Sopenharmony_ci{
347062306a36Sopenharmony_ci	struct f_fs_opts *opts;
347162306a36Sopenharmony_ci
347262306a36Sopenharmony_ci	opts = to_f_fs_opts(f);
347362306a36Sopenharmony_ci	ffs_release_dev(opts->dev);
347462306a36Sopenharmony_ci	ffs_dev_lock();
347562306a36Sopenharmony_ci	_ffs_free_dev(opts->dev);
347662306a36Sopenharmony_ci	ffs_dev_unlock();
347762306a36Sopenharmony_ci	kfree(opts);
347862306a36Sopenharmony_ci}
347962306a36Sopenharmony_ci
348062306a36Sopenharmony_cistatic int ffs_set_inst_name(struct usb_function_instance *fi, const char *name)
348162306a36Sopenharmony_ci{
348262306a36Sopenharmony_ci	if (strlen(name) >= sizeof_field(struct ffs_dev, name))
348362306a36Sopenharmony_ci		return -ENAMETOOLONG;
348462306a36Sopenharmony_ci	return ffs_name_dev(to_f_fs_opts(fi)->dev, name);
348562306a36Sopenharmony_ci}
348662306a36Sopenharmony_ci
348762306a36Sopenharmony_cistatic struct usb_function_instance *ffs_alloc_inst(void)
348862306a36Sopenharmony_ci{
348962306a36Sopenharmony_ci	struct f_fs_opts *opts;
349062306a36Sopenharmony_ci	struct ffs_dev *dev;
349162306a36Sopenharmony_ci
349262306a36Sopenharmony_ci	opts = kzalloc(sizeof(*opts), GFP_KERNEL);
349362306a36Sopenharmony_ci	if (!opts)
349462306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
349562306a36Sopenharmony_ci
349662306a36Sopenharmony_ci	opts->func_inst.set_inst_name = ffs_set_inst_name;
349762306a36Sopenharmony_ci	opts->func_inst.free_func_inst = ffs_free_inst;
349862306a36Sopenharmony_ci	ffs_dev_lock();
349962306a36Sopenharmony_ci	dev = _ffs_alloc_dev();
350062306a36Sopenharmony_ci	ffs_dev_unlock();
350162306a36Sopenharmony_ci	if (IS_ERR(dev)) {
350262306a36Sopenharmony_ci		kfree(opts);
350362306a36Sopenharmony_ci		return ERR_CAST(dev);
350462306a36Sopenharmony_ci	}
350562306a36Sopenharmony_ci	opts->dev = dev;
350662306a36Sopenharmony_ci	dev->opts = opts;
350762306a36Sopenharmony_ci
350862306a36Sopenharmony_ci	config_group_init_type_name(&opts->func_inst.group, "",
350962306a36Sopenharmony_ci				    &ffs_func_type);
351062306a36Sopenharmony_ci	return &opts->func_inst;
351162306a36Sopenharmony_ci}
351262306a36Sopenharmony_ci
351362306a36Sopenharmony_cistatic void ffs_free(struct usb_function *f)
351462306a36Sopenharmony_ci{
351562306a36Sopenharmony_ci	kfree(ffs_func_from_usb(f));
351662306a36Sopenharmony_ci}
351762306a36Sopenharmony_ci
351862306a36Sopenharmony_cistatic void ffs_func_unbind(struct usb_configuration *c,
351962306a36Sopenharmony_ci			    struct usb_function *f)
352062306a36Sopenharmony_ci{
352162306a36Sopenharmony_ci	struct ffs_function *func = ffs_func_from_usb(f);
352262306a36Sopenharmony_ci	struct ffs_data *ffs = func->ffs;
352362306a36Sopenharmony_ci	struct f_fs_opts *opts =
352462306a36Sopenharmony_ci		container_of(f->fi, struct f_fs_opts, func_inst);
352562306a36Sopenharmony_ci	struct ffs_ep *ep = func->eps;
352662306a36Sopenharmony_ci	unsigned count = ffs->eps_count;
352762306a36Sopenharmony_ci	unsigned long flags;
352862306a36Sopenharmony_ci
352962306a36Sopenharmony_ci	if (ffs->func == func) {
353062306a36Sopenharmony_ci		ffs_func_eps_disable(func);
353162306a36Sopenharmony_ci		ffs->func = NULL;
353262306a36Sopenharmony_ci	}
353362306a36Sopenharmony_ci
353462306a36Sopenharmony_ci	/* Drain any pending AIO completions */
353562306a36Sopenharmony_ci	drain_workqueue(ffs->io_completion_wq);
353662306a36Sopenharmony_ci
353762306a36Sopenharmony_ci	ffs_event_add(ffs, FUNCTIONFS_UNBIND);
353862306a36Sopenharmony_ci	if (!--opts->refcnt)
353962306a36Sopenharmony_ci		functionfs_unbind(ffs);
354062306a36Sopenharmony_ci
354162306a36Sopenharmony_ci	/* cleanup after autoconfig */
354262306a36Sopenharmony_ci	spin_lock_irqsave(&func->ffs->eps_lock, flags);
354362306a36Sopenharmony_ci	while (count--) {
354462306a36Sopenharmony_ci		if (ep->ep && ep->req)
354562306a36Sopenharmony_ci			usb_ep_free_request(ep->ep, ep->req);
354662306a36Sopenharmony_ci		ep->req = NULL;
354762306a36Sopenharmony_ci		++ep;
354862306a36Sopenharmony_ci	}
354962306a36Sopenharmony_ci	spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
355062306a36Sopenharmony_ci	kfree(func->eps);
355162306a36Sopenharmony_ci	func->eps = NULL;
355262306a36Sopenharmony_ci	/*
355362306a36Sopenharmony_ci	 * eps, descriptors and interfaces_nums are allocated in the
355462306a36Sopenharmony_ci	 * same chunk so only one free is required.
355562306a36Sopenharmony_ci	 */
355662306a36Sopenharmony_ci	func->function.fs_descriptors = NULL;
355762306a36Sopenharmony_ci	func->function.hs_descriptors = NULL;
355862306a36Sopenharmony_ci	func->function.ss_descriptors = NULL;
355962306a36Sopenharmony_ci	func->function.ssp_descriptors = NULL;
356062306a36Sopenharmony_ci	func->interfaces_nums = NULL;
356162306a36Sopenharmony_ci
356262306a36Sopenharmony_ci}
356362306a36Sopenharmony_ci
356462306a36Sopenharmony_cistatic struct usb_function *ffs_alloc(struct usb_function_instance *fi)
356562306a36Sopenharmony_ci{
356662306a36Sopenharmony_ci	struct ffs_function *func;
356762306a36Sopenharmony_ci
356862306a36Sopenharmony_ci	func = kzalloc(sizeof(*func), GFP_KERNEL);
356962306a36Sopenharmony_ci	if (!func)
357062306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
357162306a36Sopenharmony_ci
357262306a36Sopenharmony_ci	func->function.name    = "Function FS Gadget";
357362306a36Sopenharmony_ci
357462306a36Sopenharmony_ci	func->function.bind    = ffs_func_bind;
357562306a36Sopenharmony_ci	func->function.unbind  = ffs_func_unbind;
357662306a36Sopenharmony_ci	func->function.set_alt = ffs_func_set_alt;
357762306a36Sopenharmony_ci	func->function.disable = ffs_func_disable;
357862306a36Sopenharmony_ci	func->function.setup   = ffs_func_setup;
357962306a36Sopenharmony_ci	func->function.req_match = ffs_func_req_match;
358062306a36Sopenharmony_ci	func->function.suspend = ffs_func_suspend;
358162306a36Sopenharmony_ci	func->function.resume  = ffs_func_resume;
358262306a36Sopenharmony_ci	func->function.free_func = ffs_free;
358362306a36Sopenharmony_ci
358462306a36Sopenharmony_ci	return &func->function;
358562306a36Sopenharmony_ci}
358662306a36Sopenharmony_ci
358762306a36Sopenharmony_ci/*
358862306a36Sopenharmony_ci * ffs_lock must be taken by the caller of this function
358962306a36Sopenharmony_ci */
359062306a36Sopenharmony_cistatic struct ffs_dev *_ffs_alloc_dev(void)
359162306a36Sopenharmony_ci{
359262306a36Sopenharmony_ci	struct ffs_dev *dev;
359362306a36Sopenharmony_ci	int ret;
359462306a36Sopenharmony_ci
359562306a36Sopenharmony_ci	if (_ffs_get_single_dev())
359662306a36Sopenharmony_ci			return ERR_PTR(-EBUSY);
359762306a36Sopenharmony_ci
359862306a36Sopenharmony_ci	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
359962306a36Sopenharmony_ci	if (!dev)
360062306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
360162306a36Sopenharmony_ci
360262306a36Sopenharmony_ci	if (list_empty(&ffs_devices)) {
360362306a36Sopenharmony_ci		ret = functionfs_init();
360462306a36Sopenharmony_ci		if (ret) {
360562306a36Sopenharmony_ci			kfree(dev);
360662306a36Sopenharmony_ci			return ERR_PTR(ret);
360762306a36Sopenharmony_ci		}
360862306a36Sopenharmony_ci	}
360962306a36Sopenharmony_ci
361062306a36Sopenharmony_ci	list_add(&dev->entry, &ffs_devices);
361162306a36Sopenharmony_ci
361262306a36Sopenharmony_ci	return dev;
361362306a36Sopenharmony_ci}
361462306a36Sopenharmony_ci
361562306a36Sopenharmony_ciint ffs_name_dev(struct ffs_dev *dev, const char *name)
361662306a36Sopenharmony_ci{
361762306a36Sopenharmony_ci	struct ffs_dev *existing;
361862306a36Sopenharmony_ci	int ret = 0;
361962306a36Sopenharmony_ci
362062306a36Sopenharmony_ci	ffs_dev_lock();
362162306a36Sopenharmony_ci
362262306a36Sopenharmony_ci	existing = _ffs_do_find_dev(name);
362362306a36Sopenharmony_ci	if (!existing)
362462306a36Sopenharmony_ci		strscpy(dev->name, name, ARRAY_SIZE(dev->name));
362562306a36Sopenharmony_ci	else if (existing != dev)
362662306a36Sopenharmony_ci		ret = -EBUSY;
362762306a36Sopenharmony_ci
362862306a36Sopenharmony_ci	ffs_dev_unlock();
362962306a36Sopenharmony_ci
363062306a36Sopenharmony_ci	return ret;
363162306a36Sopenharmony_ci}
363262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ffs_name_dev);
363362306a36Sopenharmony_ci
363462306a36Sopenharmony_ciint ffs_single_dev(struct ffs_dev *dev)
363562306a36Sopenharmony_ci{
363662306a36Sopenharmony_ci	int ret;
363762306a36Sopenharmony_ci
363862306a36Sopenharmony_ci	ret = 0;
363962306a36Sopenharmony_ci	ffs_dev_lock();
364062306a36Sopenharmony_ci
364162306a36Sopenharmony_ci	if (!list_is_singular(&ffs_devices))
364262306a36Sopenharmony_ci		ret = -EBUSY;
364362306a36Sopenharmony_ci	else
364462306a36Sopenharmony_ci		dev->single = true;
364562306a36Sopenharmony_ci
364662306a36Sopenharmony_ci	ffs_dev_unlock();
364762306a36Sopenharmony_ci	return ret;
364862306a36Sopenharmony_ci}
364962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ffs_single_dev);
365062306a36Sopenharmony_ci
365162306a36Sopenharmony_ci/*
365262306a36Sopenharmony_ci * ffs_lock must be taken by the caller of this function
365362306a36Sopenharmony_ci */
365462306a36Sopenharmony_cistatic void _ffs_free_dev(struct ffs_dev *dev)
365562306a36Sopenharmony_ci{
365662306a36Sopenharmony_ci	list_del(&dev->entry);
365762306a36Sopenharmony_ci
365862306a36Sopenharmony_ci	kfree(dev);
365962306a36Sopenharmony_ci	if (list_empty(&ffs_devices))
366062306a36Sopenharmony_ci		functionfs_cleanup();
366162306a36Sopenharmony_ci}
366262306a36Sopenharmony_ci
366362306a36Sopenharmony_cistatic int ffs_acquire_dev(const char *dev_name, struct ffs_data *ffs_data)
366462306a36Sopenharmony_ci{
366562306a36Sopenharmony_ci	int ret = 0;
366662306a36Sopenharmony_ci	struct ffs_dev *ffs_dev;
366762306a36Sopenharmony_ci
366862306a36Sopenharmony_ci	ffs_dev_lock();
366962306a36Sopenharmony_ci
367062306a36Sopenharmony_ci	ffs_dev = _ffs_find_dev(dev_name);
367162306a36Sopenharmony_ci	if (!ffs_dev) {
367262306a36Sopenharmony_ci		ret = -ENOENT;
367362306a36Sopenharmony_ci	} else if (ffs_dev->mounted) {
367462306a36Sopenharmony_ci		ret = -EBUSY;
367562306a36Sopenharmony_ci	} else if (ffs_dev->ffs_acquire_dev_callback &&
367662306a36Sopenharmony_ci		   ffs_dev->ffs_acquire_dev_callback(ffs_dev)) {
367762306a36Sopenharmony_ci		ret = -ENOENT;
367862306a36Sopenharmony_ci	} else {
367962306a36Sopenharmony_ci		ffs_dev->mounted = true;
368062306a36Sopenharmony_ci		ffs_dev->ffs_data = ffs_data;
368162306a36Sopenharmony_ci		ffs_data->private_data = ffs_dev;
368262306a36Sopenharmony_ci	}
368362306a36Sopenharmony_ci
368462306a36Sopenharmony_ci	ffs_dev_unlock();
368562306a36Sopenharmony_ci	return ret;
368662306a36Sopenharmony_ci}
368762306a36Sopenharmony_ci
368862306a36Sopenharmony_cistatic void ffs_release_dev(struct ffs_dev *ffs_dev)
368962306a36Sopenharmony_ci{
369062306a36Sopenharmony_ci	ffs_dev_lock();
369162306a36Sopenharmony_ci
369262306a36Sopenharmony_ci	if (ffs_dev && ffs_dev->mounted) {
369362306a36Sopenharmony_ci		ffs_dev->mounted = false;
369462306a36Sopenharmony_ci		if (ffs_dev->ffs_data) {
369562306a36Sopenharmony_ci			ffs_dev->ffs_data->private_data = NULL;
369662306a36Sopenharmony_ci			ffs_dev->ffs_data = NULL;
369762306a36Sopenharmony_ci		}
369862306a36Sopenharmony_ci
369962306a36Sopenharmony_ci		if (ffs_dev->ffs_release_dev_callback)
370062306a36Sopenharmony_ci			ffs_dev->ffs_release_dev_callback(ffs_dev);
370162306a36Sopenharmony_ci	}
370262306a36Sopenharmony_ci
370362306a36Sopenharmony_ci	ffs_dev_unlock();
370462306a36Sopenharmony_ci}
370562306a36Sopenharmony_ci
370662306a36Sopenharmony_cistatic int ffs_ready(struct ffs_data *ffs)
370762306a36Sopenharmony_ci{
370862306a36Sopenharmony_ci	struct ffs_dev *ffs_obj;
370962306a36Sopenharmony_ci	int ret = 0;
371062306a36Sopenharmony_ci
371162306a36Sopenharmony_ci	ffs_dev_lock();
371262306a36Sopenharmony_ci
371362306a36Sopenharmony_ci	ffs_obj = ffs->private_data;
371462306a36Sopenharmony_ci	if (!ffs_obj) {
371562306a36Sopenharmony_ci		ret = -EINVAL;
371662306a36Sopenharmony_ci		goto done;
371762306a36Sopenharmony_ci	}
371862306a36Sopenharmony_ci	if (WARN_ON(ffs_obj->desc_ready)) {
371962306a36Sopenharmony_ci		ret = -EBUSY;
372062306a36Sopenharmony_ci		goto done;
372162306a36Sopenharmony_ci	}
372262306a36Sopenharmony_ci
372362306a36Sopenharmony_ci	ffs_obj->desc_ready = true;
372462306a36Sopenharmony_ci
372562306a36Sopenharmony_ci	if (ffs_obj->ffs_ready_callback) {
372662306a36Sopenharmony_ci		ret = ffs_obj->ffs_ready_callback(ffs);
372762306a36Sopenharmony_ci		if (ret)
372862306a36Sopenharmony_ci			goto done;
372962306a36Sopenharmony_ci	}
373062306a36Sopenharmony_ci
373162306a36Sopenharmony_ci	set_bit(FFS_FL_CALL_CLOSED_CALLBACK, &ffs->flags);
373262306a36Sopenharmony_cidone:
373362306a36Sopenharmony_ci	ffs_dev_unlock();
373462306a36Sopenharmony_ci	return ret;
373562306a36Sopenharmony_ci}
373662306a36Sopenharmony_ci
373762306a36Sopenharmony_cistatic void ffs_closed(struct ffs_data *ffs)
373862306a36Sopenharmony_ci{
373962306a36Sopenharmony_ci	struct ffs_dev *ffs_obj;
374062306a36Sopenharmony_ci	struct f_fs_opts *opts;
374162306a36Sopenharmony_ci	struct config_item *ci;
374262306a36Sopenharmony_ci
374362306a36Sopenharmony_ci	ffs_dev_lock();
374462306a36Sopenharmony_ci
374562306a36Sopenharmony_ci	ffs_obj = ffs->private_data;
374662306a36Sopenharmony_ci	if (!ffs_obj)
374762306a36Sopenharmony_ci		goto done;
374862306a36Sopenharmony_ci
374962306a36Sopenharmony_ci	ffs_obj->desc_ready = false;
375062306a36Sopenharmony_ci
375162306a36Sopenharmony_ci	if (test_and_clear_bit(FFS_FL_CALL_CLOSED_CALLBACK, &ffs->flags) &&
375262306a36Sopenharmony_ci	    ffs_obj->ffs_closed_callback)
375362306a36Sopenharmony_ci		ffs_obj->ffs_closed_callback(ffs);
375462306a36Sopenharmony_ci
375562306a36Sopenharmony_ci	if (ffs_obj->opts)
375662306a36Sopenharmony_ci		opts = ffs_obj->opts;
375762306a36Sopenharmony_ci	else
375862306a36Sopenharmony_ci		goto done;
375962306a36Sopenharmony_ci
376062306a36Sopenharmony_ci	if (opts->no_configfs || !opts->func_inst.group.cg_item.ci_parent
376162306a36Sopenharmony_ci	    || !kref_read(&opts->func_inst.group.cg_item.ci_kref))
376262306a36Sopenharmony_ci		goto done;
376362306a36Sopenharmony_ci
376462306a36Sopenharmony_ci	ci = opts->func_inst.group.cg_item.ci_parent->ci_parent;
376562306a36Sopenharmony_ci	ffs_dev_unlock();
376662306a36Sopenharmony_ci
376762306a36Sopenharmony_ci	if (test_bit(FFS_FL_BOUND, &ffs->flags))
376862306a36Sopenharmony_ci		unregister_gadget_item(ci);
376962306a36Sopenharmony_ci	return;
377062306a36Sopenharmony_cidone:
377162306a36Sopenharmony_ci	ffs_dev_unlock();
377262306a36Sopenharmony_ci}
377362306a36Sopenharmony_ci
377462306a36Sopenharmony_ci/* Misc helper functions ****************************************************/
377562306a36Sopenharmony_ci
377662306a36Sopenharmony_cistatic int ffs_mutex_lock(struct mutex *mutex, unsigned nonblock)
377762306a36Sopenharmony_ci{
377862306a36Sopenharmony_ci	return nonblock
377962306a36Sopenharmony_ci		? mutex_trylock(mutex) ? 0 : -EAGAIN
378062306a36Sopenharmony_ci		: mutex_lock_interruptible(mutex);
378162306a36Sopenharmony_ci}
378262306a36Sopenharmony_ci
378362306a36Sopenharmony_cistatic char *ffs_prepare_buffer(const char __user *buf, size_t len)
378462306a36Sopenharmony_ci{
378562306a36Sopenharmony_ci	char *data;
378662306a36Sopenharmony_ci
378762306a36Sopenharmony_ci	if (!len)
378862306a36Sopenharmony_ci		return NULL;
378962306a36Sopenharmony_ci
379062306a36Sopenharmony_ci	data = memdup_user(buf, len);
379162306a36Sopenharmony_ci	if (IS_ERR(data))
379262306a36Sopenharmony_ci		return data;
379362306a36Sopenharmony_ci
379462306a36Sopenharmony_ci	pr_vdebug("Buffer from user space:\n");
379562306a36Sopenharmony_ci	ffs_dump_mem("", data, len);
379662306a36Sopenharmony_ci
379762306a36Sopenharmony_ci	return data;
379862306a36Sopenharmony_ci}
379962306a36Sopenharmony_ci
380062306a36Sopenharmony_ciDECLARE_USB_FUNCTION_INIT(ffs, ffs_alloc_inst, ffs_alloc);
380162306a36Sopenharmony_ciMODULE_LICENSE("GPL");
380262306a36Sopenharmony_ciMODULE_AUTHOR("Michal Nazarewicz");
3803