Skip to content

Commit

Permalink
drivers: video: common: add helpers to check video control range
Browse files Browse the repository at this point in the history
This allows implementing the VIDEO_CTRL_GET_MIN/MAX/DEF controls on
drivers with minimum modification of the drivers.

A typical usage in a video_get_ctrl() implementation would be:

	ret = video_get_ctrl_range(cid, value, 0, 320, 9);
	if (ret <= 0) {
		return ret;
	}
	return sensor_read_u32(&cfg->i2c, EXPOSURE_REG, value, 2);

A typical usage in a video_set_ctrl() implementation would be:

	ret = video_check_range_u32(dev, cid, (uint32_t)value);
	if (ret < 0) {
		return ret;
	}
	return sensor_read_reg(&cfg->i2c, EXPOSURE_REG, value, 2);

Signed-off-by: Josuah Demangeon <me@josuah.net>
  • Loading branch information
josuah committed Oct 15, 2024
1 parent a54408a commit 1a4dcb1
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 0 deletions.
91 changes: 91 additions & 0 deletions drivers/video/video_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

#include <zephyr/kernel.h>
#include <zephyr/drivers/video.h>
#include <zephyr/drivers/video-controls.h>

#include "video_common.h"

#if defined(CONFIG_VIDEO_BUFFER_USE_SHARED_MULTI_HEAP)
#include <zephyr/multi_heap/shared_multi_heap.h>
Expand Down Expand Up @@ -83,3 +86,91 @@ void video_buffer_release(struct video_buffer *vbuf)
VIDEO_COMMON_FREE(block->data);
}
}

int video_get_range_int(unsigned int cid, int *value, int min, int max, int def)
{
switch (cid & VIDEO_CTRL_GET_MASK) {
case VIDEO_CTRL_GET_MIN:
*value = min;
return 0;
case VIDEO_CTRL_GET_MAX:
*value = max;
return 0;
case VIDEO_CTRL_GET_DEF:
*value = def;
return 0;
case VIDEO_CTRL_GET_CUR:
return 1;
default:
return -ENOTSUP;
}
}

int video_get_range_int64(unsigned int cid, int64_t *value, int64_t min, int64_t max, int64_t def)
{
switch (cid & VIDEO_CTRL_GET_MASK) {
case VIDEO_CTRL_GET_MIN:
*value = min;
return 0;
case VIDEO_CTRL_GET_MAX:
*value = max;
return 0;
case VIDEO_CTRL_GET_DEF:
*value = def;
return 0;
case VIDEO_CTRL_GET_CUR:
return 1;
default:
return -ENOTSUP;
}
}

int video_check_range_int(const struct device *dev, unsigned int cid, int value)
{
int min;
int max;
int ret;

ret = video_get_ctrl(dev, cid | VIDEO_CTRL_GET_MIN, &min);
if (ret < 0) {
return ret;
}

ret = video_get_ctrl(dev, cid | VIDEO_CTRL_GET_MAX, &max);
if (ret < 0) {
return ret;
}

__ASSERT(min <= max, "drivers must ensure that min/max are consistent");

if (value < min || value > max) {
return -ERANGE;
}

return 0;
}

int video_check_range_int64(const struct device *dev, unsigned int cid, int64_t value)
{
int64_t min;
int64_t max;
int ret;

ret = video_get_ctrl(dev, cid | VIDEO_CTRL_GET_MIN, &min);
if (ret < 0) {
return ret;
}

ret = video_get_ctrl(dev, cid | VIDEO_CTRL_GET_MAX, &max);
if (ret < 0) {
return ret;
}

__ASSERT(min <= max, "drivers must ensure that min/max are consistent");

if (value < min || value > max) {
return -ERANGE;
}

return 0;
}
68 changes: 68 additions & 0 deletions drivers/video/video_common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright (c) 2024, tinyVision.ai Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef ZEPHYR_INCLUDE_VIDEO_COMMON_H
#define ZEPHYR_INCLUDE_VIDEO_COMMON_H

/**
* @brief Provide the minimum/maximum/default integer value depending on the CID.
*
* Video CIDs can contain sub-operations. This function facilitates
* implementation of video controls in the drivers by handling these
* the range-related CIDs.
*
* @param cid The Video Control ID which contains the operation.
* @param value The value, selected among @p min, @p max and @p def.
* @param min The minimum value returned if the CID requested it.
* @param max The maximum value returned if the CID requested it.
* @param def The default value returned if the CID requested it.
*
* @return 0 if the operation was regarding a range CID and the value could
* be set. In which case, there is nothing else to do than returning 0.
* @return 1 if the operation is not for the range, but the current value,
* in which case it is the duty of the driver to query the current
* value to the hardware
* @return A negative error code if an error occurred.
*
* @{
*/

/** Signed integer version */
int video_get_range_int(unsigned int cid, int *value, int min, int max, int def);

/** Signed 64-bit version */
int video_get_range_int64(unsigned int cid, int64_t *value, int64_t min, int64_t max, int64_t def);

/**
* @}
*/

/**
* @brief Check if the integer value is within range for this CID.
*
* Before setting a video control, a driver might be interested in checking
* if it is within a valid range. This function facilitates it by reusing the
* video_get_ctrl() API using @c VIDEO_CTRL_GET_MIN and @c VIDEO_CTRL_GET_MAX
* to validate the input.
*
* @param dev The video device to query to learn about the min and max.
* @param cid The CID for which to check the range.
* @param value The integer value that must be matched against the range.
*
* @{
*/

/** Signed integer version */
int video_check_range_int(const struct device *dev, unsigned int cid, int value);

/** Signed 64-bit version */
int video_check_range_int64(const struct device *dev, unsigned int cid, int64_t value);

/**
* @}
*/

#endif /* ZEPHYR_INCLUDE_VIDEO_COMMON_H */

0 comments on commit 1a4dcb1

Please sign in to comment.