int testQueryControls(struct node *node)
{
	struct test_queryctrl qctrl;
	__u32 id = 0;
	int ret;
	__u32 ctrl_class = 0;
	bool found_ctrl_class = false;
	unsigned user_controls = 0;
	unsigned priv_user_controls = 0;
	unsigned user_controls_check = 0;
	unsigned priv_user_controls_check = 0;
	unsigned class_count = 0;

	for (;;) {
		memset(&qctrl, 0xff, sizeof(qctrl));
		qctrl.id = id | V4L2_CTRL_FLAG_NEXT_CTRL;
		ret = doioctl(node, VIDIOC_QUERYCTRL, &qctrl);
		if (ret == ENOTTY)
			return ret;
		if (ret && ret != EINVAL)
			return fail("invalid queryctrl return code\n");
		if (ret)
			break;
		if (checkQCtrl(node, qctrl))
			return fail("invalid control %08x\n", qctrl.id);
		if (qctrl.id <= id)
			return fail("id did not increase!\n");
		id = qctrl.id;
		if (id >= V4L2_CID_PRIVATE_BASE)
			return fail("no V4L2_CID_PRIVATE_BASE allowed\n");
		if (V4L2_CTRL_ID2CLASS(id) != ctrl_class) {
			if (ctrl_class && !found_ctrl_class)
				return fail("missing control class for class %08x\n", ctrl_class);
			if (ctrl_class && !class_count)
				return fail("no controls in class %08x\n", ctrl_class);
			ctrl_class = V4L2_CTRL_ID2CLASS(id);
			found_ctrl_class = false;
			class_count = 0;
		}
		if (qctrl.type == V4L2_CTRL_TYPE_CTRL_CLASS) {
			found_ctrl_class = true;
		} else {
			class_count++;
		}

		if (ctrl_class == V4L2_CTRL_CLASS_USER &&
		    qctrl.type != V4L2_CTRL_TYPE_INTEGER64 &&
		    qctrl.type != V4L2_CTRL_TYPE_STRING &&
		    qctrl.type != V4L2_CTRL_TYPE_CTRL_CLASS) {
			if (V4L2_CTRL_DRIVER_PRIV(id))
				priv_user_controls_check++;
			else if (id < V4L2_CID_LASTP1)
				user_controls_check++;
		}
		if (V4L2_CTRL_DRIVER_PRIV(id))
			node->priv_controls++;
		else
			node->std_controls++;
		node->controls.push_back(qctrl);
	}
	if (ctrl_class && !found_ctrl_class)
		return fail("missing control class for class %08x\n", ctrl_class);
	if (ctrl_class && !class_count)
		return fail("no controls in class %08x\n", ctrl_class);

	for (id = V4L2_CID_BASE; id < V4L2_CID_LASTP1; id++) {
		memset(&qctrl, 0xff, sizeof(qctrl));
		qctrl.id = id;
		ret = doioctl(node, VIDIOC_QUERYCTRL, &qctrl);
		if (ret && ret != EINVAL)
			return fail("invalid queryctrl return code\n");
		if (ret)
			continue;
		if (qctrl.id != id)
			return fail("qctrl.id (%08x) != id (%08x)\n",
					qctrl.id, id);
		if (checkQCtrl(node, qctrl))
			return fail("invalid control %08x\n", qctrl.id);
		user_controls++;
	}

	for (id = V4L2_CID_PRIVATE_BASE; ; id++) {
		memset(&qctrl, 0xff, sizeof(qctrl));
		qctrl.id = id;
		ret = doioctl(node, VIDIOC_QUERYCTRL, &qctrl);
		if (ret && ret != EINVAL)
			return fail("invalid queryctrl return code\n");
		if (ret)
			break;
		if (qctrl.id != id)
			return fail("qctrl.id (%08x) != id (%08x)\n",
					qctrl.id, id);
		if (checkQCtrl(node, qctrl))
			return fail("invalid control %08x\n", qctrl.id);
		priv_user_controls++;
	}

	if (priv_user_controls + user_controls && node->controls.empty())
		return fail("does not support V4L2_CTRL_FLAG_NEXT_CTRL\n");
	if (user_controls != user_controls_check)
		return fail("expected %d user controls, got %d\n",
			user_controls_check, user_controls);
	if (priv_user_controls != priv_user_controls_check)
		return fail("expected %d private controls, got %d\n",
			priv_user_controls_check, priv_user_controls);
	return 0;
}
示例#2
0
void common_get(int fd)
{
	if (options[OptGetCtrl] && !get_ctrls.empty()) {
		struct v4l2_ext_controls ctrls;
		class2ctrls_map class2ctrls;
		bool use_ext_ctrls = false;

		memset(&ctrls, 0, sizeof(ctrls));
		for (ctrl_get_list::iterator iter = get_ctrls.begin();
				iter != get_ctrls.end(); ++iter) {
			struct v4l2_ext_control ctrl;
			struct v4l2_query_ext_ctrl &qc = ctrl_str2q[*iter];

			memset(&ctrl, 0, sizeof(ctrl));
			ctrl.id = qc.id;
			if (qc.type == V4L2_CTRL_TYPE_INTEGER64)
				use_ext_ctrls = true;
			if (qc.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD) {
				use_ext_ctrls = true;
				ctrl.size = qc.elems * qc.elem_size;
				ctrl.ptr = calloc(1, ctrl.size);
			}
			if (V4L2_CTRL_DRIVER_PRIV(ctrl.id))
				use_ext_ctrls = true;
			class2ctrls[V4L2_CTRL_ID2CLASS(ctrl.id)].push_back(ctrl);
		}
		for (class2ctrls_map::iterator iter = class2ctrls.begin();
				iter != class2ctrls.end(); ++iter) {
			if (!use_ext_ctrls &&
			    (iter->first == V4L2_CTRL_CLASS_USER ||
			     iter->first == V4L2_CID_PRIVATE_BASE)) {
				for (unsigned i = 0; i < iter->second.size(); i++) {
					struct v4l2_control ctrl;

					ctrl.id = iter->second[i].id;
					doioctl(fd, VIDIOC_G_CTRL, &ctrl);
					printf("%s: %d\n", ctrl_id2str[ctrl.id].c_str(), ctrl.value);
				}
				continue;
			}
			if (iter->second.size()) {
				ctrls.ctrl_class = iter->first;
				ctrls.count = iter->second.size();
				ctrls.controls = &iter->second[0];
				doioctl(fd, VIDIOC_G_EXT_CTRLS, &ctrls);
				for (unsigned i = 0; i < iter->second.size(); i++) {
					struct v4l2_ext_control ctrl = iter->second[i];
					std::string &name = ctrl_id2str[ctrl.id];
					struct v4l2_query_ext_ctrl &qc = ctrl_str2q[name];

					if (qc.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD) {
						switch (qc.type) {
						case V4L2_CTRL_TYPE_U8:
						case V4L2_CTRL_TYPE_U16:
						case V4L2_CTRL_TYPE_U32:
							print_array(qc, ctrl.ptr);
							break;
						case V4L2_CTRL_TYPE_STRING:
							printf("%s: '%s'\n", name.c_str(),
								safename(ctrl.string).c_str());
							break;
						default:
							fprintf(stderr, "%s: unsupported payload type\n",
									qc.name);
							break;
						}
					} else
						printf("%s: %d\n", name.c_str(), ctrl.value);
				}
			}
		}
	}

	if (options[OptGetPriority]) {
		if (doioctl(fd, VIDIOC_G_PRIORITY, &prio) == 0)
			printf("Priority: %d\n", prio);
	}

	if (options[OptLogStatus]) {
		static char buf[40960];
		int len = -1;

		if (doioctl(fd, VIDIOC_LOG_STATUS, NULL) == 0) {
			printf("\nStatus Log:\n\n");
#ifdef HAVE_KLOGCTL
			len = klogctl(3, buf, sizeof(buf) - 1);
#endif
			if (len >= 0) {
				char *p = buf;
				char *q;

				buf[len] = 0;
				while ((q = strstr(p, "START STATUS"))) {
					p = q + 1;
				}
				if (p) {
					while (p > buf && *p != '<') p--;
					q = p;
					while ((q = strstr(q, "<6>"))) {
						memcpy(q, "   ", 3);
					}
					printf("%s", p);
				}
			}
		}
	}
}
示例#3
0
void common_set(int fd)
{
	if (options[OptSetPriority]) {
		if (doioctl(fd, VIDIOC_S_PRIORITY, &prio) >= 0) {
			printf("Priority set: %d\n", prio);
		}
	}

	if (options[OptSetCtrl] && !set_ctrls.empty()) {
		struct v4l2_ext_controls ctrls;
		class2ctrls_map class2ctrls;
		bool use_ext_ctrls = false;

		memset(&ctrls, 0, sizeof(ctrls));
		for (ctrl_set_map::iterator iter = set_ctrls.begin();
				iter != set_ctrls.end(); ++iter) {
			struct v4l2_ext_control ctrl;
			struct v4l2_query_ext_ctrl &qc = ctrl_str2q[iter->first];

			memset(&ctrl, 0, sizeof(ctrl));
			ctrl.id = qc.id;
			if (qc.type == V4L2_CTRL_TYPE_INTEGER64)
				use_ext_ctrls = true;
			if (qc.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD) {
				struct v4l2_ext_controls ctrls = { 0, 1 };
				unsigned divide[V4L2_CTRL_MAX_DIMS] = { 0 };
				ctrl_subset subset;
				long long v;
				unsigned d, i;

				use_ext_ctrls = true;
				ctrl.size = qc.elems * qc.elem_size;
				ctrl.ptr = malloc(ctrl.size);

				ctrls.controls = &ctrl;
				ioctl(fd, VIDIOC_G_EXT_CTRLS, &ctrls);

				if (fill_subset(qc, subset))
					return;

				divide[qc.nr_of_dims - 1] = 1;
				for (d = 0; d < qc.nr_of_dims - 1; d++) {
					divide[d] = qc.dims[d + 1];
					for (i = 0; i < d; i++)
						divide[i] *= divide[d];
				}


				switch (qc.type) {
				case V4L2_CTRL_TYPE_U8:
					v = strtoul(iter->second.c_str(), NULL, 0);
					for (i = 0; i < qc.elems; i++)
						if (idx_in_subset(qc, subset, divide, i))
							ctrl.p_u8[i] = v;
					break;
				case V4L2_CTRL_TYPE_U16:
					v = strtoul(iter->second.c_str(), NULL, 0);
					for (i = 0; i < qc.elems; i++)
						if (idx_in_subset(qc, subset, divide, i))
							ctrl.p_u16[i] = v;
					break;
				case V4L2_CTRL_TYPE_U32:
					v = strtoul(iter->second.c_str(), NULL, 0);
					for (i = 0; i < qc.elems; i++)
						if (idx_in_subset(qc, subset, divide, i))
							ctrl.p_u32[i] = v;
					break;
				case V4L2_CTRL_TYPE_STRING:
					strncpy(ctrl.string, iter->second.c_str(), qc.maximum);
					ctrl.string[qc.maximum] = 0;
					break;
				default:
					fprintf(stderr, "%s: unsupported payload type\n",
							qc.name);
					break;
				}
			} else {
				if (V4L2_CTRL_DRIVER_PRIV(ctrl.id))
					use_ext_ctrls = true;
				ctrl.value = strtol(iter->second.c_str(), NULL, 0);
			}
			class2ctrls[V4L2_CTRL_ID2CLASS(ctrl.id)].push_back(ctrl);
		}
		for (class2ctrls_map::iterator iter = class2ctrls.begin();
				iter != class2ctrls.end(); ++iter) {
			if (!use_ext_ctrls &&
			    (iter->first == V4L2_CTRL_CLASS_USER ||
			     iter->first == V4L2_CID_PRIVATE_BASE)) {
				for (unsigned i = 0; i < iter->second.size(); i++) {
					struct v4l2_control ctrl;

					ctrl.id = iter->second[i].id;
					ctrl.value = iter->second[i].value;
					if (doioctl(fd, VIDIOC_S_CTRL, &ctrl)) {
						fprintf(stderr, "%s: %s\n",
								ctrl_id2str[ctrl.id].c_str(),
								strerror(errno));
					}
				}
				continue;
			}
			if (iter->second.size()) {
				ctrls.ctrl_class = iter->first;
				ctrls.count = iter->second.size();
				ctrls.controls = &iter->second[0];
				if (doioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls)) {
					if (ctrls.error_idx >= ctrls.count) {
						fprintf(stderr, "Error setting controls: %s\n",
								strerror(errno));
					}
					else {
						fprintf(stderr, "%s: %s\n",
								ctrl_id2str[iter->second[ctrls.error_idx].id].c_str(),
								strerror(errno));
					}
				}
			}
		}
	}
}
示例#4
0
void common_get(int fd)
{
	if (options[OptGetCtrl] && !get_ctrls.empty()) {
		struct v4l2_ext_controls ctrls;
		class2ctrls_map class2ctrls;
		bool use_ext_ctrls = false;

		memset(&ctrls, 0, sizeof(ctrls));
		for (ctrl_get_list::iterator iter = get_ctrls.begin();
				iter != get_ctrls.end(); ++iter) {
			struct v4l2_ext_control ctrl;

			memset(&ctrl, 0, sizeof(ctrl));
			ctrl.id = ctrl_str2q[*iter].id;
			if (ctrl_str2q[*iter].type == V4L2_CTRL_TYPE_INTEGER64)
				use_ext_ctrls = true;
			if (ctrl_str2q[*iter].type == V4L2_CTRL_TYPE_STRING) {
				use_ext_ctrls = true;
				ctrl.size = ctrl_str2q[*iter].maximum + 1;
				ctrl.string = (char *)malloc(ctrl.size);
				ctrl.string[0] = 0;
			}
			if (V4L2_CTRL_DRIVER_PRIV(ctrl.id))
				use_ext_ctrls = true;
			class2ctrls[V4L2_CTRL_ID2CLASS(ctrl.id)].push_back(ctrl);
		}
		for (class2ctrls_map::iterator iter = class2ctrls.begin();
				iter != class2ctrls.end(); ++iter) {
			if (!use_ext_ctrls &&
			    (iter->first == V4L2_CTRL_CLASS_USER ||
			     iter->first == V4L2_CID_PRIVATE_BASE)) {
				for (unsigned i = 0; i < iter->second.size(); i++) {
					struct v4l2_control ctrl;

					ctrl.id = iter->second[i].id;
					doioctl(fd, VIDIOC_G_CTRL, &ctrl);
					printf("%s: %d\n", ctrl_id2str[ctrl.id].c_str(), ctrl.value);
				}
				continue;
			}
			if (iter->second.size()) {
				ctrls.ctrl_class = iter->first;
				ctrls.count = iter->second.size();
				ctrls.controls = &iter->second[0];
				doioctl(fd, VIDIOC_G_EXT_CTRLS, &ctrls);
				for (unsigned i = 0; i < iter->second.size(); i++) {
					struct v4l2_ext_control ctrl = iter->second[i];

					if (ctrl_str2q[ctrl_id2str[ctrl.id]].type == V4L2_CTRL_TYPE_STRING)
						printf("%s: '%s'\n", ctrl_id2str[ctrl.id].c_str(),
							       safename(ctrl.string).c_str());
					else
						printf("%s: %d\n", ctrl_id2str[ctrl.id].c_str(), ctrl.value);
				}
			}
		}
	}

	if (options[OptGetPriority]) {
		if (doioctl(fd, VIDIOC_G_PRIORITY, &prio) == 0)
			printf("Priority: %d\n", prio);
	}

	if (options[OptLogStatus]) {
		static char buf[40960];
		int len = -1;

		if (doioctl(fd, VIDIOC_LOG_STATUS, NULL) == 0) {
			printf("\nStatus Log:\n\n");
#ifdef HAVE_KLOGCTL
			len = klogctl(3, buf, sizeof(buf) - 1);
#endif
			if (len >= 0) {
				char *p = buf;
				char *q;

				buf[len] = 0;
				while ((q = strstr(p, "START STATUS"))) {
					p = q + 1;
				}
				if (p) {
					while (p > buf && *p != '<') p--;
					q = p;
					while ((q = strstr(q, "<6>"))) {
						memcpy(q, "   ", 3);
					}
					printf("%s", p);
				}
			}
		}
	}
}
示例#5
0
void common_set(int fd)
{
	if (options[OptSetPriority]) {
		if (doioctl(fd, VIDIOC_S_PRIORITY, &prio) >= 0) {
			printf("Priority set: %d\n", prio);
		}
	}

	if (options[OptSetCtrl] && !set_ctrls.empty()) {
		struct v4l2_ext_controls ctrls;
		class2ctrls_map class2ctrls;
		bool use_ext_ctrls = false;

		memset(&ctrls, 0, sizeof(ctrls));
		for (ctrl_set_map::iterator iter = set_ctrls.begin();
				iter != set_ctrls.end(); ++iter) {
			struct v4l2_ext_control ctrl;

			memset(&ctrl, 0, sizeof(ctrl));
			ctrl.id = ctrl_str2q[iter->first].id;
			if (ctrl_str2q[iter->first].type == V4L2_CTRL_TYPE_INTEGER64)
				use_ext_ctrls = true;
			if (ctrl_str2q[iter->first].type == V4L2_CTRL_TYPE_STRING) {
				unsigned len = iter->second.length();
				unsigned maxlen = ctrl_str2q[iter->first].maximum;

				use_ext_ctrls = true;
				ctrl.size = maxlen + 1;
				ctrl.string = (char *)malloc(ctrl.size);
				if (len > maxlen) {
					memcpy(ctrl.string, iter->second.c_str(), maxlen);
					ctrl.string[maxlen] = 0;
				}
				else {
					strcpy(ctrl.string, iter->second.c_str());
				}
			} else {
				if (V4L2_CTRL_DRIVER_PRIV(ctrl.id))
					use_ext_ctrls = true;
				ctrl.value = strtol(iter->second.c_str(), NULL, 0);
			}
			class2ctrls[V4L2_CTRL_ID2CLASS(ctrl.id)].push_back(ctrl);
		}
		for (class2ctrls_map::iterator iter = class2ctrls.begin();
				iter != class2ctrls.end(); ++iter) {
			if (!use_ext_ctrls &&
			    (iter->first == V4L2_CTRL_CLASS_USER ||
			     iter->first == V4L2_CID_PRIVATE_BASE)) {
				for (unsigned i = 0; i < iter->second.size(); i++) {
					struct v4l2_control ctrl;

					ctrl.id = iter->second[i].id;
					ctrl.value = iter->second[i].value;
					if (doioctl(fd, VIDIOC_S_CTRL, &ctrl)) {
						fprintf(stderr, "%s: %s\n",
								ctrl_id2str[ctrl.id].c_str(),
								strerror(errno));
					}
				}
				continue;
			}
			if (iter->second.size()) {
				ctrls.ctrl_class = iter->first;
				ctrls.count = iter->second.size();
				ctrls.controls = &iter->second[0];
				if (doioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls)) {
					if (ctrls.error_idx >= ctrls.count) {
						fprintf(stderr, "Error setting MPEG controls: %s\n",
								strerror(errno));
					}
					else {
						fprintf(stderr, "%s: %s\n",
								ctrl_id2str[iter->second[ctrls.error_idx].id].c_str(),
								strerror(errno));
					}
				}
			}
		}
	}
}
void ApplicationWindow::addTabs()
{
	v4l2_queryctrl qctrl;
	unsigned ctrl_class;
	unsigned i;
	int id;

	memset(&qctrl, 0, sizeof(qctrl));
	qctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL;
	while (queryctrl(qctrl)) {
		if (is_valid_type(qctrl.type) &&
		    (qctrl.flags & V4L2_CTRL_FLAG_DISABLED) == 0) {
			m_ctrlMap[qctrl.id] = qctrl;
			if (qctrl.type != V4L2_CTRL_TYPE_CTRL_CLASS)
				m_classMap[V4L2_CTRL_ID2CLASS(qctrl.id)].push_back(qctrl.id);
		}
		qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
	}
	if (qctrl.id == V4L2_CTRL_FLAG_NEXT_CTRL) {
		strcpy((char *)qctrl.name, "User Controls");
		qctrl.id = V4L2_CTRL_CLASS_USER | 1;
		qctrl.type = V4L2_CTRL_TYPE_CTRL_CLASS;
		m_ctrlMap[qctrl.id] = qctrl;
		for (id = V4L2_CID_USER_BASE; id < V4L2_CID_LASTP1; id++) {
			qctrl.id = id;
			if (!queryctrl(qctrl))
				continue;
			if (!is_valid_type(qctrl.type))
				continue;
			if (qctrl.flags & V4L2_CTRL_FLAG_DISABLED)
				continue;
			m_ctrlMap[qctrl.id] = qctrl;
			m_classMap[V4L2_CTRL_CLASS_USER].push_back(qctrl.id);
		}
		for (qctrl.id = V4L2_CID_PRIVATE_BASE;
				queryctrl(qctrl); qctrl.id++) {
			if (!is_valid_type(qctrl.type))
				continue;
			if (qctrl.flags & V4L2_CTRL_FLAG_DISABLED)
				continue;
			m_ctrlMap[qctrl.id] = qctrl;
			m_classMap[V4L2_CTRL_CLASS_USER].push_back(qctrl.id);
		}
	}
	
	m_haveExtendedUserCtrls = false;
	for (unsigned i = 0; i < m_classMap[V4L2_CTRL_CLASS_USER].size(); i++) {
		unsigned id = m_classMap[V4L2_CTRL_CLASS_USER][i];

		if (m_ctrlMap[id].type == V4L2_CTRL_TYPE_INTEGER64 ||
		    m_ctrlMap[id].type == V4L2_CTRL_TYPE_STRING ||
		    V4L2_CTRL_DRIVER_PRIV(id)) {
			m_haveExtendedUserCtrls = true;
			break;
		}
	}

	for (ClassMap::iterator iter = m_classMap.begin(); iter != m_classMap.end(); ++iter) {
		if (iter->second.size() == 0)
			continue;
		ctrl_class = V4L2_CTRL_ID2CLASS(iter->second[0]);
		id = ctrl_class | 1;
		m_col = m_row = 0;
		m_cols = 4;

		const v4l2_queryctrl &qctrl = m_ctrlMap[id];
		QWidget *t = new QWidget(m_tabs);
		QVBoxLayout *vbox = new QVBoxLayout(t);
		QWidget *w = new QWidget(t);

		vbox->addWidget(w);

		QGridLayout *grid = new QGridLayout(w);

		grid->setSpacing(3);
		m_tabs->addTab(t, (char *)qctrl.name);
		for (i = 0; i < iter->second.size(); i++) {
			if (i & 1)
				id = iter->second[(1+iter->second.size()) / 2 + i / 2];
			else
				id = iter->second[i / 2];
			addCtrl(grid, m_ctrlMap[id]);
		}
		grid->addWidget(new QWidget(w), grid->rowCount(), 0, 1, m_cols);
		grid->setRowStretch(grid->rowCount() - 1, 1);
		w = new QWidget(t);
		vbox->addWidget(w);
		grid = new QGridLayout(w);
		finishGrid(grid, ctrl_class);
	}
}