linux-usb.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
To: Joel Pepper <joel.pepper@rwth-aachen.de>
Cc: Felipe Balbi <balbi@kernel.org>,
	linux-usb@vger.kernel.org, Paul Elder <paul.elder@pitt.edu>
Subject: [RESEND,v6,2/2] usb/gadget/uvc-configfs Fix host unable to negotiate framesizes other than first
Date: Fri, 08 Jun 2018 22:11:07 +0300	[thread overview]
Message-ID: <1819956.5cdldLK3cV@avalon> (raw)

Hi Joel,

Thank you for the patch, and sorry for the late reply.

On Tuesday, 29 May 2018 22:02:13 EEST Joel Pepper wrote:
> - Add bFrameIndex as a UVCG_FRAME_ATTR_RO for each frame size.
> - Automatically assign ascending bFrameIndex to each frame in a format.
> 
> Before all "bFrameindex" attributes were set to "1" with no way to
> configure the gadget otherwise. This resulted in the host always
> negotiating for bFrameIndex 1 (i.e. the first framesize of the gadget).
> After the negotiation the host driver will set the user or application
> selected framesize, while the gadget is actually set to the first
> framesize.
> 
> Now, when the containing format is linked into the streaming header,
> iterate over all child frame descriptors and assign ascending indices.
> The automatically assigned indices can be read from the new read only
> bFrameIndex configsfs attribute in each frame descriptor item.
> 
> Signed-off-by: Joel Pepper <joel.pepper@rwth-aachen.de>
> ---
> 
> v2: Add the new attribute to both MJPEG and uncompressed frame descriptors
> in Documentation/ABI, with note that it was added only in a later
> kernel version
> 
> v3: Changed from simply allowing user to set the value for bFrameIndex to
> automatically assigning correct distinct frame indexes. Changed
> bFrameIndex from RW to RO
> 
> v4: Actually include updated patch
> 
> v5: bFrameIndex now returns -EBUSY if the parent fmt is not linked yet
> 
>  Documentation/ABI/testing/configfs-usb-gadget-uvc | 18 +++++++
>  drivers/usb/gadget/function/uvc_configfs.c        | 64 ++++++++++++++++++++
>  2 files changed, 82 insertions(+)
> 
> diff --git a/Documentation/ABI/testing/configfs-usb-gadget-uvc
> b/Documentation/ABI/testing/configfs-usb-gadget-uvc index 1ba0d0f..86c9b2e
> 100644
> --- a/Documentation/ABI/testing/configfs-usb-gadget-uvc
> +++ b/Documentation/ABI/testing/configfs-usb-gadget-uvc
> @@ -194,6 +194,14 @@ Description:	Specific MJPEG frame descriptors
>  		bmCapabilities		- still image support, fixed frame-rate
>  					support
> 
> +Date:		May 2018
> +KernelVersion:	4.17
> +
> +		bFrameIndex		- unique id for this framedescriptor;

This should be spelled "frame descriptor", not "framedescriptor".

> +					only defined after parent format is
> +					linked into the streaming header;
> +					read-only
> +
>  What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/
uncompressed
>  Date:		Dec 2014
>  KernelVersion:	4.0
> @@ -241,6 +249,16 @@ Description:	Specific uncompressed frame descriptors
>  		bmCapabilities		- still image support, fixed frame-rate
>  					support
> 
> +Date:           May 2018
> +KernelVersion:  4.17
> +
> +                bFrameIndex             - unique id for this
> framedescriptor;

Same here.

> +                                        only defined after parent format is
> +                                        linked into the streaming header;
> +                                        read-only

For some reason tabs got converted to space.

> +
> +
> +

One blank line is enough.

>  What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/header
>  Date:		Dec 2014
>  KernelVersion:	4.0
> diff --git a/drivers/usb/gadget/function/uvc_configfs.c
> b/drivers/usb/gadget/function/uvc_configfs.c index 7a98f9f..37b4a14 100644
> --- a/drivers/usb/gadget/function/uvc_configfs.c
> +++ b/drivers/usb/gadget/function/uvc_configfs.c
> @@ -32,6 +32,7 @@ static struct configfs_attribute prefix##attr_##cname = {
> \ }
> 
>  static inline struct f_uvc_opts *to_f_uvc_opts(struct config_item *item);
> +static void __uvcg_fmt_set_indices(struct config_group *fmt);

Please move the function before it gets called to avoid forward declarations.

