linux/drivers/media/usb/uvc/uvc_ctrl.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *      uvc_ctrl.c  --  USB Video Class driver - Controls
 *
 *      Copyright (C) 2005-2010
 *          Laurent Pinchart ([email protected])
 */

#include <asm/barrier.h>
#include <linux/bitops.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/uvc.h>
#include <linux/videodev2.h>
#include <linux/vmalloc.h>
#include <linux/wait.h>
#include <linux/workqueue.h>
#include <linux/atomic.h>
#include <media/v4l2-ctrls.h>

#include "uvcvideo.h"

#define UVC_CTRL_DATA_CURRENT
#define UVC_CTRL_DATA_BACKUP
#define UVC_CTRL_DATA_MIN
#define UVC_CTRL_DATA_MAX
#define UVC_CTRL_DATA_RES
#define UVC_CTRL_DATA_DEF
#define UVC_CTRL_DATA_LAST

/* ------------------------------------------------------------------------
 * Controls
 */

static const struct uvc_control_info uvc_ctrls[] =;

static const u32 uvc_control_classes[] =;

static const int exposure_auto_mapping[] =;

/*
 * This function translates the V4L2 menu index @idx, as exposed to userspace as
 * the V4L2 control value, to the corresponding UVC control value used by the
 * device. The custom menu_mapping in the control @mapping is used when
 * available, otherwise the function assumes that the V4L2 and UVC values are
 * identical.
 *
 * For controls of type UVC_CTRL_DATA_TYPE_BITMASK, the UVC control value is
 * expressed as a bitmask and is thus guaranteed to have a single bit set.
 *
 * The function returns -EINVAL if the V4L2 menu index @idx isn't valid for the
 * control, which includes all controls whose type isn't UVC_CTRL_DATA_TYPE_ENUM
 * or UVC_CTRL_DATA_TYPE_BITMASK.
 */
static int uvc_mapping_get_menu_value(const struct uvc_control_mapping *mapping,
				      u32 idx)
{}

static const char *
uvc_mapping_get_menu_name(const struct uvc_control_mapping *mapping, u32 idx)
{}

static s32 uvc_ctrl_get_zoom(struct uvc_control_mapping *mapping,
	u8 query, const u8 *data)
{}

static void uvc_ctrl_set_zoom(struct uvc_control_mapping *mapping,
	s32 value, u8 *data)
{}

static s32 uvc_ctrl_get_rel_speed(struct uvc_control_mapping *mapping,
	u8 query, const u8 *data)
{}

static void uvc_ctrl_set_rel_speed(struct uvc_control_mapping *mapping,
	s32 value, u8 *data)
{}

static const struct uvc_control_mapping uvc_ctrl_power_line_mapping_limited =;

static const struct uvc_control_mapping uvc_ctrl_power_line_mapping_uvc11 =;

static const struct uvc_control_mapping uvc_ctrl_power_line_mapping_uvc15 =;

static const struct uvc_control_mapping *uvc_ctrl_filter_plf_mapping(
	struct uvc_video_chain *chain, struct uvc_control *ctrl)
{}

static const struct uvc_control_mapping uvc_ctrl_mappings[] =;

/* ------------------------------------------------------------------------
 * Utility functions
 */

static inline u8 *uvc_ctrl_data(struct uvc_control *ctrl, int id)
{}

static inline int uvc_test_bit(const u8 *data, int bit)
{}

static inline void uvc_clear_bit(u8 *data, int bit)
{}

/*
 * Extract the bit string specified by mapping->offset and mapping->size
 * from the little-endian data stored at 'data' and return the result as
 * a signed 32bit integer. Sign extension will be performed if the mapping
 * references a signed data type.
 */
static s32 uvc_get_le_value(struct uvc_control_mapping *mapping,
	u8 query, const u8 *data)
{}

/*
 * Set the bit string specified by mapping->offset and mapping->size
 * in the little-endian data stored at 'data' to the value 'value'.
 */
static void uvc_set_le_value(struct uvc_control_mapping *mapping,
	s32 value, u8 *data)
{}

/* ------------------------------------------------------------------------
 * Terminal and unit management
 */

static int uvc_entity_match_guid(const struct uvc_entity *entity,
				 const u8 guid[16])
{}

/* ------------------------------------------------------------------------
 * UVC Controls
 */

static void __uvc_find_control(struct uvc_entity *entity, u32 v4l2_id,
	struct uvc_control_mapping **mapping, struct uvc_control **control,
	int next)
{}

static struct uvc_control *uvc_find_control(struct uvc_video_chain *chain,
	u32 v4l2_id, struct uvc_control_mapping **mapping)
{}

static int uvc_ctrl_populate_cache(struct uvc_video_chain *chain,
	struct uvc_control *ctrl)
{}

