int testFormats(struct node *node)
{
	int type;
	int ret;

	for (type = 0; type <= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; type++) {
		ret = testFormatsType(node, (enum v4l2_buf_type)type);

		if (ret > 0)
			return ret;
		if (ret && (node->caps & buftype2cap[type]))
			return fail("%s cap set, but no %s formats defined\n",
					buftype2s(type).c_str(), buftype2s(type).c_str());
		if (!ret && !(node->caps & buftype2cap[type]))
			return fail("%s cap not set, but %s formats defined\n",
					buftype2s(type).c_str(), buftype2s(type).c_str());
	}

	ret = testFormatsType(node, V4L2_BUF_TYPE_PRIVATE);
	if (ret > 0)
		return ret;
	if (!ret)
		warn("Buffer type PRIVATE allowed!\n");
	return 0;
}
int testGetFormats(struct node *node)
{
	struct v4l2_format fmt;
	bool supported = false;
	int type;
	int ret;

	for (type = 0; type <= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; type++) {
		memset(&fmt, 0xff, sizeof(fmt));
		fmt.type = type;
		ret = doioctl(node, VIDIOC_G_FMT, &fmt);
		ret = testFormatsType(node, ret, type, fmt);

		if (ret && ret != ENOTTY)
			return ret;
		if (!ret) {
			supported = true;
			node->valid_buftypes |= 1 << type;
		}
		if (ret && (node->caps & buftype2cap[type]))
			return fail("%s cap set, but no %s formats defined\n",
					buftype2s(type).c_str(), buftype2s(type).c_str());
		if (!ret && !(node->caps & buftype2cap[type])) {
			switch (type) {
			case V4L2_BUF_TYPE_VIDEO_CAPTURE:
			case V4L2_BUF_TYPE_VIDEO_OUTPUT:
			case V4L2_BUF_TYPE_VIDEO_OVERLAY:
			case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
			case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
				return fail("%s cap not set, but %s formats defined\n",
					buftype2s(type).c_str(), buftype2s(type).c_str());
			default:
				/* ENUMFMT doesn't support other buftypes */
				break;
			}
		}
	}

	memset(&fmt, 0xff, sizeof(fmt));
	fmt.type = V4L2_BUF_TYPE_PRIVATE;
	ret = doioctl(node, VIDIOC_G_FMT, &fmt);
	ret = testFormatsType(node, ret, V4L2_BUF_TYPE_PRIVATE, fmt);
	if (ret && ret != ENOTTY)
		return ret;
	if (!ret) {
		supported = true;
		warn("Buffer type PRIVATE allowed!\n");
	}
	return supported ? 0 : ENOTTY;
}
int testTryFormats(struct node *node)
{
	struct v4l2_format fmt, fmt_try;
	int type;
	int ret;
	
	for (type = 0; type <= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; type++) {
		if (!(node->valid_buftypes & (1 << type)))
			continue;

		memset(&fmt, 0xff, sizeof(fmt));
		fmt.type = type;
		doioctl(node, VIDIOC_G_FMT, &fmt);
		fmt_try = fmt;
		ret = doioctl(node, VIDIOC_TRY_FMT, &fmt_try);
		if (ret)
			return fail("%s is valid, but no TRY_FMT was implemented\n",
					buftype2s(type).c_str());
		ret = testFormatsType(node, ret, type, fmt_try);
		if (ret)
			return ret;
		if (memcmp(&fmt, &fmt_try, sizeof(fmt)))
			return fail("TRY_FMT(G_FMT) != G_FMT\n");
	}

	for (type = 0; type <= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; type++) {
		if (!(node->valid_buftypes & (1 << type)))
			continue;

		memset(&fmt, 0xff, sizeof(fmt));
		fmt.type = type;
		fmt.fmt.pix.field = V4L2_FIELD_ANY;
		ret = doioctl(node, VIDIOC_TRY_FMT, &fmt);
		ret = testFormatsType(node, ret, type, fmt);
		if (ret)
			return fail("%s is valid, but TRY_FMT failed to return a format\n",
					buftype2s(type).c_str());
	}

	memset(&fmt, 0xff, sizeof(fmt));
	fmt.type = V4L2_BUF_TYPE_PRIVATE;
	ret = doioctl(node, VIDIOC_TRY_FMT, &fmt);
	if (!ret)
		warn("Buffer type PRIVATE allowed!\n");
	return node->valid_buftypes ? 0 : ENOTTY;
}