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
20 #include <media/v4l2-ctrls.h>
32 /* ------------------------------------------------------------------------
365 static s32 uvc_ctrl_get_zoom(struct uvc_control_mapping *mapping, in uvc_ctrl_get_zoom() argument
366 u8 query, const u8 *data) in uvc_ctrl_get_zoom() argument
368 s8 zoom = (s8)data[0]; in uvc_ctrl_get_zoom()
372 return (zoom == 0) ? 0 : (zoom > 0 ? data[2] : -data[2]); in uvc_ctrl_get_zoom()
379 return data[2]; in uvc_ctrl_get_zoom()
383 static void uvc_ctrl_set_zoom(struct uvc_control_mapping *mapping, in uvc_ctrl_set_zoom() argument
384 s32 value, u8 *data) in uvc_ctrl_set_zoom() argument
386 data[0] = value == 0 ? 0 : (value > 0) ? 1 : 0xff; in uvc_ctrl_set_zoom()
387 data[2] = min((int)abs(value), 0xff); in uvc_ctrl_set_zoom()
390 static s32 uvc_ctrl_get_rel_speed(struct uvc_control_mapping *mapping, in uvc_ctrl_get_rel_speed() argument
391 u8 query, const u8 *data) in uvc_ctrl_get_rel_speed() argument
393 unsigned int first = mapping->offset / 8; in uvc_ctrl_get_rel_speed()
394 s8 rel = (s8)data[first]; in uvc_ctrl_get_rel_speed()
398 return (rel == 0) ? 0 : (rel > 0 ? data[first+1] in uvc_ctrl_get_rel_speed()
399 : -data[first+1]); in uvc_ctrl_get_rel_speed()
401 return -data[first+1]; in uvc_ctrl_get_rel_speed()
406 return data[first+1]; in uvc_ctrl_get_rel_speed()
410 static void uvc_ctrl_set_rel_speed(struct uvc_control_mapping *mapping, in uvc_ctrl_set_rel_speed() argument
411 s32 value, u8 *data) in uvc_ctrl_set_rel_speed() argument
413 unsigned int first = mapping->offset / 8; in uvc_ctrl_set_rel_speed()
415 data[first] = value == 0 ? 0 : (value > 0) ? 1 : 0xff; in uvc_ctrl_set_rel_speed()
416 data[first+1] = min_t(int, abs(value), 0xff); in uvc_ctrl_set_rel_speed()
740 /* ------------------------------------------------------------------------
746 return ctrl->uvc_data + id * ctrl->info.size; in uvc_ctrl_data()
749 static inline int uvc_test_bit(const u8 *data, int bit) in uvc_test_bit() argument
751 return (data[bit >> 3] >> (bit & 7)) & 1; in uvc_test_bit()
754 static inline void uvc_clear_bit(u8 *data, int bit) in uvc_clear_bit() argument
756 data[bit >> 3] &= ~(1 << (bit & 7)); in uvc_clear_bit()
759 /* Extract the bit string specified by mapping->offset and mapping->size
760 * from the little-endian data stored at 'data' and return the result as
761 * a signed 32bit integer. Sign extension will be performed if the mapping
762 * references a signed data type.
764 static s32 uvc_get_le_value(struct uvc_control_mapping *mapping, in uvc_get_le_value() argument
765 u8 query, const u8 *data) in uvc_get_le_value() argument
767 int bits = mapping->size; in uvc_get_le_value()
768 int offset = mapping->offset; in uvc_get_le_value()
772 data += offset / 8; in uvc_get_le_value()
774 mask = ((1LL << bits) - 1) << offset; in uvc_get_le_value()
776 for (; bits > 0; data++) { in uvc_get_le_value()
777 u8 byte = *data & mask; in uvc_get_le_value()
778 value |= offset > 0 ? (byte >> offset) : (byte << (-offset)); in uvc_get_le_value()
779 bits -= 8 - (offset > 0 ? offset : 0); in uvc_get_le_value()
780 offset -= 8; in uvc_get_le_value()
781 mask = (1 << bits) - 1; in uvc_get_le_value()
784 /* Sign-extend the value if needed. */ in uvc_get_le_value()
785 if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED) in uvc_get_le_value()
786 value |= -(value & (1 << (mapping->size - 1))); in uvc_get_le_value()
791 /* Set the bit string specified by mapping->offset and mapping->size
792 * in the little-endian data stored at 'data' to the value 'value'.
794 static void uvc_set_le_value(struct uvc_control_mapping *mapping, in uvc_set_le_value() argument
795 s32 value, u8 *data) in uvc_set_le_value() argument
797 int bits = mapping->size; in uvc_set_le_value()
798 int offset = mapping->offset; in uvc_set_le_value()
803 * triggered. UVC devices however want to see a 1 written -> override in uvc_set_le_value()
806 if (mapping->v4l2_type == V4L2_CTRL_TYPE_BUTTON) in uvc_set_le_value()
807 value = -1; in uvc_set_le_value()
809 data += offset / 8; in uvc_set_le_value()
812 for (; bits > 0; data++) { in uvc_set_le_value()
813 mask = ((1LL << bits) - 1) << offset; in uvc_set_le_value()
814 *data = (*data & ~mask) | ((value << offset) & mask); in uvc_set_le_value()
816 bits -= 8 - offset; in uvc_set_le_value()
821 /* ------------------------------------------------------------------------
844 return memcmp(entity->extension.guidExtensionCode, in uvc_entity_match_guid()
852 /* ------------------------------------------------------------------------
857 struct uvc_control_mapping **mapping, struct uvc_control **control, in __uvc_find_control() argument
867 for (i = 0; i < entity->ncontrols; ++i) { in __uvc_find_control()
868 ctrl = &entity->controls[i]; in __uvc_find_control()
869 if (!ctrl->initialized) in __uvc_find_control()
872 list_for_each_entry(map, &ctrl->info.mappings, list) { in __uvc_find_control()
873 if ((map->id == v4l2_id) && !next) { in __uvc_find_control()
875 *mapping = map; in __uvc_find_control()
879 if ((*mapping == NULL || (*mapping)->id > map->id) && in __uvc_find_control()
880 (map->id > v4l2_id) && next) { in __uvc_find_control()
882 *mapping = map; in __uvc_find_control()
889 u32 v4l2_id, struct uvc_control_mapping **mapping) in uvc_find_control() argument
895 *mapping = NULL; in uvc_find_control()
901 list_for_each_entry(entity, &chain->entities, chain) { in uvc_find_control()
902 __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next); in uvc_find_control()
919 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_DEF) { in uvc_ctrl_populate_cache()
920 ret = uvc_query_ctrl(chain->dev, UVC_GET_DEF, ctrl->entity->id, in uvc_ctrl_populate_cache()
921 chain->dev->intfnum, ctrl->info.selector, in uvc_ctrl_populate_cache()
923 ctrl->info.size); in uvc_ctrl_populate_cache()
928 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MIN) { in uvc_ctrl_populate_cache()
929 ret = uvc_query_ctrl(chain->dev, UVC_GET_MIN, ctrl->entity->id, in uvc_ctrl_populate_cache()
930 chain->dev->intfnum, ctrl->info.selector, in uvc_ctrl_populate_cache()
932 ctrl->info.size); in uvc_ctrl_populate_cache()
936 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX) { in uvc_ctrl_populate_cache()
937 ret = uvc_query_ctrl(chain->dev, UVC_GET_MAX, ctrl->entity->id, in uvc_ctrl_populate_cache()
938 chain->dev->intfnum, ctrl->info.selector, in uvc_ctrl_populate_cache()
940 ctrl->info.size); in uvc_ctrl_populate_cache()
944 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) { in uvc_ctrl_populate_cache()
945 ret = uvc_query_ctrl(chain->dev, UVC_GET_RES, ctrl->entity->id, in uvc_ctrl_populate_cache()
946 chain->dev->intfnum, ctrl->info.selector, in uvc_ctrl_populate_cache()
948 ctrl->info.size); in uvc_ctrl_populate_cache()
950 if (UVC_ENTITY_TYPE(ctrl->entity) != in uvc_ctrl_populate_cache()
958 uvc_warn_once(chain->dev, UVC_WARN_XU_GET_RES, in uvc_ctrl_populate_cache()
959 "UVC non compliance - GET_RES failed on " in uvc_ctrl_populate_cache()
962 ctrl->info.size); in uvc_ctrl_populate_cache()
966 ctrl->cached = 1; in uvc_ctrl_populate_cache()
970 static s32 __uvc_ctrl_get_value(struct uvc_control_mapping *mapping, in __uvc_ctrl_get_value() argument
971 const u8 *data) in __uvc_ctrl_get_value() argument
973 s32 value = mapping->get(mapping, UVC_GET_CUR, data); in __uvc_ctrl_get_value()
975 if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) { in __uvc_ctrl_get_value()
976 const struct uvc_menu_info *menu = mapping->menu_info; in __uvc_ctrl_get_value()
979 for (i = 0; i < mapping->menu_count; ++i, ++menu) { in __uvc_ctrl_get_value()
980 if (menu->value == value) { in __uvc_ctrl_get_value()
991 struct uvc_control *ctrl, struct uvc_control_mapping *mapping, in __uvc_ctrl_get() argument
996 if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) in __uvc_ctrl_get()
997 return -EACCES; in __uvc_ctrl_get()
999 if (!ctrl->loaded) { in __uvc_ctrl_get()
1000 ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, ctrl->entity->id, in __uvc_ctrl_get()
1001 chain->dev->intfnum, ctrl->info.selector, in __uvc_ctrl_get()
1003 ctrl->info.size); in __uvc_ctrl_get()
1007 ctrl->loaded = 1; in __uvc_ctrl_get()
1010 *value = __uvc_ctrl_get_value(mapping, in __uvc_ctrl_get()
1018 struct uvc_control_mapping *mapping, in __uvc_query_v4l2_ctrl() argument
1027 v4l2_ctrl->id = mapping->id; in __uvc_query_v4l2_ctrl()
1028 v4l2_ctrl->type = mapping->v4l2_type; in __uvc_query_v4l2_ctrl()
1029 strscpy(v4l2_ctrl->name, mapping->name, sizeof(v4l2_ctrl->name)); in __uvc_query_v4l2_ctrl()
1030 v4l2_ctrl->flags = 0; in __uvc_query_v4l2_ctrl()
1032 if (!(ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR)) in __uvc_query_v4l2_ctrl()
1033 v4l2_ctrl->flags |= V4L2_CTRL_FLAG_WRITE_ONLY; in __uvc_query_v4l2_ctrl()
1034 if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR)) in __uvc_query_v4l2_ctrl()
1035 v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; in __uvc_query_v4l2_ctrl()
1037 if (mapping->master_id) in __uvc_query_v4l2_ctrl()
1038 __uvc_find_control(ctrl->entity, mapping->master_id, in __uvc_query_v4l2_ctrl()
1040 if (master_ctrl && (master_ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR)) { in __uvc_query_v4l2_ctrl()
1046 if (val != mapping->master_manual) in __uvc_query_v4l2_ctrl()
1047 v4l2_ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; in __uvc_query_v4l2_ctrl()
1050 if (!ctrl->cached) { in __uvc_query_v4l2_ctrl()
1056 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_DEF) { in __uvc_query_v4l2_ctrl()
1057 v4l2_ctrl->default_value = mapping->get(mapping, UVC_GET_DEF, in __uvc_query_v4l2_ctrl()
1061 switch (mapping->v4l2_type) { in __uvc_query_v4l2_ctrl()
1063 v4l2_ctrl->minimum = 0; in __uvc_query_v4l2_ctrl()
1064 v4l2_ctrl->maximum = mapping->menu_count - 1; in __uvc_query_v4l2_ctrl()
1065 v4l2_ctrl->step = 1; in __uvc_query_v4l2_ctrl()
1067 menu = mapping->menu_info; in __uvc_query_v4l2_ctrl()
1068 for (i = 0; i < mapping->menu_count; ++i, ++menu) { in __uvc_query_v4l2_ctrl()
1069 if (menu->value == v4l2_ctrl->default_value) { in __uvc_query_v4l2_ctrl()
1070 v4l2_ctrl->default_value = i; in __uvc_query_v4l2_ctrl()
1078 v4l2_ctrl->minimum = 0; in __uvc_query_v4l2_ctrl()
1079 v4l2_ctrl->maximum = 1; in __uvc_query_v4l2_ctrl()
1080 v4l2_ctrl->step = 1; in __uvc_query_v4l2_ctrl()
1084 v4l2_ctrl->minimum = 0; in __uvc_query_v4l2_ctrl()
1085 v4l2_ctrl->maximum = 0; in __uvc_query_v4l2_ctrl()
1086 v4l2_ctrl->step = 0; in __uvc_query_v4l2_ctrl()
1093 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MIN) in __uvc_query_v4l2_ctrl()
1094 v4l2_ctrl->minimum = mapping->get(mapping, UVC_GET_MIN, in __uvc_query_v4l2_ctrl()
1097 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX) in __uvc_query_v4l2_ctrl()
1098 v4l2_ctrl->maximum = mapping->get(mapping, UVC_GET_MAX, in __uvc_query_v4l2_ctrl()
1101 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) in __uvc_query_v4l2_ctrl()
1102 v4l2_ctrl->step = mapping->get(mapping, UVC_GET_RES, in __uvc_query_v4l2_ctrl()
1112 struct uvc_control_mapping *mapping; in uvc_query_v4l2_ctrl() local
1115 ret = mutex_lock_interruptible(&chain->ctrl_mutex); in uvc_query_v4l2_ctrl()
1117 return -ERESTARTSYS; in uvc_query_v4l2_ctrl()
1119 ctrl = uvc_find_control(chain, v4l2_ctrl->id, &mapping); in uvc_query_v4l2_ctrl()
1121 ret = -EINVAL; in uvc_query_v4l2_ctrl()
1125 ret = __uvc_query_v4l2_ctrl(chain, ctrl, mapping, v4l2_ctrl); in uvc_query_v4l2_ctrl()
1127 mutex_unlock(&chain->ctrl_mutex); in uvc_query_v4l2_ctrl()
1132 * Mapping V4L2 controls to UVC controls can be straightforward if done well.
1144 struct uvc_control_mapping *mapping; in uvc_query_v4l2_menu() local
1146 u32 index = query_menu->index; in uvc_query_v4l2_menu()
1147 u32 id = query_menu->id; in uvc_query_v4l2_menu()
1151 query_menu->id = id; in uvc_query_v4l2_menu()
1152 query_menu->index = index; in uvc_query_v4l2_menu()
1154 ret = mutex_lock_interruptible(&chain->ctrl_mutex); in uvc_query_v4l2_menu()
1156 return -ERESTARTSYS; in uvc_query_v4l2_menu()
1158 ctrl = uvc_find_control(chain, query_menu->id, &mapping); in uvc_query_v4l2_menu()
1159 if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) { in uvc_query_v4l2_menu()
1160 ret = -EINVAL; in uvc_query_v4l2_menu()
1164 if (query_menu->index >= mapping->menu_count) { in uvc_query_v4l2_menu()
1165 ret = -EINVAL; in uvc_query_v4l2_menu()
1169 menu_info = &mapping->menu_info[query_menu->index]; in uvc_query_v4l2_menu()
1171 if (mapping->data_type == UVC_CTRL_DATA_TYPE_BITMASK && in uvc_query_v4l2_menu()
1172 (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)) { in uvc_query_v4l2_menu()
1175 if (!ctrl->cached) { in uvc_query_v4l2_menu()
1181 bitmap = mapping->get(mapping, UVC_GET_RES, in uvc_query_v4l2_menu()
1183 if (!(bitmap & menu_info->value)) { in uvc_query_v4l2_menu()
1184 ret = -EINVAL; in uvc_query_v4l2_menu()
1189 strscpy(query_menu->name, menu_info->name, sizeof(query_menu->name)); in uvc_query_v4l2_menu()
1192 mutex_unlock(&chain->ctrl_mutex); in uvc_query_v4l2_menu()
1196 /* --------------------------------------------------------------------------
1203 struct uvc_control_mapping *mapping, in uvc_ctrl_fill_event() argument
1208 __uvc_query_v4l2_ctrl(chain, ctrl, mapping, &v4l2_ctrl); in uvc_ctrl_fill_event()
1211 ev->type = V4L2_EVENT_CTRL; in uvc_ctrl_fill_event()
1212 ev->id = v4l2_ctrl.id; in uvc_ctrl_fill_event()
1213 ev->u.ctrl.value = value; in uvc_ctrl_fill_event()
1214 ev->u.ctrl.changes = changes; in uvc_ctrl_fill_event()
1215 ev->u.ctrl.type = v4l2_ctrl.type; in uvc_ctrl_fill_event()
1216 ev->u.ctrl.flags = v4l2_ctrl.flags; in uvc_ctrl_fill_event()
1217 ev->u.ctrl.minimum = v4l2_ctrl.minimum; in uvc_ctrl_fill_event()
1218 ev->u.ctrl.maximum = v4l2_ctrl.maximum; in uvc_ctrl_fill_event()
1219 ev->u.ctrl.step = v4l2_ctrl.step; in uvc_ctrl_fill_event()
1220 ev->u.ctrl.default_value = v4l2_ctrl.default_value; in uvc_ctrl_fill_event()
1227 * @handle can be NULL for asynchronous events related to auto-update controls,
1232 struct uvc_control_mapping *mapping, s32 value, u32 changes) in uvc_ctrl_send_event() argument
1234 struct v4l2_fh *originator = handle ? &handle->vfh : NULL; in uvc_ctrl_send_event()
1238 if (list_empty(&mapping->ev_subs)) in uvc_ctrl_send_event()
1241 uvc_ctrl_fill_event(chain, &ev, ctrl, mapping, value, changes); in uvc_ctrl_send_event()
1243 list_for_each_entry(sev, &mapping->ev_subs, node) { in uvc_ctrl_send_event()
1244 if (sev->fh != originator || in uvc_ctrl_send_event()
1245 (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK) || in uvc_ctrl_send_event()
1247 v4l2_event_queue_fh(sev->fh, &ev); in uvc_ctrl_send_event()
1254 * generated the event and may be NULL for auto-update events.
1259 struct uvc_control_mapping *mapping = NULL; in uvc_ctrl_send_slave_event() local
1264 __uvc_find_control(master->entity, slave_id, &mapping, &ctrl, 0); in uvc_ctrl_send_slave_event()
1268 if (__uvc_ctrl_get(chain, ctrl, mapping, &val) == 0) in uvc_ctrl_send_slave_event()
1271 uvc_ctrl_send_event(chain, handle, ctrl, mapping, val, changes); in uvc_ctrl_send_slave_event()
1278 struct uvc_ctrl_work *w = &dev->async_ctrl; in uvc_ctrl_status_event_work()
1279 struct uvc_video_chain *chain = w->chain; in uvc_ctrl_status_event_work()
1280 struct uvc_control_mapping *mapping; in uvc_ctrl_status_event_work() local
1281 struct uvc_control *ctrl = w->ctrl; in uvc_ctrl_status_event_work()
1286 mutex_lock(&chain->ctrl_mutex); in uvc_ctrl_status_event_work()
1288 handle = ctrl->handle; in uvc_ctrl_status_event_work()
1289 ctrl->handle = NULL; in uvc_ctrl_status_event_work()
1291 list_for_each_entry(mapping, &ctrl->info.mappings, list) { in uvc_ctrl_status_event_work()
1292 s32 value = __uvc_ctrl_get_value(mapping, w->data); in uvc_ctrl_status_event_work()
1295 * handle may be NULL here if the device sends auto-update in uvc_ctrl_status_event_work()
1298 for (i = 0; i < ARRAY_SIZE(mapping->slave_ids); ++i) { in uvc_ctrl_status_event_work()
1299 if (!mapping->slave_ids[i]) in uvc_ctrl_status_event_work()
1303 mapping->slave_ids[i]); in uvc_ctrl_status_event_work()
1306 uvc_ctrl_send_event(chain, handle, ctrl, mapping, value, in uvc_ctrl_status_event_work()
1310 mutex_unlock(&chain->ctrl_mutex); in uvc_ctrl_status_event_work()
1313 w->urb->interval = dev->int_ep->desc.bInterval; in uvc_ctrl_status_event_work()
1314 ret = usb_submit_urb(w->urb, GFP_KERNEL); in uvc_ctrl_status_event_work()
1321 struct uvc_control *ctrl, const u8 *data) in uvc_ctrl_status_event() argument
1323 struct uvc_device *dev = chain->dev; in uvc_ctrl_status_event()
1324 struct uvc_ctrl_work *w = &dev->async_ctrl; in uvc_ctrl_status_event()
1326 if (list_empty(&ctrl->info.mappings)) { in uvc_ctrl_status_event()
1327 ctrl->handle = NULL; in uvc_ctrl_status_event()
1331 w->data = data; in uvc_ctrl_status_event()
1332 w->urb = urb; in uvc_ctrl_status_event()
1333 w->chain = chain; in uvc_ctrl_status_event()
1334 w->ctrl = ctrl; in uvc_ctrl_status_event()
1336 schedule_work(&w->work); in uvc_ctrl_status_event()
1357 struct uvc_control_mapping *mapping; in uvc_ctrl_send_events() local
1364 ctrl = uvc_find_control(handle->chain, xctrls[i].id, &mapping); in uvc_ctrl_send_events()
1366 if (ctrl->info.flags & UVC_CTRL_FLAG_ASYNCHRONOUS) in uvc_ctrl_send_events()
1370 for (j = 0; j < ARRAY_SIZE(mapping->slave_ids); ++j) { in uvc_ctrl_send_events()
1371 u32 slave_id = mapping->slave_ids[j]; in uvc_ctrl_send_events()
1384 uvc_ctrl_send_slave_event(handle->chain, handle, ctrl, in uvc_ctrl_send_events()
1392 if (mapping->master_id && in uvc_ctrl_send_events()
1394 mapping->master_id)) in uvc_ctrl_send_events()
1397 uvc_ctrl_send_event(handle->chain, handle, ctrl, mapping, in uvc_ctrl_send_events()
1404 struct uvc_fh *handle = container_of(sev->fh, struct uvc_fh, vfh); in uvc_ctrl_add_event()
1405 struct uvc_control_mapping *mapping; in uvc_ctrl_add_event() local
1409 ret = mutex_lock_interruptible(&handle->chain->ctrl_mutex); in uvc_ctrl_add_event()
1411 return -ERESTARTSYS; in uvc_ctrl_add_event()
1413 ctrl = uvc_find_control(handle->chain, sev->id, &mapping); in uvc_ctrl_add_event()
1415 ret = -EINVAL; in uvc_ctrl_add_event()
1419 list_add_tail(&sev->node, &mapping->ev_subs); in uvc_ctrl_add_event()
1420 if (sev->flags & V4L2_EVENT_SUB_FL_SEND_INITIAL) { in uvc_ctrl_add_event()
1425 if (__uvc_ctrl_get(handle->chain, ctrl, mapping, &val) == 0) in uvc_ctrl_add_event()
1428 uvc_ctrl_fill_event(handle->chain, &ev, ctrl, mapping, val, in uvc_ctrl_add_event()
1432 sev->elems = elems; in uvc_ctrl_add_event()
1433 v4l2_event_queue_fh(sev->fh, &ev); in uvc_ctrl_add_event()
1437 mutex_unlock(&handle->chain->ctrl_mutex); in uvc_ctrl_add_event()
1443 struct uvc_fh *handle = container_of(sev->fh, struct uvc_fh, vfh); in uvc_ctrl_del_event()
1445 mutex_lock(&handle->chain->ctrl_mutex); in uvc_ctrl_del_event()
1446 list_del(&sev->node); in uvc_ctrl_del_event()
1447 mutex_unlock(&handle->chain->ctrl_mutex); in uvc_ctrl_del_event()
1457 /* --------------------------------------------------------------------------
1466 * When setting a control, the new value is stored in the control data field
1469 * value is loaded from the hardware before storing the new value in the data
1476 * cleared. When reverting controls, the control data field
1483 return mutex_lock_interruptible(&chain->ctrl_mutex) ? -ERESTARTSYS : 0; in uvc_ctrl_begin()
1496 for (i = 0; i < entity->ncontrols; ++i) { in uvc_ctrl_commit_entity()
1497 ctrl = &entity->controls[i]; in uvc_ctrl_commit_entity()
1498 if (!ctrl->initialized) in uvc_ctrl_commit_entity()
1501 /* Reset the loaded flag for auto-update controls that were in uvc_ctrl_commit_entity()
1503 * uvc_ctrl_get from using the cached value, and for write-only in uvc_ctrl_commit_entity()
1507 if (ctrl->info.flags & UVC_CTRL_FLAG_AUTO_UPDATE || in uvc_ctrl_commit_entity()
1508 !(ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR)) in uvc_ctrl_commit_entity()
1509 ctrl->loaded = 0; in uvc_ctrl_commit_entity()
1511 if (!ctrl->dirty) in uvc_ctrl_commit_entity()
1515 ret = uvc_query_ctrl(dev, UVC_SET_CUR, ctrl->entity->id, in uvc_ctrl_commit_entity()
1516 dev->intfnum, ctrl->info.selector, in uvc_ctrl_commit_entity()
1518 ctrl->info.size); in uvc_ctrl_commit_entity()
1525 ctrl->info.size); in uvc_ctrl_commit_entity()
1527 ctrl->dirty = 0; in uvc_ctrl_commit_entity()
1540 struct uvc_video_chain *chain = handle->chain; in __uvc_ctrl_commit()
1545 list_for_each_entry(entity, &chain->entities, chain) { in __uvc_ctrl_commit()
1546 ret = uvc_ctrl_commit_entity(chain->dev, entity, rollback); in __uvc_ctrl_commit()
1554 mutex_unlock(&chain->ctrl_mutex); in __uvc_ctrl_commit()
1562 struct uvc_control_mapping *mapping; in uvc_ctrl_get() local
1564 ctrl = uvc_find_control(chain, xctrl->id, &mapping); in uvc_ctrl_get()
1566 return -EINVAL; in uvc_ctrl_get()
1568 return __uvc_ctrl_get(chain, ctrl, mapping, &xctrl->value); in uvc_ctrl_get()
1574 struct uvc_video_chain *chain = handle->chain; in uvc_ctrl_set()
1576 struct uvc_control_mapping *mapping; in uvc_ctrl_set() local
1583 ctrl = uvc_find_control(chain, xctrl->id, &mapping); in uvc_ctrl_set()
1585 return -EINVAL; in uvc_ctrl_set()
1586 if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR)) in uvc_ctrl_set()
1587 return -EACCES; in uvc_ctrl_set()
1590 switch (mapping->v4l2_type) { in uvc_ctrl_set()
1592 if (!ctrl->cached) { in uvc_ctrl_set()
1598 min = mapping->get(mapping, UVC_GET_MIN, in uvc_ctrl_set()
1600 max = mapping->get(mapping, UVC_GET_MAX, in uvc_ctrl_set()
1602 step = mapping->get(mapping, UVC_GET_RES, in uvc_ctrl_set()
1607 xctrl->value = min + ((u32)(xctrl->value - min) + step / 2) in uvc_ctrl_set()
1609 if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED) in uvc_ctrl_set()
1610 xctrl->value = clamp(xctrl->value, min, max); in uvc_ctrl_set()
1612 xctrl->value = clamp_t(u32, xctrl->value, min, max); in uvc_ctrl_set()
1613 value = xctrl->value; in uvc_ctrl_set()
1617 xctrl->value = clamp(xctrl->value, 0, 1); in uvc_ctrl_set()
1618 value = xctrl->value; in uvc_ctrl_set()
1622 if (xctrl->value < 0 || xctrl->value >= mapping->menu_count) in uvc_ctrl_set()
1623 return -ERANGE; in uvc_ctrl_set()
1624 value = mapping->menu_info[xctrl->value].value; in uvc_ctrl_set()
1629 if (mapping->data_type == UVC_CTRL_DATA_TYPE_BITMASK && in uvc_ctrl_set()
1630 (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)) { in uvc_ctrl_set()
1631 if (!ctrl->cached) { in uvc_ctrl_set()
1637 step = mapping->get(mapping, UVC_GET_RES, in uvc_ctrl_set()
1640 return -EINVAL; in uvc_ctrl_set()
1646 value = xctrl->value; in uvc_ctrl_set()
1650 /* If the mapping doesn't span the whole UVC control, the current value in uvc_ctrl_set()
1651 * needs to be loaded from the device to perform the read-modify-write in uvc_ctrl_set()
1654 if (!ctrl->loaded && (ctrl->info.size * 8) != mapping->size) { in uvc_ctrl_set()
1655 if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) { in uvc_ctrl_set()
1657 0, ctrl->info.size); in uvc_ctrl_set()
1659 ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, in uvc_ctrl_set()
1660 ctrl->entity->id, chain->dev->intfnum, in uvc_ctrl_set()
1661 ctrl->info.selector, in uvc_ctrl_set()
1663 ctrl->info.size); in uvc_ctrl_set()
1668 ctrl->loaded = 1; in uvc_ctrl_set()
1672 if (!ctrl->dirty) { in uvc_ctrl_set()
1675 ctrl->info.size); in uvc_ctrl_set()
1678 mapping->set(mapping, value, in uvc_ctrl_set()
1681 if (ctrl->info.flags & UVC_CTRL_FLAG_ASYNCHRONOUS) in uvc_ctrl_set()
1682 ctrl->handle = handle; in uvc_ctrl_set()
1684 ctrl->dirty = 1; in uvc_ctrl_set()
1685 ctrl->modified = 1; in uvc_ctrl_set()
1689 /* --------------------------------------------------------------------------
1700 u8 *data; in uvc_ctrl_get_flags() local
1703 data = kmalloc(1, GFP_KERNEL); in uvc_ctrl_get_flags()
1704 if (data == NULL) in uvc_ctrl_get_flags()
1705 return -ENOMEM; in uvc_ctrl_get_flags()
1707 ret = uvc_query_ctrl(dev, UVC_GET_INFO, ctrl->entity->id, dev->intfnum, in uvc_ctrl_get_flags()
1708 info->selector, data, 1); in uvc_ctrl_get_flags()
1710 info->flags |= (data[0] & UVC_CONTROL_CAP_GET ? in uvc_ctrl_get_flags()
1712 | (data[0] & UVC_CONTROL_CAP_SET ? in uvc_ctrl_get_flags()
1714 | (data[0] & UVC_CONTROL_CAP_AUTOUPDATE ? in uvc_ctrl_get_flags()
1716 | (data[0] & UVC_CONTROL_CAP_ASYNCHRONOUS ? in uvc_ctrl_get_flags()
1719 kfree(data); in uvc_ctrl_get_flags()
1751 if (!usb_match_one_id(dev->intf, &fixups[i].id)) in uvc_ctrl_fixup_xu_info()
1754 if (fixups[i].entity == ctrl->entity->id && in uvc_ctrl_fixup_xu_info()
1755 fixups[i].selector == info->selector) { in uvc_ctrl_fixup_xu_info()
1756 info->flags = fixups[i].flags; in uvc_ctrl_fixup_xu_info()
1768 u8 *data; in uvc_ctrl_fill_xu_info() local
1771 data = kmalloc(2, GFP_KERNEL); in uvc_ctrl_fill_xu_info()
1772 if (data == NULL) in uvc_ctrl_fill_xu_info()
1773 return -ENOMEM; in uvc_ctrl_fill_xu_info()
1775 memcpy(info->entity, ctrl->entity->extension.guidExtensionCode, in uvc_ctrl_fill_xu_info()
1776 sizeof(info->entity)); in uvc_ctrl_fill_xu_info()
1777 info->index = ctrl->index; in uvc_ctrl_fill_xu_info()
1778 info->selector = ctrl->index + 1; in uvc_ctrl_fill_xu_info()
1781 ret = uvc_query_ctrl(dev, UVC_GET_LEN, ctrl->entity->id, dev->intfnum, in uvc_ctrl_fill_xu_info()
1782 info->selector, data, 2); in uvc_ctrl_fill_xu_info()
1786 info->entity, info->selector, ret); in uvc_ctrl_fill_xu_info()
1790 info->size = le16_to_cpup((__le16 *)data); in uvc_ctrl_fill_xu_info()
1792 info->flags = UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX in uvc_ctrl_fill_xu_info()
1799 info->entity, info->selector, ret); in uvc_ctrl_fill_xu_info()
1807 info->entity, info->selector, info->size, in uvc_ctrl_fill_xu_info()
1808 (info->flags & UVC_CTRL_FLAG_GET_CUR) ? 1 : 0, in uvc_ctrl_fill_xu_info()
1809 (info->flags & UVC_CTRL_FLAG_SET_CUR) ? 1 : 0, in uvc_ctrl_fill_xu_info()
1810 (info->flags & UVC_CTRL_FLAG_AUTO_UPDATE) ? 1 : 0); in uvc_ctrl_fill_xu_info()
1813 kfree(data); in uvc_ctrl_fill_xu_info()
1826 if (ctrl->initialized) in uvc_ctrl_init_xu_ctrl()
1837 info.selector, dev->udev->devpath, ctrl->entity->id); in uvc_ctrl_init_xu_ctrl()
1850 u8 *data = NULL; in uvc_xu_ctrl_query() local
1854 list_for_each_entry(entity, &chain->entities, chain) { in uvc_xu_ctrl_query()
1856 entity->id == xqry->unit) in uvc_xu_ctrl_query()
1860 if (entity->id != xqry->unit) { in uvc_xu_ctrl_query()
1862 xqry->unit); in uvc_xu_ctrl_query()
1863 return -ENOENT; in uvc_xu_ctrl_query()
1867 for (i = 0; i < entity->ncontrols; ++i) { in uvc_xu_ctrl_query()
1868 ctrl = &entity->controls[i]; in uvc_xu_ctrl_query()
1869 if (ctrl->index == xqry->selector - 1) { in uvc_xu_ctrl_query()
1877 entity->extension.guidExtensionCode, xqry->selector); in uvc_xu_ctrl_query()
1878 return -ENOENT; in uvc_xu_ctrl_query()
1881 if (mutex_lock_interruptible(&chain->ctrl_mutex)) in uvc_xu_ctrl_query()
1882 return -ERESTARTSYS; in uvc_xu_ctrl_query()
1884 ret = uvc_ctrl_init_xu_ctrl(chain->dev, ctrl); in uvc_xu_ctrl_query()
1886 ret = -ENOENT; in uvc_xu_ctrl_query()
1892 size = ctrl->info.size; in uvc_xu_ctrl_query()
1894 switch (xqry->query) { in uvc_xu_ctrl_query()
1920 ret = -EINVAL; in uvc_xu_ctrl_query()
1924 if (size != xqry->size) { in uvc_xu_ctrl_query()
1925 ret = -ENOBUFS; in uvc_xu_ctrl_query()
1929 if (reqflags && !(ctrl->info.flags & reqflags)) { in uvc_xu_ctrl_query()
1930 ret = -EBADRQC; in uvc_xu_ctrl_query()
1934 data = kmalloc(size, GFP_KERNEL); in uvc_xu_ctrl_query()
1935 if (data == NULL) { in uvc_xu_ctrl_query()
1936 ret = -ENOMEM; in uvc_xu_ctrl_query()
1940 if (xqry->query == UVC_SET_CUR && in uvc_xu_ctrl_query()
1941 copy_from_user(data, xqry->data, size)) { in uvc_xu_ctrl_query()
1942 ret = -EFAULT; in uvc_xu_ctrl_query()
1946 ret = uvc_query_ctrl(chain->dev, xqry->query, xqry->unit, in uvc_xu_ctrl_query()
1947 chain->dev->intfnum, xqry->selector, data, size); in uvc_xu_ctrl_query()
1951 if (xqry->query != UVC_SET_CUR && in uvc_xu_ctrl_query()
1952 copy_to_user(xqry->data, data, size)) in uvc_xu_ctrl_query()
1953 ret = -EFAULT; in uvc_xu_ctrl_query()
1955 kfree(data); in uvc_xu_ctrl_query()
1956 mutex_unlock(&chain->ctrl_mutex); in uvc_xu_ctrl_query()
1960 /* --------------------------------------------------------------------------
1969 * - Don't restore modified controls that are back to their default value.
1970 * - Handle restore order (Auto-Exposure Mode should be restored before
1981 list_for_each_entry(entity, &dev->entities, list) { in uvc_ctrl_restore_values()
1983 for (i = 0; i < entity->ncontrols; ++i) { in uvc_ctrl_restore_values()
1984 ctrl = &entity->controls[i]; in uvc_ctrl_restore_values()
1986 if (!ctrl->initialized || !ctrl->modified || in uvc_ctrl_restore_values()
1987 (ctrl->info.flags & UVC_CTRL_FLAG_RESTORE) == 0) in uvc_ctrl_restore_values()
1991 ctrl->info.entity, ctrl->info.index, in uvc_ctrl_restore_values()
1992 ctrl->info.selector); in uvc_ctrl_restore_values()
1993 ctrl->dirty = 1; in uvc_ctrl_restore_values()
2004 /* --------------------------------------------------------------------------
2005 * Control and mapping handling
2016 ctrl->info = *info; in uvc_ctrl_add_info()
2017 INIT_LIST_HEAD(&ctrl->info.mappings); in uvc_ctrl_add_info()
2020 ctrl->uvc_data = kzalloc(ctrl->info.size * UVC_CTRL_DATA_LAST + 1, in uvc_ctrl_add_info()
2022 if (ctrl->uvc_data == NULL) { in uvc_ctrl_add_info()
2023 ret = -ENOMEM; in uvc_ctrl_add_info()
2032 uvc_ctrl_get_flags(dev, ctrl, &ctrl->info); in uvc_ctrl_add_info()
2034 ctrl->initialized = 1; in uvc_ctrl_add_info()
2037 "entity %u\n", ctrl->info.entity, ctrl->info.selector, in uvc_ctrl_add_info()
2038 dev->udev->devpath, ctrl->entity->id); in uvc_ctrl_add_info()
2042 kfree(ctrl->uvc_data); in uvc_ctrl_add_info()
2047 * Add a control mapping to a given control.
2050 struct uvc_control *ctrl, const struct uvc_control_mapping *mapping) in __uvc_ctrl_add_mapping() argument
2055 /* Most mappings come from static kernel data and need to be duplicated. in __uvc_ctrl_add_mapping()
2059 map = kmemdup(mapping, sizeof(*mapping), GFP_KERNEL); in __uvc_ctrl_add_mapping()
2061 return -ENOMEM; in __uvc_ctrl_add_mapping()
2063 INIT_LIST_HEAD(&map->ev_subs); in __uvc_ctrl_add_mapping()
2065 size = sizeof(*mapping->menu_info) * mapping->menu_count; in __uvc_ctrl_add_mapping()
2066 map->menu_info = kmemdup(mapping->menu_info, size, GFP_KERNEL); in __uvc_ctrl_add_mapping()
2067 if (map->menu_info == NULL) { in __uvc_ctrl_add_mapping()
2069 return -ENOMEM; in __uvc_ctrl_add_mapping()
2072 if (map->get == NULL) in __uvc_ctrl_add_mapping()
2073 map->get = uvc_get_le_value; in __uvc_ctrl_add_mapping()
2074 if (map->set == NULL) in __uvc_ctrl_add_mapping()
2075 map->set = uvc_set_le_value; in __uvc_ctrl_add_mapping()
2077 list_add_tail(&map->list, &ctrl->info.mappings); in __uvc_ctrl_add_mapping()
2079 "Adding mapping '%s' to control %pUl/%u.\n", in __uvc_ctrl_add_mapping()
2080 map->name, ctrl->info.entity, ctrl->info.selector); in __uvc_ctrl_add_mapping()
2086 const struct uvc_control_mapping *mapping) in uvc_ctrl_add_mapping() argument
2088 struct uvc_device *dev = chain->dev; in uvc_ctrl_add_mapping()
2095 if (mapping->id & ~V4L2_CTRL_ID_MASK) { in uvc_ctrl_add_mapping()
2096 uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s', control " in uvc_ctrl_add_mapping()
2097 "id 0x%08x is invalid.\n", mapping->name, in uvc_ctrl_add_mapping()
2098 mapping->id); in uvc_ctrl_add_mapping()
2099 return -EINVAL; in uvc_ctrl_add_mapping()
2103 list_for_each_entry(entity, &chain->entities, chain) { in uvc_ctrl_add_mapping()
2107 !uvc_entity_match_guid(entity, mapping->entity)) in uvc_ctrl_add_mapping()
2110 for (i = 0; i < entity->ncontrols; ++i) { in uvc_ctrl_add_mapping()
2111 ctrl = &entity->controls[i]; in uvc_ctrl_add_mapping()
2112 if (ctrl->index == mapping->selector - 1) { in uvc_ctrl_add_mapping()
2122 return -ENOENT; in uvc_ctrl_add_mapping()
2124 if (mutex_lock_interruptible(&chain->ctrl_mutex)) in uvc_ctrl_add_mapping()
2125 return -ERESTARTSYS; in uvc_ctrl_add_mapping()
2130 ret = -ENOENT; in uvc_ctrl_add_mapping()
2134 /* Validate the user-provided bit-size and offset */ in uvc_ctrl_add_mapping()
2135 if (mapping->size > 32 || in uvc_ctrl_add_mapping()
2136 mapping->offset + mapping->size > ctrl->info.size * 8) { in uvc_ctrl_add_mapping()
2137 ret = -EINVAL; in uvc_ctrl_add_mapping()
2141 list_for_each_entry(map, &ctrl->info.mappings, list) { in uvc_ctrl_add_mapping()
2142 if (mapping->id == map->id) { in uvc_ctrl_add_mapping()
2143 uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s', " in uvc_ctrl_add_mapping()
2145 mapping->name, mapping->id); in uvc_ctrl_add_mapping()
2146 ret = -EEXIST; in uvc_ctrl_add_mapping()
2152 if (atomic_inc_return(&dev->nmappings) > UVC_MAX_CONTROL_MAPPINGS) { in uvc_ctrl_add_mapping()
2153 atomic_dec(&dev->nmappings); in uvc_ctrl_add_mapping()
2154 uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s', maximum " in uvc_ctrl_add_mapping()
2155 "mappings count (%u) exceeded.\n", mapping->name, in uvc_ctrl_add_mapping()
2157 ret = -ENOMEM; in uvc_ctrl_add_mapping()
2161 ret = __uvc_ctrl_add_mapping(dev, ctrl, mapping); in uvc_ctrl_add_mapping()
2163 atomic_dec(&dev->nmappings); in uvc_ctrl_add_mapping()
2166 mutex_unlock(&chain->ctrl_mutex); in uvc_ctrl_add_mapping()
2202 controls = entity->processing.bmControls; in uvc_ctrl_prune_entity()
2203 size = entity->processing.bControlSize; in uvc_ctrl_prune_entity()
2209 controls = entity->camera.bmControls; in uvc_ctrl_prune_entity()
2210 size = entity->camera.bControlSize; in uvc_ctrl_prune_entity()
2218 if (!usb_match_one_id(dev->intf, &blacklist[i].id)) in uvc_ctrl_prune_entity()
2226 "removing it.\n", entity->id, blacklist[i].index); in uvc_ctrl_prune_entity()
2240 const struct uvc_control_mapping *mapping = uvc_ctrl_mappings; in uvc_ctrl_init_ctrl() local
2242 mapping + ARRAY_SIZE(uvc_ctrl_mappings); in uvc_ctrl_init_ctrl()
2249 if (UVC_ENTITY_TYPE(ctrl->entity) == UVC_VC_EXTENSION_UNIT) in uvc_ctrl_init_ctrl()
2253 if (uvc_entity_match_guid(ctrl->entity, info->entity) && in uvc_ctrl_init_ctrl()
2254 ctrl->index == info->index) { in uvc_ctrl_init_ctrl()
2260 if (!ctrl->initialized) in uvc_ctrl_init_ctrl()
2263 for (; mapping < mend; ++mapping) { in uvc_ctrl_init_ctrl()
2264 if (uvc_entity_match_guid(ctrl->entity, mapping->entity) && in uvc_ctrl_init_ctrl()
2265 ctrl->info.selector == mapping->selector) in uvc_ctrl_init_ctrl()
2266 __uvc_ctrl_add_mapping(dev, ctrl, mapping); in uvc_ctrl_init_ctrl()
2278 INIT_WORK(&dev->async_ctrl.work, uvc_ctrl_status_event_work); in uvc_ctrl_init_device()
2281 list_for_each_entry(entity, &dev->entities, list) { in uvc_ctrl_init_device()
2287 bmControls = entity->extension.bmControls; in uvc_ctrl_init_device()
2288 bControlSize = entity->extension.bControlSize; in uvc_ctrl_init_device()
2290 bmControls = entity->processing.bmControls; in uvc_ctrl_init_device()
2291 bControlSize = entity->processing.bControlSize; in uvc_ctrl_init_device()
2293 bmControls = entity->camera.bmControls; in uvc_ctrl_init_device()
2294 bControlSize = entity->camera.bControlSize; in uvc_ctrl_init_device()
2305 entity->controls = kcalloc(ncontrols, sizeof(*ctrl), in uvc_ctrl_init_device()
2307 if (entity->controls == NULL) in uvc_ctrl_init_device()
2308 return -ENOMEM; in uvc_ctrl_init_device()
2309 entity->ncontrols = ncontrols; in uvc_ctrl_init_device()
2312 ctrl = entity->controls; in uvc_ctrl_init_device()
2317 ctrl->entity = entity; in uvc_ctrl_init_device()
2318 ctrl->index = i; in uvc_ctrl_init_device()
2334 struct uvc_control_mapping *mapping, *nm; in uvc_ctrl_cleanup_mappings() local
2336 list_for_each_entry_safe(mapping, nm, &ctrl->info.mappings, list) { in uvc_ctrl_cleanup_mappings()
2337 list_del(&mapping->list); in uvc_ctrl_cleanup_mappings()
2338 kfree(mapping->menu_info); in uvc_ctrl_cleanup_mappings()
2339 kfree(mapping); in uvc_ctrl_cleanup_mappings()
2349 if (dev->async_ctrl.work.func) in uvc_ctrl_cleanup_device()
2350 cancel_work_sync(&dev->async_ctrl.work); in uvc_ctrl_cleanup_device()
2353 list_for_each_entry(entity, &dev->entities, list) { in uvc_ctrl_cleanup_device()
2354 for (i = 0; i < entity->ncontrols; ++i) { in uvc_ctrl_cleanup_device()
2355 struct uvc_control *ctrl = &entity->controls[i]; in uvc_ctrl_cleanup_device()
2357 if (!ctrl->initialized) in uvc_ctrl_cleanup_device()
2361 kfree(ctrl->uvc_data); in uvc_ctrl_cleanup_device()
2364 kfree(entity->controls); in uvc_ctrl_cleanup_device()