static s32 __uvc_ctrl_get_value(struct uvc_control_mapping *mapping,
				const u8 *data)
{}

static int __uvc_ctrl_load_cur(struct uvc_video_chain *chain,
			       struct uvc_control *ctrl)
{}

static int __uvc_ctrl_get(struct uvc_video_chain *chain,
			  struct uvc_control *ctrl,
			  struct uvc_control_mapping *mapping,
			  s32 *value)
{}

static int __uvc_query_v4l2_class(struct uvc_video_chain *chain, u32 req_id,
				  u32 found_id)
{}

static int uvc_query_v4l2_class(struct uvc_video_chain *chain, u32 req_id,
				u32 found_id, struct v4l2_queryctrl *v4l2_ctrl)
{}

/*
 * Check if control @v4l2_id can be accessed by the given control @ioctl
 * (VIDIOC_G_EXT_CTRLS, VIDIOC_TRY_EXT_CTRLS or VIDIOC_S_EXT_CTRLS).
 *
 * For set operations on slave controls, check if the master's value is set to
 * manual, either in the others controls set in the same ioctl call, or from
 * the master's current value. This catches VIDIOC_S_EXT_CTRLS calls that set
 * both the master and slave control, such as for instance setting
 * auto_exposure=1, exposure_time_absolute=251.
 */
int uvc_ctrl_is_accessible(struct uvc_video_chain *chain, u32 v4l2_id,
			   const struct v4l2_ext_controls *ctrls,
			   unsigned long ioctl)
{}

static const char *uvc_map_get_name(const struct uvc_control_mapping *map)
{}

static u32 uvc_get_ctrl_bitmap(struct uvc_control *ctrl,
			       struct uvc_control_mapping *mapping)
{}

static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
	struct uvc_control *ctrl,
	struct uvc_control_mapping *mapping,
	struct v4l2_queryctrl *v4l2_ctrl)
{}

int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
	struct v4l2_queryctrl *v4l2_ctrl)
{}

/*
 * Mapping V4L2 controls to UVC controls can be straightforward if done well.
 * Most of the UVC controls exist in V4L2, and can be mapped directly. Some
 * must be grouped (for instance the Red Balance, Blue Balance and Do White
 * Balance V4L2 controls use the White Balance Component UVC control) or
 * otherwise translated. The approach we take here is to use a translation
 * table for the controls that can be mapped directly, and handle the others
 * manually.
 */
int uvc_query_v4l2_menu(struct uvc_video_chain *chain,
	struct v4l2_querymenu *query_menu)
{}

/* --------------------------------------------------------------------------
 * Ctrl event handling
 */

static void uvc_ctrl_fill_event(struct uvc_video_chain *chain,
	struct v4l2_event *ev,
	struct uvc_control *ctrl,
	struct uvc_control_mapping *mapping,
	s32 value, u32 changes)
{}

/*
 * Send control change events to all subscribers for the @ctrl control. By
 * default the subscriber that generated the event, as identified by @handle,
 * is not notified unless it has set the V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK flag.
 * @handle can be NULL for asynchronous events related to auto-update controls,
 * in which case all subscribers are notified.
 */
static void uvc_ctrl_send_event(struct uvc_video_chain *chain,
	struct uvc_fh *handle, struct uvc_control *ctrl,
	struct uvc_control_mapping *mapping, s32 value, u32 changes)
{}

/*
 * Send control change events for the slave of the @master control identified
 * by the V4L2 ID @slave_id. The @handle identifies the event subscriber that
 * generated the event and may be NULL for auto-update events.
 */
static void uvc_ctrl_send_slave_event(struct uvc_video_chain *chain,
	struct uvc_fh *handle, struct uvc_control *master, u32 slave_id)
{}

void uvc_ctrl_status_event(struct uvc_video_chain *chain,
			   struct uvc_control *ctrl, const u8 *data)
{}

static void uvc_ctrl_status_event_work(struct work_struct *work)
{}

bool uvc_ctrl_status_event_async(struct urb *urb, struct uvc_video_chain *chain,
				 struct uvc_control *ctrl, const u8 *data)
{}

static bool uvc_ctrl_xctrls_has_control(const struct v4l2_ext_control *xctrls,
					unsigned int xctrls_count, u32 id)
{}

static void uvc_ctrl_send_events(struct uvc_fh *handle,
	const struct v4l2_ext_control *xctrls, unsigned int xctrls_count)
{}

static int uvc_ctrl_add_event(struct v4l2_subscribed_event *sev, unsigned elems)
{}

static void uvc_ctrl_del_event(struct v4l2_subscribed_event *sev)
{}

const struct v4l2_subscribed_event_ops uvc_ctrl_sub_ev_ops =;

