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 /* ------------------------------------------------------------------------
373 * device. The custom menu_mapping in the control @mapping is used when
380 * The function returns -EINVAL if the V4L2 menu index @idx isn't valid for the
384 static int uvc_mapping_get_menu_value(const struct uvc_control_mapping *mapping, in uvc_mapping_get_menu_value() argument
387 if (!test_bit(idx, &mapping->menu_mask)) in uvc_mapping_get_menu_value()
388 return -EINVAL; in uvc_mapping_get_menu_value()
390 if (mapping->menu_mapping) in uvc_mapping_get_menu_value()
391 return mapping->menu_mapping[idx]; in uvc_mapping_get_menu_value()
397 uvc_mapping_get_menu_name(const struct uvc_control_mapping *mapping, u32 idx) in uvc_mapping_get_menu_name() argument
399 if (!test_bit(idx, &mapping->menu_mask)) in uvc_mapping_get_menu_name()
402 if (mapping->menu_names) in uvc_mapping_get_menu_name()
403 return mapping->menu_names[idx]; in uvc_mapping_get_menu_name()
405 return v4l2_ctrl_get_menu(mapping->id)[idx]; in uvc_mapping_get_menu_name()
408 static s32 uvc_ctrl_get_zoom(struct uvc_control_mapping *mapping, in uvc_ctrl_get_zoom() argument
409 u8 query, const u8 *data) in uvc_ctrl_get_zoom() argument
411 s8 zoom = (s8)data[0]; in uvc_ctrl_get_zoom()
415 return (zoom == 0) ? 0 : (zoom > 0 ? data[2] : -data[2]); in uvc_ctrl_get_zoom()
422 return data[2]; in uvc_ctrl_get_zoom()
426 static void uvc_ctrl_set_zoom(struct uvc_control_mapping *mapping, in uvc_ctrl_set_zoom() argument
427 s32 value, u8 *data) in uvc_ctrl_set_zoom() argument
429 data[0] = value == 0 ? 0 : (value > 0) ? 1 : 0xff; in uvc_ctrl_set_zoom()
430 data[2] = min((int)abs(value), 0xff); in uvc_ctrl_set_zoom()
433 static s32 uvc_ctrl_get_rel_speed(struct uvc_control_mapping *mapping, in uvc_ctrl_get_rel_speed() argument
434 u8 query, const u8 *data) in uvc_ctrl_get_rel_speed() argument
436 unsigned int first = mapping->offset / 8; in uvc_ctrl_get_rel_speed()
437 s8 rel = (s8)data[first]; in uvc_ctrl_get_rel_speed()
441 return (rel == 0) ? 0 : (rel > 0 ? data[first+1] in uvc_ctrl_get_rel_speed()
442 : -data[first+1]); in uvc_ctrl_get_rel_speed()
444 return -data[first+1]; in uvc_ctrl_get_rel_speed()
449 return data[first+1]; in uvc_ctrl_get_rel_speed()
453 static void uvc_ctrl_set_rel_speed(struct uvc_control_mapping *mapping, in uvc_ctrl_set_rel_speed() argument
454 s32 value, u8 *data) in uvc_ctrl_set_rel_speed() argument
456 unsigned int first = mapping->offset / 8; in uvc_ctrl_set_rel_speed()
458 data[first] = value == 0 ? 0 : (value > 0) ? 1 : 0xff; in uvc_ctrl_set_rel_speed()
459 data[first+1] = min_t(int, abs(value), 0xff); in uvc_ctrl_set_rel_speed()
512 ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, ctrl->entity->id, in uvc_ctrl_filter_plf_mapping()
513 chain->dev->intfnum, ctrl->info.selector, in uvc_ctrl_filter_plf_mapping()
522 ret = uvc_query_ctrl(chain->dev, UVC_SET_CUR, ctrl->entity->id, in uvc_ctrl_filter_plf_mapping()
523 chain->dev->intfnum, ctrl->info.selector, in uvc_ctrl_filter_plf_mapping()
529 if (chain->dev->uvc_version < 0x150) in uvc_ctrl_filter_plf_mapping()
534 ret = uvc_query_ctrl(chain->dev, UVC_SET_CUR, ctrl->entity->id, in uvc_ctrl_filter_plf_mapping()
535 chain->dev->intfnum, ctrl->info.selector, in uvc_ctrl_filter_plf_mapping()
541 /* Restore initial value and add mapping. */ in uvc_ctrl_filter_plf_mapping()
543 uvc_query_ctrl(chain->dev, UVC_SET_CUR, ctrl->entity->id, in uvc_ctrl_filter_plf_mapping()
544 chain->dev->intfnum, ctrl->info.selector, in uvc_ctrl_filter_plf_mapping()
846 /* ------------------------------------------------------------------------
852 return ctrl->uvc_data + id * ctrl->info.size; in uvc_ctrl_data()
855 static inline int uvc_test_bit(const u8 *data, int bit) in uvc_test_bit() argument
857 return (data[bit >> 3] >> (bit & 7)) & 1; in uvc_test_bit()
860 static inline void uvc_clear_bit(u8 *data, int bit) in uvc_clear_bit() argument
862 data[bit >> 3] &= ~(1 << (bit & 7)); in uvc_clear_bit()
866 * Extract the bit string specified by mapping->offset and mapping->size
867 * from the little-endian data stored at 'data' and return the result as
868 * a signed 32bit integer. Sign extension will be performed if the mapping
869 * references a signed data type.
871 static s32 uvc_get_le_value(struct uvc_control_mapping *mapping, in uvc_get_le_value() argument
872 u8 query, const u8 *data) in uvc_get_le_value() argument
874 int bits = mapping->size; in uvc_get_le_value()
875 int offset = mapping->offset; in uvc_get_le_value()
879 data += offset / 8; in uvc_get_le_value()
881 mask = ((1LL << bits) - 1) << offset; in uvc_get_le_value()
884 u8 byte = *data & mask; in uvc_get_le_value()
885 value |= offset > 0 ? (byte >> offset) : (byte << (-offset)); in uvc_get_le_value()
886 bits -= 8 - max(offset, 0); in uvc_get_le_value()
890 offset -= 8; in uvc_get_le_value()
891 mask = (1 << bits) - 1; in uvc_get_le_value()
892 data++; in uvc_get_le_value()
895 /* Sign-extend the value if needed. */ in uvc_get_le_value()
896 if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED) in uvc_get_le_value()
897 value |= -(value & (1 << (mapping->size - 1))); in uvc_get_le_value()
903 * Set the bit string specified by mapping->offset and mapping->size
904 * in the little-endian data stored at 'data' to the value 'value'.
906 static void uvc_set_le_value(struct uvc_control_mapping *mapping, in uvc_set_le_value() argument
907 s32 value, u8 *data) in uvc_set_le_value() argument
909 int bits = mapping->size; in uvc_set_le_value()
910 int offset = mapping->offset; in uvc_set_le_value()
916 * triggered. UVC devices however want to see a 1 written -> override in uvc_set_le_value()
919 if (mapping->v4l2_type == V4L2_CTRL_TYPE_BUTTON) in uvc_set_le_value()
920 value = -1; in uvc_set_le_value()
922 data += offset / 8; in uvc_set_le_value()
925 for (; bits > 0; data++) { in uvc_set_le_value()
926 mask = ((1LL << bits) - 1) << offset; in uvc_set_le_value()
927 *data = (*data & ~mask) | ((value << offset) & mask); in uvc_set_le_value()
929 bits -= 8 - offset; in uvc_set_le_value()
934 /* ------------------------------------------------------------------------
941 return memcmp(entity->guid, guid, sizeof(entity->guid)) == 0; in uvc_entity_match_guid()
944 /* ------------------------------------------------------------------------
949 struct uvc_control_mapping **mapping, struct uvc_control **control, in __uvc_find_control() argument
959 for (i = 0; i < entity->ncontrols; ++i) { in __uvc_find_control()
960 ctrl = &entity->controls[i]; in __uvc_find_control()
961 if (!ctrl->initialized) in __uvc_find_control()
964 list_for_each_entry(map, &ctrl->info.mappings, list) { in __uvc_find_control()
965 if ((map->id == v4l2_id) && !next) { in __uvc_find_control()
967 *mapping = map; in __uvc_find_control()
971 if ((*mapping == NULL || (*mapping)->id > map->id) && in __uvc_find_control()
972 (map->id > v4l2_id) && next) { in __uvc_find_control()
974 *mapping = map; in __uvc_find_control()
981 u32 v4l2_id, struct uvc_control_mapping **mapping) in uvc_find_control() argument
987 *mapping = NULL; in uvc_find_control()
993 list_for_each_entry(entity, &chain->entities, chain) { in uvc_find_control()
994 __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next); in uvc_find_control()
1000 uvc_dbg(chain->dev, CONTROL, "Control 0x%08x not found\n", in uvc_find_control()
1011 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_DEF) { in uvc_ctrl_populate_cache()
1012 ret = uvc_query_ctrl(chain->dev, UVC_GET_DEF, ctrl->entity->id, in uvc_ctrl_populate_cache()
1013 chain->dev->intfnum, ctrl->info.selector, in uvc_ctrl_populate_cache()
1015 ctrl->info.size); in uvc_ctrl_populate_cache()
1020 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MIN) { in uvc_ctrl_populate_cache()
1021 ret = uvc_query_ctrl(chain->dev, UVC_GET_MIN, ctrl->entity->id, in uvc_ctrl_populate_cache()
1022 chain->dev->intfnum, ctrl->info.selector, in uvc_ctrl_populate_cache()
1024 ctrl->info.size); in uvc_ctrl_populate_cache()
1028 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX) { in uvc_ctrl_populate_cache()
1029 ret = uvc_query_ctrl(chain->dev, UVC_GET_MAX, ctrl->entity->id, in uvc_ctrl_populate_cache()
1030 chain->dev->intfnum, ctrl->info.selector, in uvc_ctrl_populate_cache()
1032 ctrl->info.size); in uvc_ctrl_populate_cache()
1036 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) { in uvc_ctrl_populate_cache()
1037 ret = uvc_query_ctrl(chain->dev, UVC_GET_RES, ctrl->entity->id, in uvc_ctrl_populate_cache()
1038 chain->dev->intfnum, ctrl->info.selector, in uvc_ctrl_populate_cache()
1040 ctrl->info.size); in uvc_ctrl_populate_cache()
1042 if (UVC_ENTITY_TYPE(ctrl->entity) != in uvc_ctrl_populate_cache()
1051 uvc_warn_once(chain->dev, UVC_WARN_XU_GET_RES, in uvc_ctrl_populate_cache()
1052 "UVC non compliance - GET_RES failed on " in uvc_ctrl_populate_cache()
1055 ctrl->info.size); in uvc_ctrl_populate_cache()
1059 ctrl->cached = 1; in uvc_ctrl_populate_cache()
1063 static s32 __uvc_ctrl_get_value(struct uvc_control_mapping *mapping, in __uvc_ctrl_get_value() argument
1064 const u8 *data) in __uvc_ctrl_get_value() argument
1066 s32 value = mapping->get(mapping, UVC_GET_CUR, data); in __uvc_ctrl_get_value()
1068 if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) { in __uvc_ctrl_get_value()
1071 for (i = 0; BIT(i) <= mapping->menu_mask; ++i) { in __uvc_ctrl_get_value()
1074 if (!test_bit(i, &mapping->menu_mask)) in __uvc_ctrl_get_value()
1077 menu_value = uvc_mapping_get_menu_value(mapping, i); in __uvc_ctrl_get_value()
1092 u8 *data; in __uvc_ctrl_load_cur() local
1095 if (ctrl->loaded) in __uvc_ctrl_load_cur()
1098 data = uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT); in __uvc_ctrl_load_cur()
1100 if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) { in __uvc_ctrl_load_cur()
1101 memset(data, 0, ctrl->info.size); in __uvc_ctrl_load_cur()
1102 ctrl->loaded = 1; in __uvc_ctrl_load_cur()
1107 if (ctrl->entity->get_cur) in __uvc_ctrl_load_cur()
1108 ret = ctrl->entity->get_cur(chain->dev, ctrl->entity, in __uvc_ctrl_load_cur()
1109 ctrl->info.selector, data, in __uvc_ctrl_load_cur()
1110 ctrl->info.size); in __uvc_ctrl_load_cur()
1112 ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, in __uvc_ctrl_load_cur()
1113 ctrl->entity->id, chain->dev->intfnum, in __uvc_ctrl_load_cur()
1114 ctrl->info.selector, data, in __uvc_ctrl_load_cur()
1115 ctrl->info.size); in __uvc_ctrl_load_cur()
1120 ctrl->loaded = 1; in __uvc_ctrl_load_cur()
1127 struct uvc_control_mapping *mapping, in __uvc_ctrl_get() argument
1132 if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) in __uvc_ctrl_get()
1133 return -EACCES; in __uvc_ctrl_get()
1139 *value = __uvc_ctrl_get_value(mapping, in __uvc_ctrl_get()
1154 if (!(chain->ctrl_class_bitmap & BIT(i))) in __uvc_query_v4l2_class()
1166 return -ENODEV; in __uvc_query_v4l2_class()
1176 return -ENODEV; in uvc_query_v4l2_class()
1179 v4l2_ctrl->id = uvc_control_classes[idx]; in uvc_query_v4l2_class()
1180 strscpy(v4l2_ctrl->name, v4l2_ctrl_get_name(v4l2_ctrl->id), in uvc_query_v4l2_class()
1181 sizeof(v4l2_ctrl->name)); in uvc_query_v4l2_class()
1182 v4l2_ctrl->type = V4L2_CTRL_TYPE_CTRL_CLASS; in uvc_query_v4l2_class()
1183 v4l2_ctrl->flags = V4L2_CTRL_FLAG_WRITE_ONLY in uvc_query_v4l2_class()
1204 struct uvc_control_mapping *mapping; in uvc_ctrl_is_accessible() local
1212 return -EACCES; in uvc_ctrl_is_accessible()
1214 ctrl = uvc_find_control(chain, v4l2_id, &mapping); in uvc_ctrl_is_accessible()
1216 return -EINVAL; in uvc_ctrl_is_accessible()
1218 if (!(ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) && read) in uvc_ctrl_is_accessible()
1219 return -EACCES; in uvc_ctrl_is_accessible()
1221 if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR) && !read) in uvc_ctrl_is_accessible()
1222 return -EACCES; in uvc_ctrl_is_accessible()
1224 if (ioctl != VIDIOC_S_EXT_CTRLS || !mapping->master_id) in uvc_ctrl_is_accessible()
1231 for (i = ctrls->count - 1; i >= 0; i--) { in uvc_ctrl_is_accessible()
1232 if (ctrls->controls[i].id == mapping->master_id) in uvc_ctrl_is_accessible()
1233 return ctrls->controls[i].value == in uvc_ctrl_is_accessible()
1234 mapping->master_manual ? 0 : -EACCES; in uvc_ctrl_is_accessible()
1237 __uvc_find_control(ctrl->entity, mapping->master_id, &master_map, in uvc_ctrl_is_accessible()
1240 if (!master_ctrl || !(master_ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR)) in uvc_ctrl_is_accessible()
1244 if (ret >= 0 && val != mapping->master_manual) in uvc_ctrl_is_accessible()
1245 return -EACCES; in uvc_ctrl_is_accessible()
1254 if (map->name) in uvc_map_get_name()
1255 return map->name; in uvc_map_get_name()
1257 name = v4l2_ctrl_get_name(map->id); in uvc_map_get_name()
1265 struct uvc_control_mapping *mapping) in uvc_get_ctrl_bitmap() argument
1272 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) in uvc_get_ctrl_bitmap()
1273 return mapping->get(mapping, UVC_GET_RES, in uvc_get_ctrl_bitmap()
1276 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX) in uvc_get_ctrl_bitmap()
1277 return mapping->get(mapping, UVC_GET_MAX, in uvc_get_ctrl_bitmap()
1285 struct uvc_control_mapping *mapping, in __uvc_query_v4l2_ctrl() argument
1293 v4l2_ctrl->id = mapping->id; in __uvc_query_v4l2_ctrl()
1294 v4l2_ctrl->type = mapping->v4l2_type; in __uvc_query_v4l2_ctrl()
1295 strscpy(v4l2_ctrl->name, uvc_map_get_name(mapping), in __uvc_query_v4l2_ctrl()
1296 sizeof(v4l2_ctrl->name)); in __uvc_query_v4l2_ctrl()
1297 v4l2_ctrl->flags = 0; in __uvc_query_v4l2_ctrl()
1299 if (!(ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR)) in __uvc_query_v4l2_ctrl()
1300 v4l2_ctrl->flags |= V4L2_CTRL_FLAG_WRITE_ONLY; in __uvc_query_v4l2_ctrl()
1301 if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR)) in __uvc_query_v4l2_ctrl()
1302 v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; in __uvc_query_v4l2_ctrl()
1304 if (mapping->master_id) in __uvc_query_v4l2_ctrl()
1305 __uvc_find_control(ctrl->entity, mapping->master_id, in __uvc_query_v4l2_ctrl()
1307 if (master_ctrl && (master_ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR)) { in __uvc_query_v4l2_ctrl()
1313 if (val != mapping->master_manual) in __uvc_query_v4l2_ctrl()
1314 v4l2_ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; in __uvc_query_v4l2_ctrl()
1317 if (!ctrl->cached) { in __uvc_query_v4l2_ctrl()
1323 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_DEF) { in __uvc_query_v4l2_ctrl()
1324 v4l2_ctrl->default_value = mapping->get(mapping, UVC_GET_DEF, in __uvc_query_v4l2_ctrl()
1328 switch (mapping->v4l2_type) { in __uvc_query_v4l2_ctrl()
1330 v4l2_ctrl->minimum = ffs(mapping->menu_mask) - 1; in __uvc_query_v4l2_ctrl()
1331 v4l2_ctrl->maximum = fls(mapping->menu_mask) - 1; in __uvc_query_v4l2_ctrl()
1332 v4l2_ctrl->step = 1; in __uvc_query_v4l2_ctrl()
1334 for (i = 0; BIT(i) <= mapping->menu_mask; ++i) { in __uvc_query_v4l2_ctrl()
1337 if (!test_bit(i, &mapping->menu_mask)) in __uvc_query_v4l2_ctrl()
1340 menu_value = uvc_mapping_get_menu_value(mapping, i); in __uvc_query_v4l2_ctrl()
1342 if (menu_value == v4l2_ctrl->default_value) { in __uvc_query_v4l2_ctrl()
1343 v4l2_ctrl->default_value = i; in __uvc_query_v4l2_ctrl()
1351 v4l2_ctrl->minimum = 0; in __uvc_query_v4l2_ctrl()
1352 v4l2_ctrl->maximum = 1; in __uvc_query_v4l2_ctrl()
1353 v4l2_ctrl->step = 1; in __uvc_query_v4l2_ctrl()
1357 v4l2_ctrl->minimum = 0; in __uvc_query_v4l2_ctrl()
1358 v4l2_ctrl->maximum = 0; in __uvc_query_v4l2_ctrl()
1359 v4l2_ctrl->step = 0; in __uvc_query_v4l2_ctrl()
1363 v4l2_ctrl->minimum = 0; in __uvc_query_v4l2_ctrl()
1364 v4l2_ctrl->maximum = uvc_get_ctrl_bitmap(ctrl, mapping); in __uvc_query_v4l2_ctrl()
1365 v4l2_ctrl->step = 0; in __uvc_query_v4l2_ctrl()
1372 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MIN) in __uvc_query_v4l2_ctrl()
1373 v4l2_ctrl->minimum = mapping->get(mapping, UVC_GET_MIN, in __uvc_query_v4l2_ctrl()
1376 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX) in __uvc_query_v4l2_ctrl()
1377 v4l2_ctrl->maximum = mapping->get(mapping, UVC_GET_MAX, in __uvc_query_v4l2_ctrl()
1380 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) in __uvc_query_v4l2_ctrl()
1381 v4l2_ctrl->step = mapping->get(mapping, UVC_GET_RES, in __uvc_query_v4l2_ctrl()
1391 struct uvc_control_mapping *mapping; in uvc_query_v4l2_ctrl() local
1394 ret = mutex_lock_interruptible(&chain->ctrl_mutex); in uvc_query_v4l2_ctrl()
1396 return -ERESTARTSYS; in uvc_query_v4l2_ctrl()
1399 if (!(v4l2_ctrl->id & V4L2_CTRL_FLAG_NEXT_CTRL)) { in uvc_query_v4l2_ctrl()
1400 ret = uvc_query_v4l2_class(chain, v4l2_ctrl->id, 0, v4l2_ctrl); in uvc_query_v4l2_ctrl()
1405 ctrl = uvc_find_control(chain, v4l2_ctrl->id, &mapping); in uvc_query_v4l2_ctrl()
1407 ret = -EINVAL; in uvc_query_v4l2_ctrl()
1416 if (v4l2_ctrl->id & V4L2_CTRL_FLAG_NEXT_CTRL) { in uvc_query_v4l2_ctrl()
1417 ret = uvc_query_v4l2_class(chain, v4l2_ctrl->id, mapping->id, in uvc_query_v4l2_ctrl()
1423 ret = __uvc_query_v4l2_ctrl(chain, ctrl, mapping, v4l2_ctrl); in uvc_query_v4l2_ctrl()
1425 mutex_unlock(&chain->ctrl_mutex); in uvc_query_v4l2_ctrl()
1430 * Mapping V4L2 controls to UVC controls can be straightforward if done well.
1441 struct uvc_control_mapping *mapping; in uvc_query_v4l2_menu() local
1443 u32 index = query_menu->index; in uvc_query_v4l2_menu()
1444 u32 id = query_menu->id; in uvc_query_v4l2_menu()
1449 query_menu->id = id; in uvc_query_v4l2_menu()
1450 query_menu->index = index; in uvc_query_v4l2_menu()
1452 if (index >= BITS_PER_TYPE(mapping->menu_mask)) in uvc_query_v4l2_menu()
1453 return -EINVAL; in uvc_query_v4l2_menu()
1455 ret = mutex_lock_interruptible(&chain->ctrl_mutex); in uvc_query_v4l2_menu()
1457 return -ERESTARTSYS; in uvc_query_v4l2_menu()
1459 ctrl = uvc_find_control(chain, query_menu->id, &mapping); in uvc_query_v4l2_menu()
1460 if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) { in uvc_query_v4l2_menu()
1461 ret = -EINVAL; in uvc_query_v4l2_menu()
1465 if (!test_bit(query_menu->index, &mapping->menu_mask)) { in uvc_query_v4l2_menu()
1466 ret = -EINVAL; in uvc_query_v4l2_menu()
1470 if (mapping->data_type == UVC_CTRL_DATA_TYPE_BITMASK) { in uvc_query_v4l2_menu()
1473 if (!ctrl->cached) { in uvc_query_v4l2_menu()
1479 mask = uvc_mapping_get_menu_value(mapping, query_menu->index); in uvc_query_v4l2_menu()
1485 if (!(uvc_get_ctrl_bitmap(ctrl, mapping) & mask)) { in uvc_query_v4l2_menu()
1486 ret = -EINVAL; in uvc_query_v4l2_menu()
1491 name = uvc_mapping_get_menu_name(mapping, query_menu->index); in uvc_query_v4l2_menu()
1493 ret = -EINVAL; in uvc_query_v4l2_menu()
1497 strscpy(query_menu->name, name, sizeof(query_menu->name)); in uvc_query_v4l2_menu()
1500 mutex_unlock(&chain->ctrl_mutex); in uvc_query_v4l2_menu()
1504 /* --------------------------------------------------------------------------
1511 struct uvc_control_mapping *mapping, in uvc_ctrl_fill_event() argument
1516 __uvc_query_v4l2_ctrl(chain, ctrl, mapping, &v4l2_ctrl); in uvc_ctrl_fill_event()
1519 ev->type = V4L2_EVENT_CTRL; in uvc_ctrl_fill_event()
1520 ev->id = v4l2_ctrl.id; in uvc_ctrl_fill_event()
1521 ev->u.ctrl.value = value; in uvc_ctrl_fill_event()
1522 ev->u.ctrl.changes = changes; in uvc_ctrl_fill_event()
1523 ev->u.ctrl.type = v4l2_ctrl.type; in uvc_ctrl_fill_event()
1524 ev->u.ctrl.flags = v4l2_ctrl.flags; in uvc_ctrl_fill_event()
1525 ev->u.ctrl.minimum = v4l2_ctrl.minimum; in uvc_ctrl_fill_event()
1526 ev->u.ctrl.maximum = v4l2_ctrl.maximum; in uvc_ctrl_fill_event()
1527 ev->u.ctrl.step = v4l2_ctrl.step; in uvc_ctrl_fill_event()
1528 ev->u.ctrl.default_value = v4l2_ctrl.default_value; in uvc_ctrl_fill_event()
1535 * @handle can be NULL for asynchronous events related to auto-update controls,
1540 struct uvc_control_mapping *mapping, s32 value, u32 changes) in uvc_ctrl_send_event() argument
1542 struct v4l2_fh *originator = handle ? &handle->vfh : NULL; in uvc_ctrl_send_event()
1546 if (list_empty(&mapping->ev_subs)) in uvc_ctrl_send_event()
1549 uvc_ctrl_fill_event(chain, &ev, ctrl, mapping, value, changes); in uvc_ctrl_send_event()
1551 list_for_each_entry(sev, &mapping->ev_subs, node) { in uvc_ctrl_send_event()
1552 if (sev->fh != originator || in uvc_ctrl_send_event()
1553 (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK) || in uvc_ctrl_send_event()
1555 v4l2_event_queue_fh(sev->fh, &ev); in uvc_ctrl_send_event()
1562 * generated the event and may be NULL for auto-update events.
1567 struct uvc_control_mapping *mapping = NULL; in uvc_ctrl_send_slave_event() local
1572 __uvc_find_control(master->entity, slave_id, &mapping, &ctrl, 0); in uvc_ctrl_send_slave_event()
1576 if (__uvc_ctrl_get(chain, ctrl, mapping, &val) == 0) in uvc_ctrl_send_slave_event()
1579 uvc_ctrl_send_event(chain, handle, ctrl, mapping, val, changes); in uvc_ctrl_send_slave_event()
1585 lockdep_assert_held(&handle->chain->ctrl_mutex); in uvc_ctrl_set_handle()
1588 if (ctrl->handle) in uvc_ctrl_set_handle()
1589 dev_warn_ratelimited(&handle->stream->dev->udev->dev, in uvc_ctrl_set_handle()
1592 if (new_handle == ctrl->handle) in uvc_ctrl_set_handle()
1595 if (ctrl->handle) { in uvc_ctrl_set_handle()
1596 WARN_ON(!ctrl->handle->pending_async_ctrls); in uvc_ctrl_set_handle()
1597 if (ctrl->handle->pending_async_ctrls) in uvc_ctrl_set_handle()
1598 ctrl->handle->pending_async_ctrls--; in uvc_ctrl_set_handle()
1601 ctrl->handle = new_handle; in uvc_ctrl_set_handle()
1602 handle->pending_async_ctrls++; in uvc_ctrl_set_handle()
1607 if (WARN_ON(ctrl->handle != handle)) in uvc_ctrl_set_handle()
1610 ctrl->handle = NULL; in uvc_ctrl_set_handle()
1611 if (WARN_ON(!handle->pending_async_ctrls)) in uvc_ctrl_set_handle()
1613 handle->pending_async_ctrls--; in uvc_ctrl_set_handle()
1617 struct uvc_control *ctrl, const u8 *data) in uvc_ctrl_status_event() argument
1619 struct uvc_control_mapping *mapping; in uvc_ctrl_status_event() local
1623 mutex_lock(&chain->ctrl_mutex); in uvc_ctrl_status_event()
1625 /* Flush the control cache, the data might have changed. */ in uvc_ctrl_status_event()
1626 ctrl->loaded = 0; in uvc_ctrl_status_event()
1628 handle = ctrl->handle; in uvc_ctrl_status_event()
1632 list_for_each_entry(mapping, &ctrl->info.mappings, list) { in uvc_ctrl_status_event()
1633 s32 value = __uvc_ctrl_get_value(mapping, data); in uvc_ctrl_status_event()
1636 * handle may be NULL here if the device sends auto-update in uvc_ctrl_status_event()
1639 for (i = 0; i < ARRAY_SIZE(mapping->slave_ids); ++i) { in uvc_ctrl_status_event()
1640 if (!mapping->slave_ids[i]) in uvc_ctrl_status_event()
1644 mapping->slave_ids[i]); in uvc_ctrl_status_event()
1647 uvc_ctrl_send_event(chain, handle, ctrl, mapping, value, in uvc_ctrl_status_event()
1651 mutex_unlock(&chain->ctrl_mutex); in uvc_ctrl_status_event()
1658 struct uvc_ctrl_work *w = &dev->async_ctrl; in uvc_ctrl_status_event_work()
1661 uvc_ctrl_status_event(w->chain, w->ctrl, w->data); in uvc_ctrl_status_event_work()
1664 if (smp_load_acquire(&dev->flush_status)) in uvc_ctrl_status_event_work()
1668 w->urb->interval = dev->int_ep->desc.bInterval; in uvc_ctrl_status_event_work()
1669 ret = usb_submit_urb(w->urb, GFP_KERNEL); in uvc_ctrl_status_event_work()
1671 dev_err(&dev->udev->dev, in uvc_ctrl_status_event_work()
1676 struct uvc_control *ctrl, const u8 *data) in uvc_ctrl_status_event_async() argument
1678 struct uvc_device *dev = chain->dev; in uvc_ctrl_status_event_async()
1679 struct uvc_ctrl_work *w = &dev->async_ctrl; in uvc_ctrl_status_event_async()
1681 if (list_empty(&ctrl->info.mappings)) in uvc_ctrl_status_event_async()
1684 w->data = data; in uvc_ctrl_status_event_async()
1685 w->urb = urb; in uvc_ctrl_status_event_async()
1686 w->chain = chain; in uvc_ctrl_status_event_async()
1687 w->ctrl = ctrl; in uvc_ctrl_status_event_async()
1689 schedule_work(&w->work); in uvc_ctrl_status_event_async()
1710 struct uvc_control_mapping *mapping; in uvc_ctrl_send_events() local
1718 ctrl = uvc_find_control(handle->chain, xctrls[i].id, &mapping); in uvc_ctrl_send_events()
1719 if (ctrl->info.flags & UVC_CTRL_FLAG_ASYNCHRONOUS) in uvc_ctrl_send_events()
1723 for (j = 0; j < ARRAY_SIZE(mapping->slave_ids); ++j) { in uvc_ctrl_send_events()
1724 u32 slave_id = mapping->slave_ids[j]; in uvc_ctrl_send_events()
1737 uvc_ctrl_send_slave_event(handle->chain, handle, ctrl, in uvc_ctrl_send_events()
1745 if (mapping->master_id && in uvc_ctrl_send_events()
1747 mapping->master_id)) in uvc_ctrl_send_events()
1750 uvc_ctrl_send_event(handle->chain, handle, ctrl, mapping, in uvc_ctrl_send_events()
1757 struct uvc_fh *handle = container_of(sev->fh, struct uvc_fh, vfh); in uvc_ctrl_add_event()
1758 struct uvc_control_mapping *mapping; in uvc_ctrl_add_event() local
1762 ret = mutex_lock_interruptible(&handle->chain->ctrl_mutex); in uvc_ctrl_add_event()
1764 return -ERESTARTSYS; in uvc_ctrl_add_event()
1766 if (__uvc_query_v4l2_class(handle->chain, sev->id, 0) >= 0) { in uvc_ctrl_add_event()
1771 ctrl = uvc_find_control(handle->chain, sev->id, &mapping); in uvc_ctrl_add_event()
1773 ret = -EINVAL; in uvc_ctrl_add_event()
1777 list_add_tail(&sev->node, &mapping->ev_subs); in uvc_ctrl_add_event()
1778 if (sev->flags & V4L2_EVENT_SUB_FL_SEND_INITIAL) { in uvc_ctrl_add_event()
1783 if (__uvc_ctrl_get(handle->chain, ctrl, mapping, &val) == 0) in uvc_ctrl_add_event()
1786 uvc_ctrl_fill_event(handle->chain, &ev, ctrl, mapping, val, in uvc_ctrl_add_event()
1792 sev->elems = elems; in uvc_ctrl_add_event()
1793 v4l2_event_queue_fh(sev->fh, &ev); in uvc_ctrl_add_event()
1797 mutex_unlock(&handle->chain->ctrl_mutex); in uvc_ctrl_add_event()
1803 struct uvc_fh *handle = container_of(sev->fh, struct uvc_fh, vfh); in uvc_ctrl_del_event()
1805 mutex_lock(&handle->chain->ctrl_mutex); in uvc_ctrl_del_event()
1806 if (__uvc_query_v4l2_class(handle->chain, sev->id, 0) >= 0) in uvc_ctrl_del_event()
1808 list_del(&sev->node); in uvc_ctrl_del_event()
1810 mutex_unlock(&handle->chain->ctrl_mutex); in uvc_ctrl_del_event()
1820 /* --------------------------------------------------------------------------
1829 * When setting a control, the new value is stored in the control data field
1832 * value is loaded from the hardware before storing the new value in the data
1839 * cleared. When reverting controls, the control data field
1846 return mutex_lock_interruptible(&chain->ctrl_mutex) ? -ERESTARTSYS : 0; in uvc_ctrl_begin()
1862 for (i = 0; i < entity->ncontrols; ++i) { in uvc_ctrl_commit_entity()
1863 ctrl = &entity->controls[i]; in uvc_ctrl_commit_entity()
1864 if (!ctrl->initialized) in uvc_ctrl_commit_entity()
1868 * Reset the loaded flag for auto-update controls that were in uvc_ctrl_commit_entity()
1870 * uvc_ctrl_get from using the cached value, and for write-only in uvc_ctrl_commit_entity()
1874 if (ctrl->info.flags & UVC_CTRL_FLAG_AUTO_UPDATE || in uvc_ctrl_commit_entity()
1875 !(ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR)) in uvc_ctrl_commit_entity()
1876 ctrl->loaded = 0; in uvc_ctrl_commit_entity()
1878 if (!ctrl->dirty) in uvc_ctrl_commit_entity()
1882 ret = uvc_query_ctrl(dev, UVC_SET_CUR, ctrl->entity->id, in uvc_ctrl_commit_entity()
1883 dev->intfnum, ctrl->info.selector, in uvc_ctrl_commit_entity()
1885 ctrl->info.size); in uvc_ctrl_commit_entity()
1892 ctrl->info.size); in uvc_ctrl_commit_entity()
1894 ctrl->dirty = 0; in uvc_ctrl_commit_entity()
1903 ctrl->info.flags & UVC_CTRL_FLAG_ASYNCHRONOUS) in uvc_ctrl_commit_entity()
1914 struct uvc_control_mapping *mapping = NULL; in uvc_ctrl_find_ctrl_idx() local
1919 return ctrls->count; in uvc_ctrl_find_ctrl_idx()
1921 for (i = 0; i < ctrls->count; i++) { in uvc_ctrl_find_ctrl_idx()
1922 __uvc_find_control(entity, ctrls->controls[i].id, &mapping, in uvc_ctrl_find_ctrl_idx()
1928 return ctrls->count; in uvc_ctrl_find_ctrl_idx()
1934 struct uvc_video_chain *chain = handle->chain; in __uvc_ctrl_commit()
1940 list_for_each_entry(entity, &chain->entities, chain) { in __uvc_ctrl_commit()
1941 ret = uvc_ctrl_commit_entity(chain->dev, handle, entity, in __uvc_ctrl_commit()
1945 ctrls->error_idx = in __uvc_ctrl_commit()
1953 uvc_ctrl_send_events(handle, ctrls->controls, ctrls->count); in __uvc_ctrl_commit()
1955 mutex_unlock(&chain->ctrl_mutex); in __uvc_ctrl_commit()
1963 struct uvc_control_mapping *mapping; in uvc_ctrl_get() local
1965 if (__uvc_query_v4l2_class(chain, xctrl->id, 0) >= 0) in uvc_ctrl_get()
1966 return -EACCES; in uvc_ctrl_get()
1968 ctrl = uvc_find_control(chain, xctrl->id, &mapping); in uvc_ctrl_get()
1970 return -EINVAL; in uvc_ctrl_get()
1972 return __uvc_ctrl_get(chain, ctrl, mapping, &xctrl->value); in uvc_ctrl_get()
1978 struct uvc_video_chain *chain = handle->chain; in uvc_ctrl_set()
1980 struct uvc_control_mapping *mapping; in uvc_ctrl_set() local
1987 lockdep_assert_held(&chain->ctrl_mutex); in uvc_ctrl_set()
1989 if (__uvc_query_v4l2_class(chain, xctrl->id, 0) >= 0) in uvc_ctrl_set()
1990 return -EACCES; in uvc_ctrl_set()
1992 ctrl = uvc_find_control(chain, xctrl->id, &mapping); in uvc_ctrl_set()
1994 return -EINVAL; in uvc_ctrl_set()
1995 if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR)) in uvc_ctrl_set()
1996 return -EACCES; in uvc_ctrl_set()
1999 switch (mapping->v4l2_type) { in uvc_ctrl_set()
2001 if (!ctrl->cached) { in uvc_ctrl_set()
2007 min = mapping->get(mapping, UVC_GET_MIN, in uvc_ctrl_set()
2009 max = mapping->get(mapping, UVC_GET_MAX, in uvc_ctrl_set()
2011 step = mapping->get(mapping, UVC_GET_RES, in uvc_ctrl_set()
2016 xctrl->value = min + DIV_ROUND_CLOSEST((u32)(xctrl->value - min), in uvc_ctrl_set()
2018 if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED) in uvc_ctrl_set()
2019 xctrl->value = clamp(xctrl->value, min, max); in uvc_ctrl_set()
2021 xctrl->value = clamp_t(u32, xctrl->value, min, max); in uvc_ctrl_set()
2022 value = xctrl->value; in uvc_ctrl_set()
2026 if (!ctrl->cached) { in uvc_ctrl_set()
2032 xctrl->value &= uvc_get_ctrl_bitmap(ctrl, mapping); in uvc_ctrl_set()
2033 value = xctrl->value; in uvc_ctrl_set()
2037 xctrl->value = clamp(xctrl->value, 0, 1); in uvc_ctrl_set()
2038 value = xctrl->value; in uvc_ctrl_set()
2042 if (xctrl->value < (ffs(mapping->menu_mask) - 1) || in uvc_ctrl_set()
2043 xctrl->value > (fls(mapping->menu_mask) - 1)) in uvc_ctrl_set()
2044 return -ERANGE; in uvc_ctrl_set()
2046 if (!test_bit(xctrl->value, &mapping->menu_mask)) in uvc_ctrl_set()
2047 return -EINVAL; in uvc_ctrl_set()
2049 value = uvc_mapping_get_menu_value(mapping, xctrl->value); in uvc_ctrl_set()
2055 if (mapping->data_type == UVC_CTRL_DATA_TYPE_BITMASK) { in uvc_ctrl_set()
2056 if (!ctrl->cached) { in uvc_ctrl_set()
2062 if (!(uvc_get_ctrl_bitmap(ctrl, mapping) & value)) in uvc_ctrl_set()
2063 return -EINVAL; in uvc_ctrl_set()
2069 value = xctrl->value; in uvc_ctrl_set()
2074 * If the mapping doesn't span the whole UVC control, the current value in uvc_ctrl_set()
2075 * needs to be loaded from the device to perform the read-modify-write in uvc_ctrl_set()
2078 if ((ctrl->info.size * 8) != mapping->size) { in uvc_ctrl_set()
2085 if (!ctrl->dirty) { in uvc_ctrl_set()
2088 ctrl->info.size); in uvc_ctrl_set()
2091 mapping->set(mapping, value, in uvc_ctrl_set()
2094 ctrl->dirty = 1; in uvc_ctrl_set()
2095 ctrl->modified = 1; in uvc_ctrl_set()
2099 /* --------------------------------------------------------------------------
2110 u8 *data; in uvc_ctrl_get_flags() local
2113 data = kmalloc(1, GFP_KERNEL); in uvc_ctrl_get_flags()
2114 if (data == NULL) in uvc_ctrl_get_flags()
2115 return -ENOMEM; in uvc_ctrl_get_flags()
2117 if (ctrl->entity->get_info) in uvc_ctrl_get_flags()
2118 ret = ctrl->entity->get_info(dev, ctrl->entity, in uvc_ctrl_get_flags()
2119 ctrl->info.selector, data); in uvc_ctrl_get_flags()
2121 ret = uvc_query_ctrl(dev, UVC_GET_INFO, ctrl->entity->id, in uvc_ctrl_get_flags()
2122 dev->intfnum, info->selector, data, 1); in uvc_ctrl_get_flags()
2125 info->flags &= ~(UVC_CTRL_FLAG_GET_CUR | in uvc_ctrl_get_flags()
2130 info->flags |= (data[0] & UVC_CONTROL_CAP_GET ? in uvc_ctrl_get_flags()
2132 | (data[0] & UVC_CONTROL_CAP_SET ? in uvc_ctrl_get_flags()
2134 | (data[0] & UVC_CONTROL_CAP_AUTOUPDATE ? in uvc_ctrl_get_flags()
2136 | (data[0] & UVC_CONTROL_CAP_ASYNCHRONOUS ? in uvc_ctrl_get_flags()
2140 kfree(data); in uvc_ctrl_get_flags()
2172 if (!usb_match_one_id(dev->intf, &fixups[i].id)) in uvc_ctrl_fixup_xu_info()
2175 if (fixups[i].entity == ctrl->entity->id && in uvc_ctrl_fixup_xu_info()
2176 fixups[i].selector == info->selector) { in uvc_ctrl_fixup_xu_info()
2177 info->flags = fixups[i].flags; in uvc_ctrl_fixup_xu_info()
2189 u8 *data; in uvc_ctrl_fill_xu_info() local
2192 data = kmalloc(2, GFP_KERNEL); in uvc_ctrl_fill_xu_info()
2193 if (data == NULL) in uvc_ctrl_fill_xu_info()
2194 return -ENOMEM; in uvc_ctrl_fill_xu_info()
2196 memcpy(info->entity, ctrl->entity->guid, sizeof(info->entity)); in uvc_ctrl_fill_xu_info()
2197 info->index = ctrl->index; in uvc_ctrl_fill_xu_info()
2198 info->selector = ctrl->index + 1; in uvc_ctrl_fill_xu_info()
2201 ret = uvc_query_ctrl(dev, UVC_GET_LEN, ctrl->entity->id, dev->intfnum, in uvc_ctrl_fill_xu_info()
2202 info->selector, data, 2); in uvc_ctrl_fill_xu_info()
2206 info->entity, info->selector, ret); in uvc_ctrl_fill_xu_info()
2210 info->size = le16_to_cpup((__le16 *)data); in uvc_ctrl_fill_xu_info()
2212 info->flags = UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX in uvc_ctrl_fill_xu_info()
2219 info->entity, info->selector, ret); in uvc_ctrl_fill_xu_info()
2227 info->entity, info->selector, info->size, in uvc_ctrl_fill_xu_info()
2228 (info->flags & UVC_CTRL_FLAG_GET_CUR) ? 1 : 0, in uvc_ctrl_fill_xu_info()
2229 (info->flags & UVC_CTRL_FLAG_SET_CUR) ? 1 : 0, in uvc_ctrl_fill_xu_info()
2230 (info->flags & UVC_CTRL_FLAG_AUTO_UPDATE) ? 1 : 0); in uvc_ctrl_fill_xu_info()
2233 kfree(data); in uvc_ctrl_fill_xu_info()
2246 if (ctrl->initialized) in uvc_ctrl_init_xu_ctrl()
2257 info.entity, info.selector, dev->udev->devpath, in uvc_ctrl_init_xu_ctrl()
2258 ctrl->entity->id); in uvc_ctrl_init_xu_ctrl()
2272 u8 *data = NULL; in uvc_xu_ctrl_query() local
2277 list_for_each_entry(iter, &chain->entities, chain) { in uvc_xu_ctrl_query()
2279 iter->id == xqry->unit) { in uvc_xu_ctrl_query()
2286 uvc_dbg(chain->dev, CONTROL, "Extension unit %u not found\n", in uvc_xu_ctrl_query()
2287 xqry->unit); in uvc_xu_ctrl_query()
2288 return -ENOENT; in uvc_xu_ctrl_query()
2293 for (i = 0; i < entity->ncontrols; ++i) { in uvc_xu_ctrl_query()
2294 ctrl = &entity->controls[i]; in uvc_xu_ctrl_query()
2295 if (ctrl->index == xqry->selector - 1) { in uvc_xu_ctrl_query()
2302 uvc_dbg(chain->dev, CONTROL, "Control %pUl/%u not found\n", in uvc_xu_ctrl_query()
2303 entity->guid, xqry->selector); in uvc_xu_ctrl_query()
2304 return -ENOENT; in uvc_xu_ctrl_query()
2307 if (mutex_lock_interruptible(&chain->ctrl_mutex)) in uvc_xu_ctrl_query()
2308 return -ERESTARTSYS; in uvc_xu_ctrl_query()
2310 ret = uvc_ctrl_init_xu_ctrl(chain->dev, ctrl); in uvc_xu_ctrl_query()
2312 ret = -ENOENT; in uvc_xu_ctrl_query()
2318 size = ctrl->info.size; in uvc_xu_ctrl_query()
2320 switch (xqry->query) { in uvc_xu_ctrl_query()
2346 ret = -EINVAL; in uvc_xu_ctrl_query()
2350 if (size != xqry->size) { in uvc_xu_ctrl_query()
2351 ret = -ENOBUFS; in uvc_xu_ctrl_query()
2355 if (reqflags && !(ctrl->info.flags & reqflags)) { in uvc_xu_ctrl_query()
2356 ret = -EBADRQC; in uvc_xu_ctrl_query()
2360 data = kmalloc(size, GFP_KERNEL); in uvc_xu_ctrl_query()
2361 if (data == NULL) { in uvc_xu_ctrl_query()
2362 ret = -ENOMEM; in uvc_xu_ctrl_query()
2366 if (xqry->query == UVC_SET_CUR && in uvc_xu_ctrl_query()
2367 copy_from_user(data, xqry->data, size)) { in uvc_xu_ctrl_query()
2368 ret = -EFAULT; in uvc_xu_ctrl_query()
2372 ret = uvc_query_ctrl(chain->dev, xqry->query, xqry->unit, in uvc_xu_ctrl_query()
2373 chain->dev->intfnum, xqry->selector, data, size); in uvc_xu_ctrl_query()
2377 if (xqry->query != UVC_SET_CUR && in uvc_xu_ctrl_query()
2378 copy_to_user(xqry->data, data, size)) in uvc_xu_ctrl_query()
2379 ret = -EFAULT; in uvc_xu_ctrl_query()
2381 kfree(data); in uvc_xu_ctrl_query()
2382 mutex_unlock(&chain->ctrl_mutex); in uvc_xu_ctrl_query()
2386 /* --------------------------------------------------------------------------
2395 * - Don't restore modified controls that are back to their default value.
2396 * - Handle restore order (Auto-Exposure Mode should be restored before
2407 list_for_each_entry(entity, &dev->entities, list) { in uvc_ctrl_restore_values()
2409 for (i = 0; i < entity->ncontrols; ++i) { in uvc_ctrl_restore_values()
2410 ctrl = &entity->controls[i]; in uvc_ctrl_restore_values()
2412 if (!ctrl->initialized || !ctrl->modified || in uvc_ctrl_restore_values()
2413 (ctrl->info.flags & UVC_CTRL_FLAG_RESTORE) == 0) in uvc_ctrl_restore_values()
2415 dev_dbg(&dev->udev->dev, in uvc_ctrl_restore_values()
2417 ctrl->info.entity, ctrl->info.index, in uvc_ctrl_restore_values()
2418 ctrl->info.selector); in uvc_ctrl_restore_values()
2419 ctrl->dirty = 1; in uvc_ctrl_restore_values()
2430 /* --------------------------------------------------------------------------
2431 * Control and mapping handling
2440 ctrl->info = *info; in uvc_ctrl_add_info()
2441 INIT_LIST_HEAD(&ctrl->info.mappings); in uvc_ctrl_add_info()
2444 ctrl->uvc_data = kzalloc(ctrl->info.size * UVC_CTRL_DATA_LAST + 1, in uvc_ctrl_add_info()
2446 if (!ctrl->uvc_data) in uvc_ctrl_add_info()
2447 return -ENOMEM; in uvc_ctrl_add_info()
2449 ctrl->initialized = 1; in uvc_ctrl_add_info()
2452 ctrl->info.entity, ctrl->info.selector, dev->udev->devpath, in uvc_ctrl_add_info()
2453 ctrl->entity->id); in uvc_ctrl_add_info()
2459 * Add a control mapping to a given control.
2462 struct uvc_control *ctrl, const struct uvc_control_mapping *mapping) in __uvc_ctrl_add_mapping() argument
2469 * Most mappings come from static kernel data, and need to be duplicated. in __uvc_ctrl_add_mapping()
2473 map = kmemdup(mapping, sizeof(*mapping), GFP_KERNEL); in __uvc_ctrl_add_mapping()
2475 return -ENOMEM; in __uvc_ctrl_add_mapping()
2477 map->name = NULL; in __uvc_ctrl_add_mapping()
2478 map->menu_names = NULL; in __uvc_ctrl_add_mapping()
2479 map->menu_mapping = NULL; in __uvc_ctrl_add_mapping()
2482 if (mapping->name) { in __uvc_ctrl_add_mapping()
2483 map->name = kstrdup(mapping->name, GFP_KERNEL); in __uvc_ctrl_add_mapping()
2484 if (!map->name) in __uvc_ctrl_add_mapping()
2488 INIT_LIST_HEAD(&map->ev_subs); in __uvc_ctrl_add_mapping()
2490 if (mapping->menu_mapping && mapping->menu_mask) { in __uvc_ctrl_add_mapping()
2491 size = sizeof(mapping->menu_mapping[0]) in __uvc_ctrl_add_mapping()
2492 * fls(mapping->menu_mask); in __uvc_ctrl_add_mapping()
2493 map->menu_mapping = kmemdup(mapping->menu_mapping, size, in __uvc_ctrl_add_mapping()
2495 if (!map->menu_mapping) in __uvc_ctrl_add_mapping()
2498 if (mapping->menu_names && mapping->menu_mask) { in __uvc_ctrl_add_mapping()
2499 size = sizeof(mapping->menu_names[0]) in __uvc_ctrl_add_mapping()
2500 * fls(mapping->menu_mask); in __uvc_ctrl_add_mapping()
2501 map->menu_names = kmemdup(mapping->menu_names, size, in __uvc_ctrl_add_mapping()
2503 if (!map->menu_names) in __uvc_ctrl_add_mapping()
2507 if (map->get == NULL) in __uvc_ctrl_add_mapping()
2508 map->get = uvc_get_le_value; in __uvc_ctrl_add_mapping()
2509 if (map->set == NULL) in __uvc_ctrl_add_mapping()
2510 map->set = uvc_set_le_value; in __uvc_ctrl_add_mapping()
2514 V4L2_CTRL_ID2WHICH(map->id)) { in __uvc_ctrl_add_mapping()
2515 chain->ctrl_class_bitmap |= BIT(i); in __uvc_ctrl_add_mapping()
2520 list_add_tail(&map->list, &ctrl->info.mappings); in __uvc_ctrl_add_mapping()
2521 uvc_dbg(chain->dev, CONTROL, "Adding mapping '%s' to control %pUl/%u\n", in __uvc_ctrl_add_mapping()
2522 uvc_map_get_name(map), ctrl->info.entity, in __uvc_ctrl_add_mapping()
2523 ctrl->info.selector); in __uvc_ctrl_add_mapping()
2528 kfree(map->menu_names); in __uvc_ctrl_add_mapping()
2529 kfree(map->menu_mapping); in __uvc_ctrl_add_mapping()
2530 kfree(map->name); in __uvc_ctrl_add_mapping()
2532 return -ENOMEM; in __uvc_ctrl_add_mapping()
2536 const struct uvc_control_mapping *mapping) in uvc_ctrl_add_mapping() argument
2538 struct uvc_device *dev = chain->dev; in uvc_ctrl_add_mapping()
2545 if (mapping->id & ~V4L2_CTRL_ID_MASK) { in uvc_ctrl_add_mapping()
2547 "Can't add mapping '%s', control id 0x%08x is invalid\n", in uvc_ctrl_add_mapping()
2548 uvc_map_get_name(mapping), mapping->id); in uvc_ctrl_add_mapping()
2549 return -EINVAL; in uvc_ctrl_add_mapping()
2553 list_for_each_entry(entity, &chain->entities, chain) { in uvc_ctrl_add_mapping()
2557 !uvc_entity_match_guid(entity, mapping->entity)) in uvc_ctrl_add_mapping()
2560 for (i = 0; i < entity->ncontrols; ++i) { in uvc_ctrl_add_mapping()
2561 ctrl = &entity->controls[i]; in uvc_ctrl_add_mapping()
2562 if (ctrl->index == mapping->selector - 1) { in uvc_ctrl_add_mapping()
2572 return -ENOENT; in uvc_ctrl_add_mapping()
2574 if (mutex_lock_interruptible(&chain->ctrl_mutex)) in uvc_ctrl_add_mapping()
2575 return -ERESTARTSYS; in uvc_ctrl_add_mapping()
2580 ret = -ENOENT; in uvc_ctrl_add_mapping()
2584 /* Validate the user-provided bit-size and offset */ in uvc_ctrl_add_mapping()
2585 if (mapping->size > 32 || in uvc_ctrl_add_mapping()
2586 mapping->offset + mapping->size > ctrl->info.size * 8) { in uvc_ctrl_add_mapping()
2587 ret = -EINVAL; in uvc_ctrl_add_mapping()
2591 list_for_each_entry(map, &ctrl->info.mappings, list) { in uvc_ctrl_add_mapping()
2592 if (mapping->id == map->id) { in uvc_ctrl_add_mapping()
2594 "Can't add mapping '%s', control id 0x%08x already exists\n", in uvc_ctrl_add_mapping()
2595 uvc_map_get_name(mapping), mapping->id); in uvc_ctrl_add_mapping()
2596 ret = -EEXIST; in uvc_ctrl_add_mapping()
2602 if (atomic_inc_return(&dev->nmappings) > UVC_MAX_CONTROL_MAPPINGS) { in uvc_ctrl_add_mapping()
2603 atomic_dec(&dev->nmappings); in uvc_ctrl_add_mapping()
2605 "Can't add mapping '%s', maximum mappings count (%u) exceeded\n", in uvc_ctrl_add_mapping()
2606 uvc_map_get_name(mapping), UVC_MAX_CONTROL_MAPPINGS); in uvc_ctrl_add_mapping()
2607 ret = -ENOMEM; in uvc_ctrl_add_mapping()
2611 ret = __uvc_ctrl_add_mapping(chain, ctrl, mapping); in uvc_ctrl_add_mapping()
2613 atomic_dec(&dev->nmappings); in uvc_ctrl_add_mapping()
2616 mutex_unlock(&chain->ctrl_mutex); in uvc_ctrl_add_mapping()
2652 controls = entity->processing.bmControls; in uvc_ctrl_prune_entity()
2653 size = entity->processing.bControlSize; in uvc_ctrl_prune_entity()
2659 controls = entity->camera.bmControls; in uvc_ctrl_prune_entity()
2660 size = entity->camera.bControlSize; in uvc_ctrl_prune_entity()
2668 if (!usb_match_one_id(dev->intf, &blacklist[i].id)) in uvc_ctrl_prune_entity()
2677 entity->id, blacklist[i].index); in uvc_ctrl_prune_entity()
2698 if (UVC_ENTITY_TYPE(ctrl->entity) == UVC_VC_EXTENSION_UNIT) in uvc_ctrl_init_ctrl()
2704 if (uvc_entity_match_guid(ctrl->entity, info->entity) && in uvc_ctrl_init_ctrl()
2705 ctrl->index == info->index) { in uvc_ctrl_init_ctrl()
2706 uvc_ctrl_add_info(chain->dev, ctrl, info); in uvc_ctrl_init_ctrl()
2713 uvc_ctrl_get_flags(chain->dev, ctrl, &ctrl->info); in uvc_ctrl_init_ctrl()
2718 if (!ctrl->initialized) in uvc_ctrl_init_ctrl()
2723 const struct uvc_control_mapping *mapping = &uvc_ctrl_mappings[i]; in uvc_ctrl_init_ctrl() local
2725 if (!uvc_entity_match_guid(ctrl->entity, mapping->entity) || in uvc_ctrl_init_ctrl()
2726 ctrl->info.selector != mapping->selector) in uvc_ctrl_init_ctrl()
2729 /* Let the device provide a custom mapping. */ in uvc_ctrl_init_ctrl()
2730 if (mapping->filter_mapping) { in uvc_ctrl_init_ctrl()
2731 mapping = mapping->filter_mapping(chain, ctrl); in uvc_ctrl_init_ctrl()
2732 if (!mapping) in uvc_ctrl_init_ctrl()
2736 __uvc_ctrl_add_mapping(chain, ctrl, mapping); in uvc_ctrl_init_ctrl()
2749 list_for_each_entry(entity, &chain->entities, chain) { in uvc_ctrl_init_chain()
2755 bmControls = entity->extension.bmControls; in uvc_ctrl_init_chain()
2756 bControlSize = entity->extension.bControlSize; in uvc_ctrl_init_chain()
2758 bmControls = entity->processing.bmControls; in uvc_ctrl_init_chain()
2759 bControlSize = entity->processing.bControlSize; in uvc_ctrl_init_chain()
2761 bmControls = entity->camera.bmControls; in uvc_ctrl_init_chain()
2762 bControlSize = entity->camera.bControlSize; in uvc_ctrl_init_chain()
2764 bmControls = entity->gpio.bmControls; in uvc_ctrl_init_chain()
2765 bControlSize = entity->gpio.bControlSize; in uvc_ctrl_init_chain()
2769 uvc_ctrl_prune_entity(chain->dev, entity); in uvc_ctrl_init_chain()
2776 entity->controls = kcalloc(ncontrols, sizeof(*ctrl), in uvc_ctrl_init_chain()
2778 if (entity->controls == NULL) in uvc_ctrl_init_chain()
2779 return -ENOMEM; in uvc_ctrl_init_chain()
2780 entity->ncontrols = ncontrols; in uvc_ctrl_init_chain()
2783 ctrl = entity->controls; in uvc_ctrl_init_chain()
2788 ctrl->entity = entity; in uvc_ctrl_init_chain()
2789 ctrl->index = i; in uvc_ctrl_init_chain()
2804 INIT_WORK(&dev->async_ctrl.work, uvc_ctrl_status_event_work); in uvc_ctrl_init_device()
2806 list_for_each_entry(chain, &dev->chains, list) { in uvc_ctrl_init_device()
2819 guard(mutex)(&handle->chain->ctrl_mutex); in uvc_ctrl_cleanup_fh()
2821 if (!handle->pending_async_ctrls) in uvc_ctrl_cleanup_fh()
2824 list_for_each_entry(entity, &handle->chain->dev->entities, list) { in uvc_ctrl_cleanup_fh()
2825 for (unsigned int i = 0; i < entity->ncontrols; ++i) { in uvc_ctrl_cleanup_fh()
2826 if (entity->controls[i].handle != handle) in uvc_ctrl_cleanup_fh()
2828 uvc_ctrl_set_handle(handle, &entity->controls[i], NULL); in uvc_ctrl_cleanup_fh()
2832 WARN_ON(handle->pending_async_ctrls); in uvc_ctrl_cleanup_fh()
2841 struct uvc_control_mapping *mapping, *nm; in uvc_ctrl_cleanup_mappings() local
2843 list_for_each_entry_safe(mapping, nm, &ctrl->info.mappings, list) { in uvc_ctrl_cleanup_mappings()
2844 list_del(&mapping->list); in uvc_ctrl_cleanup_mappings()
2845 kfree(mapping->menu_names); in uvc_ctrl_cleanup_mappings()
2846 kfree(mapping->menu_mapping); in uvc_ctrl_cleanup_mappings()
2847 kfree(mapping->name); in uvc_ctrl_cleanup_mappings()
2848 kfree(mapping); in uvc_ctrl_cleanup_mappings()
2858 if (dev->async_ctrl.work.func) in uvc_ctrl_cleanup_device()
2859 cancel_work_sync(&dev->async_ctrl.work); in uvc_ctrl_cleanup_device()
2862 list_for_each_entry(entity, &dev->entities, list) { in uvc_ctrl_cleanup_device()
2863 for (i = 0; i < entity->ncontrols; ++i) { in uvc_ctrl_cleanup_device()
2864 struct uvc_control *ctrl = &entity->controls[i]; in uvc_ctrl_cleanup_device()
2866 if (!ctrl->initialized) in uvc_ctrl_cleanup_device()
2870 kfree(ctrl->uvc_data); in uvc_ctrl_cleanup_device()
2873 kfree(entity->controls); in uvc_ctrl_cleanup_device()