Beispiel #1
0
static int standby_resume_wakeup(struct node *node, unsigned me, unsigned la, bool interactive)
{
	if (!node->remote[la].in_standby)
		return NOTAPPLICABLE;

	int ret;

	if (is_tv(la, node->remote[la].prim_type))
		ret = wakeup_tv(node, me, la);
	else
		ret = wakeup_source(node, me, la);
	if (ret)
		return ret;

	unsigned unresponsive_time = 0;

	announce("Device is woken up");
	fail_on_test(!poll_stable_power_status(node, me, la, CEC_OP_POWER_STATUS_ON, unresponsive_time));
	fail_on_test(interactive && !question("Is the device in On state?"));

	if (unresponsive_time > 0)
		warn("The device went correctly out of standby, but became unresponsive for %d s during the transition.\n",
		     unresponsive_time);

	return 0;
}
int testReadWrite(struct node *node)
{
	bool can_rw = node->caps & V4L2_CAP_READWRITE;
	int fd_flags = fcntl(node->fd, F_GETFL);
	char buf = 0;
	int ret;

	fcntl(node->fd, F_SETFL, fd_flags | O_NONBLOCK);
	if (node->can_capture)
		ret = read(node->fd, &buf, 1);
	else
		ret = write(node->fd, &buf, 1);
	// Note: RDS can only return multiples of 3, so we accept
	// both 0 and 1 as return code.
	if (can_rw)
		fail_on_test((ret < 0 && errno != EAGAIN) || ret > 1);
	else
		fail_on_test(ret < 0 && errno != EINVAL);
	if (!can_rw)
		goto rw_exit;

	reopen(node);
	fcntl(node->fd, F_SETFL, fd_flags | O_NONBLOCK);

	/* check that the close cleared the busy flag */
	if (node->can_capture)
		ret = read(node->fd, &buf, 1);
	else
		ret = write(node->fd, &buf, 1);
	fail_on_test((ret < 0 && errno != EAGAIN) || ret > 1);
rw_exit:
	reopen(node);
	return 0;
}
Beispiel #3
0
static int standby_resume_standby_toggle(struct node *node, unsigned me, unsigned la, bool interactive)
{
	if (!node->remote[la].in_standby)
		return NOTAPPLICABLE;

	struct cec_msg msg = {};
	unsigned unresponsive_time = 0;
	__u8 new_status;

	node->remote[la].in_standby = false;

	/* Send Standby again to test that it is not acting like a toggle */
	announce("Sending Standby message.");
	cec_msg_init(&msg, me, la);
	cec_msg_standby(&msg);
	int res = doioctl(node, CEC_TRANSMIT, &msg);
	fail_on_test(res && res != ENONET);
	fail_on_test(cec_msg_status_is_abort(&msg));
	fail_on_test(wait_changing_power_status(node, me, la, new_status, unresponsive_time));
	fail_on_test(new_status != CEC_OP_POWER_STATUS_STANDBY);
	fail_on_test(interactive && !question("Is the device still in standby?"));
	node->remote[la].in_standby = true;
	if (unresponsive_time > 0)
		warn("The device went correctly into standby, but became unresponsive for %d s during the transition.\n",
		     unresponsive_time);

	return 0;
}
Beispiel #4
0
static int standby_resume_standby(struct node *node, unsigned me, unsigned la, bool interactive)
{
	if (!node->remote[la].has_power_status)
		return NOTAPPLICABLE;

	struct cec_msg msg = {};
	unsigned unresponsive_time = 0;

	fail_on_test(!util_interactive_ensure_power_state(node, me, la, interactive, CEC_OP_POWER_STATUS_ON));

	announce("Sending Standby message.");
	cec_msg_init(&msg, me, la);
	cec_msg_standby(&msg);
	fail_on_test(!transmit_timeout(node, &msg));
	fail_on_test(cec_msg_status_is_abort(&msg));
	fail_on_test(!poll_stable_power_status(node, me, la, CEC_OP_POWER_STATUS_STANDBY, unresponsive_time));
	fail_on_test(interactive && !question("Is the device in standby?"));
	node->remote[la].in_standby = true;

	if (unresponsive_time > 0)
		warn("The device went correctly into standby, but became unresponsive for %d s during the transition.\n",
		     unresponsive_time);

	return 0;
}
static int testParmType(struct node *node, unsigned type)
{
	struct v4l2_streamparm parm;
	int ret;

	memset(&parm, 0, sizeof(parm));
	parm.type = type;
	ret = doioctl(node, VIDIOC_G_PARM, &parm);
	if (ret == ENOTTY)
		return ret;
	if (ret == EINVAL)
		return ENOTTY;
	if (ret)
		return fail("expected EINVAL, but got %d when getting parms for buftype %d\n", ret, type);
	fail_on_test(parm.type != type);
	ret = testParmStruct(node, parm);
	if (ret)
		return ret;

	memset(&parm, 0, sizeof(parm));
	parm.type = type;
	ret = doioctl(node, VIDIOC_S_PARM, &parm);
	if (ret == ENOTTY)
		return 0;
	if (ret)
		return fail("got error %d when setting parms for buftype %d\n", ret, type);
	fail_on_test(parm.type != type);
	return testParmStruct(node, parm);
}
int testRegister(struct node *node)
{
	struct v4l2_dbg_register reg;
	struct v4l2_dbg_chip_ident chip;
	int ret;
	int uid = getuid();

	reg.match.type = V4L2_CHIP_MATCH_HOST;
	reg.match.addr = 0;
	reg.reg = 0;
	ret = doioctl(node, VIDIOC_DBG_G_REGISTER, &reg);
	if (ret == ENOTTY)
		return ret;
	// Not allowed to call VIDIOC_DBG_G_REGISTER unless root
	fail_on_test(uid && ret != EPERM);
	fail_on_test(uid == 0 && ret);
	chip.match.type = V4L2_CHIP_MATCH_HOST;
	chip.match.addr = 0;
	fail_on_test(doioctl(node, VIDIOC_DBG_G_CHIP_IDENT, &chip));
	if (uid) {
		// Don't test S_REGISTER as root, don't want to risk
		// messing with registers in the compliance test.
		reg.reg = reg.val = 0;
		ret = doioctl(node, VIDIOC_DBG_S_REGISTER, &reg);
		fail_on_test(ret != ENOTTY && ret != EINVAL && ret != EPERM);
	}
	return 0;
}
Beispiel #7
0
static int standby_resume_active_source_nowake(struct node *node, unsigned me, unsigned la, bool interactive)
{
	if (!node->remote[la].in_standby)
		return NOTAPPLICABLE;

	struct cec_msg msg = {};
	unsigned unresponsive_time = 0;
	__u8 new_status;

	node->remote[la].in_standby = false;

	/* In CEC 2.0 it is specified that a device shall not go out of standby
	   if an Active Source message is received. */
	announce("Sending Active Source message.");
	cec_msg_init(&msg, me, la);
	cec_msg_active_source(&msg, node->phys_addr);
	int res = doioctl(node, CEC_TRANSMIT, &msg);
	fail_on_test(res && res != ENONET);
	fail_on_test(wait_changing_power_status(node, me, la, new_status, unresponsive_time));
	fail_on_test_v2_warn(node->remote[la].cec_version, new_status != CEC_OP_POWER_STATUS_STANDBY);
	node->remote[la].in_standby = true;
	if (unresponsive_time > 0)
		warn("The device stayed correctly in standby, but became unresponsive for %d s.\n",
		     unresponsive_time);

	return 0;
}
int testReadWrite(struct node *node)
{
	bool can_rw = node->caps & V4L2_CAP_READWRITE;
	char buf = 0;
	int ret;

	if (node->can_capture)
		ret = read(node->fd, &buf, 1);
	else
		ret = write(node->fd, &buf, 1);
	// Note: RDS can only return multiples of 3, so we accept
	// both 0 and 1 as return code.
	if (can_rw)
		fail_on_test(ret != 0 && ret != 1);
	else
		fail_on_test(ret < 0 && errno != EINVAL);
	if (!can_rw)
		return 0;

	reopen(node);

	/* check that the close cleared the busy flag */
	if (node->can_capture)
		ret = read(node->fd, &buf, 1);
	else
		ret = write(node->fd, &buf, 1);
	fail_on_test(ret != 0 && ret != 1);
	reopen(node);
	return 0;
}
Beispiel #9
0
static int check_prio(struct node *node, struct node *node2, enum v4l2_priority match)
{
	enum v4l2_priority prio;

	// Must be able to get priority
	fail_on_test(doioctl(node, VIDIOC_G_PRIORITY, &prio));
	// Must match the expected prio
	fail_on_test(prio != match);
	fail_on_test(doioctl(node2, VIDIOC_G_PRIORITY, &prio));
	fail_on_test(prio != match);
	return 0;
}
Beispiel #10
0
static int wakeup_rc(struct node *node, unsigned me, unsigned la)
{
	struct cec_msg msg = {};
	struct cec_op_ui_command rc_press = {};

	/* Todo: A release should be sent after this */
	cec_msg_init(&msg, me, la);
	rc_press.ui_cmd = 0x6D;  /* Power On Function */
	cec_msg_user_control_pressed(&msg, &rc_press);
	fail_on_test(!transmit_timeout(node, &msg));
	fail_on_test(cec_msg_status_is_abort(&msg));

	return 0;
}
static int testSlicedVBICapType(struct node *node, unsigned type)
{
	struct v4l2_sliced_vbi_cap cap;
	bool sliced_type = (type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE ||
			    type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT);
	__u32 service_set = 0;
	int ret;

	memset(&cap, 0xff, sizeof(cap));
	memset(&cap.reserved, 0, sizeof(cap.reserved));
	cap.type = type;
	ret = doioctl(node, VIDIOC_G_SLICED_VBI_CAP, &cap);
	if (ret == ENOTTY) {
		fail_on_test(sliced_type && (node->caps & buftype2cap[type]));
		return ret;
	}
	fail_on_test(check_0(cap.reserved, sizeof(cap.reserved)));
	fail_on_test(cap.type != type);
	fail_on_test(ret && ret != EINVAL);
	fail_on_test(ret && sliced_type && (node->caps & buftype2cap[type]));
	fail_on_test(!ret && (!sliced_type || !(node->caps & buftype2cap[type])));
	if (ret)
		return 0;

	for (int f = 0; f < 2; f++)
		for (int i = 0; i < 24; i++)
			service_set |= cap.service_lines[f][i];
	fail_on_test(cap.service_set != service_set);
	fail_on_test(cap.service_lines[0][0] || cap.service_lines[1][0]);
	return 0;
}
int testChipIdent(struct node *node)
{
	struct v4l2_dbg_chip_ident chip;
	int ret;

	memset(&chip, 0, sizeof(chip));
	chip.match.type = V4L2_CHIP_MATCH_HOST;
	chip.match.addr = 0;
	ret = doioctl(node, VIDIOC_DBG_G_CHIP_IDENT, &chip);
	// Must return either 0 (OK) or EINVAL (not supported)
	if (ret == 0) {
		struct v4l2_dbg_chip_ident orig;

		memset(&orig, 0, sizeof(orig));
		// set invalid match_type
		chip.match.type = V4L2_CHIP_MATCH_I2C_ADDR + 1;
		chip.match.addr = 0xdeadbeef;
		chip.ident = 0xdeadbeef;
		chip.revision = 0xdeadbeef;
		orig = chip;
		ret = doioctl(node, VIDIOC_DBG_G_CHIP_IDENT, &chip);
		if (ret != EINVAL)
			return fail("Invalid match_type accepted\n");
		fail_on_test(memcmp(&orig, &chip, sizeof(chip)));
		return 0;
	}
	return ret;
}
int testEncIndex(struct node *node)
{
	struct v4l2_enc_idx idx;
	int ret;

	memset(&idx, 0xff, sizeof(idx));
	ret = doioctl(node, VIDIOC_G_ENC_INDEX, &idx);
	if (ret == ENOTTY)
		return ret;
	if (check_0(idx.reserved, sizeof(idx.reserved)))
		return fail("idx.reserved not zeroed\n");
	fail_on_test(ret);
	fail_on_test(idx.entries != 0);
	fail_on_test(idx.entries_cap == 0);
	return 0;
}
Beispiel #14
0
static int one_touch_play_view_on_wakeup(struct node *node, unsigned me, unsigned la, bool interactive,
					 __u8 opcode)
{
	fail_on_test(!util_interactive_ensure_power_state(node, me, la, interactive, CEC_OP_POWER_STATUS_STANDBY));

	int ret = one_touch_play_view_on(node, me, la, interactive, opcode);

	if (ret && ret != PRESUMED_OK)
		return ret;
	fail_on_test(interactive && !question("Did the TV turn on?"));

	if (interactive)
		return 0;
	else
		return PRESUMED_OK;
}
Beispiel #15
0
static int one_touch_play_req_active_source(struct node *node, unsigned me, unsigned la, bool interactive)
{
	struct cec_msg msg = {};

	cec_msg_init(&msg, me, la);
	cec_msg_active_source(&msg, node->phys_addr);
	fail_on_test(!transmit_timeout(node, &msg));

	/* We have now said that we are active source, so receiving a reply to
	   Request Active Source should fail the test. */
	cec_msg_init(&msg, me, la);
	cec_msg_request_active_source(&msg, true);
	fail_on_test(!transmit_timeout(node, &msg));
	fail_on_test(!timed_out(&msg));

	return 0;
}
int testDecoder(struct node *node)
{
	struct v4l2_decoder_cmd cmd;
	int ret;

	memset(&cmd, 0xff, sizeof(cmd));
	memset(&cmd.raw, 0, sizeof(cmd.raw));
	ret = doioctl(node, VIDIOC_DECODER_CMD, &cmd);
	if (ret == ENOTTY)
		return ret;
	fail_on_test(ret != EINVAL);
	ret = doioctl(node, VIDIOC_TRY_DECODER_CMD, &cmd);
	fail_on_test(ret == ENOTTY);
	fail_on_test(ret != EINVAL);
	cmd.cmd = V4L2_DEC_CMD_STOP;
	cmd.flags = V4L2_DEC_CMD_STOP_IMMEDIATELY;
	ret = doioctl(node, VIDIOC_TRY_DECODER_CMD, &cmd);
	fail_on_test(ret != 0);
	ret = doioctl(node, VIDIOC_DECODER_CMD, &cmd);
	fail_on_test(ret != 0);
	cmd.cmd = V4L2_DEC_CMD_PAUSE;
	cmd.flags = 0;
	ret = doioctl(node, VIDIOC_DECODER_CMD, &cmd);
	fail_on_test(ret != EPERM && ret != EINVAL);
	cmd.cmd = V4L2_DEC_CMD_RESUME;
	ret = doioctl(node, VIDIOC_DECODER_CMD, &cmd);
	fail_on_test(ret != EPERM && ret != EINVAL);
	return 0;
}
static int testSlicedVBICapType(struct node *node, enum v4l2_buf_type type)
{
	struct v4l2_sliced_vbi_cap cap;
	bool sliced_type = (type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE ||
			    type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT);
	__u32 service_set = 0;
	int ret;

	memset(&cap, 0xff, sizeof(cap));
	memset(&cap.reserved, 0, sizeof(cap.reserved));
	cap.type = type;
	ret = doioctl(node, VIDIOC_G_SLICED_VBI_CAP, &cap);
	fail_on_test(check_0(cap.reserved, sizeof(cap.reserved)));
	fail_on_test(cap.type != type);
	fail_on_test(ret && ret != EINVAL && sliced_type);
	if (ret == EINVAL) {
		fail_on_test(sliced_type && (node->caps & buftype2cap[type]));
		if (node->caps & (V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_OUTPUT))
			return 0;
		return -ENOSYS;
	}
	if (ret)
		return fail("expected EINVAL, but got %d when getting sliced VBI caps buftype %d\n", ret, type);
	fail_on_test(!(node->caps & buftype2cap[type]));

	for (int f = 0; f < 2; f++)
		for (int i = 0; i < 24; i++)
			service_set |= cap.service_lines[f][i];
	fail_on_test(cap.service_set != service_set);
	fail_on_test(cap.service_lines[0][0] || cap.service_lines[1][0]);
	return 0;
}
int testInput(struct node *node)
{
	struct v4l2_input descr;
	int cur_input = MAGIC;
	int input;
	int ret = doioctl(node, VIDIOC_G_INPUT, &cur_input);
	int i = 0;

	if (ret == ENOTTY) {
		descr.index = 0;
		ret = doioctl(node, VIDIOC_ENUMINPUT, &descr);
		if (ret != ENOTTY)
			return fail("G_INPUT not supported, but ENUMINPUT is\n");
		cur_input = 0;
		ret = doioctl(node, VIDIOC_S_INPUT, &cur_input);
		if (ret != ENOTTY)
			return fail("G_INPUT not supported, but S_INPUT is\n");
		return ENOTTY;
	}
	if (ret)
		return fail("could not get current input\n");
	if (cur_input == MAGIC)
		return fail("VIDIOC_G_INPUT didn't fill in the input\n");
	if (node->is_radio)
		return fail("radio can't have input support\n");
	for (;;) {
		memset(&descr, 0xff, sizeof(descr));
		descr.index = i;
		ret = doioctl(node, VIDIOC_ENUMINPUT, &descr);
		if (ret == EINVAL)
			break;
		if (ret)
			return fail("could not enumerate input %d\n", i);
		input = i;
		if (doioctl(node, VIDIOC_S_INPUT, &input))
			return fail("could not set input to %d\n", i);
		if (input != i)
			return fail("input set to %d, but becomes %d?!\n", i, input);
		if (checkInput(node, descr, i))
			return fail("invalid attributes for input %d\n", i);
		node->inputs++;
		i++;
	}
	input = i;
	if (doioctl(node, VIDIOC_S_INPUT, &input) != EINVAL)
		return fail("could set input to invalid input %d\n", i);
	if (doioctl(node, VIDIOC_S_INPUT, &cur_input))
		return fail("couldn't set input to the original input %d\n", cur_input);
	if (node->inputs && !node->has_inputs)
		return fail("inputs found, but no input capabilities set\n");
	if (!node->inputs && node->has_inputs)
		return fail("no inputs found, but input capabilities set\n");
	fail_on_test(node->is_m2m && node->inputs > 1);
	return 0;
}
Beispiel #19
0
static int power_status_give(struct node *node, unsigned me, unsigned la, bool interactive)
{
	struct cec_msg msg = { };

	cec_msg_init(&msg, me, la);
	cec_msg_give_device_power_status(&msg, true);
	fail_on_test(!transmit_timeout(node, &msg));
	fail_on_test(timed_out(&msg));
	fail_on_test(unrecognized_op(&msg));
	if (refused(&msg))
		return REFUSED;
	if (cec_msg_status_is_abort(&msg))
		return PRESUMED_OK;

	__u8 power_status;
	cec_ops_report_power_status(&msg, &power_status);
	fail_on_test(power_status >= 4);

	return 0;
}
Beispiel #20
0
static int wakeup_source(struct node *node, unsigned me, unsigned la)
{
	struct cec_msg msg = {};

	cec_msg_init(&msg, me, la);
	cec_msg_set_stream_path(&msg, node->remote[la].phys_addr);
	fail_on_test(!transmit_timeout(node, &msg));
	if (!cec_msg_status_is_abort(&msg))
		return 0;

	return wakeup_rc(node, me, la);
}
static int checkEnumFreqBands(struct node *node, __u32 tuner, __u32 type, __u32 caps)
{
	unsigned i;
	__u32 caps_union = 0;

	for (i = 0; ; i++) {
		struct v4l2_frequency_band band;
		int ret;

		memset(band.reserved, 0, sizeof(band.reserved));
		band.tuner = tuner;
		band.type = type;
		band.index = i;
		ret = doioctl(node, VIDIOC_ENUM_FREQ_BANDS, &band);
		if (ret == EINVAL && i)
			return 0;
		if (ret)
			return fail("couldn't get freq band\n");
		caps_union |= band.capability;
		if ((caps & V4L2_TUNER_CAP_LOW) != (band.capability & V4L2_TUNER_CAP_LOW))
			return fail("Inconsistent CAP_LOW usage\n");
		fail_on_test(band.rangehigh < band.rangelow);
		fail_on_test(band.index != i);
		fail_on_test(band.type != type);
		fail_on_test(band.tuner != tuner);
		fail_on_test((band.capability & V4L2_TUNER_CAP_FREQ_BANDS) == 0);
		check_0(band.reserved, sizeof(band.reserved));
	}
	fail_on_test(caps_union != caps);
	return 0;
}
Beispiel #22
0
static int testPrio(struct node *node, struct node *node2)
{
	enum v4l2_priority prio;
	int err;

	if (node->is_m2m) {
		fail_on_test(doioctl(node, VIDIOC_G_PRIORITY, &prio) != ENOTTY);
		return 0;
	}
	err = check_prio(node, node2, V4L2_PRIORITY_DEFAULT);
	if (err)
		return err;

	prio = V4L2_PRIORITY_RECORD;
	// Must be able to change priority
	fail_on_test(doioctl(node, VIDIOC_S_PRIORITY, &prio));
	// Must match the new prio
	fail_on_test(check_prio(node, node2, V4L2_PRIORITY_RECORD));

	prio = V4L2_PRIORITY_INTERACTIVE;
	// Going back to interactive on the other node must fail
	fail_on_test(!doioctl(node2, VIDIOC_S_PRIORITY, &prio));
	prio = V4L2_PRIORITY_INTERACTIVE;
	// Changing it on the first node must work.
	fail_on_test(doioctl(node, VIDIOC_S_PRIORITY, &prio));
	fail_on_test(check_prio(node, node2, V4L2_PRIORITY_INTERACTIVE));
	return 0;
}
static int testQueryBuf(struct node *node, unsigned type, unsigned count)
{
	struct v4l2_buffer buf;
	int ret;
	unsigned i;

	memset(&buf, 0, sizeof(buf));
	buf.type = type;
	for (i = 0; i < count; i++) {
		buf.index = i;
		fail_on_test(doioctl(node, VIDIOC_QUERYBUF, &buf));
		fail_on_test(buf.index != i);
		fail_on_test(buf.type != type);
		fail_on_test(buf.flags & (V4L2_BUF_FLAG_QUEUED |
					V4L2_BUF_FLAG_DONE |
					V4L2_BUF_FLAG_ERROR));
	}
	buf.index = count;
	ret = doioctl(node, VIDIOC_QUERYBUF, &buf);
	fail_on_test(ret != EINVAL);
	return 0;
}
Beispiel #24
0
static int one_touch_play_view_on_change(struct node *node, unsigned me, unsigned la, bool interactive,
					 __u8 opcode)
{
	struct cec_msg msg = {};
	int ret;

	fail_on_test(!util_interactive_ensure_power_state(node, me, la, interactive, CEC_OP_POWER_STATUS_ON));

	interactive_info(true, "Please switch the TV to another source.");
	ret = one_touch_play_view_on(node, me, la, interactive, opcode);
	if (ret && ret != PRESUMED_OK)
		return ret;
	cec_msg_init(&msg, me, la);
	cec_msg_active_source(&msg, node->phys_addr);
	fail_on_test(!transmit_timeout(node, &msg));
	fail_on_test(interactive && !question("Did the TV switch to this source?"));

	if (interactive)
		return 0;
	else
		return PRESUMED_OK;
}
Beispiel #25
0
static int power_status_report(struct node *node, unsigned me, unsigned la, bool interactive)
{
	struct cec_msg msg = {};

	cec_msg_init(&msg, me, la);
	cec_msg_report_power_status(&msg, CEC_OP_POWER_STATUS_ON);
	fail_on_test(!transmit_timeout(node, &msg));
	if (unrecognized_op(&msg))
		return NOTSUPPORTED;
	if (refused(&msg))
		return REFUSED;

	return PRESUMED_OK;
}
int testOutput(struct node *node)
{
	struct v4l2_output descr;
	int cur_output = MAGIC;
	int output;
	int ret = doioctl(node, VIDIOC_G_OUTPUT, &cur_output);
	int o = 0;

	if (ret == ENOTTY) {
		descr.index = 0;
		ret = doioctl(node, VIDIOC_ENUMOUTPUT, &descr);
		if (ret != ENOTTY)
			return fail("G_OUTPUT not supported, but ENUMOUTPUT is\n");
		output = 0;
		ret = doioctl(node, VIDIOC_S_OUTPUT, &output);
		if (ret != ENOTTY)
			return fail("G_OUTPUT not supported, but S_OUTPUT is\n");
	}
	if (ret)
		return ret;
	if (cur_output == MAGIC)
		return fail("VIDIOC_G_OUTPUT didn't fill in the output\n");
	for (;;) {
		memset(&descr, 0xff, sizeof(descr));
		descr.index = o;
		ret = doioctl(node, VIDIOC_ENUMOUTPUT, &descr);
		if (ret)
			break;
		output = o;
		if (doioctl(node, VIDIOC_S_OUTPUT, &output))
			return fail("could not set output to %d\n", o);
		if (output != o)
			return fail("output set to %d, but becomes %d?!\n", o, output);
		if (checkOutput(node, descr, o))
			return fail("invalid attributes for output %d\n", o);
		node->outputs++;
		o++;
	}
	output = o;
	if (doioctl(node, VIDIOC_S_OUTPUT, &output) != EINVAL)
		return fail("could set output to invalid output %d\n", o);
	if (doioctl(node, VIDIOC_S_OUTPUT, &cur_output))
		return fail("couldn't set output to the original output %d\n", cur_output);
	if (node->outputs && !node->has_outputs)
		return fail("outputs found, but no output capabilities set\n");
	if (!node->outputs && node->has_outputs)
		return fail("no outputs found, but output capabilities set\n");
	fail_on_test(node->is_m2m && node->outputs > 1);
	return 0;
}
static int checkTimingsCap(struct node *node, bool has_timings)
{
	struct v4l2_dv_timings_cap timingscap;
	int ret;

	memset(&timingscap, 0xff, sizeof(timingscap));
	ret = doioctl(node, VIDIOC_DV_TIMINGS_CAP, &timingscap);
	if (ret && has_timings)
		return fail("TIMINGS cap set, but could not get timings caps\n");
	if (!ret && !has_timings)
		return fail("TIMINGS cap not set, but could still get timings caps\n");
	if (ret && !has_timings)
		return 0;
	if (check_0(timingscap.reserved, sizeof(timingscap.reserved)))
		return fail("reserved not zeroed\n");
	fail_on_test(timingscap.type != V4L2_DV_BT_656_1120);
	if (check_0(timingscap.bt.reserved, sizeof(timingscap.bt.reserved)))
		return fail("reserved not zeroed\n");
	fail_on_test(timingscap.bt.min_width > timingscap.bt.max_width);
	fail_on_test(timingscap.bt.min_height > timingscap.bt.max_height);
	fail_on_test(timingscap.bt.min_pixelclock > timingscap.bt.max_pixelclock);
	return 0;
}
Beispiel #28
0
static int one_touch_play_view_on(struct node *node, unsigned me, unsigned la, bool interactive,
				  __u8 opcode)
{
	struct cec_msg msg = {};

	cec_msg_init(&msg, me, la);
	if (opcode == CEC_MSG_IMAGE_VIEW_ON)
		cec_msg_image_view_on(&msg);
	else if (opcode == CEC_MSG_TEXT_VIEW_ON)
		cec_msg_text_view_on(&msg);
	fail_on_test(!transmit_timeout(node, &msg));
	fail_on_test(is_tv(la, node->remote[la].prim_type) && unrecognized_op(&msg));
	if (refused(&msg))
		return REFUSED;
	if (cec_msg_status_is_abort(&msg))
		return PRESUMED_OK;
	if (opcode == CEC_MSG_IMAGE_VIEW_ON)
		node->remote[la].has_image_view_on = true;
	else if (opcode == CEC_MSG_TEXT_VIEW_ON)
		node->remote[la].has_text_view_on = true;

	return 0;
}
Beispiel #29
0
static int wakeup_tv(struct node *node, unsigned me, unsigned la)
{
	struct cec_msg msg = {};

	cec_msg_init(&msg, me, la);
	cec_msg_image_view_on(&msg);
	msg.timeout = 2000;
	int res = doioctl(node, CEC_TRANSMIT, &msg);
	if (res == ENONET && la == CEC_LOG_ADDR_TV) {
		msg.msg[0] = (CEC_LOG_ADDR_UNREGISTERED << 4) | la;
		res = doioctl(node, CEC_TRANSMIT, &msg);
	}
	fail_on_test(res || !(msg.tx_status & CEC_TX_STATUS_OK));
	if (!cec_msg_status_is_abort(&msg))
		return 0;

	cec_msg_init(&msg, me, la);
	cec_msg_text_view_on(&msg);
	fail_on_test(!transmit_timeout(node, &msg));
	if (!cec_msg_status_is_abort(&msg))
		return 0;

	return wakeup_rc(node, me, la);
}
static int checkModulator(struct node *node, const struct v4l2_modulator &mod, unsigned m)
{
	bool tv = !node->is_radio;

	if (mod.index != m)
		return fail("invalid index\n");
	if (check_ustring(mod.name, sizeof(mod.name)))
		return fail("invalid name\n");
	if (check_0(mod.reserved, sizeof(mod.reserved)))
		return fail("non-zero reserved fields\n");
	if (tv)
		return fail("currently only radio modulators are supported\n");
	if (!(mod.capability & V4L2_TUNER_CAP_LOW))
		return fail("V4L2_TUNER_CAP_LOW was not set for a radio modulator\n");
	if (mod.capability & (V4L2_TUNER_CAP_NORM |
					V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2))
		return fail("TV capabilities for radio modulator?\n");
	fail_on_test(!(mod.capability & V4L2_TUNER_CAP_FREQ_BANDS));
	if (mod.rangelow >= mod.rangehigh)
		return fail("rangelow >= rangehigh\n");
	if (mod.rangelow == 0 || mod.rangehigh == 0xffffffff)
		return fail("invalid rangelow or rangehigh\n");
	if (!(mod.capability & V4L2_TUNER_CAP_STEREO) &&
			(mod.txsubchans & V4L2_TUNER_SUB_STEREO))
		return fail("stereo subchan, but no stereo caps?\n");
	if (!(mod.capability & V4L2_TUNER_CAP_LANG1) &&
			(mod.txsubchans & V4L2_TUNER_SUB_LANG1))
		return fail("lang1 subchan, but no lang1 caps?\n");
	if (!(mod.capability & V4L2_TUNER_CAP_LANG2) &&
			(mod.txsubchans & V4L2_TUNER_SUB_LANG2))
		return fail("lang2 subchan, but no lang2 caps?\n");
	if (!(mod.capability & V4L2_TUNER_CAP_RDS) &&
			(mod.txsubchans & V4L2_TUNER_SUB_RDS))
		return fail("RDS subchan, but no RDS caps?\n");
	bool have_rds = mod.capability & V4L2_TUNER_CAP_RDS;
	bool have_rds_method = mod.capability &
                        (V4L2_TUNER_CAP_RDS_BLOCK_IO | V4L2_TUNER_CAP_RDS_CONTROLS);
	if (have_rds ^ have_rds_method)
		return fail("V4L2_TUNER_CAP_RDS is set, but not V4L2_TUNER_CAP_RDS_* or vice versa\n");
	if ((mod.capability & V4L2_TUNER_CAP_RDS_BLOCK_IO) &&
			!(node->caps & V4L2_CAP_READWRITE))
		return fail("V4L2_TUNER_CAP_RDS_BLOCK_IO is set, but not V4L2_CAP_READWRITE\n");
	if (!(mod.capability & V4L2_TUNER_CAP_RDS_BLOCK_IO) &&
			(node->caps & V4L2_CAP_READWRITE))
		return fail("V4L2_TUNER_CAP_RDS_BLOCK_IO is not set, but V4L2_CAP_READWRITE is\n");
	return checkEnumFreqBands(node, mod.index, V4L2_TUNER_RADIO, mod.capability);
}