Lines Matching +full:data +full:- +full:mapping

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * uvc_ctrl.c -- USB Video Class driver - Controls
5 * Copyright (C) 2005-2010
23 #include <media/v4l2-ctrls.h>
35 /* ------------------------------------------------------------------------
388 static bool uvc_ctrl_mapping_is_compound(struct uvc_control_mapping *mapping) in uvc_ctrl_mapping_is_compound() argument
390 return mapping->v4l2_type >= V4L2_CTRL_COMPOUND_TYPES; in uvc_ctrl_mapping_is_compound()
393 static s32 uvc_mapping_get_s32(struct uvc_control_mapping *mapping, in uvc_mapping_get_s32() argument
398 mapping->get(mapping, query, data_in, sizeof(data_out), &data_out); in uvc_mapping_get_s32()
403 static void uvc_mapping_set_s32(struct uvc_control_mapping *mapping, in uvc_mapping_set_s32() argument
406 mapping->set(mapping, sizeof(data_in), &data_in, data_out); in uvc_mapping_set_s32()
412 * device. The custom menu_mapping in the control @mapping is used when
419 * The function returns -EINVAL if the V4L2 menu index @idx isn't valid for the
423 static int uvc_mapping_get_menu_value(const struct uvc_control_mapping *mapping, in uvc_mapping_get_menu_value() argument
426 if (!test_bit(idx, &mapping->menu_mask)) in uvc_mapping_get_menu_value()
427 return -EINVAL; in uvc_mapping_get_menu_value()
429 if (mapping->menu_mapping) in uvc_mapping_get_menu_value()
430 return mapping->menu_mapping[idx]; in uvc_mapping_get_menu_value()
436 uvc_mapping_get_menu_name(const struct uvc_control_mapping *mapping, u32 idx) in uvc_mapping_get_menu_name() argument
438 if (!test_bit(idx, &mapping->menu_mask)) in uvc_mapping_get_menu_name()
441 if (mapping->menu_names) in uvc_mapping_get_menu_name()
442 return mapping->menu_names[idx]; in uvc_mapping_get_menu_name()
444 return v4l2_ctrl_get_menu(mapping->id)[idx]; in uvc_mapping_get_menu_name()
447 static int uvc_ctrl_get_zoom(struct uvc_control_mapping *mapping, u8 query, in uvc_ctrl_get_zoom() argument
456 return -EINVAL; in uvc_ctrl_get_zoom()
460 *out = (sign == 0) ? 0 : (sign > 0 ? value : -value); in uvc_ctrl_get_zoom()
473 static int uvc_ctrl_set_zoom(struct uvc_control_mapping *mapping, in uvc_ctrl_set_zoom() argument
481 return -EINVAL; in uvc_ctrl_set_zoom()
490 static int uvc_ctrl_get_rel_speed(struct uvc_control_mapping *mapping, in uvc_ctrl_get_rel_speed() argument
494 unsigned int first = mapping->offset / 8; in uvc_ctrl_get_rel_speed()
500 return -EINVAL; in uvc_ctrl_get_rel_speed()
504 *out = (sign == 0) ? 0 : (sign > 0 ? value : -value); in uvc_ctrl_get_rel_speed()
507 *out = -value; in uvc_ctrl_get_rel_speed()
518 static int uvc_ctrl_set_rel_speed(struct uvc_control_mapping *mapping, in uvc_ctrl_set_rel_speed() argument
522 unsigned int first = mapping->offset / 8; in uvc_ctrl_set_rel_speed()
527 return -EINVAL; in uvc_ctrl_set_rel_speed()
586 ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, ctrl->entity->id, in uvc_ctrl_filter_plf_mapping()
587 chain->dev->intfnum, ctrl->info.selector, in uvc_ctrl_filter_plf_mapping()
596 ret = uvc_query_ctrl(chain->dev, UVC_SET_CUR, ctrl->entity->id, in uvc_ctrl_filter_plf_mapping()
597 chain->dev->intfnum, ctrl->info.selector, in uvc_ctrl_filter_plf_mapping()
603 if (chain->dev->uvc_version < 0x150) in uvc_ctrl_filter_plf_mapping()
608 ret = uvc_query_ctrl(chain->dev, UVC_SET_CUR, ctrl->entity->id, in uvc_ctrl_filter_plf_mapping()
609 chain->dev->intfnum, ctrl->info.selector, in uvc_ctrl_filter_plf_mapping()
615 /* Restore initial value and add mapping. */ in uvc_ctrl_filter_plf_mapping()
617 uvc_query_ctrl(chain->dev, UVC_SET_CUR, ctrl->entity->id, in uvc_ctrl_filter_plf_mapping()
618 chain->dev->intfnum, ctrl->info.selector, in uvc_ctrl_filter_plf_mapping()
624 static int uvc_get_rect(struct uvc_control_mapping *mapping, u8 query, in uvc_get_rect() argument
631 return -EINVAL; in uvc_get_rect()
633 if (uvc_rect->left > uvc_rect->right || in uvc_get_rect()
634 uvc_rect->top > uvc_rect->bottom) in uvc_get_rect()
635 return -EIO; in uvc_get_rect()
637 v4l2_rect->top = uvc_rect->top; in uvc_get_rect()
638 v4l2_rect->left = uvc_rect->left; in uvc_get_rect()
639 v4l2_rect->height = uvc_rect->bottom - uvc_rect->top + 1; in uvc_get_rect()
640 v4l2_rect->width = uvc_rect->right - uvc_rect->left + 1; in uvc_get_rect()
645 static int uvc_set_rect(struct uvc_control_mapping *mapping, size_t v4l2_size, in uvc_set_rect() argument
652 return -EINVAL; in uvc_set_rect()
654 uvc_rect->top = min(0xffff, v4l2_rect->top); in uvc_set_rect()
655 uvc_rect->left = min(0xffff, v4l2_rect->left); in uvc_set_rect()
656 uvc_rect->bottom = min(0xffff, v4l2_rect->top + v4l2_rect->height - 1); in uvc_set_rect()
657 uvc_rect->right = min(0xffff, v4l2_rect->left + v4l2_rect->width - 1); in uvc_set_rect()
980 /* ------------------------------------------------------------------------
986 return ctrl->uvc_data + id * ctrl->info.size; in uvc_ctrl_data()
989 static inline int uvc_test_bit(const u8 *data, int bit) in uvc_test_bit() argument
991 return (data[bit >> 3] >> (bit & 7)) & 1; in uvc_test_bit()
994 static inline void uvc_clear_bit(u8 *data, int bit) in uvc_clear_bit() argument
996 data[bit >> 3] &= ~(1 << (bit & 7)); in uvc_clear_bit()
999 static s32 uvc_menu_to_v4l2_menu(struct uvc_control_mapping *mapping, s32 val) in uvc_menu_to_v4l2_menu() argument
1003 for (i = 0; BIT(i) <= mapping->menu_mask; ++i) { in uvc_menu_to_v4l2_menu()
1006 if (!test_bit(i, &mapping->menu_mask)) in uvc_menu_to_v4l2_menu()
1009 menu_value = uvc_mapping_get_menu_value(mapping, i); in uvc_menu_to_v4l2_menu()
1019 * Extract the bit string specified by mapping->offset and mapping->size
1020 * from the little-endian data stored at 'data' and return the result as
1021 * a signed 32bit integer. Sign extension will be performed if the mapping
1022 * references a signed data type.
1024 static int uvc_get_le_value(struct uvc_control_mapping *mapping, in uvc_get_le_value() argument
1028 int offset = mapping->offset; in uvc_get_le_value()
1029 int bits = mapping->size; in uvc_get_le_value()
1030 const u8 *data = uvc_in; in uvc_get_le_value() local
1036 return -EINVAL; in uvc_get_le_value()
1038 data += offset / 8; in uvc_get_le_value()
1040 mask = ((1LL << bits) - 1) << offset; in uvc_get_le_value()
1043 u8 byte = *data & mask; in uvc_get_le_value()
1044 value |= offset > 0 ? (byte >> offset) : (byte << (-offset)); in uvc_get_le_value()
1045 bits -= 8 - max(offset, 0); in uvc_get_le_value()
1049 offset -= 8; in uvc_get_le_value()
1050 mask = (1 << bits) - 1; in uvc_get_le_value()
1051 data++; in uvc_get_le_value()
1054 /* Sign-extend the value if needed. */ in uvc_get_le_value()
1055 if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED) in uvc_get_le_value()
1056 value |= -(value & (1 << (mapping->size - 1))); in uvc_get_le_value()
1059 if (mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) { in uvc_get_le_value()
1067 *out = uvc_menu_to_v4l2_menu(mapping, value); in uvc_get_le_value()
1076 * Set the bit string specified by mapping->offset and mapping->size
1077 * in the little-endian data stored at 'data' to the value 'value'.
1079 static int uvc_set_le_value(struct uvc_control_mapping *mapping, in uvc_set_le_value() argument
1083 int offset = mapping->offset; in uvc_set_le_value()
1084 int bits = mapping->size; in uvc_set_le_value()
1085 u8 *data = uvc_out; in uvc_set_le_value() local
1090 return -EINVAL; in uvc_set_le_value()
1094 switch (mapping->v4l2_type) { in uvc_set_le_value()
1096 value = uvc_mapping_get_menu_value(mapping, value); in uvc_set_le_value()
1103 * written -> override value. in uvc_set_le_value()
1105 value = -1; in uvc_set_le_value()
1111 data += offset / 8; in uvc_set_le_value()
1114 for (; bits > 0; data++) { in uvc_set_le_value()
1115 mask = ((1LL << bits) - 1) << offset; in uvc_set_le_value()
1116 *data = (*data & ~mask) | ((value << offset) & mask); in uvc_set_le_value()
1118 bits -= 8 - offset; in uvc_set_le_value()
1125 /* ------------------------------------------------------------------------
1132 return memcmp(entity->guid, guid, sizeof(entity->guid)) == 0; in uvc_entity_match_guid()
1135 /* ------------------------------------------------------------------------
1140 struct uvc_control_mapping **mapping, struct uvc_control **control, in __uvc_find_control() argument
1150 for (i = 0; i < entity->ncontrols; ++i) { in __uvc_find_control()
1151 ctrl = &entity->controls[i]; in __uvc_find_control()
1152 if (!ctrl->initialized) in __uvc_find_control()
1155 list_for_each_entry(map, &ctrl->info.mappings, list) { in __uvc_find_control()
1156 if (map->id == v4l2_id && !next && !next_compound) { in __uvc_find_control()
1158 *mapping = map; in __uvc_find_control()
1162 if ((*mapping == NULL || (*mapping)->id > map->id) && in __uvc_find_control()
1163 (map->id > v4l2_id) && in __uvc_find_control()
1167 *mapping = map; in __uvc_find_control()
1174 u32 v4l2_id, struct uvc_control_mapping **mapping) in uvc_find_control() argument
1181 *mapping = NULL; in uvc_find_control()
1187 list_for_each_entry(entity, &chain->entities, chain) { in uvc_find_control()
1188 __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next, in uvc_find_control()
1195 uvc_dbg(chain->dev, CONTROL, "Control 0x%08x not found\n", in uvc_find_control()
1206 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_DEF) { in uvc_ctrl_populate_cache()
1207 ret = uvc_query_ctrl(chain->dev, UVC_GET_DEF, ctrl->entity->id, in uvc_ctrl_populate_cache()
1208 chain->dev->intfnum, ctrl->info.selector, in uvc_ctrl_populate_cache()
1210 ctrl->info.size); in uvc_ctrl_populate_cache()
1215 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MIN) { in uvc_ctrl_populate_cache()
1216 ret = uvc_query_ctrl(chain->dev, UVC_GET_MIN, ctrl->entity->id, in uvc_ctrl_populate_cache()
1217 chain->dev->intfnum, ctrl->info.selector, in uvc_ctrl_populate_cache()
1219 ctrl->info.size); in uvc_ctrl_populate_cache()
1223 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX) { in uvc_ctrl_populate_cache()
1224 ret = uvc_query_ctrl(chain->dev, UVC_GET_MAX, ctrl->entity->id, in uvc_ctrl_populate_cache()
1225 chain->dev->intfnum, ctrl->info.selector, in uvc_ctrl_populate_cache()
1227 ctrl->info.size); in uvc_ctrl_populate_cache()
1231 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) { in uvc_ctrl_populate_cache()
1232 ret = uvc_query_ctrl(chain->dev, UVC_GET_RES, ctrl->entity->id, in uvc_ctrl_populate_cache()
1233 chain->dev->intfnum, ctrl->info.selector, in uvc_ctrl_populate_cache()
1235 ctrl->info.size); in uvc_ctrl_populate_cache()
1237 if (UVC_ENTITY_TYPE(ctrl->entity) != in uvc_ctrl_populate_cache()
1246 uvc_warn_once(chain->dev, UVC_WARN_XU_GET_RES, in uvc_ctrl_populate_cache()
1247 "UVC non compliance - GET_RES failed on " in uvc_ctrl_populate_cache()
1250 ctrl->info.size); in uvc_ctrl_populate_cache()
1254 ctrl->cached = 1; in uvc_ctrl_populate_cache()
1261 u8 *data; in __uvc_ctrl_load_cur() local
1264 if (ctrl->loaded) in __uvc_ctrl_load_cur()
1267 data = uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT); in __uvc_ctrl_load_cur()
1269 if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) { in __uvc_ctrl_load_cur()
1270 memset(data, 0, ctrl->info.size); in __uvc_ctrl_load_cur()
1271 ctrl->loaded = 1; in __uvc_ctrl_load_cur()
1276 if (ctrl->entity->get_cur) in __uvc_ctrl_load_cur()
1277 ret = ctrl->entity->get_cur(chain->dev, ctrl->entity, in __uvc_ctrl_load_cur()
1278 ctrl->info.selector, data, in __uvc_ctrl_load_cur()
1279 ctrl->info.size); in __uvc_ctrl_load_cur()
1281 ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, in __uvc_ctrl_load_cur()
1282 ctrl->entity->id, chain->dev->intfnum, in __uvc_ctrl_load_cur()
1283 ctrl->info.selector, data, in __uvc_ctrl_load_cur()
1284 ctrl->info.size); in __uvc_ctrl_load_cur()
1289 ctrl->loaded = 1; in __uvc_ctrl_load_cur()
1296 struct uvc_control_mapping *mapping, in __uvc_ctrl_get() argument
1301 if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) in __uvc_ctrl_get()
1302 return -EACCES; in __uvc_ctrl_get()
1308 *value = uvc_mapping_get_s32(mapping, UVC_GET_CUR, in __uvc_ctrl_get()
1324 if (!(chain->ctrl_class_bitmap & BIT(i))) in __uvc_query_v4l2_class()
1336 return -ENODEV; in __uvc_query_v4l2_class()
1347 return -ENODEV; in uvc_query_v4l2_class()
1350 v4l2_ctrl->id = uvc_control_classes[idx]; in uvc_query_v4l2_class()
1351 strscpy(v4l2_ctrl->name, v4l2_ctrl_get_name(v4l2_ctrl->id), in uvc_query_v4l2_class()
1352 sizeof(v4l2_ctrl->name)); in uvc_query_v4l2_class()
1353 v4l2_ctrl->type = V4L2_CTRL_TYPE_CTRL_CLASS; in uvc_query_v4l2_class()
1354 v4l2_ctrl->flags = V4L2_CTRL_FLAG_WRITE_ONLY in uvc_query_v4l2_class()
1360 struct uvc_control_mapping *mapping) in uvc_ctrl_is_readable() argument
1363 return !!(ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR); in uvc_ctrl_is_readable()
1366 return !!(ctrl->info.flags & UVC_CTRL_FLAG_GET_DEF); in uvc_ctrl_is_readable()
1369 switch (mapping->v4l2_type) { in uvc_ctrl_is_readable()
1375 return (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) || in uvc_ctrl_is_readable()
1376 (ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX); in uvc_ctrl_is_readable()
1382 return !!(ctrl->info.flags & UVC_CTRL_FLAG_GET_MIN); in uvc_ctrl_is_readable()
1385 return !!(ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX); in uvc_ctrl_is_readable()
1406 struct uvc_control_mapping *mapping; in uvc_ctrl_is_accessible() local
1413 return -EACCES; in uvc_ctrl_is_accessible()
1415 ctrl = uvc_find_control(chain, v4l2_id, &mapping); in uvc_ctrl_is_accessible()
1417 return -EINVAL; in uvc_ctrl_is_accessible()
1420 return uvc_ctrl_is_readable(ctrls->which, ctrl, mapping); in uvc_ctrl_is_accessible()
1422 if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR)) in uvc_ctrl_is_accessible()
1423 return -EACCES; in uvc_ctrl_is_accessible()
1425 if (ioctl != VIDIOC_S_EXT_CTRLS || !mapping->master_id) in uvc_ctrl_is_accessible()
1432 for (i = ctrls->count - 1; i >= 0; i--) { in uvc_ctrl_is_accessible()
1433 if (ctrls->controls[i].id == mapping->master_id) in uvc_ctrl_is_accessible()
1434 return ctrls->controls[i].value == in uvc_ctrl_is_accessible()
1435 mapping->master_manual ? 0 : -EACCES; in uvc_ctrl_is_accessible()
1438 __uvc_find_control(ctrl->entity, mapping->master_id, &master_map, in uvc_ctrl_is_accessible()
1441 if (!master_ctrl || !(master_ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR)) in uvc_ctrl_is_accessible()
1444 return -EIO; in uvc_ctrl_is_accessible()
1447 if (ret >= 0 && val != mapping->master_manual) in uvc_ctrl_is_accessible()
1448 return -EACCES; in uvc_ctrl_is_accessible()
1457 if (map->name) in uvc_map_get_name()
1458 return map->name; in uvc_map_get_name()
1460 name = v4l2_ctrl_get_name(map->id); in uvc_map_get_name()
1468 struct uvc_control_mapping *mapping) in uvc_get_ctrl_bitmap() argument
1475 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) in uvc_get_ctrl_bitmap()
1476 return uvc_mapping_get_s32(mapping, UVC_GET_RES, in uvc_get_ctrl_bitmap()
1479 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX) in uvc_get_ctrl_bitmap()
1480 return uvc_mapping_get_s32(mapping, UVC_GET_MAX, in uvc_get_ctrl_bitmap()
1488 struct uvc_control_mapping *mapping, in __uvc_queryctrl_boundaries() argument
1491 if (!ctrl->cached) { in __uvc_queryctrl_boundaries()
1497 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_DEF) { in __uvc_queryctrl_boundaries()
1498 v4l2_ctrl->default_value = uvc_mapping_get_s32(mapping, in __uvc_queryctrl_boundaries()
1502 switch (mapping->v4l2_type) { in __uvc_queryctrl_boundaries()
1504 v4l2_ctrl->minimum = ffs(mapping->menu_mask) - 1; in __uvc_queryctrl_boundaries()
1505 v4l2_ctrl->maximum = fls(mapping->menu_mask) - 1; in __uvc_queryctrl_boundaries()
1506 v4l2_ctrl->step = 1; in __uvc_queryctrl_boundaries()
1510 v4l2_ctrl->minimum = 0; in __uvc_queryctrl_boundaries()
1511 v4l2_ctrl->maximum = 1; in __uvc_queryctrl_boundaries()
1512 v4l2_ctrl->step = 1; in __uvc_queryctrl_boundaries()
1516 v4l2_ctrl->minimum = 0; in __uvc_queryctrl_boundaries()
1517 v4l2_ctrl->maximum = 0; in __uvc_queryctrl_boundaries()
1518 v4l2_ctrl->step = 0; in __uvc_queryctrl_boundaries()
1522 v4l2_ctrl->minimum = 0; in __uvc_queryctrl_boundaries()
1523 v4l2_ctrl->maximum = uvc_get_ctrl_bitmap(ctrl, mapping); in __uvc_queryctrl_boundaries()
1524 v4l2_ctrl->step = 0; in __uvc_queryctrl_boundaries()
1531 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MIN) in __uvc_queryctrl_boundaries()
1532 v4l2_ctrl->minimum = uvc_mapping_get_s32(mapping, UVC_GET_MIN, in __uvc_queryctrl_boundaries()
1535 v4l2_ctrl->minimum = 0; in __uvc_queryctrl_boundaries()
1537 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX) in __uvc_queryctrl_boundaries()
1538 v4l2_ctrl->maximum = uvc_mapping_get_s32(mapping, UVC_GET_MAX, in __uvc_queryctrl_boundaries()
1541 v4l2_ctrl->maximum = 0; in __uvc_queryctrl_boundaries()
1543 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) in __uvc_queryctrl_boundaries()
1544 v4l2_ctrl->step = uvc_mapping_get_s32(mapping, UVC_GET_RES, in __uvc_queryctrl_boundaries()
1547 v4l2_ctrl->step = 0; in __uvc_queryctrl_boundaries()
1552 static size_t uvc_mapping_v4l2_size(struct uvc_control_mapping *mapping) in uvc_mapping_v4l2_size() argument
1554 if (mapping->v4l2_type == V4L2_CTRL_TYPE_RECT) in uvc_mapping_v4l2_size()
1557 if (uvc_ctrl_mapping_is_compound(mapping)) in uvc_mapping_v4l2_size()
1558 return DIV_ROUND_UP(mapping->size, 8); in uvc_mapping_v4l2_size()
1565 struct uvc_control_mapping *mapping, in __uvc_query_v4l2_ctrl() argument
1572 v4l2_ctrl->id = mapping->id; in __uvc_query_v4l2_ctrl()
1573 v4l2_ctrl->type = mapping->v4l2_type; in __uvc_query_v4l2_ctrl()
1574 strscpy(v4l2_ctrl->name, uvc_map_get_name(mapping), in __uvc_query_v4l2_ctrl()
1575 sizeof(v4l2_ctrl->name)); in __uvc_query_v4l2_ctrl()
1576 v4l2_ctrl->flags = 0; in __uvc_query_v4l2_ctrl()
1578 if (!(ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR)) in __uvc_query_v4l2_ctrl()
1579 v4l2_ctrl->flags |= V4L2_CTRL_FLAG_WRITE_ONLY; in __uvc_query_v4l2_ctrl()
1580 if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR)) in __uvc_query_v4l2_ctrl()
1581 v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; in __uvc_query_v4l2_ctrl()
1582 if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX) && in __uvc_query_v4l2_ctrl()
1583 (ctrl->info.flags & UVC_CTRL_FLAG_GET_MIN)) in __uvc_query_v4l2_ctrl()
1584 v4l2_ctrl->flags |= V4L2_CTRL_FLAG_HAS_WHICH_MIN_MAX; in __uvc_query_v4l2_ctrl()
1586 if (mapping->master_id) in __uvc_query_v4l2_ctrl()
1587 __uvc_find_control(ctrl->entity, mapping->master_id, in __uvc_query_v4l2_ctrl()
1589 if (master_ctrl && (master_ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR)) { in __uvc_query_v4l2_ctrl()
1594 return -EIO; in __uvc_query_v4l2_ctrl()
1600 if (val != mapping->master_manual) in __uvc_query_v4l2_ctrl()
1601 v4l2_ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; in __uvc_query_v4l2_ctrl()
1604 v4l2_ctrl->elem_size = uvc_mapping_v4l2_size(mapping); in __uvc_query_v4l2_ctrl()
1605 v4l2_ctrl->elems = 1; in __uvc_query_v4l2_ctrl()
1607 if (v4l2_ctrl->type >= V4L2_CTRL_COMPOUND_TYPES) { in __uvc_query_v4l2_ctrl()
1608 v4l2_ctrl->flags |= V4L2_CTRL_FLAG_HAS_PAYLOAD; in __uvc_query_v4l2_ctrl()
1609 v4l2_ctrl->default_value = 0; in __uvc_query_v4l2_ctrl()
1610 v4l2_ctrl->minimum = 0; in __uvc_query_v4l2_ctrl()
1611 v4l2_ctrl->maximum = 0; in __uvc_query_v4l2_ctrl()
1612 v4l2_ctrl->step = 0; in __uvc_query_v4l2_ctrl()
1616 return __uvc_queryctrl_boundaries(chain, ctrl, mapping, v4l2_ctrl); in __uvc_query_v4l2_ctrl()
1623 struct uvc_control_mapping *mapping; in uvc_query_v4l2_ctrl() local
1626 ret = mutex_lock_interruptible(&chain->ctrl_mutex); in uvc_query_v4l2_ctrl()
1628 return -ERESTARTSYS; in uvc_query_v4l2_ctrl()
1631 if (!(v4l2_ctrl->id & V4L2_CTRL_FLAG_NEXT_CTRL)) { in uvc_query_v4l2_ctrl()
1632 ret = uvc_query_v4l2_class(chain, v4l2_ctrl->id, 0, v4l2_ctrl); in uvc_query_v4l2_ctrl()
1637 ctrl = uvc_find_control(chain, v4l2_ctrl->id, &mapping); in uvc_query_v4l2_ctrl()
1639 ret = -EINVAL; in uvc_query_v4l2_ctrl()
1648 if (v4l2_ctrl->id & V4L2_CTRL_FLAG_NEXT_CTRL) { in uvc_query_v4l2_ctrl()
1649 ret = uvc_query_v4l2_class(chain, v4l2_ctrl->id, mapping->id, in uvc_query_v4l2_ctrl()
1655 ret = __uvc_query_v4l2_ctrl(chain, ctrl, mapping, v4l2_ctrl); in uvc_query_v4l2_ctrl()
1657 mutex_unlock(&chain->ctrl_mutex); in uvc_query_v4l2_ctrl()
1662 * Mapping V4L2 controls to UVC controls can be straightforward if done well.
1673 struct uvc_control_mapping *mapping; in uvc_query_v4l2_menu() local
1675 u32 index = query_menu->index; in uvc_query_v4l2_menu()
1676 u32 id = query_menu->id; in uvc_query_v4l2_menu()
1681 query_menu->id = id; in uvc_query_v4l2_menu()
1682 query_menu->index = index; in uvc_query_v4l2_menu()
1684 if (index >= BITS_PER_TYPE(mapping->menu_mask)) in uvc_query_v4l2_menu()
1685 return -EINVAL; in uvc_query_v4l2_menu()
1687 ret = mutex_lock_interruptible(&chain->ctrl_mutex); in uvc_query_v4l2_menu()
1689 return -ERESTARTSYS; in uvc_query_v4l2_menu()
1691 ctrl = uvc_find_control(chain, query_menu->id, &mapping); in uvc_query_v4l2_menu()
1692 if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) { in uvc_query_v4l2_menu()
1693 ret = -EINVAL; in uvc_query_v4l2_menu()
1697 if (!test_bit(query_menu->index, &mapping->menu_mask)) { in uvc_query_v4l2_menu()
1698 ret = -EINVAL; in uvc_query_v4l2_menu()
1702 if (mapping->data_type == UVC_CTRL_DATA_TYPE_BITMASK) { in uvc_query_v4l2_menu()
1705 if (!ctrl->cached) { in uvc_query_v4l2_menu()
1711 mask = uvc_mapping_get_menu_value(mapping, query_menu->index); in uvc_query_v4l2_menu()
1717 if (!(uvc_get_ctrl_bitmap(ctrl, mapping) & mask)) { in uvc_query_v4l2_menu()
1718 ret = -EINVAL; in uvc_query_v4l2_menu()
1723 name = uvc_mapping_get_menu_name(mapping, query_menu->index); in uvc_query_v4l2_menu()
1725 ret = -EINVAL; in uvc_query_v4l2_menu()
1729 strscpy(query_menu->name, name, sizeof(query_menu->name)); in uvc_query_v4l2_menu()
1732 mutex_unlock(&chain->ctrl_mutex); in uvc_query_v4l2_menu()
1736 /* --------------------------------------------------------------------------
1743 struct uvc_control_mapping *mapping, in uvc_ctrl_fill_event() argument
1748 __uvc_query_v4l2_ctrl(chain, ctrl, mapping, &v4l2_ctrl); in uvc_ctrl_fill_event()
1751 ev->type = V4L2_EVENT_CTRL; in uvc_ctrl_fill_event()
1752 ev->id = v4l2_ctrl.id; in uvc_ctrl_fill_event()
1753 ev->u.ctrl.value = value; in uvc_ctrl_fill_event()
1754 ev->u.ctrl.changes = changes; in uvc_ctrl_fill_event()
1755 ev->u.ctrl.type = v4l2_ctrl.type; in uvc_ctrl_fill_event()
1756 ev->u.ctrl.flags = v4l2_ctrl.flags; in uvc_ctrl_fill_event()
1757 ev->u.ctrl.minimum = v4l2_ctrl.minimum; in uvc_ctrl_fill_event()
1758 ev->u.ctrl.maximum = v4l2_ctrl.maximum; in uvc_ctrl_fill_event()
1759 ev->u.ctrl.step = v4l2_ctrl.step; in uvc_ctrl_fill_event()
1760 ev->u.ctrl.default_value = v4l2_ctrl.default_value; in uvc_ctrl_fill_event()
1767 * @handle can be NULL for asynchronous events related to auto-update controls,
1772 struct uvc_control_mapping *mapping, s32 value, u32 changes) in uvc_ctrl_send_event() argument
1774 struct v4l2_fh *originator = handle ? &handle->vfh : NULL; in uvc_ctrl_send_event()
1778 if (list_empty(&mapping->ev_subs)) in uvc_ctrl_send_event()
1781 uvc_ctrl_fill_event(chain, &ev, ctrl, mapping, value, changes); in uvc_ctrl_send_event()
1783 list_for_each_entry(sev, &mapping->ev_subs, node) { in uvc_ctrl_send_event()
1784 if (sev->fh != originator || in uvc_ctrl_send_event()
1785 (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK) || in uvc_ctrl_send_event()
1787 v4l2_event_queue_fh(sev->fh, &ev); in uvc_ctrl_send_event()
1794 * generated the event and may be NULL for auto-update events.
1799 struct uvc_control_mapping *mapping = NULL; in uvc_ctrl_send_slave_event() local
1804 __uvc_find_control(master->entity, slave_id, &mapping, &ctrl, 0, 0); in uvc_ctrl_send_slave_event()
1808 if (uvc_ctrl_mapping_is_compound(mapping) || in uvc_ctrl_send_slave_event()
1809 __uvc_ctrl_get(chain, ctrl, mapping, &val) == 0) in uvc_ctrl_send_slave_event()
1812 uvc_ctrl_send_event(chain, handle, ctrl, mapping, val, changes); in uvc_ctrl_send_slave_event()
1818 lockdep_assert_held(&handle->chain->ctrl_mutex); in uvc_ctrl_set_handle()
1821 if (ctrl->handle) in uvc_ctrl_set_handle()
1822 dev_warn_ratelimited(&handle->stream->dev->udev->dev, in uvc_ctrl_set_handle()
1825 if (new_handle == ctrl->handle) in uvc_ctrl_set_handle()
1828 if (ctrl->handle) { in uvc_ctrl_set_handle()
1829 WARN_ON(!ctrl->handle->pending_async_ctrls); in uvc_ctrl_set_handle()
1830 if (ctrl->handle->pending_async_ctrls) in uvc_ctrl_set_handle()
1831 ctrl->handle->pending_async_ctrls--; in uvc_ctrl_set_handle()
1834 ctrl->handle = new_handle; in uvc_ctrl_set_handle()
1835 handle->pending_async_ctrls++; in uvc_ctrl_set_handle()
1840 if (WARN_ON(ctrl->handle != handle)) in uvc_ctrl_set_handle()
1843 ctrl->handle = NULL; in uvc_ctrl_set_handle()
1844 if (WARN_ON(!handle->pending_async_ctrls)) in uvc_ctrl_set_handle()
1846 handle->pending_async_ctrls--; in uvc_ctrl_set_handle()
1850 struct uvc_control *ctrl, const u8 *data) in uvc_ctrl_status_event() argument
1852 struct uvc_control_mapping *mapping; in uvc_ctrl_status_event() local
1856 mutex_lock(&chain->ctrl_mutex); in uvc_ctrl_status_event()
1858 /* Flush the control cache, the data might have changed. */ in uvc_ctrl_status_event()
1859 ctrl->loaded = 0; in uvc_ctrl_status_event()
1861 handle = ctrl->handle; in uvc_ctrl_status_event()
1865 list_for_each_entry(mapping, &ctrl->info.mappings, list) { in uvc_ctrl_status_event()
1868 if (uvc_ctrl_mapping_is_compound(mapping)) in uvc_ctrl_status_event()
1871 value = uvc_mapping_get_s32(mapping, UVC_GET_CUR, data); in uvc_ctrl_status_event()
1874 * handle may be NULL here if the device sends auto-update in uvc_ctrl_status_event()
1877 for (i = 0; i < ARRAY_SIZE(mapping->slave_ids); ++i) { in uvc_ctrl_status_event()
1878 if (!mapping->slave_ids[i]) in uvc_ctrl_status_event()
1882 mapping->slave_ids[i]); in uvc_ctrl_status_event()
1885 uvc_ctrl_send_event(chain, handle, ctrl, mapping, value, in uvc_ctrl_status_event()
1889 mutex_unlock(&chain->ctrl_mutex); in uvc_ctrl_status_event()
1896 struct uvc_ctrl_work *w = &dev->async_ctrl; in uvc_ctrl_status_event_work()
1899 uvc_ctrl_status_event(w->chain, w->ctrl, w->data); in uvc_ctrl_status_event_work()
1902 if (smp_load_acquire(&dev->flush_status)) in uvc_ctrl_status_event_work()
1906 w->urb->interval = dev->int_ep->desc.bInterval; in uvc_ctrl_status_event_work()
1907 ret = usb_submit_urb(w->urb, GFP_KERNEL); in uvc_ctrl_status_event_work()
1909 dev_err(&dev->udev->dev, in uvc_ctrl_status_event_work()
1914 struct uvc_control *ctrl, const u8 *data) in uvc_ctrl_status_event_async() argument
1916 struct uvc_device *dev = chain->dev; in uvc_ctrl_status_event_async()
1917 struct uvc_ctrl_work *w = &dev->async_ctrl; in uvc_ctrl_status_event_async()
1919 if (list_empty(&ctrl->info.mappings)) in uvc_ctrl_status_event_async()
1922 w->data = data; in uvc_ctrl_status_event_async()
1923 w->urb = urb; in uvc_ctrl_status_event_async()
1924 w->chain = chain; in uvc_ctrl_status_event_async()
1925 w->ctrl = ctrl; in uvc_ctrl_status_event_async()
1927 schedule_work(&w->work); in uvc_ctrl_status_event_async()
1948 struct uvc_control_mapping *mapping; in uvc_ctrl_send_events() local
1957 ctrl = uvc_find_control(handle->chain, xctrls[i].id, &mapping); in uvc_ctrl_send_events()
1958 if (ctrl->info.flags & UVC_CTRL_FLAG_ASYNCHRONOUS) in uvc_ctrl_send_events()
1962 for (j = 0; j < ARRAY_SIZE(mapping->slave_ids); ++j) { in uvc_ctrl_send_events()
1963 u32 slave_id = mapping->slave_ids[j]; in uvc_ctrl_send_events()
1976 uvc_ctrl_send_slave_event(handle->chain, handle, ctrl, in uvc_ctrl_send_events()
1980 if (uvc_ctrl_mapping_is_compound(mapping)) in uvc_ctrl_send_events()
1988 if (mapping->master_id && in uvc_ctrl_send_events()
1990 mapping->master_id)) in uvc_ctrl_send_events()
1993 uvc_ctrl_send_event(handle->chain, handle, ctrl, mapping, in uvc_ctrl_send_events()
2000 struct uvc_fh *handle = container_of(sev->fh, struct uvc_fh, vfh); in uvc_ctrl_add_event()
2001 struct uvc_control_mapping *mapping; in uvc_ctrl_add_event() local
2005 ret = mutex_lock_interruptible(&handle->chain->ctrl_mutex); in uvc_ctrl_add_event()
2007 return -ERESTARTSYS; in uvc_ctrl_add_event()
2009 if (__uvc_query_v4l2_class(handle->chain, sev->id, 0) >= 0) { in uvc_ctrl_add_event()
2014 ctrl = uvc_find_control(handle->chain, sev->id, &mapping); in uvc_ctrl_add_event()
2016 ret = -EINVAL; in uvc_ctrl_add_event()
2020 list_add_tail(&sev->node, &mapping->ev_subs); in uvc_ctrl_add_event()
2021 if (sev->flags & V4L2_EVENT_SUB_FL_SEND_INITIAL) { in uvc_ctrl_add_event()
2026 if (uvc_ctrl_mapping_is_compound(mapping) || in uvc_ctrl_add_event()
2027 __uvc_ctrl_get(handle->chain, ctrl, mapping, &val) == 0) in uvc_ctrl_add_event()
2030 uvc_ctrl_fill_event(handle->chain, &ev, ctrl, mapping, val, in uvc_ctrl_add_event()
2036 sev->elems = elems; in uvc_ctrl_add_event()
2037 v4l2_event_queue_fh(sev->fh, &ev); in uvc_ctrl_add_event()
2041 mutex_unlock(&handle->chain->ctrl_mutex); in uvc_ctrl_add_event()
2047 struct uvc_fh *handle = container_of(sev->fh, struct uvc_fh, vfh); in uvc_ctrl_del_event()
2049 mutex_lock(&handle->chain->ctrl_mutex); in uvc_ctrl_del_event()
2050 if (__uvc_query_v4l2_class(handle->chain, sev->id, 0) >= 0) in uvc_ctrl_del_event()
2052 list_del(&sev->node); in uvc_ctrl_del_event()
2054 mutex_unlock(&handle->chain->ctrl_mutex); in uvc_ctrl_del_event()
2064 /* --------------------------------------------------------------------------
2073 * When setting a control, the new value is stored in the control data field
2076 * value is loaded from the hardware before storing the new value in the data
2083 * cleared. When reverting controls, the control data field
2090 return mutex_lock_interruptible(&chain->ctrl_mutex) ? -ERESTARTSYS : 0; in uvc_ctrl_begin()
2106 for (i = 0; i < entity->ncontrols; ++i) { in uvc_ctrl_commit_entity()
2107 ctrl = &entity->controls[i]; in uvc_ctrl_commit_entity()
2108 if (!ctrl->initialized) in uvc_ctrl_commit_entity()
2112 * Reset the loaded flag for auto-update controls that were in uvc_ctrl_commit_entity()
2114 * uvc_ctrl_get from using the cached value, and for write-only in uvc_ctrl_commit_entity()
2118 if (ctrl->info.flags & UVC_CTRL_FLAG_AUTO_UPDATE || in uvc_ctrl_commit_entity()
2119 !(ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR)) in uvc_ctrl_commit_entity()
2120 ctrl->loaded = 0; in uvc_ctrl_commit_entity()
2122 if (!ctrl->dirty) in uvc_ctrl_commit_entity()
2126 ret = uvc_query_ctrl(dev, UVC_SET_CUR, ctrl->entity->id, in uvc_ctrl_commit_entity()
2127 dev->intfnum, ctrl->info.selector, in uvc_ctrl_commit_entity()
2129 ctrl->info.size); in uvc_ctrl_commit_entity()
2136 ctrl->info.size); in uvc_ctrl_commit_entity()
2138 ctrl->dirty = 0; in uvc_ctrl_commit_entity()
2147 ctrl->info.flags & UVC_CTRL_FLAG_ASYNCHRONOUS) in uvc_ctrl_commit_entity()
2158 struct uvc_control_mapping *mapping = NULL; in uvc_ctrl_find_ctrl_idx() local
2163 return ctrls->count; in uvc_ctrl_find_ctrl_idx()
2165 for (i = 0; i < ctrls->count; i++) { in uvc_ctrl_find_ctrl_idx()
2166 __uvc_find_control(entity, ctrls->controls[i].id, &mapping, in uvc_ctrl_find_ctrl_idx()
2172 return ctrls->count; in uvc_ctrl_find_ctrl_idx()
2178 struct uvc_video_chain *chain = handle->chain; in __uvc_ctrl_commit()
2184 list_for_each_entry(entity, &chain->entities, chain) { in __uvc_ctrl_commit()
2185 ret = uvc_ctrl_commit_entity(chain->dev, handle, entity, in __uvc_ctrl_commit()
2189 ctrls->error_idx = in __uvc_ctrl_commit()
2197 uvc_ctrl_send_events(handle, ctrls->controls, ctrls->count); in __uvc_ctrl_commit()
2199 mutex_unlock(&chain->ctrl_mutex); in __uvc_ctrl_commit()
2205 struct uvc_control_mapping *mapping, in uvc_mapping_get_xctrl_compound() argument
2209 u8 *data __free(kfree) = NULL; in uvc_mapping_get_xctrl_compound()
2233 return -EINVAL; in uvc_mapping_get_xctrl_compound()
2236 size = uvc_mapping_v4l2_size(mapping); in uvc_mapping_get_xctrl_compound()
2237 if (xctrl->size < size) { in uvc_mapping_get_xctrl_compound()
2238 xctrl->size = size; in uvc_mapping_get_xctrl_compound()
2239 return -ENOSPC; in uvc_mapping_get_xctrl_compound()
2242 data = kmalloc(size, GFP_KERNEL); in uvc_mapping_get_xctrl_compound()
2243 if (!data) in uvc_mapping_get_xctrl_compound()
2244 return -ENOMEM; in uvc_mapping_get_xctrl_compound()
2254 ret = mapping->get(mapping, query, uvc_ctrl_data(ctrl, id), size, data); in uvc_mapping_get_xctrl_compound()
2260 * Instead, the value is in the user memory at xctrl->ptr. The v4l2 in uvc_mapping_get_xctrl_compound()
2263 return copy_to_user(xctrl->ptr, data, size) ? -EFAULT : 0; in uvc_mapping_get_xctrl_compound()
2268 struct uvc_control_mapping *mapping, in uvc_mapping_get_xctrl_std() argument
2276 return __uvc_ctrl_get(chain, ctrl, mapping, &xctrl->value); in uvc_mapping_get_xctrl_std()
2282 return -EINVAL; in uvc_mapping_get_xctrl_std()
2285 ret = __uvc_queryctrl_boundaries(chain, ctrl, mapping, &qec); in uvc_mapping_get_xctrl_std()
2291 xctrl->value = qec.default_value; in uvc_mapping_get_xctrl_std()
2294 xctrl->value = qec.minimum; in uvc_mapping_get_xctrl_std()
2297 xctrl->value = qec.maximum; in uvc_mapping_get_xctrl_std()
2306 struct uvc_control_mapping *mapping, in uvc_mapping_get_xctrl() argument
2309 if (uvc_ctrl_mapping_is_compound(mapping)) in uvc_mapping_get_xctrl()
2310 return uvc_mapping_get_xctrl_compound(chain, ctrl, mapping, in uvc_mapping_get_xctrl()
2312 return uvc_mapping_get_xctrl_std(chain, ctrl, mapping, which, xctrl); in uvc_mapping_get_xctrl()
2319 struct uvc_control_mapping *mapping; in uvc_ctrl_get() local
2321 if (__uvc_query_v4l2_class(chain, xctrl->id, 0) >= 0) in uvc_ctrl_get()
2322 return -EACCES; in uvc_ctrl_get()
2324 ctrl = uvc_find_control(chain, xctrl->id, &mapping); in uvc_ctrl_get()
2326 return -EINVAL; in uvc_ctrl_get()
2328 return uvc_mapping_get_xctrl(chain, ctrl, mapping, which, xctrl); in uvc_ctrl_get()
2333 struct uvc_control_mapping *mapping, in uvc_ctrl_clamp() argument
2342 switch (mapping->v4l2_type) { in uvc_ctrl_clamp()
2344 if (!ctrl->cached) { in uvc_ctrl_clamp()
2350 min = uvc_mapping_get_s32(mapping, UVC_GET_MIN, in uvc_ctrl_clamp()
2352 max = uvc_mapping_get_s32(mapping, UVC_GET_MAX, in uvc_ctrl_clamp()
2354 step = uvc_mapping_get_s32(mapping, UVC_GET_RES, in uvc_ctrl_clamp()
2359 value = min + DIV_ROUND_CLOSEST((u32)(value - min), step) * step; in uvc_ctrl_clamp()
2360 if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED) in uvc_ctrl_clamp()
2368 if (!ctrl->cached) { in uvc_ctrl_clamp()
2374 value &= uvc_get_ctrl_bitmap(ctrl, mapping); in uvc_ctrl_clamp()
2383 if (value < (ffs(mapping->menu_mask) - 1) || in uvc_ctrl_clamp()
2384 value > (fls(mapping->menu_mask) - 1)) in uvc_ctrl_clamp()
2385 return -ERANGE; in uvc_ctrl_clamp()
2387 if (!test_bit(value, &mapping->menu_mask)) in uvc_ctrl_clamp()
2388 return -EINVAL; in uvc_ctrl_clamp()
2394 if (mapping->data_type == UVC_CTRL_DATA_TYPE_BITMASK) { in uvc_ctrl_clamp()
2395 int val = uvc_mapping_get_menu_value(mapping, value); in uvc_ctrl_clamp()
2396 if (!ctrl->cached) { in uvc_ctrl_clamp()
2402 if (!(uvc_get_ctrl_bitmap(ctrl, mapping) & val)) in uvc_ctrl_clamp()
2403 return -EINVAL; in uvc_ctrl_clamp()
2415 struct uvc_control_mapping *mapping, in uvc_mapping_set_xctrl_compound() argument
2418 u8 *data __free(kfree) = NULL; in uvc_mapping_set_xctrl_compound()
2419 size_t size = uvc_mapping_v4l2_size(mapping); in uvc_mapping_set_xctrl_compound()
2421 if (xctrl->size != size) in uvc_mapping_set_xctrl_compound()
2422 return -EINVAL; in uvc_mapping_set_xctrl_compound()
2426 * Instead, the value is in the user memory at xctrl->ptr. The v4l2 in uvc_mapping_set_xctrl_compound()
2429 data = memdup_user(xctrl->ptr, size); in uvc_mapping_set_xctrl_compound()
2430 if (IS_ERR(data)) in uvc_mapping_set_xctrl_compound()
2431 return PTR_ERR(data); in uvc_mapping_set_xctrl_compound()
2433 return mapping->set(mapping, size, data, in uvc_mapping_set_xctrl_compound()
2438 struct uvc_control_mapping *mapping, in uvc_mapping_set_xctrl() argument
2441 if (uvc_ctrl_mapping_is_compound(mapping)) in uvc_mapping_set_xctrl()
2442 return uvc_mapping_set_xctrl_compound(ctrl, mapping, xctrl); in uvc_mapping_set_xctrl()
2444 uvc_mapping_set_s32(mapping, xctrl->value, in uvc_mapping_set_xctrl()
2451 struct uvc_video_chain *chain = handle->chain; in uvc_ctrl_set()
2452 struct uvc_control_mapping *mapping; in uvc_ctrl_set() local
2456 lockdep_assert_held(&chain->ctrl_mutex); in uvc_ctrl_set()
2458 if (__uvc_query_v4l2_class(chain, xctrl->id, 0) >= 0) in uvc_ctrl_set()
2459 return -EACCES; in uvc_ctrl_set()
2461 ctrl = uvc_find_control(chain, xctrl->id, &mapping); in uvc_ctrl_set()
2463 return -EINVAL; in uvc_ctrl_set()
2464 if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR)) in uvc_ctrl_set()
2465 return -EACCES; in uvc_ctrl_set()
2467 ret = uvc_ctrl_clamp(chain, ctrl, mapping, &xctrl->value); in uvc_ctrl_set()
2471 * If the mapping doesn't span the whole UVC control, the current value in uvc_ctrl_set()
2472 * needs to be loaded from the device to perform the read-modify-write in uvc_ctrl_set()
2475 if ((ctrl->info.size * 8) != mapping->size) { in uvc_ctrl_set()
2482 if (!ctrl->dirty) { in uvc_ctrl_set()
2485 ctrl->info.size); in uvc_ctrl_set()
2488 ret = uvc_mapping_set_xctrl(ctrl, mapping, xctrl); in uvc_ctrl_set()
2492 ctrl->dirty = 1; in uvc_ctrl_set()
2493 ctrl->modified = 1; in uvc_ctrl_set()
2497 /* --------------------------------------------------------------------------
2508 u8 *data; in uvc_ctrl_get_flags() local
2511 data = kmalloc(1, GFP_KERNEL); in uvc_ctrl_get_flags()
2512 if (data == NULL) in uvc_ctrl_get_flags()
2513 return -ENOMEM; in uvc_ctrl_get_flags()
2515 if (ctrl->entity->get_info) in uvc_ctrl_get_flags()
2516 ret = ctrl->entity->get_info(dev, ctrl->entity, in uvc_ctrl_get_flags()
2517 ctrl->info.selector, data); in uvc_ctrl_get_flags()
2519 ret = uvc_query_ctrl(dev, UVC_GET_INFO, ctrl->entity->id, in uvc_ctrl_get_flags()
2520 dev->intfnum, info->selector, data, 1); in uvc_ctrl_get_flags()
2523 info->flags &= ~(UVC_CTRL_FLAG_GET_CUR | in uvc_ctrl_get_flags()
2528 info->flags |= (data[0] & UVC_CONTROL_CAP_GET ? in uvc_ctrl_get_flags()
2530 | (data[0] & UVC_CONTROL_CAP_SET ? in uvc_ctrl_get_flags()
2532 | (data[0] & UVC_CONTROL_CAP_AUTOUPDATE ? in uvc_ctrl_get_flags()
2534 | (data[0] & UVC_CONTROL_CAP_ASYNCHRONOUS ? in uvc_ctrl_get_flags()
2538 kfree(data); in uvc_ctrl_get_flags()
2570 if (!usb_match_one_id(dev->intf, &fixups[i].id)) in uvc_ctrl_fixup_xu_info()
2573 if (fixups[i].entity == ctrl->entity->id && in uvc_ctrl_fixup_xu_info()
2574 fixups[i].selector == info->selector) { in uvc_ctrl_fixup_xu_info()
2575 info->flags = fixups[i].flags; in uvc_ctrl_fixup_xu_info()
2587 u8 *data; in uvc_ctrl_fill_xu_info() local
2590 data = kmalloc(2, GFP_KERNEL); in uvc_ctrl_fill_xu_info()
2591 if (data == NULL) in uvc_ctrl_fill_xu_info()
2592 return -ENOMEM; in uvc_ctrl_fill_xu_info()
2594 memcpy(info->entity, ctrl->entity->guid, sizeof(info->entity)); in uvc_ctrl_fill_xu_info()
2595 info->index = ctrl->index; in uvc_ctrl_fill_xu_info()
2596 info->selector = ctrl->index + 1; in uvc_ctrl_fill_xu_info()
2599 ret = uvc_query_ctrl(dev, UVC_GET_LEN, ctrl->entity->id, dev->intfnum, in uvc_ctrl_fill_xu_info()
2600 info->selector, data, 2); in uvc_ctrl_fill_xu_info()
2604 info->entity, info->selector, ret); in uvc_ctrl_fill_xu_info()
2608 info->size = le16_to_cpup((__le16 *)data); in uvc_ctrl_fill_xu_info()
2610 info->flags = UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX in uvc_ctrl_fill_xu_info()
2617 info->entity, info->selector, ret); in uvc_ctrl_fill_xu_info()
2625 info->entity, info->selector, info->size, in uvc_ctrl_fill_xu_info()
2626 (info->flags & UVC_CTRL_FLAG_GET_CUR) ? 1 : 0, in uvc_ctrl_fill_xu_info()
2627 (info->flags & UVC_CTRL_FLAG_SET_CUR) ? 1 : 0, in uvc_ctrl_fill_xu_info()
2628 (info->flags & UVC_CTRL_FLAG_AUTO_UPDATE) ? 1 : 0); in uvc_ctrl_fill_xu_info()
2631 kfree(data); in uvc_ctrl_fill_xu_info()
2644 if (ctrl->initialized) in uvc_ctrl_init_xu_ctrl()
2655 info.entity, info.selector, dev->udev->devpath, in uvc_ctrl_init_xu_ctrl()
2656 ctrl->entity->id); in uvc_ctrl_init_xu_ctrl()
2670 u8 *data = NULL; in uvc_xu_ctrl_query() local
2675 list_for_each_entry(iter, &chain->entities, chain) { in uvc_xu_ctrl_query()
2677 iter->id == xqry->unit) { in uvc_xu_ctrl_query()
2684 uvc_dbg(chain->dev, CONTROL, "Extension unit %u not found\n", in uvc_xu_ctrl_query()
2685 xqry->unit); in uvc_xu_ctrl_query()
2686 return -ENOENT; in uvc_xu_ctrl_query()
2691 for (i = 0; i < entity->ncontrols; ++i) { in uvc_xu_ctrl_query()
2692 ctrl = &entity->controls[i]; in uvc_xu_ctrl_query()
2693 if (ctrl->index == xqry->selector - 1) { in uvc_xu_ctrl_query()
2700 uvc_dbg(chain->dev, CONTROL, "Control %pUl/%u not found\n", in uvc_xu_ctrl_query()
2701 entity->guid, xqry->selector); in uvc_xu_ctrl_query()
2702 return -ENOENT; in uvc_xu_ctrl_query()
2705 if (mutex_lock_interruptible(&chain->ctrl_mutex)) in uvc_xu_ctrl_query()
2706 return -ERESTARTSYS; in uvc_xu_ctrl_query()
2708 ret = uvc_ctrl_init_xu_ctrl(chain->dev, ctrl); in uvc_xu_ctrl_query()
2710 ret = -ENOENT; in uvc_xu_ctrl_query()
2716 size = ctrl->info.size; in uvc_xu_ctrl_query()
2718 switch (xqry->query) { in uvc_xu_ctrl_query()
2744 ret = -EINVAL; in uvc_xu_ctrl_query()
2748 if (size != xqry->size) { in uvc_xu_ctrl_query()
2749 ret = -ENOBUFS; in uvc_xu_ctrl_query()
2753 if (reqflags && !(ctrl->info.flags & reqflags)) { in uvc_xu_ctrl_query()
2754 ret = -EBADRQC; in uvc_xu_ctrl_query()
2758 data = kmalloc(size, GFP_KERNEL); in uvc_xu_ctrl_query()
2759 if (data == NULL) { in uvc_xu_ctrl_query()
2760 ret = -ENOMEM; in uvc_xu_ctrl_query()
2764 if (xqry->query == UVC_SET_CUR && in uvc_xu_ctrl_query()
2765 copy_from_user(data, xqry->data, size)) { in uvc_xu_ctrl_query()
2766 ret = -EFAULT; in uvc_xu_ctrl_query()
2770 ret = uvc_query_ctrl(chain->dev, xqry->query, xqry->unit, in uvc_xu_ctrl_query()
2771 chain->dev->intfnum, xqry->selector, data, size); in uvc_xu_ctrl_query()
2775 if (xqry->query != UVC_SET_CUR && in uvc_xu_ctrl_query()
2776 copy_to_user(xqry->data, data, size)) in uvc_xu_ctrl_query()
2777 ret = -EFAULT; in uvc_xu_ctrl_query()
2779 kfree(data); in uvc_xu_ctrl_query()
2780 mutex_unlock(&chain->ctrl_mutex); in uvc_xu_ctrl_query()
2784 /* --------------------------------------------------------------------------
2793 * - Don't restore modified controls that are back to their default value.
2794 * - Handle restore order (Auto-Exposure Mode should be restored before
2805 list_for_each_entry(entity, &dev->entities, list) { in uvc_ctrl_restore_values()
2807 for (i = 0; i < entity->ncontrols; ++i) { in uvc_ctrl_restore_values()
2808 ctrl = &entity->controls[i]; in uvc_ctrl_restore_values()
2810 if (!ctrl->initialized || !ctrl->modified || in uvc_ctrl_restore_values()
2811 (ctrl->info.flags & UVC_CTRL_FLAG_RESTORE) == 0) in uvc_ctrl_restore_values()
2813 dev_dbg(&dev->udev->dev, in uvc_ctrl_restore_values()
2815 ctrl->info.entity, ctrl->info.index, in uvc_ctrl_restore_values()
2816 ctrl->info.selector); in uvc_ctrl_restore_values()
2817 ctrl->dirty = 1; in uvc_ctrl_restore_values()
2828 /* --------------------------------------------------------------------------
2829 * Control and mapping handling
2838 ctrl->info = *info; in uvc_ctrl_add_info()
2839 INIT_LIST_HEAD(&ctrl->info.mappings); in uvc_ctrl_add_info()
2842 ctrl->uvc_data = kzalloc(ctrl->info.size * UVC_CTRL_DATA_LAST + 1, in uvc_ctrl_add_info()
2844 if (!ctrl->uvc_data) in uvc_ctrl_add_info()
2845 return -ENOMEM; in uvc_ctrl_add_info()
2847 ctrl->initialized = 1; in uvc_ctrl_add_info()
2850 ctrl->info.entity, ctrl->info.selector, dev->udev->devpath, in uvc_ctrl_add_info()
2851 ctrl->entity->id); in uvc_ctrl_add_info()
2857 * Add a control mapping to a given control.
2860 struct uvc_control *ctrl, const struct uvc_control_mapping *mapping) in __uvc_ctrl_add_mapping() argument
2868 * Most mappings come from static kernel data, and need to be duplicated. in __uvc_ctrl_add_mapping()
2872 map = kmemdup(mapping, sizeof(*mapping), GFP_KERNEL); in __uvc_ctrl_add_mapping()
2874 return -ENOMEM; in __uvc_ctrl_add_mapping()
2876 map->name = NULL; in __uvc_ctrl_add_mapping()
2877 map->menu_names = NULL; in __uvc_ctrl_add_mapping()
2878 map->menu_mapping = NULL; in __uvc_ctrl_add_mapping()
2881 if (mapping->name) { in __uvc_ctrl_add_mapping()
2882 map->name = kstrdup(mapping->name, GFP_KERNEL); in __uvc_ctrl_add_mapping()
2883 if (!map->name) in __uvc_ctrl_add_mapping()
2887 INIT_LIST_HEAD(&map->ev_subs); in __uvc_ctrl_add_mapping()
2889 if (mapping->menu_mapping && mapping->menu_mask) { in __uvc_ctrl_add_mapping()
2890 size = sizeof(mapping->menu_mapping[0]) in __uvc_ctrl_add_mapping()
2891 * fls(mapping->menu_mask); in __uvc_ctrl_add_mapping()
2892 map->menu_mapping = kmemdup(mapping->menu_mapping, size, in __uvc_ctrl_add_mapping()
2894 if (!map->menu_mapping) in __uvc_ctrl_add_mapping()
2897 if (mapping->menu_names && mapping->menu_mask) { in __uvc_ctrl_add_mapping()
2898 size = sizeof(mapping->menu_names[0]) in __uvc_ctrl_add_mapping()
2899 * fls(mapping->menu_mask); in __uvc_ctrl_add_mapping()
2900 map->menu_names = kmemdup(mapping->menu_names, size, in __uvc_ctrl_add_mapping()
2902 if (!map->menu_names) in __uvc_ctrl_add_mapping()
2907 if (WARN_ON(!map->set || !map->get)) { in __uvc_ctrl_add_mapping()
2908 ret = -EIO; in __uvc_ctrl_add_mapping()
2912 if (map->get == NULL) in __uvc_ctrl_add_mapping()
2913 map->get = uvc_get_le_value; in __uvc_ctrl_add_mapping()
2914 if (map->set == NULL) in __uvc_ctrl_add_mapping()
2915 map->set = uvc_set_le_value; in __uvc_ctrl_add_mapping()
2919 V4L2_CTRL_ID2WHICH(map->id)) { in __uvc_ctrl_add_mapping()
2920 chain->ctrl_class_bitmap |= BIT(i); in __uvc_ctrl_add_mapping()
2925 list_add_tail(&map->list, &ctrl->info.mappings); in __uvc_ctrl_add_mapping()
2926 uvc_dbg(chain->dev, CONTROL, "Adding mapping '%s' to control %pUl/%u\n", in __uvc_ctrl_add_mapping()
2927 uvc_map_get_name(map), ctrl->info.entity, in __uvc_ctrl_add_mapping()
2928 ctrl->info.selector); in __uvc_ctrl_add_mapping()
2933 ret = -ENOMEM; in __uvc_ctrl_add_mapping()
2935 kfree(map->menu_names); in __uvc_ctrl_add_mapping()
2936 kfree(map->menu_mapping); in __uvc_ctrl_add_mapping()
2937 kfree(map->name); in __uvc_ctrl_add_mapping()
2943 const struct uvc_control_mapping *mapping) in uvc_ctrl_add_mapping() argument
2945 struct uvc_device *dev = chain->dev; in uvc_ctrl_add_mapping()
2952 if (mapping->id & ~V4L2_CTRL_ID_MASK) { in uvc_ctrl_add_mapping()
2954 "Can't add mapping '%s', control id 0x%08x is invalid\n", in uvc_ctrl_add_mapping()
2955 uvc_map_get_name(mapping), mapping->id); in uvc_ctrl_add_mapping()
2956 return -EINVAL; in uvc_ctrl_add_mapping()
2960 list_for_each_entry(entity, &chain->entities, chain) { in uvc_ctrl_add_mapping()
2964 !uvc_entity_match_guid(entity, mapping->entity)) in uvc_ctrl_add_mapping()
2967 for (i = 0; i < entity->ncontrols; ++i) { in uvc_ctrl_add_mapping()
2968 ctrl = &entity->controls[i]; in uvc_ctrl_add_mapping()
2969 if (ctrl->index == mapping->selector - 1) { in uvc_ctrl_add_mapping()
2979 return -ENOENT; in uvc_ctrl_add_mapping()
2981 if (mutex_lock_interruptible(&chain->ctrl_mutex)) in uvc_ctrl_add_mapping()
2982 return -ERESTARTSYS; in uvc_ctrl_add_mapping()
2987 ret = -ENOENT; in uvc_ctrl_add_mapping()
2991 /* Validate the user-provided bit-size and offset */ in uvc_ctrl_add_mapping()
2992 if (mapping->size > 32 || in uvc_ctrl_add_mapping()
2993 mapping->offset + mapping->size > ctrl->info.size * 8) { in uvc_ctrl_add_mapping()
2994 ret = -EINVAL; in uvc_ctrl_add_mapping()
2998 list_for_each_entry(map, &ctrl->info.mappings, list) { in uvc_ctrl_add_mapping()
2999 if (mapping->id == map->id) { in uvc_ctrl_add_mapping()
3001 "Can't add mapping '%s', control id 0x%08x already exists\n", in uvc_ctrl_add_mapping()
3002 uvc_map_get_name(mapping), mapping->id); in uvc_ctrl_add_mapping()
3003 ret = -EEXIST; in uvc_ctrl_add_mapping()
3009 if (atomic_inc_return(&dev->nmappings) > UVC_MAX_CONTROL_MAPPINGS) { in uvc_ctrl_add_mapping()
3010 atomic_dec(&dev->nmappings); in uvc_ctrl_add_mapping()
3012 "Can't add mapping '%s', maximum mappings count (%u) exceeded\n", in uvc_ctrl_add_mapping()
3013 uvc_map_get_name(mapping), UVC_MAX_CONTROL_MAPPINGS); in uvc_ctrl_add_mapping()
3014 ret = -ENOMEM; in uvc_ctrl_add_mapping()
3018 ret = __uvc_ctrl_add_mapping(chain, ctrl, mapping); in uvc_ctrl_add_mapping()
3020 atomic_dec(&dev->nmappings); in uvc_ctrl_add_mapping()
3023 mutex_unlock(&chain->ctrl_mutex); in uvc_ctrl_add_mapping()
3059 controls = entity->processing.bmControls; in uvc_ctrl_prune_entity()
3060 size = entity->processing.bControlSize; in uvc_ctrl_prune_entity()
3066 controls = entity->camera.bmControls; in uvc_ctrl_prune_entity()
3067 size = entity->camera.bControlSize; in uvc_ctrl_prune_entity()
3075 if (!usb_match_one_id(dev->intf, &blacklist[i].id)) in uvc_ctrl_prune_entity()
3084 entity->id, blacklist[i].index); in uvc_ctrl_prune_entity()
3105 if (UVC_ENTITY_TYPE(ctrl->entity) == UVC_VC_EXTENSION_UNIT) in uvc_ctrl_init_ctrl()
3111 if (uvc_entity_match_guid(ctrl->entity, info->entity) && in uvc_ctrl_init_ctrl()
3112 ctrl->index == info->index) { in uvc_ctrl_init_ctrl()
3113 uvc_ctrl_add_info(chain->dev, ctrl, info); in uvc_ctrl_init_ctrl()
3120 uvc_ctrl_get_flags(chain->dev, ctrl, &ctrl->info); in uvc_ctrl_init_ctrl()
3125 if (!ctrl->initialized) in uvc_ctrl_init_ctrl()
3130 const struct uvc_control_mapping *mapping = &uvc_ctrl_mappings[i]; in uvc_ctrl_init_ctrl() local
3132 if (!uvc_entity_match_guid(ctrl->entity, mapping->entity) || in uvc_ctrl_init_ctrl()
3133 ctrl->info.selector != mapping->selector) in uvc_ctrl_init_ctrl()
3136 /* Let the device provide a custom mapping. */ in uvc_ctrl_init_ctrl()
3137 if (mapping->filter_mapping) { in uvc_ctrl_init_ctrl()
3138 mapping = mapping->filter_mapping(chain, ctrl); in uvc_ctrl_init_ctrl()
3139 if (!mapping) in uvc_ctrl_init_ctrl()
3143 __uvc_ctrl_add_mapping(chain, ctrl, mapping); in uvc_ctrl_init_ctrl()
3156 list_for_each_entry(entity, &chain->entities, chain) { in uvc_ctrl_init_chain()
3162 bmControls = entity->extension.bmControls; in uvc_ctrl_init_chain()
3163 bControlSize = entity->extension.bControlSize; in uvc_ctrl_init_chain()
3165 bmControls = entity->processing.bmControls; in uvc_ctrl_init_chain()
3166 bControlSize = entity->processing.bControlSize; in uvc_ctrl_init_chain()
3168 bmControls = entity->camera.bmControls; in uvc_ctrl_init_chain()
3169 bControlSize = entity->camera.bControlSize; in uvc_ctrl_init_chain()
3171 bmControls = entity->gpio.bmControls; in uvc_ctrl_init_chain()
3172 bControlSize = entity->gpio.bControlSize; in uvc_ctrl_init_chain()
3176 uvc_ctrl_prune_entity(chain->dev, entity); in uvc_ctrl_init_chain()
3183 entity->controls = kcalloc(ncontrols, sizeof(*ctrl), in uvc_ctrl_init_chain()
3185 if (entity->controls == NULL) in uvc_ctrl_init_chain()
3186 return -ENOMEM; in uvc_ctrl_init_chain()
3187 entity->ncontrols = ncontrols; in uvc_ctrl_init_chain()
3190 ctrl = entity->controls; in uvc_ctrl_init_chain()
3195 ctrl->entity = entity; in uvc_ctrl_init_chain()
3196 ctrl->index = i; in uvc_ctrl_init_chain()
3211 INIT_WORK(&dev->async_ctrl.work, uvc_ctrl_status_event_work); in uvc_ctrl_init_device()
3213 list_for_each_entry(chain, &dev->chains, list) { in uvc_ctrl_init_device()
3226 guard(mutex)(&handle->chain->ctrl_mutex); in uvc_ctrl_cleanup_fh()
3228 if (!handle->pending_async_ctrls) in uvc_ctrl_cleanup_fh()
3231 list_for_each_entry(entity, &handle->chain->dev->entities, list) { in uvc_ctrl_cleanup_fh()
3232 for (unsigned int i = 0; i < entity->ncontrols; ++i) { in uvc_ctrl_cleanup_fh()
3233 if (entity->controls[i].handle != handle) in uvc_ctrl_cleanup_fh()
3235 uvc_ctrl_set_handle(handle, &entity->controls[i], NULL); in uvc_ctrl_cleanup_fh()
3239 WARN_ON(handle->pending_async_ctrls); in uvc_ctrl_cleanup_fh()
3248 struct uvc_control_mapping *mapping, *nm; in uvc_ctrl_cleanup_mappings() local
3250 list_for_each_entry_safe(mapping, nm, &ctrl->info.mappings, list) { in uvc_ctrl_cleanup_mappings()
3251 list_del(&mapping->list); in uvc_ctrl_cleanup_mappings()
3252 kfree(mapping->menu_names); in uvc_ctrl_cleanup_mappings()
3253 kfree(mapping->menu_mapping); in uvc_ctrl_cleanup_mappings()
3254 kfree(mapping->name); in uvc_ctrl_cleanup_mappings()
3255 kfree(mapping); in uvc_ctrl_cleanup_mappings()
3265 if (dev->async_ctrl.work.func) in uvc_ctrl_cleanup_device()
3266 cancel_work_sync(&dev->async_ctrl.work); in uvc_ctrl_cleanup_device()
3269 list_for_each_entry(entity, &dev->entities, list) { in uvc_ctrl_cleanup_device()
3270 for (i = 0; i < entity->ncontrols; ++i) { in uvc_ctrl_cleanup_device()
3271 struct uvc_control *ctrl = &entity->controls[i]; in uvc_ctrl_cleanup_device()
3273 if (!ctrl->initialized) in uvc_ctrl_cleanup_device()
3277 kfree(ctrl->uvc_data); in uvc_ctrl_cleanup_device()
3280 kfree(entity->controls); in uvc_ctrl_cleanup_device()