Exemplo n.º 1
0
int previewer_doioctl(struct inode *inode, struct file *file,
		      unsigned int cmd, unsigned long arg)
{
	int ret = 0;
	struct prev_fh *fh = (struct prev_fh *)file->private_data;
	struct imp_logical_channel *chan = fh->chan;
	unsigned int mode, user_mode;

	if (ISNULL(chan)) {
		dev_err(prev_dev, "channel ptr is null\n");
		return -EFAULT;
	}

	if (ISNULL((void *)arg)) {
		dev_err(prev_dev, "arg ptr is null\n");
		return -EFAULT;
	}


	mode = imp_hw_if->get_preview_oper_mode();

	switch (cmd) {
	case PREV_QUERYBUF:
	case PREV_REQBUF:
	case PREV_S_PARAM:
	case PREV_PREVIEW:
	case PREV_S_CONFIG:
		{
			if (!fh->primary_user)
				return -EACCES;
		}
		break;
	}

	switch (cmd) {
	case PREV_QUERYBUF:
	case PREV_REQBUF:
	case PREV_PREVIEW:
		{
			if (chan->mode == PREV_MODE_CONTINUOUS)
				return -EACCES;
		}
		break;
	}

	/* switch according value of cmd */
	switch (cmd) {

	case PREV_S_OPER_MODE:
		{
			user_mode = *((unsigned long *)arg);
			if (chan->mode != IMP_MODE_INVALID) {
				dev_err(prev_dev,
					"Mode set for this channel already\n");
				ret = -EINVAL;
				goto ERROR;
			}

			/* primary user trying to set mode */
			if (user_mode >= IMP_MODE_INVALID) {
				dev_err(prev_dev, "Invalid mode\n");
				ret = -EINVAL;
				goto ERROR;
			}

			if (user_mode != mode) {
				dev_err(prev_dev,
					"Operation mode doesn't match"
					" with current hw mode\n");
				ret = -EINVAL;
				goto ERROR;
			}

			if (mutex_lock_interruptible(&chan->lock)) {
				ret = -EINTR;
				goto ERROR;
			}

			chan->mode = mode;
			chan->primary_user = 1;
			fh->primary_user = 1;
			mutex_unlock(&chan->lock);
			dev_dbg(prev_dev,
				"PREV_S_OPER_MODE: Operation mode set to %d\n",
				user_mode);
		}
		break;
		/* if case is to query for buffer address */
	case PREV_G_OPER_MODE:
		{
			*(unsigned long *)arg = chan->mode;
			dev_dbg(prev_dev,
				"PREV_G_OPER_MODE: mode = %d\n", chan->mode);
		}
		break;

	case PREV_ENUM_CAP:
		{
			struct prev_cap *cap = (struct prev_cap *)arg;
			struct prev_module_if *module_if;
			dev_dbg(prev_dev, "PREV_ENUM_CAP:\n");

			module_if =
			    imp_hw_if->prev_enum_modules(prev_dev, cap->index);

			if (ISNULL(module_if)) {
				dev_dbg(prev_dev,
					"PREV_ENUM_CAP - Last module \n");
				ret = -EINVAL;
				goto ERROR;
			} else {
				strcpy(cap->version, module_if->version);
				cap->module_id = module_if->module_id;
				cap->control = module_if->control;
				cap->path = module_if->path;
				strcpy(cap->module_name,
				       module_if->module_name);
			}
		}
		break;

		/* if case is to set configuration parameters */
	case PREV_S_PARAM:
		{
			struct prev_module_param *module_param =
			    (struct prev_module_param *)arg;
			struct prev_module_if *module_if;

			dev_dbg(prev_dev, "PREV_S_PARAM:\n");

			if (chan->config_state != STATE_CONFIGURED) {
				dev_err(prev_dev, "Channel not configured\n");
				ret = -EINVAL;
				goto ERROR;
			}

			module_if =
			    imp_get_module_interface(prev_dev,
						     module_param->module_id);
			if (ISNULL(module_if)) {
				dev_err(prev_dev, "Invalid module id\n");
				ret = -EINVAL;
				goto ERROR;
			} else {
				if (strcmp
				    (module_if->version,
				     module_param->version)) {
					dev_err(prev_dev,
						"Invalid module version\n");
					ret = -EINVAL;
					goto ERROR;
				}
				/* we have a valid */
				ret = module_if->set(prev_dev,
						     module_param->
						     param, module_param->len);
				if (ret < 0) {
					dev_err(prev_dev,
						"error in PREV_S_PARAM\n");
					goto ERROR;
				}
			}
		}
		break;
		/* if case is to get configuration parameters */
	case PREV_G_PARAM:
		{
			struct prev_module_param *module_param =
			    (struct prev_module_param *)arg;
			struct prev_module_if *module_if;

			dev_dbg(prev_dev, "PREV_G_PARAM:\n");

			if (ISNULL(module_param)) {
				ret = -EINVAL;
				goto ERROR;
			}
			module_if =
			    imp_get_module_interface(prev_dev,
						     module_param->module_id);
			if (ISNULL(module_if)) {
				dev_err(prev_dev, "Invalid module id\n");
				ret = -EINVAL;
				goto ERROR;
			} else {
				if (strcmp
				    (module_if->version,
				     module_param->version)) {
					dev_err(prev_dev,
						"Invalid module version\n");
					ret = -EINVAL;
					goto ERROR;
				}

				ret = module_if->get(prev_dev,
						     module_param->param,
						     module_param->len);
				if (ret < 0) {
					dev_err(prev_dev,
						"error in PREV_G_PARAM\n");
					goto ERROR;
				}
			}
		}
		break;

	case PREV_S_CONFIG:
		{
			dev_dbg(prev_dev, "PREV_S_CONFIG:\n");
			if (mutex_lock_interruptible(&(chan->lock))) {
				ret = -EINTR;
				goto ERROR;
			}

			ret =
			    imp_set_preview_config(prev_dev, chan,
						   (struct prev_channel_config
						    *)arg);
			mutex_unlock(&(chan->lock));
		}
		break;

	case PREV_G_CONFIG:
		{
			struct prev_channel_config *user_config =
			    (struct prev_channel_config *)arg;

			dev_dbg(prev_dev, "PREV_G_CONFIG:\n");
			if (ISNULL(user_config->config)) {
				ret = -EINVAL;
				dev_err(prev_dev, "error in PREV_GET_CONFIG\n");
				goto ERROR;
			}

			ret =
			    imp_get_preview_config(prev_dev, chan, user_config);
		}
		break;
	case PREV_S_CONTROL:
		{
			struct prev_module_if *module_if;
			struct prev_control *control_param =
			    (struct prev_control *)arg;

			dev_dbg(prev_dev, "PREV_S_CONTROL:\n");
			if (ISNULL(control_param)) {
				ret = -EINVAL;
				goto ERROR;
			}

			if (chan->mode != IMP_MODE_CONTINUOUS) {
				dev_err(prev_dev,
					"Control operation allowed"
					" only in continuous mode\n");
				ret = -EINVAL;
				goto ERROR;
			}
			module_if =
			    imp_get_module_interface(prev_dev,
						     control_param->module_id);
			if (ISNULL(module_if)) {
				dev_err(prev_dev, "Invalid module id\n");
				ret = -EINVAL;
				goto ERROR;
			} else {
				if (strcmp
				    (module_if->version,
				     control_param->version)) {
					dev_err(prev_dev,
						"Invalid module version\n");
					ret = -EINVAL;
					goto ERROR;
				}
			}

			if (mutex_lock_interruptible(&chan->lock)) {
				ret = -EINTR;
				goto ERROR;
			}

			ret = module_if->set(prev_dev,
					     control_param->param,
					     control_param->len);
			if (ret < 0) {
				dev_err(prev_dev,
					"error in handling PREV_SET_CONTROL\n");
			}
			mutex_unlock(&(chan->lock));
		}
		break;
	case PREV_G_CONTROL:
		{
			struct prev_module_if *module_if;
			struct prev_control *control_param =
			    (struct prev_control *)arg;

			dev_dbg(prev_dev, "PREV_G_CONTROL:\n");
			if (ISNULL(control_param)) {
				ret = -EINVAL;
				goto ERROR;
			}
			module_if =
			    imp_get_module_interface(prev_dev,
						     control_param->module_id);
			if (ISNULL(module_if)) {
				dev_err(prev_dev, "Invalid module id\n");
				ret = -EINVAL;
				goto ERROR;
			} else {
				if (strcmp
				    (module_if->version,
				     control_param->version)) {
					dev_err(prev_dev,
						"Invalid module version\n");
					ret = -EINVAL;
					goto ERROR;
				}
			}
			ret = module_if->get(prev_dev,
					     control_param->param,
					     control_param->len);
			if (ret < 0) {
				dev_err(prev_dev,
					"error in handling PREV_GET_CONTROL\n");
			}
		}
		break;

	case PREV_QUERYBUF:
		{
			dev_dbg(prev_dev, "PREV_QUERYBUF:\n");
			if (mutex_lock_interruptible(&chan->lock)) {
				ret = -EINTR;
				goto ERROR;
			}

			/* call query buffer which will return buffer address */
			ret = imp_common_query_buffer(prev_dev,
						      chan,
						      (struct imp_buffer *)arg);
			mutex_unlock(&(chan->lock));
		}
		break;

		/* if case is to request buffers */
	case PREV_REQBUF:
		{
			dev_dbg(prev_dev, "PREV_REQBUF:\n");
			if (mutex_lock_interruptible(&chan->lock)) {
				ret = -EINTR;
				goto ERROR;
			}

			/* call request buffer to allocate buffers */
			ret = imp_common_request_buffer(prev_dev,
							chan,
							(struct imp_reqbufs *)
							arg);
			mutex_unlock(&(chan->lock));
		}
		break;

		/* if the case is to do previewing */
	case PREV_PREVIEW:
		{
			dev_dbg(prev_dev, "PREV_PREVIEW:\n");
			if (mutex_lock_interruptible(&chan->lock)) {
				ret = -EINTR;
				goto ERROR;
			}
			ret =
			    imp_common_start_preview(prev_dev, chan,
						     (struct imp_convert *)arg);
			mutex_unlock(&(chan->lock));
		}
		break;
#ifdef CONFIG_IMP_DEBUG
	case PREV_DUMP_HW_CONFIG:
		{
			dev_dbg(prev_dev, "PREV_DUMP_HW_CONFIG:\n");
			if (mutex_lock_interruptible(&chan->lock)) {
				ret = -EINTR;
				goto ERROR;
			}
			if (imp_hw_if->dump_hw_config)
				imp_hw_if->dump_hw_config();
			mutex_unlock(&(chan->lock));
		}
		break;
#endif
	default:
		dev_err(prev_dev, "previewer_ioctl: Invalid Command Value\n");
		ret = -EINVAL;
	}

ERROR:
	return ret;
}
Exemplo n.º 2
0
/*
=====================rsz_ioctl===========================
This function	will process IOCTL commands sent by
the application	and
control the device IO operations.
*/
static int rsz_doioctl(struct inode *inode, struct file *file,
		       unsigned int cmd, unsigned long arg)
{
	int ret = 0, prio;
	unsigned mode, user_mode;
	/*get the configuratin of this channel from
	   private_date member of file */
	struct imp_logical_channel *rsz_conf_chan =
	    (struct imp_logical_channel *)file->private_data;

	if (ISNULL(rsz_conf_chan)) {
		dev_err(rsz_device, "channel ptr is null\n");
		return -EFAULT;
	}

	if (ISNULL((void *)arg)) {
		dev_err(rsz_device, "arg ptr is null\n");
		return -EFAULT;
	}

	mode = imp_hw_if->get_resize_oper_mode();
	switch (cmd) {
	case RSZ_QUERYBUF:
	case RSZ_REQBUF:
	case RSZ_RESIZE:
	case RSZ_RECONFIG:
		{
			if (mode == IMP_MODE_CONTINUOUS)
				return -EACCES;
		}
		break;
	}

	switch (cmd) {
	case RSZ_S_OPER_MODE:
		{
			dev_dbg(rsz_device, "RSZ_S_OPER_MODE:\n");
			user_mode = *((unsigned long *)arg);
			if (rsz_conf_chan->mode != IMP_MODE_INVALID) {
				dev_err(rsz_device,
					"Mode set for this channel already\n");
				ret = -EINVAL;
				goto ERROR;
			}

			if (user_mode >= IMP_MODE_INVALID) {
				dev_err(rsz_device, "Invalid mode\n");
				ret = -EINVAL;
				goto ERROR;
			}

			imp_hw_if->set_resize_oper_mode(user_mode);
			mode = imp_hw_if->get_resize_oper_mode();

			if (user_mode != mode) {
				dev_err(rsz_device,
					"Operation mode doesn't match"
					" with current hw mode\n");
				ret = -EINVAL;
				goto ERROR;
			}
			ret = mutex_lock_interruptible(&(rsz_conf_chan->lock));
			if (!ret) {
				rsz_conf_chan->mode = mode;
				mutex_unlock(&(rsz_conf_chan->lock));
			}
			dev_dbg(rsz_device,
				"RSZ_S_OPER_MODE: Operation mode set to %d",
				user_mode);
		}
		break;
		/* if case is to query for buffer address */
	case RSZ_G_OPER_MODE:
		{
			dev_dbg(rsz_device, "RSZ_G_OPER_MODE:\n");
			*((unsigned long *)arg) = rsz_conf_chan->mode;
			dev_dbg(rsz_device,
				"RSZ_G_OPER_MODE: mode = %d",
				rsz_conf_chan->mode);
		}
		break;

	case RSZ_S_CONFIG:
		{
			dev_dbg(rsz_device, "RSZ_S_CONFIG:\n");
			ret = mutex_lock_interruptible(&(rsz_conf_chan->lock));
			if (!ret) {
				ret = imp_set_resizer_config(rsz_device,
						     rsz_conf_chan,
						     (struct rsz_channel_config
						      *)arg);
				mutex_unlock(&(rsz_conf_chan->lock));
			}
		}
		break;

	case RSZ_G_CONFIG:
		{
			struct rsz_channel_config *user_config =
			    (struct rsz_channel_config *)arg;

			dev_err(rsz_device, "RSZ_G_CONFIG:%d:%d:%d\n",
				user_config->oper_mode, user_config->chain,
				user_config->len);
			if (ISNULL(user_config->config)) {
				ret = -EINVAL;
				dev_err(rsz_device,
					"error in PREV_GET_CONFIG\n");
				goto ERROR;
			}
			ret =
			    imp_get_resize_config(rsz_device, rsz_conf_chan,
						  user_config);
		}
		break;

	case RSZ_QUERYBUF:
		{
			dev_dbg(rsz_device, "RSZ_QUERYBUF:\n");
			ret = mutex_lock_interruptible(&(rsz_conf_chan->lock));
			if (!ret) {
				ret = imp_common_query_buffer(rsz_device,
						      rsz_conf_chan,
						      (struct imp_buffer *)arg);
				mutex_unlock(&(rsz_conf_chan->lock));
			}
		}
		break;

		/* if case is to request buffers */
	case RSZ_REQBUF:
		{
			dev_dbg(rsz_device, "RSZ_REQBUF:\n");
			ret = mutex_lock_interruptible(&(rsz_conf_chan->lock));
			if (!ret) {
				ret = imp_common_request_buffer(rsz_device,
							rsz_conf_chan,
							(struct imp_reqbufs *)
							arg);
				mutex_unlock(&(rsz_conf_chan->lock));
			}
		}
		break;
		/* if the case is to do resize */
	case RSZ_S_PRIORITY:
		{
			prio = *((unsigned long *)arg);

			dev_dbg(rsz_device, "RSZ_S_PRIORITY: priority = %d\n",
				prio);
			/* Check the prioroty range and assign the priority */
			if (prio > MAX_PRIORITY || prio < MIN_PRIORITY) {
				ret = -EINVAL;
				goto ERROR;
			} else {
				ret = mutex_lock_interruptible(
					&(rsz_conf_chan->lock));
				if (!ret) {
					rsz_conf_chan->priority = prio;
					mutex_unlock(&(rsz_conf_chan->lock));
				}
			}
			dev_dbg(rsz_device, "\n resizer_Priority:end");
		}
		break;
		/* This ioctl is used to get the priority of
		   the current logic channel */
	case RSZ_G_PRIORITY:
		{
			dev_dbg(rsz_device, "RSZ_S_PRIORITY: \n");
			/* Get the priority     from the channel */
			*((unsigned long *)arg) = rsz_conf_chan->priority;
		}
		break;

	case RSZ_RESIZE:
		{
			dev_dbg(rsz_device, "RSZ_RESIZE: \n");
			ret = mutex_lock_interruptible(&(rsz_conf_chan->lock));
			if (!ret) {
				ret = imp_common_start_resize(rsz_device,
						      rsz_conf_chan,
						      (struct imp_convert *)
						      arg);
				mutex_unlock(&(rsz_conf_chan->lock));
			}
		}
		break;

	case RSZ_RECONFIG:
		{
			dev_dbg(rsz_device, "RSZ_RECONFIG: \n");
			ret = mutex_lock_interruptible(&(rsz_conf_chan->lock));
			if (!ret) {
				ret = imp_common_reconfig_resizer(rsz_device,
						(struct rsz_reconfig *)arg,
						 rsz_conf_chan);
				mutex_unlock(&(rsz_conf_chan->lock));
			}
		}
		break;

#ifdef CONFIG_IMP_DEBUG
	case RSZ_DUMP_HW_CONFIG:
		{
			dev_dbg(rsz_device, "RSZ_DUMP_HW_CONFIG: \n");
			ret = mutex_lock_interruptible(&(rsz_conf_chan->lock));
			if (!ret) {
				if (imp_hw_if->dump_hw_config)
					imp_hw_if->dump_hw_config();
				mutex_unlock(&(rsz_conf_chan->lock));
			}
		}
		break;
#endif
	default:
		dev_dbg(rsz_device, "resizer_ioctl: Invalid Command Value");
		ret = -EINVAL;
	}

ERROR:
	return ret;
}				/*End of function IOCTL */