Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

media: uvcvideo: support V4L2_CTRL_WHICH_MIN/MAX_VAL

Add support for V4L2_CTRL_WHICH_MIN/MAX_VAL in uvc driver.
It is needed for the V4L2_CID_UVC_REGION_OF_INTEREST_RECT control.

Signed-off-by: Yunke Cao <yunkec@google.com>
Tested-by: Yunke Cao <yunkec@google.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
Link: https://lore.kernel.org/r/20250203-uvc-roi-v17-12-5900a9fed613@chromium.org
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>

authored by

Yunke Cao and committed by
Hans Verkuil
39d2c891 cc9a7cb3

+80 -20
+78 -20
drivers/media/usb/uvc/uvc_ctrl.c
··· 1277 1277 return 0; 1278 1278 } 1279 1279 1280 + static bool uvc_ctrl_is_readable(u32 which, struct uvc_control *ctrl, 1281 + struct uvc_control_mapping *mapping) 1282 + { 1283 + if (which == V4L2_CTRL_WHICH_CUR_VAL) 1284 + return !!(ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR); 1285 + 1286 + if (which == V4L2_CTRL_WHICH_DEF_VAL) 1287 + return !!(ctrl->info.flags & UVC_CTRL_FLAG_GET_DEF); 1288 + 1289 + /* Types with implicit boundaries. */ 1290 + switch (mapping->v4l2_type) { 1291 + case V4L2_CTRL_TYPE_MENU: 1292 + case V4L2_CTRL_TYPE_BOOLEAN: 1293 + case V4L2_CTRL_TYPE_BUTTON: 1294 + return true; 1295 + case V4L2_CTRL_TYPE_BITMASK: 1296 + return (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) || 1297 + (ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX); 1298 + default: 1299 + break; 1300 + } 1301 + 1302 + if (which == V4L2_CTRL_WHICH_MIN_VAL) 1303 + return !!(ctrl->info.flags & UVC_CTRL_FLAG_GET_MIN); 1304 + 1305 + if (which == V4L2_CTRL_WHICH_MAX_VAL) 1306 + return !!(ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX); 1307 + 1308 + return false; 1309 + } 1310 + 1280 1311 /* 1281 1312 * Check if control @v4l2_id can be accessed by the given control @ioctl 1282 1313 * (VIDIOC_G_EXT_CTRLS, VIDIOC_TRY_EXT_CTRLS or VIDIOC_S_EXT_CTRLS). ··· 1326 1295 struct uvc_control *master_ctrl = NULL; 1327 1296 struct uvc_control_mapping *mapping; 1328 1297 struct uvc_control *ctrl; 1329 - bool read = ioctl == VIDIOC_G_EXT_CTRLS; 1330 1298 s32 val; 1331 1299 int ret; 1332 1300 int i; ··· 1337 1307 if (!ctrl) 1338 1308 return -EINVAL; 1339 1309 1340 - if (!(ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) && read) 1341 - return -EACCES; 1310 + if (ioctl == VIDIOC_G_EXT_CTRLS) 1311 + return uvc_ctrl_is_readable(ctrls->which, ctrl, mapping); 1342 1312 1343 - if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR) && !read) 1313 + if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR)) 1344 1314 return -EACCES; 1345 1315 1346 1316 if (ioctl != VIDIOC_S_EXT_CTRLS || !mapping->master_id) ··· 1489 1459 v4l2_ctrl->flags |= V4L2_CTRL_FLAG_WRITE_ONLY; 1490 1460 if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR)) 1491 1461 v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; 1462 + if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX) && 1463 + (ctrl->info.flags & UVC_CTRL_FLAG_GET_MIN)) 1464 + v4l2_ctrl->flags |= V4L2_CTRL_FLAG_HAS_WHICH_MIN_MAX; 1492 1465 1493 1466 if (mapping->master_id) 1494 1467 __uvc_find_control(ctrl->entity, mapping->master_id, ··· 2121 2088 2122 2089 switch (which) { 2123 2090 case V4L2_CTRL_WHICH_CUR_VAL: 2124 - ret = __uvc_ctrl_load_cur(chain, ctrl); 2125 - if (ret < 0) 2126 - return ret; 2127 2091 id = UVC_CTRL_DATA_CURRENT; 2128 2092 query = UVC_GET_CUR; 2129 2093 break; 2094 + case V4L2_CTRL_WHICH_MIN_VAL: 2095 + id = UVC_CTRL_DATA_MIN; 2096 + query = UVC_GET_MIN; 2097 + break; 2098 + case V4L2_CTRL_WHICH_MAX_VAL: 2099 + id = UVC_CTRL_DATA_MAX; 2100 + query = UVC_GET_MAX; 2101 + break; 2130 2102 case V4L2_CTRL_WHICH_DEF_VAL: 2131 - ret = uvc_ctrl_populate_cache(chain, ctrl); 2132 - if (ret < 0) 2133 - return ret; 2134 2103 id = UVC_CTRL_DATA_DEF; 2135 2104 query = UVC_GET_DEF; 2136 2105 break; ··· 2149 2114 data = kmalloc(size, GFP_KERNEL); 2150 2115 if (!data) 2151 2116 return -ENOMEM; 2117 + 2118 + if (which == V4L2_CTRL_WHICH_CUR_VAL) 2119 + ret = __uvc_ctrl_load_cur(chain, ctrl); 2120 + else 2121 + ret = uvc_ctrl_populate_cache(chain, ctrl); 2122 + 2123 + if (ret < 0) 2124 + return ret; 2152 2125 2153 2126 ret = mapping->get(mapping, query, uvc_ctrl_data(ctrl, id), size, data); 2154 2127 if (ret < 0) ··· 2175 2132 struct uvc_control_mapping *mapping, 2176 2133 u32 which, struct v4l2_ext_control *xctrl) 2177 2134 { 2135 + struct v4l2_queryctrl qc; 2136 + int ret; 2137 + 2178 2138 switch (which) { 2179 2139 case V4L2_CTRL_WHICH_CUR_VAL: 2180 2140 return __uvc_ctrl_get(chain, ctrl, mapping, &xctrl->value); 2181 2141 case V4L2_CTRL_WHICH_DEF_VAL: 2182 - if (!ctrl->cached) { 2183 - int ret = uvc_ctrl_populate_cache(chain, ctrl); 2184 - 2185 - if (ret < 0) 2186 - return ret; 2187 - } 2188 - xctrl->value = uvc_mapping_get_s32(mapping, UVC_GET_DEF, 2189 - uvc_ctrl_data(ctrl, UVC_CTRL_DATA_DEF)); 2190 - return 0; 2142 + case V4L2_CTRL_WHICH_MIN_VAL: 2143 + case V4L2_CTRL_WHICH_MAX_VAL: 2144 + break; 2145 + default: 2146 + return -EINVAL; 2191 2147 } 2192 2148 2193 - return -EINVAL; 2149 + ret = __uvc_queryctrl_boundaries(chain, ctrl, mapping, &qc); 2150 + if (ret < 0) 2151 + return ret; 2152 + 2153 + switch (which) { 2154 + case V4L2_CTRL_WHICH_DEF_VAL: 2155 + xctrl->value = qc.default_value; 2156 + break; 2157 + case V4L2_CTRL_WHICH_MIN_VAL: 2158 + xctrl->value = qc.minimum; 2159 + break; 2160 + case V4L2_CTRL_WHICH_MAX_VAL: 2161 + xctrl->value = qc.maximum; 2162 + break; 2163 + } 2164 + 2165 + return 0; 2194 2166 } 2195 2167 2196 2168 static int uvc_mapping_get_xctrl(struct uvc_video_chain *chain,
+2
drivers/media/usb/uvc/uvc_v4l2.c
··· 1036 1036 switch (ctrls->which) { 1037 1037 case V4L2_CTRL_WHICH_DEF_VAL: 1038 1038 case V4L2_CTRL_WHICH_CUR_VAL: 1039 + case V4L2_CTRL_WHICH_MAX_VAL: 1040 + case V4L2_CTRL_WHICH_MIN_VAL: 1039 1041 which = ctrls->which; 1040 1042 break; 1041 1043 default: