return 0;
 }
 
+/*
+ * Check if control @v4l2_id can be accessed by the given control @ioctl
+ * (VIDIOC_G_EXT_CTRLS, VIDIOC_TRY_EXT_CTRLS or VIDIOC_S_EXT_CTRLS).
+ *
+ * For set operations on slave controls, check if the master's value is set to
+ * manual, either in the others controls set in the same ioctl call, or from
+ * the master's current value. This catches VIDIOC_S_EXT_CTRLS calls that set
+ * both the master and slave control, such as for instance setting
+ * auto_exposure=1, exposure_time_absolute=251.
+ */
 int uvc_ctrl_is_accessible(struct uvc_video_chain *chain, u32 v4l2_id,
-                          bool read)
+                          const struct v4l2_ext_controls *ctrls,
+                          unsigned long ioctl)
 {
+       struct uvc_control_mapping *master_map = NULL;
+       struct uvc_control *master_ctrl = NULL;
        struct uvc_control_mapping *mapping;
        struct uvc_control *ctrl;
+       bool read = ioctl == VIDIOC_G_EXT_CTRLS;
+       s32 val;
+       int ret;
+       int i;
 
        if (__uvc_query_v4l2_class(chain, v4l2_id, 0) >= 0)
                return -EACCES;
        if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR) && !read)
                return -EACCES;
 
+       if (ioctl != VIDIOC_S_EXT_CTRLS || !mapping->master_id)
+               return 0;
+
+       /*
+        * Iterate backwards in cases where the master control is accessed
+        * multiple times in the same ioctl. We want the last value.
+        */
+       for (i = ctrls->count - 1; i >= 0; i--) {
+               if (ctrls->controls[i].id == mapping->master_id)
+                       return ctrls->controls[i].value ==
+                                       mapping->master_manual ? 0 : -EACCES;
+       }
+
+       __uvc_find_control(ctrl->entity, mapping->master_id, &master_map,
+                          &master_ctrl, 0);
+
+       if (!master_ctrl || !(master_ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR))
+               return 0;
+
+       ret = __uvc_ctrl_get(chain, master_ctrl, master_map, &val);
+       if (ret >= 0 && val != mapping->master_manual)
+               return -EACCES;
+
        return 0;
 }
 
 
 int uvc_ctrl_get(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,
-                          bool read);
+                          const struct v4l2_ext_controls *ctrls,
+                          unsigned long ioctl);
 
 int uvc_xu_ctrl_query(struct uvc_video_chain *chain,
                      struct uvc_xu_control_query *xqry);