// SPDX-License-Identifier: GPL-2.0-only /* * cec-api.c - HDMI Consumer Electronics Control framework - API * * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
*/
/* * Exclusive initiators and followers can always access the CEC adapter
*/ if (valid_initiator || valid_follower) returnfalse; /* * All others can only access the CEC adapter if there is no * exclusive initiator and they are in INITIATOR mode.
*/ return adap->cec_initiator ||
fh->mode_initiator == CEC_MODE_NO_INITIATOR;
}
staticint cec_validate_phys_addr(u16 phys_addr)
{ int i;
if (phys_addr == CEC_PHYS_ADDR_INVALID) return0; for (i = 0; i < 16; i += 4) if (phys_addr & (0xf << i)) break; if (i == 16) return0; for (i += 4; i < 16; i += 4) if ((phys_addr & (0xf << i)) == 0) return -EINVAL; return0;
}
mutex_lock(&adap->lock); /* * We use memcpy here instead of assignment since there is a * hole at the end of struct cec_log_addrs that an assignment * might ignore. So when we do copy_to_user() we could leak * one byte of memory.
*/
memcpy(&log_addrs, &adap->log_addrs, sizeof(log_addrs)); if (!adap->is_configured)
memset(log_addrs.log_addr, CEC_LOG_ADDR_INVALID, sizeof(log_addrs.log_addr));
mutex_unlock(&adap->lock);
if (copy_to_user(parg, &log_addrs, sizeof(log_addrs))) return -EFAULT; return0;
}
/* Called by CEC_RECEIVE: wait for a message to arrive */ staticint cec_receive_msg(struct cec_fh *fh, struct cec_msg *msg, bool block)
{
u32 timeout = msg->timeout; int res;
do {
mutex_lock(&fh->lock); /* Are there received messages queued up? */ if (fh->queued_msgs) { /* Yes, return the first one */ struct cec_msg_entry *entry =
list_first_entry(&fh->msgs, struct cec_msg_entry, list);
list_del(&entry->list);
*msg = entry->msg;
kfree(entry);
fh->queued_msgs--;
mutex_unlock(&fh->lock); /* restore original timeout value */
msg->timeout = timeout; return0;
}
/* No, return EAGAIN in non-blocking mode or wait */
mutex_unlock(&fh->lock);
/* Return when in non-blocking mode */ if (!block) return -EAGAIN;
if (msg->timeout) { /* The user specified a timeout */
res = wait_event_interruptible_timeout(fh->wait,
fh->queued_msgs,
msecs_to_jiffies(msg->timeout)); if (res == 0)
res = -ETIMEDOUT; elseif (res > 0)
res = 0;
} else { /* Wait indefinitely */
res = wait_event_interruptible(fh->wait,
fh->queued_msgs);
} /* Exit on error, otherwise loop to get the new message */
} while (!res); return res;
}
switch (cmd) { case CEC_ADAP_G_CAPS: return cec_adap_g_caps(adap, parg);
case CEC_ADAP_G_PHYS_ADDR: return cec_adap_g_phys_addr(adap, parg);
case CEC_ADAP_S_PHYS_ADDR: return cec_adap_s_phys_addr(adap, fh, block, parg);
case CEC_ADAP_G_LOG_ADDRS: return cec_adap_g_log_addrs(adap, parg);
case CEC_ADAP_S_LOG_ADDRS: return cec_adap_s_log_addrs(adap, fh, block, parg);
case CEC_ADAP_G_CONNECTOR_INFO: return cec_adap_g_connector_info(adap, parg);
case CEC_TRANSMIT: return cec_transmit(adap, fh, block, parg);
case CEC_RECEIVE: return cec_receive(adap, fh, block, parg);
case CEC_DQEVENT: return cec_dqevent(adap, fh, block, parg);
case CEC_G_MODE: return cec_g_mode(adap, fh, parg);
case CEC_S_MODE: return cec_s_mode(adap, fh, parg);
default: return -ENOTTY;
}
}
staticint cec_open(struct inode *inode, struct file *filp)
{ struct cec_devnode *devnode =
container_of(inode->i_cdev, struct cec_devnode, cdev); struct cec_adapter *adap = to_cec_adapter(devnode); struct cec_fh *fh = kzalloc(sizeof(*fh), GFP_KERNEL); /* * Initial events that are automatically sent when the cec device is * opened.
*/ struct cec_event ev = {
.event = CEC_EVENT_STATE_CHANGE,
.flags = CEC_EVENT_FL_INITIAL_STATE,
}; unsignedint i; int err;
if (!fh) return -ENOMEM;
INIT_LIST_HEAD(&fh->msgs);
INIT_LIST_HEAD(&fh->xfer_list); for (i = 0; i < CEC_NUM_EVENTS; i++)
INIT_LIST_HEAD(&fh->events[i]);
mutex_init(&fh->lock);
init_waitqueue_head(&fh->wait);
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.13Bemerkung:
(vorverarbeitet am 2026-06-07)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.