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: Handle uvc menu translation inside uvc_get_le_value

map->get() gets a value from an uvc_control in "UVC format" and converts
it to a value that can be consumed by v4l2.

Instead of using a special get function for V4L2_CTRL_TYPE_MENU, we
were converting from uvc_get_le_value in two different places.

Move the conversion to uvc_get_le_value().

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

authored by

Ricardo Ribalda and committed by
Hans Verkuil
9109a0b4 ad2ebde8

+32 -45
+32 -45
drivers/media/usb/uvc/uvc_ctrl.c
··· 862 862 data[bit >> 3] &= ~(1 << (bit & 7)); 863 863 } 864 864 865 + static s32 uvc_menu_to_v4l2_menu(struct uvc_control_mapping *mapping, s32 val) 866 + { 867 + unsigned int i; 868 + 869 + for (i = 0; BIT(i) <= mapping->menu_mask; ++i) { 870 + u32 menu_value; 871 + 872 + if (!test_bit(i, &mapping->menu_mask)) 873 + continue; 874 + 875 + menu_value = uvc_mapping_get_menu_value(mapping, i); 876 + 877 + if (menu_value == val) 878 + return i; 879 + } 880 + 881 + return val; 882 + } 883 + 865 884 /* 866 885 * Extract the bit string specified by mapping->offset and mapping->size 867 886 * from the little-endian data stored at 'data' and return the result as ··· 914 895 /* Sign-extend the value if needed. */ 915 896 if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED) 916 897 value |= -(value & (1 << (mapping->size - 1))); 898 + 899 + /* If it is a menu, convert from uvc to v4l2. */ 900 + if (mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) 901 + return value; 902 + 903 + switch (query) { 904 + case UVC_GET_CUR: 905 + case UVC_GET_DEF: 906 + return uvc_menu_to_v4l2_menu(mapping, value); 907 + } 917 908 918 909 return value; 919 910 } ··· 1089 1060 return 0; 1090 1061 } 1091 1062 1092 - static s32 __uvc_ctrl_get_value(struct uvc_control_mapping *mapping, 1093 - const u8 *data) 1094 - { 1095 - s32 value = mapping->get(mapping, UVC_GET_CUR, data); 1096 - 1097 - if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) { 1098 - unsigned int i; 1099 - 1100 - for (i = 0; BIT(i) <= mapping->menu_mask; ++i) { 1101 - u32 menu_value; 1102 - 1103 - if (!test_bit(i, &mapping->menu_mask)) 1104 - continue; 1105 - 1106 - menu_value = uvc_mapping_get_menu_value(mapping, i); 1107 - 1108 - if (menu_value == value) { 1109 - value = i; 1110 - break; 1111 - } 1112 - } 1113 - } 1114 - 1115 - return value; 1116 - } 1117 - 1118 1063 static int __uvc_ctrl_load_cur(struct uvc_video_chain *chain, 1119 1064 struct uvc_control *ctrl) 1120 1065 { ··· 1139 1136 if (ret < 0) 1140 1137 return ret; 1141 1138 1142 - *value = __uvc_ctrl_get_value(mapping, 1143 - uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT)); 1139 + *value = mapping->get(mapping, UVC_GET_CUR, 1140 + uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT)); 1144 1141 1145 1142 return 0; 1146 1143 } ··· 1290 1287 { 1291 1288 struct uvc_control_mapping *master_map = NULL; 1292 1289 struct uvc_control *master_ctrl = NULL; 1293 - unsigned int i; 1294 1290 1295 1291 memset(v4l2_ctrl, 0, sizeof(*v4l2_ctrl)); 1296 1292 v4l2_ctrl->id = mapping->id; ··· 1332 1330 v4l2_ctrl->minimum = ffs(mapping->menu_mask) - 1; 1333 1331 v4l2_ctrl->maximum = fls(mapping->menu_mask) - 1; 1334 1332 v4l2_ctrl->step = 1; 1335 - 1336 - for (i = 0; BIT(i) <= mapping->menu_mask; ++i) { 1337 - u32 menu_value; 1338 - 1339 - if (!test_bit(i, &mapping->menu_mask)) 1340 - continue; 1341 - 1342 - menu_value = uvc_mapping_get_menu_value(mapping, i); 1343 - 1344 - if (menu_value == v4l2_ctrl->default_value) { 1345 - v4l2_ctrl->default_value = i; 1346 - break; 1347 - } 1348 - } 1349 - 1350 1333 return 0; 1351 1334 1352 1335 case V4L2_CTRL_TYPE_BOOLEAN: ··· 1617 1630 uvc_ctrl_set_handle(handle, ctrl, NULL); 1618 1631 1619 1632 list_for_each_entry(mapping, &ctrl->info.mappings, list) { 1620 - s32 value = __uvc_ctrl_get_value(mapping, data); 1633 + s32 value = mapping->get(mapping, UVC_GET_CUR, data); 1621 1634 1622 1635 /* 1623 1636 * handle may be NULL here if the device sends auto-update