media: uvcvideo: Handle uvc menu translation inside uvc_get_le_value
[ Upstream commit 9109a0b4cb10fd681e9c6e9a4497a6fec5b91c39 ] 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> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
faa24692f7
commit
032f3bf647
@@ -815,6 +815,25 @@ static inline void uvc_clear_bit(u8 *data, int bit)
|
||||
data[bit >> 3] &= ~(1 << (bit & 7));
|
||||
}
|
||||
|
||||
static s32 uvc_menu_to_v4l2_menu(struct uvc_control_mapping *mapping, s32 val)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; BIT(i) <= mapping->menu_mask; ++i) {
|
||||
u32 menu_value;
|
||||
|
||||
if (!test_bit(i, &mapping->menu_mask))
|
||||
continue;
|
||||
|
||||
menu_value = uvc_mapping_get_menu_value(mapping, i);
|
||||
|
||||
if (menu_value == val)
|
||||
return i;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract the bit string specified by mapping->offset and mapping->size
|
||||
* from the little-endian data stored at 'data' and return the result as
|
||||
@@ -849,6 +868,16 @@ static s32 uvc_get_le_value(struct uvc_control_mapping *mapping,
|
||||
if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED)
|
||||
value |= -(value & (1 << (mapping->size - 1)));
|
||||
|
||||
/* If it is a menu, convert from uvc to v4l2. */
|
||||
if (mapping->v4l2_type != V4L2_CTRL_TYPE_MENU)
|
||||
return value;
|
||||
|
||||
switch (query) {
|
||||
case UVC_GET_CUR:
|
||||
case UVC_GET_DEF:
|
||||
return uvc_menu_to_v4l2_menu(mapping, value);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -1013,32 +1042,6 @@ static int uvc_ctrl_populate_cache(struct uvc_video_chain *chain,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static s32 __uvc_ctrl_get_value(struct uvc_control_mapping *mapping,
|
||||
const u8 *data)
|
||||
{
|
||||
s32 value = mapping->get(mapping, UVC_GET_CUR, data);
|
||||
|
||||
if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) {
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; BIT(i) <= mapping->menu_mask; ++i) {
|
||||
u32 menu_value;
|
||||
|
||||
if (!test_bit(i, &mapping->menu_mask))
|
||||
continue;
|
||||
|
||||
menu_value = uvc_mapping_get_menu_value(mapping, i);
|
||||
|
||||
if (menu_value == value) {
|
||||
value = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static int __uvc_ctrl_load_cur(struct uvc_video_chain *chain,
|
||||
struct uvc_control *ctrl)
|
||||
{
|
||||
@@ -1089,8 +1092,8 @@ static int __uvc_ctrl_get(struct uvc_video_chain *chain,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
*value = __uvc_ctrl_get_value(mapping,
|
||||
uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
|
||||
*value = mapping->get(mapping, UVC_GET_CUR,
|
||||
uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1240,7 +1243,6 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
|
||||
{
|
||||
struct uvc_control_mapping *master_map = NULL;
|
||||
struct uvc_control *master_ctrl = NULL;
|
||||
unsigned int i;
|
||||
|
||||
memset(v4l2_ctrl, 0, sizeof(*v4l2_ctrl));
|
||||
v4l2_ctrl->id = mapping->id;
|
||||
@@ -1283,21 +1285,6 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
|
||||
v4l2_ctrl->minimum = ffs(mapping->menu_mask) - 1;
|
||||
v4l2_ctrl->maximum = fls(mapping->menu_mask) - 1;
|
||||
v4l2_ctrl->step = 1;
|
||||
|
||||
for (i = 0; BIT(i) <= mapping->menu_mask; ++i) {
|
||||
u32 menu_value;
|
||||
|
||||
if (!test_bit(i, &mapping->menu_mask))
|
||||
continue;
|
||||
|
||||
menu_value = uvc_mapping_get_menu_value(mapping, i);
|
||||
|
||||
if (menu_value == v4l2_ctrl->default_value) {
|
||||
v4l2_ctrl->default_value = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
case V4L2_CTRL_TYPE_BOOLEAN:
|
||||
@@ -1580,7 +1567,7 @@ void uvc_ctrl_status_event(struct uvc_video_chain *chain,
|
||||
uvc_ctrl_set_handle(handle, ctrl, NULL);
|
||||
|
||||
list_for_each_entry(mapping, &ctrl->info.mappings, list) {
|
||||
s32 value = __uvc_ctrl_get_value(mapping, data);
|
||||
s32 value = mapping->get(mapping, UVC_GET_CUR, data);
|
||||
|
||||
/*
|
||||
* handle may be NULL here if the device sends auto-update
|
||||
|
Reference in New Issue
Block a user