media: vivid: add <Vendor Command With ID> support

This makes it possible to test the new CEC_MSG_FL_REPLY_VENDOR_ID flag.

The vivid driver will Feature Abort any messages that do not have
exactly 1 payload byte. It ignores messages where the payload byte is
even, and where it is odd it will reply with the payload byte incremented
by 1. Basically a simple ping-pong command.

Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
This commit is contained in:
Hans Verkuil 2024-07-25 10:06:39 +02:00 committed by Mauro Carvalho Chehab
parent 613f21505b
commit 812765cd69

View File

@ -316,15 +316,16 @@ static int vivid_received(struct cec_adapter *adap, struct cec_msg *msg)
struct vivid_dev *dev = cec_get_drvdata(adap);
struct cec_msg reply;
u8 dest = cec_msg_destination(msg);
u8 disp_ctl;
char osd[14];
if (cec_msg_is_broadcast(msg))
dest = adap->log_addrs.log_addr[0];
cec_msg_init(&reply, dest, cec_msg_initiator(msg));
switch (cec_msg_opcode(msg)) {
case CEC_MSG_SET_OSD_STRING:
case CEC_MSG_SET_OSD_STRING: {
u8 disp_ctl;
char osd[14];
if (!cec_is_sink(adap))
return -ENOMSG;
cec_ops_set_osd_string(msg, &disp_ctl, osd);
@ -348,6 +349,47 @@ static int vivid_received(struct cec_adapter *adap, struct cec_msg *msg)
break;
}
break;
}
case CEC_MSG_VENDOR_COMMAND_WITH_ID: {
u32 vendor_id;
u8 size;
const u8 *vendor_cmd;
/*
* If we receive <Vendor Command With ID> with our vendor ID
* and with a payload of size 1, and the payload value is odd,
* then we reply with the same message, but with the payload
* byte incremented by 1.
*
* If the size is 1 and the payload value is even, then we
* ignore the message.
*
* The reason we reply to odd instead of even payload values
* is that it allows for testing of the corner case where the
* reply value is 0 (0xff + 1 % 256).
*
* For other sizes we Feature Abort.
*
* This is added for the specific purpose of testing the
* CEC_MSG_FL_REPLY_VENDOR_ID flag using vivid.
*/
cec_ops_vendor_command_with_id(msg, &vendor_id, &size, &vendor_cmd);
if (vendor_id != adap->log_addrs.vendor_id)
break;
if (size == 1) {
// Ignore even op values
if (!(vendor_cmd[0] & 1))
break;
reply.len = msg->len;
memcpy(reply.msg + 1, msg->msg + 1, msg->len - 1);
reply.msg[msg->len - 1]++;
} else {
cec_msg_feature_abort(&reply, cec_msg_opcode(msg),
CEC_OP_ABORT_INVALID_OP);
}
cec_transmit_msg(adap, &reply, false);
break;
}
default:
return -ENOMSG;
}