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; }
/* =====================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 */