Re: gadgetfs USB2.0 Chapter 9 Tests: Test after "Addressed State" fails

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Dec 24 2013, roshan.jhalani@xxxxxxxxxxxx wrote:
>> Do you have a patch that does that?  It would help in analysing the
>> issue.  Something quick and dirty will do just to see.

> Please refer patch below. I am not so good in gadgetFs, so just tried
> to hack this issue as per the following:

That's fine, thanks.

BTW, GadgetFS and FunctionFS are not the same things, even though ABI of
the latter is based on, but not compatible with, the ABI of the former.

> Signed-off-by: Roshan Jhalani<roshan.jhalani@xxxxxxxxxxxx>
> ---
>  drivers/usb/gadget/composite.c |    7 +++++++
>  drivers/usb/gadget/f_fs.c      |   25 +++++++++++++++++--------
>  2 files changed, 24 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
> index 97633e5..8cd4022 100644
> --- a/drivers/usb/gadget/composite.c
> +++ b/drivers/usb/gadget/composite.c
> @@ -1294,6 +1294,13 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
>  	req->length = 0;
>  	gadget->ep0->driver_data = cdev;
>  
> +	if (cdev->config) {
> +		list_for_each_entry(f, &cdev->config->functions, list) {
> +			if (f && f->setup)
> +				value = f->setup(f, ctrl);
> +		}
> +	}
> +
>  	switch (ctrl->bRequest) {
>  
>  	/* we handle all standard USB descriptors */
> diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
> index bf7d627..8e2bcee 100644
> --- a/drivers/usb/gadget/f_fs.c
> +++ b/drivers/usb/gadget/f_fs.c
> @@ -107,7 +107,10 @@ enum ffs_setup_state {
>  	FFS_SETUP_CANCELED
>  };
>  
> -
> +enum ffs_work_state {
> +	FFS_STOP,
> +	FFS_START
> +};
>  
>  struct ffs_epfile;
>  struct ffs_function;
> @@ -149,6 +152,7 @@ struct ffs_data {
>  
>  	/* EP0 state */
>  	enum ffs_state			state;
> +	enum ffs_work_state		work_state;
>  
>  	/*
>  	 * Possible transitions:
> @@ -460,7 +464,8 @@ static ssize_t ffs_ep0_write(struct file *file, const char __user *buf,
>  			ffs->state = FFS_ACTIVE;
>  			mutex_unlock(&ffs->mutex);
>  
> -			ret = functionfs_ready_callback(ffs);
> +			if (ffs->work_state != FFS_START)
> +				ret = functionfs_ready_callback(ffs);
>  			if (unlikely(ret < 0)) {
>  				ffs->state = FFS_CLOSING;
>  				return ret;
> @@ -1292,11 +1297,16 @@ static void ffs_data_closed(struct ffs_data *ffs)
>  {
>  	ENTER();
>  
> +	if (ffs->work_state == FFS_START) {
> +		atomic_dec(&ffs->opened);
> +		atomic_dec(&ffs->ref);
> +		ffs->state = FFS_READ_DESCRIPTORS;
> +		return;
> +	}
>  	if (atomic_dec_and_test(&ffs->opened)) {
>  		ffs->state = FFS_CLOSING;
>  		ffs_data_reset(ffs);
>  	}
> -
>  	ffs_data_put(ffs);
>  }

This function is called whenever an ep file is released by user space
(be it ep0 file or the other “regular” ep files).  It is complementary
to the ffs_data_opened function which in tandem track whether at least
one epfile is open.

The way it works is that if user space closes all the ep files,
FunctionFS will assume it's done with the function and reset to a clean
state for a new user space program to access and make use.

So I think what's happening is that you are closing all the ep files in
your user space program which causes the whole thing to be reset.  To
prevent it you just need to stick to at least one of the ep files.  If
you do so, you should no longer see the disconnects.

>  
> @@ -1311,6 +1321,7 @@ static struct ffs_data *ffs_data_new(void)
>  	atomic_set(&ffs->ref, 1);
>  	atomic_set(&ffs->opened, 0);
>  	ffs->state = FFS_READ_DESCRIPTORS;
> +	ffs->work_state = FFS_STOP;
>  	mutex_init(&ffs->mutex);
>  	spin_lock_init(&ffs->eps_lock);
>  	init_waitqueue_head(&ffs->ev.waitq);
> @@ -1334,6 +1345,7 @@ static void ffs_data_clear(struct ffs_data *ffs)
>  	if (ffs->epfiles)
>  		ffs_epfiles_destroy(ffs->epfiles, ffs->eps_count);
>  
> +	ffs->work_state = FFS_STOP;
>  	kfree(ffs->raw_descs);
>  	kfree(ffs->raw_strings);
>  	kfree(ffs->stringtabs);
> @@ -1358,15 +1370,12 @@ static void ffs_data_reset(struct ffs_data *ffs)
>  	ffs->strings_count = 0;
>  	ffs->interfaces_count = 0;
>  	ffs->eps_count = 0;
> -
>  	ffs->ev.count = 0;
>  
>  	ffs->state = FFS_READ_DESCRIPTORS;
>  	ffs->setup_state = FFS_NO_SETUP;
>  	ffs->flags = 0;
>  }
> -
> -
>  static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev)
>  {
>  	struct usb_gadget_strings **lang;
> @@ -2367,8 +2376,6 @@ static int ffs_func_setup(struct usb_function *f,
>  	 * as well (as it's straightforward) but what to do with any
>  	 * other request?
>  	 */
> -	if (ffs->state != FFS_ACTIVE)
> -		return -ENODEV;
>  
>  	switch (creq->bRequestType & USB_RECIP_MASK) {
>  	case USB_RECIP_INTERFACE:
> @@ -2384,6 +2391,8 @@ static int ffs_func_setup(struct usb_function *f,
>  		break;
>  
>  	default:
> +		ffs->work_state = FFS_START;
> +		ffs->state = FFS_ACTIVE;
>  		return -EOPNOTSUPP;
>  	}
>  

-- 
Best regards,                                         _     _
.o. | Liege of Serenely Enlightened Majesty of      o' \,=./ `o
..o | Computer Science,  Michał “mina86” Nazarewicz    (o o)
ooo +--<mpn@xxxxxxxxxx>--<xmpp:mina86@xxxxxxxxxx>--ooO--(_)--Ooo--

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux