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

Commit 859086ae authored by Edgar Thier's avatar Edgar Thier Committed by Mauro Carvalho Chehab
Browse files

media: uvcvideo: Apply flags from device to actual properties



Use flags the device exposes for UVC controls.
This allows the device to define which property flags are set.

Since some cameras offer auto-adjustments for properties (e.g. auto-gain),
the values of other properties (e.g. gain) can change in the camera.
Examining the flags ensures that the driver is aware of such properties.

Signed-off-by: default avatarEdgar Thier <info@edgarthier.net>
Reviewed-by: default avatarKieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent 4395fb47
Loading
Loading
Loading
Loading
+39 −13
Original line number Original line Diff line number Diff line
@@ -1590,6 +1590,36 @@ int uvc_ctrl_set(struct uvc_video_chain *chain,
 * Dynamic controls
 * Dynamic controls
 */
 */


/*
 * Retrieve flags for a given control
 */
static int uvc_ctrl_get_flags(struct uvc_device *dev,
			      const struct uvc_control *ctrl,
			      struct uvc_control_info *info)
{
	u8 *data;
	int ret;

	data = kmalloc(1, GFP_KERNEL);
	if (data == NULL)
		return -ENOMEM;

	ret = uvc_query_ctrl(dev, UVC_GET_INFO, ctrl->entity->id, dev->intfnum,
			     info->selector, data, 1);
	if (!ret)
		info->flags = UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX
			    | UVC_CTRL_FLAG_GET_RES | UVC_CTRL_FLAG_GET_DEF
			    | (data[0] & UVC_CONTROL_CAP_GET ?
			       UVC_CTRL_FLAG_GET_CUR : 0)
			    | (data[0] & UVC_CONTROL_CAP_SET ?
			       UVC_CTRL_FLAG_SET_CUR : 0)
			    | (data[0] & UVC_CONTROL_CAP_AUTOUPDATE ?
			       UVC_CTRL_FLAG_AUTO_UPDATE : 0);

	kfree(data);
	return ret;
}

static void uvc_ctrl_fixup_xu_info(struct uvc_device *dev,
static void uvc_ctrl_fixup_xu_info(struct uvc_device *dev,
	const struct uvc_control *ctrl, struct uvc_control_info *info)
	const struct uvc_control *ctrl, struct uvc_control_info *info)
{
{
@@ -1659,25 +1689,14 @@ static int uvc_ctrl_fill_xu_info(struct uvc_device *dev,


	info->size = le16_to_cpup((__le16 *)data);
	info->size = le16_to_cpup((__le16 *)data);


	/* Query the control information (GET_INFO) */
	ret = uvc_ctrl_get_flags(dev, ctrl, info);
	ret = uvc_query_ctrl(dev, UVC_GET_INFO, ctrl->entity->id, dev->intfnum,
			     info->selector, data, 1);
	if (ret < 0) {
	if (ret < 0) {
		uvc_trace(UVC_TRACE_CONTROL,
		uvc_trace(UVC_TRACE_CONTROL,
			  "GET_INFO failed on control %pUl/%u (%d).\n",
			  "Failed to get flags for control %pUl/%u (%d).\n",
			  info->entity, info->selector, ret);
			  info->entity, info->selector, ret);
		goto done;
		goto done;
	}
	}


	info->flags = UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX
		    | UVC_CTRL_FLAG_GET_RES | UVC_CTRL_FLAG_GET_DEF
		    | (data[0] & UVC_CONTROL_CAP_GET ?
		       UVC_CTRL_FLAG_GET_CUR : 0)
		    | (data[0] & UVC_CONTROL_CAP_SET ?
		       UVC_CTRL_FLAG_SET_CUR : 0)
		    | (data[0] & UVC_CONTROL_CAP_AUTOUPDATE ?
		       UVC_CTRL_FLAG_AUTO_UPDATE : 0);

	uvc_ctrl_fixup_xu_info(dev, ctrl, info);
	uvc_ctrl_fixup_xu_info(dev, ctrl, info);


	uvc_trace(UVC_TRACE_CONTROL, "XU control %pUl/%u queried: len %u, "
	uvc_trace(UVC_TRACE_CONTROL, "XU control %pUl/%u queried: len %u, "
@@ -1902,6 +1921,13 @@ static int uvc_ctrl_add_info(struct uvc_device *dev, struct uvc_control *ctrl,
		goto done;
		goto done;
	}
	}


	/*
	 * Retrieve control flags from the device. Ignore errors and work with
	 * default flag values from the uvc_ctrl array when the device doesn't
	 * properly implement GET_INFO on standard controls.
	 */
	uvc_ctrl_get_flags(dev, ctrl, &ctrl->info);

	ctrl->initialized = 1;
	ctrl->initialized = 1;


	uvc_trace(UVC_TRACE_CONTROL, "Added control %pUl/%u to device %s "
	uvc_trace(UVC_TRACE_CONTROL, "Added control %pUl/%u to device %s "