[PATCH] media: uvcvideo: fix incorrect minimum value mapping for relative ptz controls

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

 



When mapping from UVC_CT_PANTILT_RELATIVE_CONTROL
to V4L2_CID_PAN_SPEED and V4L2_CID_TILT_SPEED,
and from UVC_CT_ZOOM_RELATIVE_CONTROL to V4L2_CID_ZOOM_CONTINUOUS,
the minimum value of the movement should be negated of the maximum value.

For example, if a UVC device (e.g., OBSBOT Tiny 2) declares a pan speed
range [1, 160], its V4L2_CID_PAN_SPEED mapping has range [-160, 160].

Currently, calling ioctl with VIDIOC_QUERY_EXT_CTRL and V4L2_CID_PAN_SPEED
returns a minimum value of -1. When calling ioctl with VIDIOC_S_CTRL,
V4L2_CID_PAN_SPEED and -100, the speed (velocity) of the pan movement gets
clamped to -1.

To get the minimum value of V4L2_CID_PAN_SPEED,
uvc_ctrl_get_rel_speed is called with
uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN) as data, 
which should be uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX).

The same thing should be done for V4L2_CID_TILT_SPEED and
V4L2_CID_ZOOM_CONTINUOUS.

For V4L2_CID_ZOOM_CONTINUOUS, uvc_ctrl_get_zoom does not add the
sign to the returned minimum value, so it's impossible to zoom out.

Modify the data that is passed when querying the minimum
value for V4L2_CID_PAN_SPEED, V4L2_CID_TILT_SPEED and
V4L2_CID_ZOOM_CONTINUOUS.
Also add sign to the returned minimum value in uvc_ctrl_get_zoom.
Thus, the correct minimum value for relative PTZ controls can be returned.

Signed-off-by: Linh Vu <linh.tp.vu@xxxxxxxxx>
---
 drivers/media/usb/uvc/uvc_ctrl.c | 24 +++++++++++++++++++-----
 1 file changed, 19 insertions(+), 5 deletions(-)

diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
index e59a463c27618..00fd7e74e6d6b 100644
--- a/drivers/media/usb/uvc/uvc_ctrl.c
+++ b/drivers/media/usb/uvc/uvc_ctrl.c
@@ -415,6 +415,7 @@ static s32 uvc_ctrl_get_zoom(struct uvc_control_mapping *mapping,
 		return (zoom == 0) ? 0 : (zoom > 0 ? data[2] : -data[2]);
 
 	case UVC_GET_MIN:
+		return -data[2];
 	case UVC_GET_MAX:
 	case UVC_GET_RES:
 	case UVC_GET_DEF:
@@ -1322,9 +1323,16 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
 		break;
 	}
 
-	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));
+	if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MIN) {
+		if (v4l2_ctrl->id == V4L2_CID_PAN_SPEED
+		|| v4l2_ctrl->id == V4L2_CID_TILT_SPEED
+		|| v4l2_ctrl->id == V4L2_CID_ZOOM_CONTINUOUS)
+			v4l2_ctrl->minimum = mapping->get(mapping, UVC_GET_MIN,
+						uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX));
+		else
+			v4l2_ctrl->minimum = mapping->get(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,
@@ -1909,9 +1917,15 @@ int uvc_ctrl_set(struct uvc_fh *handle,
 			if (ret < 0)
 				return ret;
 		}
+		if (mapping->id == V4L2_CID_PAN_SPEED
+		|| mapping->id == V4L2_CID_TILT_SPEED
+		|| mapping->id == V4L2_CID_ZOOM_CONTINUOUS)
+			min = mapping->get(mapping, UVC_GET_MIN,
+					uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX));
+		else
+			min = mapping->get(mapping, UVC_GET_MIN,
+					uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN));
 
-		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,

base-commit: e0b8eb0f6d652981bfd9ba7c619c9d81ed087ad0
-- 
2.34.1





[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux