Ejemplo n.º 1
0
void cec_register_cec_notifier(struct cec_adapter *adap,
			       struct cec_notifier *notifier)
{
	if (WARN_ON(!cec_is_registered(adap)))
		return;

	adap->notifier = notifier;
	cec_notifier_register(adap->notifier, adap, cec_cec_notify);
}
Ejemplo n.º 2
0
static long cec_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
	struct cec_fh *fh = filp->private_data;
	struct cec_adapter *adap = fh->adap;
	bool block = !(filp->f_flags & O_NONBLOCK);
	void __user *parg = (void __user *)arg;

	if (!cec_is_registered(adap))
		return -ENODEV;

	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_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;
	}
}
Ejemplo n.º 3
0
static __poll_t cec_poll(struct file *filp,
			     struct poll_table_struct *poll)
{
	struct cec_fh *fh = filp->private_data;
	struct cec_adapter *adap = fh->adap;
	__poll_t res = 0;

	if (!cec_is_registered(adap))
		return EPOLLERR | EPOLLHUP;
	mutex_lock(&adap->lock);
	if (adap->is_configured &&
	    adap->transmit_queue_sz < CEC_MAX_MSG_TX_QUEUE_SZ)
		res |= EPOLLOUT | EPOLLWRNORM;
	if (fh->queued_msgs)
		res |= EPOLLIN | EPOLLRDNORM;
	if (fh->total_queued_events)
		res |= EPOLLPRI;
	poll_wait(filp, &fh->wait, poll);
	mutex_unlock(&adap->lock);
	return res;
}
Ejemplo n.º 4
0
/* Override for the release function */
static int cec_release(struct inode *inode, struct file *filp)
{
	struct cec_devnode *devnode = cec_devnode_data(filp);
	struct cec_adapter *adap = to_cec_adapter(devnode);
	struct cec_fh *fh = filp->private_data;
	unsigned int i;

	mutex_lock(&adap->lock);
	if (adap->cec_initiator == fh)
		adap->cec_initiator = NULL;
	if (adap->cec_follower == fh) {
		adap->cec_follower = NULL;
		adap->passthrough = false;
	}
	if (fh->mode_follower == CEC_MODE_FOLLOWER)
		adap->follower_cnt--;
	if (fh->mode_follower == CEC_MODE_MONITOR_PIN)
		cec_monitor_pin_cnt_dec(adap);
	if (fh->mode_follower == CEC_MODE_MONITOR_ALL)
		cec_monitor_all_cnt_dec(adap);
	mutex_unlock(&adap->lock);

	mutex_lock(&devnode->lock);
	list_del(&fh->list);
	if (cec_is_registered(adap) && list_empty(&devnode->fhs) &&
	    !adap->needs_hpd && adap->phys_addr == CEC_PHYS_ADDR_INVALID) {
		WARN_ON(adap->ops->adap_enable(adap, false));
	}
	mutex_unlock(&devnode->lock);

	/* Unhook pending transmits from this filehandle. */
	mutex_lock(&adap->lock);
	while (!list_empty(&fh->xfer_list)) {
		struct cec_data *data =
			list_first_entry(&fh->xfer_list, struct cec_data, xfer_list);

		data->blocking = false;
		data->fh = NULL;
		list_del(&data->xfer_list);
	}
	mutex_unlock(&adap->lock);
	while (!list_empty(&fh->msgs)) {
		struct cec_msg_entry *entry =
			list_first_entry(&fh->msgs, struct cec_msg_entry, list);

		list_del(&entry->list);
		kfree(entry);
	}
	for (i = CEC_NUM_CORE_EVENTS; i < CEC_NUM_EVENTS; i++) {
		while (!list_empty(&fh->events[i])) {
			struct cec_event_entry *entry =
				list_first_entry(&fh->events[i],
						 struct cec_event_entry, list);

			list_del(&entry->list);
			kfree(entry);
		}
	}
	kfree(fh);

	cec_put_device(devnode);
	filp->private_data = NULL;
	return 0;
}