Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ade2576e authored by Ajay Agarwal's avatar Ajay Agarwal
Browse files

USB: gadget: ffs: Fix USBCV compliance failure due to adbd



Userspace f_fs client e.g. ADB daemon can re-open ep0 file node
on adb_read/write error (or on bus reset). This results in device
disabling and enabling pull-up on bus reset. USBCV CH9 tests which
perform bus resets also fail due to this.
Fix this by not failing adb_read on bus reset so that adbd client
woudln't attempt ep0-file close. This behavior is not changed for
composition switch or cable disconnect by checking if adb_read
was attempting first transfer after online state or it was in middle
of a session when disconnect happened.

Change-Id: I2378f22995b7ddffb17d618df059d8aedb594d97
Signed-off-by: default avatarAjay Agarwal <ajaya@codeaurora.org>
parent a3851309
Loading
Loading
Loading
Loading
+32 −2
Original line number Diff line number Diff line
@@ -71,6 +71,7 @@ __ffs_data_got_strings(struct ffs_data *ffs, char *data, size_t len);
/* The function structure ***************************************************/

struct ffs_ep;
static bool first_read_done;

struct ffs_function {
	struct usb_configuration	*conf;
@@ -756,6 +757,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
{
	struct ffs_epfile *epfile = file->private_data;
	struct ffs_ep *ep;
	struct ffs_data *ffs = epfile->ffs;
	char *data = NULL;
	ssize_t ret, data_len = -EINVAL;
	int halt;
@@ -764,6 +766,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
		atomic_read(&epfile->error), io_data->read ? "READ" : "WRITE");

	smp_mb__before_atomic();
retry:
	if (atomic_read(&epfile->error))
		return -ENODEV;

@@ -968,10 +971,36 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
				 * disabled (disconnect) or changed
				 * (composition switch) ?
				 */
				if (epfile->ep == ep)
				if (epfile->ep == ep) {
					ret = ep->status;
				else
					if (ret >= 0)
						first_read_done = true;
				} else {
					ret = -ENODEV;
				}

				/* do wait again if func eps are not enabled */
				if (io_data->read && !first_read_done
							&& ret < 0) {
					unsigned short count = ffs->eps_count;

					pr_debug("%s: waiting for the online state\n",
						 __func__);
					ret = 0;
					kfree(data);
					data = NULL;
					data_len = -EINVAL;
					spin_unlock_irq(&epfile->ffs->eps_lock);
					mutex_unlock(&epfile->mutex);
					epfile = ffs->epfiles;
					do {
						atomic_set(&epfile->error, 0);
						++epfile;
					} while (--count);
					epfile = file->private_data;
					goto retry;
				}

				spin_unlock_irq(&epfile->ffs->eps_lock);
				if (io_data->read && ret > 0) {

@@ -1038,6 +1067,7 @@ ffs_epfile_open(struct inode *inode, struct file *file)

	smp_mb__before_atomic();
	atomic_set(&epfile->error, 0);
	first_read_done = false;

	ffs_log("exit:state %d setup_state %d flag %lu", epfile->ffs->state,
		epfile->ffs->setup_state, epfile->ffs->flags);