camera-streamer/device/hw/device_options.c
2022-04-08 18:47:12 +02:00

129 lines
2.8 KiB
C

#include "device/hw/device.h"
#include <ctype.h>
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);
}