>  /* control/header/<NAME> */
>  DECLARE_UVC_HEADER_DESCRIPTOR(1);
> @@ -751,6 +752,8 @@ static int uvcg_streaming_header_allow_link(struct
> config_item *src, if (!target_fmt)
>  		goto out;
> 
> +	__uvcg_fmt_set_indices(to_config_group(target));
> +

Is there a need to prefix the function name with __ ?

>  	format_ptr = kzalloc(sizeof(*format_ptr), GFP_KERNEL);
>  	if (!format_ptr) {
>  		ret = -ENOMEM;
> @@ -991,8 +994,46 @@ end:									\
>  									\
>  UVC_ATTR(uvcg_frame_, cname, aname);
> 
> +

No need for a new blank line.

> +static ssize_t uvcg_frame_b_frame_index_show(struct config_item *item,
> +		char *page)
> +{
> +	struct uvcg_frame *f = to_uvcg_frame(item);
> +	struct uvcg_format *fmt;
> +	struct f_uvc_opts *opts;
> +	struct config_item *opts_item;
> +	struct config_item *fmt_item;
> +	struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;
> +	int result;
> +
> +	mutex_lock(su_mutex); /* for navigating configfs hierarchy */
> +
> +	fmt_item = f->item.ci_parent;
> +	fmt = to_uvcg_format(fmt_item);
> +
> +	if (!fmt->linked) {
> +		result = -EBUSY;
> +		goto out;
> +	}
> +
> +	opts_item = fmt_item->ci_parent->ci_parent->ci_parent;
> +	opts = to_f_uvc_opts(opts_item);
> +
> +	mutex_lock(&opts->lock);
> +	result = sprintf(page, "%d\n", f->frame.b_frame_index);
> +	mutex_unlock(&opts->lock);
> +
> +out:
> +	mutex_unlock(su_mutex);
> +	return result;
> +}
> +
> +UVC_ATTR_RO(uvcg_frame_, b_frame_index, bFrameIndex);
> +

As we already have UVCG_FRAME_ATTR, should we turn this into a 
UVCG_FRAME_ATTR_RO macro ?

>  #define noop_conversion(x) (x)
> 
> +
> +
>  UVCG_FRAME_ATTR(bm_capabilities, bmCapabilities, noop_conversion,
>  		noop_conversion, 8);
>  UVCG_FRAME_ATTR(w_width, wWidth, le16_to_cpu, cpu_to_le16, 16);
> @@ -1140,6 +1181,7 @@ UVC_ATTR(uvcg_frame_, dw_frame_interval,
> dwFrameInterval);
> 
>  static struct configfs_attribute *uvcg_frame_attrs[] = {
>  	&uvcg_frame_attr_bm_capabilities,
> +	&uvcg_frame_attr_b_frame_index,
>  	&uvcg_frame_attr_w_width,
>  	&uvcg_frame_attr_w_height,
>  	&uvcg_frame_attr_dw_min_bit_rate,
> @@ -1217,6 +1259,28 @@ static void uvcg_frame_drop(struct config_group
> *group, struct config_item *item mutex_unlock(&opts->lock);
>  }
> 
> +static void __uvcg_fmt_set_indices(struct config_group *fmt)
> +{
> +	u8 i = 1;

I think you can simply use an unsigned int.

> +	struct list_head *entry;
> +	struct config_item *ci;
> +	struct uvcg_frame *frm;

You could declare the last two variables inside the loop. I'll let you decide 
on this change, as the function is small and the variables are thus already 
close to the code that uses them.

> +
> +	list_for_each(entry, &(fmt->cg_children)) {
> +

No need for a blank line here.

> +		ci = container_of(entry, struct config_item, ci_entry);
> +
> +		if (ci->ci_type != &uvcg_frame_type)
> +			continue;
> +
> +		frm = to_uvcg_frame(ci);
> +		frm->frame.b_frame_index = i;
> +		i++;

You could write this

		frm->frame.b_frame_index = i++;

> +

And no need for a blank line here either.

> +	}
> +

Same here.

> +}
> +
>  /* streaming/uncompressed/<NAME> */
>  struct uvcg_uncompressed {
>  	struct uvcg_format		fmt;

Can't you set b_frame_index from __uvcg_fill_strm(), in a similar way as the 
b_format_index is set ? I've received a competing implementation from Paul in 
parallel to your patch that does so, I'll post it as a reply to this e-mail to 
discuss which approach is best.

             reply	other threads:[~2018-06-08 19:11 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-06-08 19:11 Laurent Pinchart [this message]
  -- strict thread matches above, loose matches on Subject: below --
2018-05-29 19:02 [RESEND,v6,2/2] usb/gadget/uvc-configfs Fix host unable to negotiate framesizes other than first Joel Pepper

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1819956.5cdldLK3cV@avalon \
    --to=laurent.pinchart@ideasonboard.com \
    --cc=balbi@kernel.org \
    --cc=joel.pepper@rwth-aachen.de \
    --cc=linux-usb@vger.kernel.org \
    --cc=paul.elder@pitt.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).