/* --------------------------------------------------------------------------
 * Control transactions
 *
 * To make extended set operations as atomic as the hardware allows, controls
 * are handled using begin/commit/rollback operations.
 *
 * At the beginning of a set request, uvc_ctrl_begin should be called to
 * initialize the request. This function acquires the control lock.
 *
 * When setting a control, the new value is stored in the control data field
 * at position UVC_CTRL_DATA_CURRENT. The control is then marked as dirty for
 * later processing. If the UVC and V4L2 control sizes differ, the current
 * value is loaded from the hardware before storing the new value in the data
 * field.
 *
 * After processing all controls in the transaction, uvc_ctrl_commit or
 * uvc_ctrl_rollback must be called to apply the pending changes to the
 * hardware or revert them. When applying changes, all controls marked as
 * dirty will be modified in the UVC device, and the dirty flag will be
 * cleared. When reverting controls, the control data field
 * UVC_CTRL_DATA_CURRENT is reverted to its previous value
 * (UVC_CTRL_DATA_BACKUP) for all dirty controls. Both functions release the
 * control lock.
 */
int uvc_ctrl_begin(struct uvc_video_chain *chain)
{}

static int uvc_ctrl_commit_entity(struct uvc_device *dev,
	struct uvc_entity *entity, int rollback, struct uvc_control **err_ctrl)
{}

static int uvc_ctrl_find_ctrl_idx(struct uvc_entity *entity,
				  struct v4l2_ext_controls *ctrls,
				  struct uvc_control *uvc_control)
{}

int __uvc_ctrl_commit(struct uvc_fh *handle, int rollback,
		      struct v4l2_ext_controls *ctrls)
{}

int uvc_ctrl_get(struct uvc_video_chain *chain,
	struct v4l2_ext_control *xctrl)
{}

int uvc_ctrl_set(struct uvc_fh *handle,
	struct v4l2_ext_control *xctrl)
{}

/* --------------------------------------------------------------------------
 * Dynamic controls
 */

/*
 * Retrieve flags for a given control
 */
static int uvc_ctrl_get_flags(struct uvc_device *dev,
			      const struct uvc_control *ctrl,
			      struct uvc_control_info *info)
{}

static void uvc_ctrl_fixup_xu_info(struct uvc_device *dev,
	const struct uvc_control *ctrl, struct uvc_control_info *info)
{}

/*
 * Query control information (size and flags) for XU controls.
 */
static int uvc_ctrl_fill_xu_info(struct uvc_device *dev,
	const struct uvc_control *ctrl, struct uvc_control_info *info)
{}

static int uvc_ctrl_add_info(struct uvc_device *dev, struct uvc_control *ctrl,
	const struct uvc_control_info *info);

static int uvc_ctrl_init_xu_ctrl(struct uvc_device *dev,
	struct uvc_control *ctrl)
{}

int uvc_xu_ctrl_query(struct uvc_video_chain *chain,
	struct uvc_xu_control_query *xqry)
{}

/* --------------------------------------------------------------------------
 * Suspend/resume
 */

/*
 * Restore control values after resume, skipping controls that haven't been
 * changed.
 *
 * TODO
 * - Don't restore modified controls that are back to their default value.
 * - Handle restore order (Auto-Exposure Mode should be restored before
 *   Exposure Time).
 */
int uvc_ctrl_restore_values(struct uvc_device *dev)
{}

/* --------------------------------------------------------------------------
 * Control and mapping handling
 */

/*
 * Add control information to a given control.
 */
static int uvc_ctrl_add_info(struct uvc_device *dev, struct uvc_control *ctrl,
	const struct uvc_control_info *info)
{}

/*
 * Add a control mapping to a given control.
 */
static int __uvc_ctrl_add_mapping(struct uvc_video_chain *chain,
	struct uvc_control *ctrl, const struct uvc_control_mapping *mapping)
{}

int uvc_ctrl_add_mapping(struct uvc_video_chain *chain,
	const struct uvc_control_mapping *mapping)
{}

/*
 * Prune an entity of its bogus controls using a blacklist. Bogus controls
 * are currently the ones that crash the camera or unconditionally return an
 * error when queried.
 */
static void uvc_ctrl_prune_entity(struct uvc_device *dev,
	struct uvc_entity *entity)
{}

/*
 * Add control information and hardcoded stock control mappings to the given
 * device.
 */
static void uvc_ctrl_init_ctrl(struct uvc_video_chain *chain,
			       struct uvc_control *ctrl)
{}

/*
 * Initialize device controls.
 */
static int uvc_ctrl_init_chain(struct uvc_video_chain *chain)
{}

int uvc_ctrl_init_device(struct uvc_device *dev)
{}

/*
 * Cleanup device controls.
 */
static void uvc_ctrl_cleanup_mappings(struct uvc_device *dev,
	struct uvc_control *ctrl)
{}

void uvc_ctrl_cleanup_device(struct uvc_device *dev)
{}