@@ -884,6 +884,12 @@ static void uvc_set_le_value(struct uvc_control_mapping *mapping,
}
}
+static bool
+uvc_ctrl_mapping_is_compound(const struct uvc_control_mapping *mapping)
+{
+ return mapping->v4l2_type >= V4L2_CTRL_COMPOUND_TYPES;
+}
+
/* ------------------------------------------------------------------------
* Terminal and unit management
*/
@@ -1877,6 +1883,48 @@ int uvc_ctrl_get(struct uvc_video_chain *chain,
return __uvc_ctrl_get(chain, ctrl, mapping, &xctrl->value);
}
+static int __uvc_ctrl_get_boundary_std(struct uvc_video_chain *chain,
+ struct uvc_control *ctrl,
+ struct uvc_control_mapping *mapping,
+ struct v4l2_ext_control *xctrl)
+{
+ struct v4l2_queryctrl qc = { .id = xctrl->id };
+
+ int ret = __uvc_query_v4l2_ctrl(chain, ctrl, mapping, &qc);
+
+ if (ret < 0)
+ return ret;
+
+ xctrl->value = qc.default_value;
+ return 0;
+}
+
+int uvc_ctrl_get_boundary(struct uvc_video_chain *chain,
+ struct v4l2_ext_control *xctrl)
+{
+ struct uvc_control *ctrl;
+ struct uvc_control_mapping *mapping;
+ int ret;
+
+ if (mutex_lock_interruptible(&chain->ctrl_mutex))
+ return -ERESTARTSYS;
+
+ ctrl = uvc_find_control(chain, xctrl->id, &mapping);
+ if (!ctrl) {
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (uvc_ctrl_mapping_is_compound(mapping))
+ ret = -EINVAL;
+ else
+ ret = __uvc_ctrl_get_boundary_std(chain, ctrl, mapping, xctrl);
+
+done:
+ mutex_unlock(&chain->ctrl_mutex);
+ return ret;
+}
+
int uvc_ctrl_set(struct uvc_fh *handle,
struct v4l2_ext_control *xctrl)
{
@@ -1095,15 +1095,11 @@ static int uvc_ioctl_g_ext_ctrls(struct file *file, void *fh,
if (ctrls->which == V4L2_CTRL_WHICH_DEF_VAL) {
for (i = 0; i < ctrls->count; ++ctrl, ++i) {
- struct v4l2_queryctrl qc = { .id = ctrl->id };
-
- ret = uvc_query_v4l2_ctrl(chain, &qc);
+ ret = uvc_ctrl_get_boundary(chain, ctrl);
if (ret < 0) {
ctrls->error_idx = i;
return ret;
}
-
- ctrl->value = qc.default_value;
}
return 0;
@@ -781,6 +781,8 @@ static inline int uvc_ctrl_rollback(struct uvc_fh *handle)
}
int uvc_ctrl_get(struct uvc_video_chain *chain, struct v4l2_ext_control *xctrl);
+int uvc_ctrl_get_boundary(struct uvc_video_chain *chain,
+ struct v4l2_ext_control *xctrl);
int uvc_ctrl_set(struct uvc_fh *handle, struct v4l2_ext_control *xctrl);
int uvc_ctrl_is_accessible(struct uvc_video_chain *chain, u32 v4l2_id,
const struct v4l2_ext_controls *ctrls,