Exemplo n.º 1
0
static long cec_adap_s_log_addrs(struct cec_adapter *adap, struct cec_fh *fh,
				 bool block, struct cec_log_addrs __user *parg)
{
	struct cec_log_addrs log_addrs;
	long err = -EBUSY;

	if (!(adap->capabilities & CEC_CAP_LOG_ADDRS))
		return -ENOTTY;
	if (copy_from_user(&log_addrs, parg, sizeof(log_addrs)))
		return -EFAULT;
	log_addrs.flags &= CEC_LOG_ADDRS_FL_ALLOW_UNREG_FALLBACK |
			   CEC_LOG_ADDRS_FL_ALLOW_RC_PASSTHRU |
			   CEC_LOG_ADDRS_FL_CDC_ONLY;
	mutex_lock(&adap->lock);
	if (!adap->is_configuring &&
	    (!log_addrs.num_log_addrs || !adap->is_configured) &&
	    !cec_is_busy(adap, fh)) {
		err = __cec_s_log_addrs(adap, &log_addrs, block);
		if (!err)
			log_addrs = adap->log_addrs;
	}
	mutex_unlock(&adap->lock);
	if (err)
		return err;
	if (copy_to_user(parg, &log_addrs, sizeof(log_addrs)))
		return -EFAULT;
	return 0;
}
Exemplo n.º 2
0
/*
 * Unregister a cec device node
 *
 * This unregisters the passed device. Future open calls will be met with
 * errors.
 *
 * This function can safely be called if the device node has never been
 * registered or has already been unregistered.
 */
static void cec_devnode_unregister(struct cec_adapter *adap)
{
	struct cec_devnode *devnode = &adap->devnode;
	struct cec_fh *fh;

	mutex_lock(&devnode->lock);

	/* Check if devnode was never registered or already unregistered */
	if (!devnode->registered || devnode->unregistered) {
		mutex_unlock(&devnode->lock);
		return;
	}

	list_for_each_entry(fh, &devnode->fhs, list)
		wake_up_interruptible(&fh->wait);

	devnode->registered = false;
	devnode->unregistered = true;
	mutex_unlock(&devnode->lock);

	mutex_lock(&adap->lock);
	__cec_s_phys_addr(adap, CEC_PHYS_ADDR_INVALID, false);
	__cec_s_log_addrs(adap, NULL, false);
	mutex_unlock(&adap->lock);

	cdev_device_del(&devnode->cdev, &devnode->dev);
	put_device(&devnode->dev);
}