struct v4l2_ctrl;
struct video_device;
struct v4l2_subdev;
+struct v4l2_event_subscription;
+struct v4l2_fh;
/** struct v4l2_ctrl_ops - The control operations that the driver has to provide.
* @g_volatile_ctrl: Get a new value for this control. Generally only relevant
* control's current value cannot be cached and needs to be
* retrieved through the g_volatile_ctrl op. Drivers can set
* this flag.
+ * @is_auto: If set, then this control selects whether the other cluster
+ * members are in 'automatic' mode or 'manual' mode. This is
+ * used for autogain/gain type clusters. Drivers should never
+ * set this flag directly.
+ * @manual_mode_value: If the is_auto flag is set, then this is the value
+ * of the auto control that determines if that control is in
+ * manual mode. So if the value of the auto control equals this
+ * value, then the whole cluster is in manual mode. Drivers should
+ * never set this flag directly.
* @ops: The control ops.
* @id: The control ID.
* @name: The control name.
struct v4l2_ctrl {
/* Administrative fields */
struct list_head node;
+ struct list_head fhs;
struct v4l2_ctrl_handler *handler;
struct v4l2_ctrl **cluster;
unsigned ncontrols;
unsigned int is_new:1;
unsigned int is_private:1;
unsigned int is_volatile:1;
+ unsigned int is_auto:1;
+ unsigned int manual_mode_value:8;
const struct v4l2_ctrl_ops *ops;
u32 id;
* control is needed multiple times, so this is a simple
* optimization.
* @buckets: Buckets for the hashing. Allows for quick control lookup.
+ * @nr_of_refs: Total number of control references in the list.
* @nr_of_buckets: Total number of buckets in the array.
* @error: The error code of the first failed control addition.
*/
struct list_head ctrl_refs;
struct v4l2_ctrl_ref *cached;
struct v4l2_ctrl_ref **buckets;
+ u16 nr_of_refs;
u16 nr_of_buckets;
int error;
};
+struct v4l2_ctrl_fh {
+ struct list_head node;
+ struct v4l2_fh *fh;
+};
+
/** struct v4l2_ctrl_config - Control configuration structure.
* @ops: The control ops.
* @id: The control ID.
void v4l2_ctrl_cluster(unsigned ncontrols, struct v4l2_ctrl **controls);
+/** v4l2_ctrl_auto_cluster() - Mark all controls in the cluster as belonging to
+ * that cluster and set it up for autofoo/foo-type handling.
+ * @ncontrols: The number of controls in this cluster.
+ * @controls: The cluster control array of size @ncontrols. The first control
+ * must be the 'auto' control (e.g. autogain, autoexposure, etc.)
+ * @manual_val: The value for the first control in the cluster that equals the
+ * manual setting.
+ * @set_volatile: If true, then all controls except the first auto control will
+ * have is_volatile set to true. If false, then is_volatile will not
+ * be touched.
+ *
+ * Use for control groups where one control selects some automatic feature and
+ * the other controls are only active whenever the automatic feature is turned
+ * off (manual mode). Typical examples: autogain vs gain, auto-whitebalance vs
+ * red and blue balance, etc.
+ *
+ * The behavior of such controls is as follows:
+ *
+ * When the autofoo control is set to automatic, then any manual controls
+ * are set to inactive and any reads will call g_volatile_ctrl (if the control
+ * was marked volatile).
+ *
+ * When the autofoo control is set to manual, then any manual controls will
+ * be marked active, and any reads will just return the current value without
+ * going through g_volatile_ctrl.
+ *
+ * In addition, this function will set the V4L2_CTRL_FLAG_UPDATE flag
+ * on the autofoo control and V4L2_CTRL_FLAG_INACTIVE on the foo control(s)
+ * if autofoo is in auto mode.
+ */
+void v4l2_ctrl_auto_cluster(unsigned ncontrols, struct v4l2_ctrl **controls,
+ u8 manual_val, bool set_volatile);
+
+
/** v4l2_ctrl_find() - Find a control with the given ID.
* @hdl: The control handler.
* @id: The control ID to find.
* This sets or clears the V4L2_CTRL_FLAG_INACTIVE flag atomically.
* Does nothing if @ctrl == NULL.
* This will usually be called from within the s_ctrl op.
+ * The V4L2_EVENT_CTRL event will be generated afterwards.
*
- * This function can be called regardless of whether the control handler
- * is locked or not.
+ * This function assumes that the control handler is locked.
*/
void v4l2_ctrl_activate(struct v4l2_ctrl *ctrl, bool active);
*
* This sets or clears the V4L2_CTRL_FLAG_GRABBED flag atomically.
* Does nothing if @ctrl == NULL.
+ * The V4L2_EVENT_CTRL event will be generated afterwards.
* This will usually be called when starting or stopping streaming in the
* driver.
*
- * This function can be called regardless of whether the control handler
- * is locked or not.
+ * This function assumes that the control handler is not locked and will
+ * take the lock itself.
*/
void v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed);
*/
int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val);
+/* Internal helper functions that deal with control events. */
+void v4l2_ctrl_add_fh(struct v4l2_ctrl_handler *hdl,
+ struct v4l2_ctrl_fh *ctrl_fh,
+ struct v4l2_event_subscription *sub);
+void v4l2_ctrl_del_fh(struct v4l2_ctrl *ctrl, struct v4l2_fh *fh);
+
+/** v4l2_ctrl_subscribe_fh() - Helper function that subscribes a control event.
+ * @fh: The file handler that subscribed the control event.
+ * @sub: The event to subscribe (type must be V4L2_EVENT_CTRL).
+ * @n: How many events should be allocated? (Passed to v4l2_event_alloc).
+ * Recommended to set to twice the number of controls plus whatever
+ * is needed for other events. This function will set n to
+ * max(n, 2 * fh->ctrl_handler->nr_of_refs).
+ *
+ * A helper function that initializes the fh for events, allocates the
+ * list of events and subscribes the control event.
+ *
+ * Typically called in the handler of VIDIOC_SUBSCRIBE_EVENT in the
+ * V4L2_EVENT_CTRL case.
+ */
+int v4l2_ctrl_subscribe_fh(struct v4l2_fh *fh,
+ struct v4l2_event_subscription *sub, unsigned n);
/* Helpers for ioctl_ops. If hdl == NULL then they will all return -EINVAL. */
int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc);
int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, struct v4l2_querymenu *qm);
int v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *ctrl);
-int v4l2_s_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *ctrl);
+int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
+ struct v4l2_control *ctrl);
int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *c);
int v4l2_try_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *c);
-int v4l2_s_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *c);
+int v4l2_s_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
+ struct v4l2_ext_controls *c);
/* Helpers for subdevices. If the associated ctrl_handler == NULL then they
will all return -EINVAL. */