diff --git a/cmd/camera.c b/cmd/camera.c index 051fdf5..c4a8144 100644 --- a/cmd/camera.c +++ b/cmd/camera.c @@ -60,7 +60,6 @@ camera_t *camera_open(camera_options_t *options) if (camera->options.fps > 0) { camera->camera->capture_list->fmt_interval_us = 1000 * 1000 / camera->options.fps; - printf("buffer_lock.c: frame interval: %d\n", camera->camera->capture_list->fmt_interval_us); } switch (camera->camera->capture_list->fmt_format) { @@ -108,6 +107,7 @@ error: int camera_set_params(camera_t *camera) { device_set_fps(camera->camera, camera->options.fps); + device_set_option_list(camera->camera, camera->options.options); // DEVICE_SET_OPTION(camera->camera, EXPOSURE, 2684); // DEVICE_SET_OPTION(camera->camera, ANALOGUE_GAIN, 938); diff --git a/hw/device.c b/hw/device.c index 5e6e506..4625e1d 100644 --- a/hw/device.c +++ b/hw/device.c @@ -246,20 +246,3 @@ int device_set_fps(device_t *dev, int desired_fps) error: return -1; } - -int device_set_option(device_t *dev, const char *name, uint32_t id, int32_t value) -{ - struct v4l2_control ctl = {0}; - - if (!dev) { - return -1; - } - - ctl.id = id; - ctl.value = value; - E_LOG_DEBUG(dev, "Configuring option %s (%08x) = %d", name, id, value); - E_XIOCTL(dev, dev->subdev_fd >= 0 ? dev->subdev_fd : dev->fd, VIDIOC_S_CTRL, &ctl, "Can't set option %s", name); - return 0; -error: - return -1; -} diff --git a/hw/device.h b/hw/device.h index 332f459..459d31b 100644 --- a/hw/device.h +++ b/hw/device.h @@ -30,9 +30,12 @@ int device_consume_event(device_t *device); int device_set_stream(device_t *dev, bool do_on); int device_set_decoder_start(device_t *dev, bool do_on); int device_video_force_key(device_t *dev); + +int device_set_fps(device_t *dev, int desired_fps); int device_set_pad_format(device_t *device, unsigned width, unsigned height, unsigned format); int device_set_option(device_t *dev, const char *name, uint32_t id, int32_t value); -int device_set_fps(device_t *dev, int desired_fps); +int device_set_option_string(device_t *dev, const char *option); +void device_set_option_list(device_t *dev, const char *option_list); #define DEVICE_SET_OPTION(dev, name, value) \ device_set_option(dev, #name, V4L2_CID_##name, value) diff --git a/hw/device_options.c b/hw/device_options.c new file mode 100644 index 0000000..fdf1ba4 --- /dev/null +++ b/hw/device_options.c @@ -0,0 +1,129 @@ +#include "hw/device.h" + +#include + +int device_set_option(device_t *dev, const char *name, uint32_t id, int32_t value) +{ + struct v4l2_control ctl = {0}; + + if (!dev) { + return -1; + } + + ctl.id = id; + ctl.value = value; + E_LOG_DEBUG(dev, "Configuring option %s (%08x) = %d", name, id, value); + E_XIOCTL(dev, dev->subdev_fd >= 0 ? dev->subdev_fd : dev->fd, VIDIOC_S_CTRL, &ctl, "Can't set option %s", name); + return 0; +error: + return -1; +} + +void device_option_normalize_name(char *in) +{ + char *out = in; + + while (*in) { + if (isalnum(*in)) { + *out++ = tolower(*in++); + } else if (isprint(*in)) { + *out++ = '_'; + while (*++in && isprint(*in) && !isalnum(*in)); + } else { + in++; + } + } + + *out++ = 0; +} + +int device_set_option_string_fd(device_t *dev, int fd, const char *name, const char *value) +{ + struct v4l2_query_ext_ctrl qctrl = {0}; + struct v4l2_control ctl = {0}; + + qctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL; + while (0 == ioctl (fd, VIDIOC_QUERY_EXT_CTRL, &qctrl)) { + ctl.id = qctrl.id; + qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL; + + device_option_normalize_name(qctrl.name); + + if (strcmp(qctrl.name, name) != 0) + continue; + + if (qctrl.flags & V4L2_CTRL_FLAG_DISABLED) { + E_LOG_INFO(dev, "The '%s' is disabled", name); + continue; + } else if (qctrl.flags & V4L2_CTRL_FLAG_READ_ONLY) { + E_LOG_INFO(dev, "The '%s' is read-only", name); + continue; + } + + switch(qctrl.type) { + case V4L2_CTRL_TYPE_INTEGER: + case V4L2_CTRL_TYPE_BOOLEAN: + case V4L2_CTRL_TYPE_MENU: + ctl.value = atoi(value); + E_LOG_VERBOSE(dev, "Configuring option %s (%08x) = %d", name, ctl.id, ctl.value); + E_XIOCTL(dev, fd, VIDIOC_S_CTRL, &ctl, "Can't set option %s", name); + return 1; + + default: + E_LOG_INFO(dev, "The '%s' control type '%d' is not supported", name, qctrl.type); + return 0; + } + } + + return 0; + +error: + return -1; +} + +int device_set_option_string(device_t *dev, const char *option) +{ + char name[256]; + strcpy(name, option); + + char *value = strchr(name, '='); + if (!value) { + E_LOG_ERROR(dev, "Missing 'key=value': '%s'", option); + } + *value++ = 0; + + device_option_normalize_name(name); + + int ret = device_set_option_string_fd(dev, dev->subdev_fd, name, value); + if (ret > 0) + return 0; + + ret = device_set_option_string_fd(dev, dev->fd, name, value); + + if (ret == 0) + E_LOG_ERROR(dev, "The '%s' was failed to find.", option); + else if (ret < 0) + E_LOG_ERROR(dev, "The '%s' did fail to be set.", option); + + return 0; + +error: + return -1; +} + +void device_set_option_list(device_t *dev, const char *option_list) +{ + if (!dev || !option_list || !option_list[0]) { + return; + } + + char *start = strdup(option_list); + char *string = start; + char *option; + + while (option = strsep(&string, ",")) { + device_set_option_string(dev, option); + } + + free(start); +} \ No newline at end of file diff --git a/opts/opts.c b/opts/opts.c index 7a811f0..4b08988 100644 --- a/opts/opts.c +++ b/opts/opts.c @@ -8,8 +8,6 @@ static int option_handler_print(option_t *option, char *data); static int option_handler_set(option_t *option, char *data); -#define OPTION_VALUE_LIST_SEP "," - static void print_help(option_t *options) { for (int i = 0; options[i].name; i++) { diff --git a/opts/opts.h b/opts/opts.h index 70887c0..5ecf801 100644 --- a/opts/opts.h +++ b/opts/opts.h @@ -31,6 +31,8 @@ typedef struct options_s { __fn__; \ }) +#define OPTION_VALUE_LIST_SEP "," + #define OPTION_FORMAT_uint "%d" #define OPTION_FORMAT_hex "%08x" #define OPTION_FORMAT_bool "%d"