All of lore.kernel.org
 help / color / mirror / Atom feed
From: Hans de Goede <hdegoede@redhat.com>
To: Ricardo Ribalda <ribalda@chromium.org>,
	Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
	Mauro Carvalho Chehab <mchehab@kernel.org>,
	Ricardo Ribalda <ribalda@kernel.org>,
	Sakari Ailus <sakari.ailus@linux.intel.com>,
	Hans Verkuil <hverkuil@xs4all.nl>
Cc: Yunke Cao <yunkec@chromium.org>,
	linux-media@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v15 09/19] media: uvcvideo: Support any size for mapping get/set
Date: Mon, 9 Dec 2024 13:49:32 +0100	[thread overview]
Message-ID: <2c095d07-739f-4e9d-ac71-ba484bfe2a4d@redhat.com> (raw)
In-Reply-To: <20241114-uvc-roi-v15-9-64cfeb56b6f8@chromium.org>

Hi,

On 14-Nov-24 8:10 PM, Ricardo Ribalda wrote:
> Right now, we only support mappings for v4l2 controls with a max size of
> s32. This patch modifies the prototype of get/set so it can support any
> size.
> 
> This is done to prepare for compound controls.
> 
> Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
> ---
>  drivers/media/usb/uvc/uvc_ctrl.c | 183 +++++++++++++++++++++++++++------------
>  drivers/media/usb/uvc/uvcvideo.h |   8 +-
>  2 files changed, 130 insertions(+), 61 deletions(-)
> 
> diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
> index d6afa131a5e1..6d5167eb368d 100644
> --- a/drivers/media/usb/uvc/uvc_ctrl.c
> +++ b/drivers/media/usb/uvc/uvc_ctrl.c
> @@ -367,6 +367,22 @@ static const u32 uvc_control_classes[] = {
>  
>  static const int exposure_auto_mapping[] = { 2, 1, 4, 8 };
>  
> +static s32 uvc_mapping_get_s32(struct uvc_control_mapping *mapping,
> +			       u8 query, const void *data_in)
> +{
> +	s32 data_out;
> +
> +	mapping->get(mapping, query, data_in, sizeof(data_out), &data_out);

If mapping->get() fails, e.g. hits the -EINVAL path in uvc_ctrl_get_zoom()
then this will return the uninitialized data_out.

I realize that this is supposed to never happen and adding error-handling
here would not be helpful since there is no way to return an error-code
without changing the function prototype.

But I think you should at least initialize data_out to 0 to avoid leaking
stack-memory contents to userspace if we somehow do manage to hit this.


> +
> +	return data_out;
> +}
> +
> +static void uvc_mapping_set_s32(struct uvc_control_mapping *mapping,
> +				s32 data_in, void *data_out)
> +{
> +	mapping->set(mapping, sizeof(data_in), &data_in, data_out);
> +}
> +
>  /*
>   * This function translates the V4L2 menu index @idx, as exposed to userspace as
>   * the V4L2 control value, to the corresponding UVC control value used by the
> @@ -405,58 +421,93 @@ uvc_mapping_get_menu_name(const struct uvc_control_mapping *mapping, u32 idx)
>  	return v4l2_ctrl_get_menu(mapping->id)[idx];
>  }
>  
> -static s32 uvc_ctrl_get_zoom(struct uvc_control_mapping *mapping,
> -	u8 query, const u8 *data)
> +static int uvc_ctrl_get_zoom(struct uvc_control_mapping *mapping, u8 query,
> +			     const void *uvc_in, size_t v4l2_size,
> +			     void *v4l2_out)
>  {
> -	s8 zoom = (s8)data[0];
> +	u8 value = ((u8 *)uvc_in)[2];
> +	s8 sign = ((s8 *)uvc_in)[0];
> +	s32 *out = v4l2_out;
> +
> +	if (WARN_ON(v4l2_size != sizeof(s32)))
> +		return -EINVAL;
>  
>  	switch (query) {
>  	case UVC_GET_CUR:
> -		return (zoom == 0) ? 0 : (zoom > 0 ? data[2] : -data[2]);
> +		*out = (sign == 0) ? 0 : (sign > 0 ? value : -value);
> +		return 0;
>  
>  	case UVC_GET_MIN:
>  	case UVC_GET_MAX:
>  	case UVC_GET_RES:
>  	case UVC_GET_DEF:
>  	default:
> -		return data[2];
> +		*out = value;
> +		return 0;
>  	}
>  }
>  
> -static void uvc_ctrl_set_zoom(struct uvc_control_mapping *mapping,
> -	s32 value, u8 *data)
> +static int uvc_ctrl_set_zoom(struct uvc_control_mapping *mapping,
> +			     size_t v4l2_size, const void *v4l2_in,
> +			     void *uvc_out)
>  {
> -	data[0] = value == 0 ? 0 : (value > 0) ? 1 : 0xff;
> -	data[2] = min((int)abs(value), 0xff);
> +	u8 *out = uvc_out;
> +	s32 value;
> +
> +	if (WARN_ON(v4l2_size != sizeof(s32)))
> +		return -EINVAL;
> +
> +	value = *(u32 *)v4l2_in;
> +	out[0] = value == 0 ? 0 : (value > 0) ? 1 : 0xff;
> +	out[2] = min_t(int, abs(value), 0xff);
> +
> +	return 0;
>  }
>  
> -static s32 uvc_ctrl_get_rel_speed(struct uvc_control_mapping *mapping,
> -	u8 query, const u8 *data)
> +static int uvc_ctrl_get_rel_speed(struct uvc_control_mapping *mapping,
> +				  u8 query, const void *uvc_in,
> +				  size_t v4l2_size, void *v4l2_out)
>  {
>  	unsigned int first = mapping->offset / 8;
> -	s8 rel = (s8)data[first];
> +	u8 value = ((u8 *)uvc_in)[first + 1];
> +	s8 sign = ((s8 *)uvc_in)[first];
> +	s32 *out = v4l2_out;
> +
> +	if (WARN_ON(v4l2_size != sizeof(s32)))
> +		return -EINVAL;
>  
>  	switch (query) {
>  	case UVC_GET_CUR:
> -		return (rel == 0) ? 0 : (rel > 0 ? data[first+1]
> -						 : -data[first+1]);
> +		*out = (sign == 0) ? 0 : (sign > 0 ? value : -value);
> +		return 0;
>  	case UVC_GET_MIN:
> -		return -data[first+1];
> +		*out = -value;
> +		return 0;
>  	case UVC_GET_MAX:
>  	case UVC_GET_RES:
>  	case UVC_GET_DEF:
>  	default:
> -		return data[first+1];
> +		*out = value;
> +		return 0;
>  	}
>  }
>  
> -static void uvc_ctrl_set_rel_speed(struct uvc_control_mapping *mapping,
> -	s32 value, u8 *data)
> +static int uvc_ctrl_set_rel_speed(struct uvc_control_mapping *mapping,
> +				  size_t v4l2_size, const void *v4l2_in,
> +				  void *uvc_out)
>  {
>  	unsigned int first = mapping->offset / 8;
> +	u8 *out = uvc_out;
> +	s32 value;
> +
> +	if (WARN_ON(v4l2_size != sizeof(s32)))
> +		return -EINVAL;
>  
> -	data[first] = value == 0 ? 0 : (value > 0) ? 1 : 0xff;
> -	data[first+1] = min_t(int, abs(value), 0xff);
> +	value = *(u32 *)v4l2_in;
> +	out[first] = value == 0 ? 0 : (value > 0) ? 1 : 0xff;
> +	out[first + 1] = min_t(int, abs(value), 0xff);
> +
> +	return 0;
>  }
>  
>  static const struct uvc_control_mapping uvc_ctrl_power_line_mapping_limited = {
> @@ -887,14 +938,20 @@ static s32 uvc_menu_to_v4l2_menu(struct uvc_control_mapping *mapping, s32 val)
>   * a signed 32bit integer. Sign extension will be performed if the mapping
>   * references a signed data type.
>   */
> -static s32 uvc_get_le_value(struct uvc_control_mapping *mapping,
> -	u8 query, const u8 *data)
> +static int uvc_get_le_value(struct uvc_control_mapping *mapping,
> +			    u8 query, const void *uvc_in, size_t v4l2_size,
> +			    void *v4l2_out)
>  {
> -	int bits = mapping->size;
>  	int offset = mapping->offset;
> +	int bits = mapping->size;
> +	const u8 *data = uvc_in;
> +	s32 *out = v4l2_out;
>  	s32 value = 0;
>  	u8 mask;
>  
> +	if (WARN_ON(v4l2_size != sizeof(s32)))
> +		return -EINVAL;
> +
>  	data += offset / 8;
>  	offset &= 7;
>  	mask = ((1LL << bits) - 1) << offset;
> @@ -916,29 +973,40 @@ static s32 uvc_get_le_value(struct uvc_control_mapping *mapping,
>  		value |= -(value & (1 << (mapping->size - 1)));
>  
>  	/* If it is a menu, convert from uvc to v4l2. */
> -	if (mapping->v4l2_type != V4L2_CTRL_TYPE_MENU)
> -		return value;
> +	if (mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) {
> +		*out = value;
> +		return 0;
> +	}
>  
>  	switch (query) {
>  	case UVC_GET_CUR:
>  	case UVC_GET_DEF:
> -		return uvc_menu_to_v4l2_menu(mapping, value);
> +		*out = uvc_menu_to_v4l2_menu(mapping, value);
> +		return 0;
>  	}
>  
> -	return value;
> +	*out = value;
> +	return 0;
>  }
>  
>  /*
>   * Set the bit string specified by mapping->offset and mapping->size
>   * in the little-endian data stored at 'data' to the value 'value'.
>   */
> -static void uvc_set_le_value(struct uvc_control_mapping *mapping,
> -	s32 value, u8 *data)
> +static int uvc_set_le_value(struct uvc_control_mapping *mapping,
> +			    size_t v4l2_size, const void *v4l2_in,
> +			    void *uvc_out)
>  {
> -	int bits = mapping->size;
>  	int offset = mapping->offset;
> +	int bits = mapping->size;
> +	u8 *data = uvc_out;
> +	s32 value;
>  	u8 mask;
>  
> +	if (WARN_ON(v4l2_size != sizeof(s32)))
> +		return -EINVAL;
> +
> +	value = *(s32 *)v4l2_in;
>  	if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU)
>  		value = uvc_mapping_get_menu_value(mapping, value);
>  	/*
> @@ -960,6 +1028,8 @@ static void uvc_set_le_value(struct uvc_control_mapping *mapping,
>  		bits -= 8 - offset;
>  		offset = 0;
>  	}
> +
> +	return 0;
>  }
>  
>  /* ------------------------------------------------------------------------
> @@ -1141,8 +1211,8 @@ static int __uvc_ctrl_get(struct uvc_video_chain *chain,
>  	if (ret < 0)
>  		return ret;
>  
> -	*value = mapping->get(mapping, UVC_GET_CUR,
> -			      uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
> +	*value = uvc_mapping_get_s32(mapping, UVC_GET_CUR,
> +				     uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
>  
>  	return 0;
>  }
> @@ -1275,12 +1345,12 @@ static u32 uvc_get_ctrl_bitmap(struct uvc_control *ctrl,
>  	 * as supported.
>  	 */
>  	if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)
> -		return mapping->get(mapping, UVC_GET_RES,
> -				    uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES));
> +		return uvc_mapping_get_s32(mapping, UVC_GET_RES,
> +					   uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES));
>  
>  	if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX)
> -		return mapping->get(mapping, UVC_GET_MAX,
> -				    uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX));
> +		return uvc_mapping_get_s32(mapping, UVC_GET_MAX,
> +					   uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX));
>  
>  	return ~0;
>  }
> @@ -1324,10 +1394,9 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
>  			return ret;
>  	}
>  
> -	if (ctrl->info.flags & UVC_CTRL_FLAG_GET_DEF) {
> -		v4l2_ctrl->default_value = mapping->get(mapping, UVC_GET_DEF,
> -				uvc_ctrl_data(ctrl, UVC_CTRL_DATA_DEF));
> -	}
> +	if (ctrl->info.flags & UVC_CTRL_FLAG_GET_DEF)
> +		v4l2_ctrl->default_value = uvc_mapping_get_s32(mapping,
> +				UVC_GET_DEF, uvc_ctrl_data(ctrl, UVC_CTRL_DATA_DEF));
>  
>  	switch (mapping->v4l2_type) {
>  	case V4L2_CTRL_TYPE_MENU:

The dropping of the { } here seems to be an unrelated code style change, please
drop this.


> @@ -1359,16 +1428,16 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
>  	}
>  
>  	if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MIN)
> -		v4l2_ctrl->minimum = mapping->get(mapping, UVC_GET_MIN,
> -				     uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN));
> +		v4l2_ctrl->minimum = uvc_mapping_get_s32(mapping, UVC_GET_MIN,
> +				uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN));
>  
>  	if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX)
> -		v4l2_ctrl->maximum = mapping->get(mapping, UVC_GET_MAX,
> -				     uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX));
> +		v4l2_ctrl->maximum = uvc_mapping_get_s32(mapping, UVC_GET_MAX,
> +				uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX));
>  
>  	if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)
> -		v4l2_ctrl->step = mapping->get(mapping, UVC_GET_RES,
> -				  uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES));
> +		v4l2_ctrl->step = uvc_mapping_get_s32(mapping, UVC_GET_RES,
> +				uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES));
>  
>  	return 0;
>  }
> @@ -1581,7 +1650,7 @@ void uvc_ctrl_status_event(struct uvc_video_chain *chain,
>  	ctrl->handle = NULL;
>  
>  	list_for_each_entry(mapping, &ctrl->info.mappings, list) {
> -		s32 value = mapping->get(mapping, UVC_GET_CUR, data);
> +		s32 value = uvc_mapping_get_s32(mapping, UVC_GET_CUR, data);
>  
>  		/*
>  		 * handle may be NULL here if the device sends auto-update
> @@ -1925,8 +1994,8 @@ int uvc_ctrl_get(struct uvc_video_chain *chain, u32 which,
>  			if (ret < 0)
>  				return ret;
>  		}
> -		xctrl->value = mapping->get(mapping, UVC_GET_DEF,
> -					    uvc_ctrl_data(ctrl, UVC_CTRL_DATA_DEF));
> +		xctrl->value = uvc_mapping_get_s32(mapping, UVC_GET_DEF,
> +						   uvc_ctrl_data(ctrl, UVC_CTRL_DATA_DEF));
>  		return 0;
>  	}
>  
> @@ -1963,12 +2032,12 @@ int uvc_ctrl_set(struct uvc_fh *handle,
>  				return ret;
>  		}
>  
> -		min = mapping->get(mapping, UVC_GET_MIN,
> -				   uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN));
> -		max = mapping->get(mapping, UVC_GET_MAX,
> -				   uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX));
> -		step = mapping->get(mapping, UVC_GET_RES,
> -				    uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES));
> +		min = uvc_mapping_get_s32(mapping, UVC_GET_MIN,
> +					  uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN));
> +		max = uvc_mapping_get_s32(mapping, UVC_GET_MAX,
> +					  uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX));
> +		step = uvc_mapping_get_s32(mapping, UVC_GET_RES,
> +					   uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES));
>  		if (step == 0)
>  			step = 1;
>  
> @@ -2047,8 +2116,8 @@ int uvc_ctrl_set(struct uvc_fh *handle,
>  		       ctrl->info.size);
>  	}
>  
> -	mapping->set(mapping, value,
> -		uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
> +	uvc_mapping_set_s32(mapping, value,
> +			    uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
>  
>  	if (ctrl->info.flags & UVC_CTRL_FLAG_ASYNCHRONOUS)
>  		ctrl->handle = handle;
> diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
> index 6ebaabd11443..3d32a56c5ff8 100644
> --- a/drivers/media/usb/uvc/uvcvideo.h
> +++ b/drivers/media/usb/uvc/uvcvideo.h
> @@ -131,10 +131,10 @@ struct uvc_control_mapping {
>  	const struct uvc_control_mapping *(*filter_mapping)
>  				(struct uvc_video_chain *chain,
>  				struct uvc_control *ctrl);
> -	s32 (*get)(struct uvc_control_mapping *mapping, u8 query,
> -		   const u8 *data);
> -	void (*set)(struct uvc_control_mapping *mapping, s32 value,
> -		    u8 *data);
> +	int (*get)(struct uvc_control_mapping *mapping, u8 query,
> +		   const void *uvc_in, size_t v4l2_size, void *v4l2_out);
> +	int (*set)(struct uvc_control_mapping *mapping, size_t v4l2_size,
> +		   const void *v4l2_in, void *uvc_out);
>  };
>  
>  struct uvc_control {
> 

Exceot for my 2 small remarks this patch looks good to me:

Reviewed-by: Hans de Goede <hdegoede@redhat.com>

Regards,

Hans




  parent reply	other threads:[~2024-12-09 12:49 UTC|newest]

Thread overview: 62+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-11-14 19:10 [PATCH v15 00/19] media: uvcvideo: Implement UVC v1.5 ROI Ricardo Ribalda
2024-11-14 19:10 ` [PATCH v15 01/19] media: uvcvideo: Fix event flags in uvc_ctrl_send_events Ricardo Ribalda
2024-11-14 19:10 ` [PATCH v15 02/19] media: v4l2_ctrl: Add V4L2_CTRL_TYPE_RECT Ricardo Ribalda
2024-11-14 19:10 ` [PATCH v15 03/19] media: v4l2-ctrls: add support for V4L2_CTRL_WHICH_MIN/MAX_VAL Ricardo Ribalda
2024-11-14 19:10 ` [PATCH v15 04/19] media: vivid: Add a rectangle control Ricardo Ribalda
2024-11-14 19:10 ` [PATCH v15 05/19] media: uvcvideo: Handle uvc menu translation inside uvc_get_le_value Ricardo Ribalda
2024-11-25 15:50   ` Hans de Goede
2024-11-14 19:10 ` [PATCH v15 06/19] media: uvcvideo: Handle uvc menu translation inside uvc_set_le_value Ricardo Ribalda
2024-11-25 15:58   ` Hans de Goede
2024-11-14 19:10 ` [PATCH v15 07/19] media: uvcvideo: refactor uvc_ioctl_g_ext_ctrls Ricardo Ribalda
2024-11-25 16:01   ` Hans de Goede
2024-11-14 19:10 ` [PATCH v15 08/19] media: uvcvideo: uvc_ioctl_(g|s)_ext_ctrls: handle NoP case Ricardo Ribalda
2024-11-25 16:01   ` Hans de Goede
2024-11-14 19:10 ` [PATCH v15 09/19] media: uvcvideo: Support any size for mapping get/set Ricardo Ribalda
2024-12-09  8:56   ` Yunke Cao
2024-12-09 12:49   ` Hans de Goede [this message]
2024-11-14 19:10 ` [PATCH v15 10/19] media: uvcvideo: Factor out clamping from uvc_ctrl_set Ricardo Ribalda
2024-12-09  8:50   ` Yunke Cao
2024-12-09 12:57   ` Hans de Goede
2024-11-14 19:10 ` [PATCH v15 11/19] media: uvcvideo: add support for compound controls Ricardo Ribalda
2024-12-09 13:35   ` Hans de Goede
2024-12-09 13:58   ` Hans de Goede
2024-11-14 19:10 ` [PATCH v15 12/19] media: uvcvideo: Factor out query_boundaries from query_ctrl Ricardo Ribalda
2024-12-09  8:50   ` Yunke Cao
2024-12-09 13:38   ` Hans de Goede
2024-11-14 19:10 ` [PATCH v15 13/19] media: uvcvideo: support V4L2_CTRL_WHICH_MIN/MAX_VAL Ricardo Ribalda
2024-12-09 13:47   ` Hans de Goede
2024-11-14 19:10 ` [PATCH v15 14/19] media: uvcvideo: Use the camera to clamp compound controls Ricardo Ribalda
2024-12-09 14:05   ` Hans de Goede
2024-12-09 14:46     ` Ricardo Ribalda
2024-11-14 19:10 ` [PATCH v15 15/19] media: uvcvideo: let v4l2_query_v4l2_ctrl() work with v4l2_query_ext_ctrl Ricardo Ribalda
2024-12-09  8:50   ` Yunke Cao
2024-12-09 14:08   ` Hans de Goede
2024-12-09 14:12     ` Ricardo Ribalda
2024-11-14 19:10 ` [PATCH v15 16/19] media: uvcvideo: Introduce uvc_mapping_v4l2_size Ricardo Ribalda
2024-12-09  8:51   ` Yunke Cao
2024-12-09 14:09   ` Hans de Goede
2024-11-14 19:10 ` [PATCH v15 17/19] media: uvcvideo: Add sanity check to uvc_ioctl_xu_ctrl_map Ricardo Ribalda
2024-11-29  8:15   ` Ricardo Ribalda
2024-12-09 14:11   ` Hans de Goede
2024-12-09 14:15     ` Ricardo Ribalda
2024-11-14 19:10 ` [PATCH v15 18/19] media: uvcvideo: implement UVC v1.5 ROI Ricardo Ribalda
2024-11-14 19:53   ` Gergo Koteles
2024-11-14 20:03     ` Ricardo Ribalda
2024-11-14 20:16       ` Gergo Koteles
2024-11-14 20:28         ` Ricardo Ribalda
2024-11-15  0:04           ` Gergo Koteles
2024-11-15  8:22             ` Ricardo Ribalda
2024-11-18 15:59       ` Hans de Goede
2024-11-18 16:16         ` Ricardo Ribalda Delgado
2024-11-25 14:27           ` Hans de Goede
2024-12-02  8:02   ` Yunke Cao
2024-12-02  9:26     ` Ricardo Ribalda
2024-12-06  7:50       ` Yunke Cao
2024-12-09 14:22   ` Hans de Goede
2024-12-09 15:23     ` Ricardo Ribalda
2024-12-09 15:28       ` Hans de Goede
2024-11-14 19:10 ` [PATCH v15 19/19] media: uvcvideo: document " Ricardo Ribalda
2024-12-09 14:36   ` Hans de Goede
2024-12-09 15:22     ` Ricardo Ribalda
2024-12-09 15:31       ` Hans de Goede
2024-12-09  8:53 ` [PATCH v15 00/19] media: uvcvideo: Implement " Yunke Cao

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=2c095d07-739f-4e9d-ac71-ba484bfe2a4d@redhat.com \
    --to=hdegoede@redhat.com \
    --cc=hverkuil@xs4all.nl \
    --cc=laurent.pinchart@ideasonboard.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=mchehab@kernel.org \
    --cc=ribalda@chromium.org \
    --cc=ribalda@kernel.org \
    --cc=sakari.ailus@linux.intel.com \
    --cc=yunkec@chromium.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.