/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * */ #include #include #include #include "vcd.h" u32 vcd_init(struct vcd_init_config *config, s32 *driver_handle) { u32 rc = VCD_S_SUCCESS; struct vcd_drv_ctxt *drv_ctxt; VCD_MSG_MED("vcd_init:"); if (!config || !driver_handle || !config->map_dev_base_addr) { VCD_MSG_ERROR("Bad parameters"); return VCD_ERR_ILLEGAL_PARM; } drv_ctxt = vcd_get_drv_context(); mutex_init(&drv_ctxt->dev_mutex); mutex_lock(&drv_ctxt->dev_mutex); if (drv_ctxt->dev_state.state_table->ev_hdlr.init) { rc = drv_ctxt->dev_state.state_table->ev_hdlr. init(drv_ctxt, config, driver_handle); } else { VCD_MSG_ERROR("Unsupported API in device state %d", drv_ctxt->dev_state.state); rc = VCD_ERR_BAD_STATE; } mutex_unlock(&drv_ctxt->dev_mutex); return rc; } EXPORT_SYMBOL(vcd_init); u32 vcd_term(s32 driver_handle) { u32 rc = VCD_S_SUCCESS; struct vcd_drv_ctxt *drv_ctxt; VCD_MSG_MED("vcd_term:"); drv_ctxt = vcd_get_drv_context(); mutex_lock(&drv_ctxt->dev_mutex); if (drv_ctxt->dev_state.state_table->ev_hdlr.term) { rc = drv_ctxt->dev_state.state_table->ev_hdlr. term(drv_ctxt, driver_handle); } else { VCD_MSG_ERROR("Unsupported API in device state %d", drv_ctxt->dev_state.state); rc = VCD_ERR_BAD_STATE; } mutex_unlock(&drv_ctxt->dev_mutex); return rc; } EXPORT_SYMBOL(vcd_term); struct client_security_info { int secure_enc; int secure_dec; int non_secure_enc; int non_secure_dec; }; static int vcd_get_clients_security_info(struct client_security_info *sec_info) { struct vcd_drv_ctxt *drv_ctxt; struct vcd_clnt_ctxt *cctxt; int count = 0; if (!sec_info) { VCD_MSG_ERROR("Invalid argument\n"); return -EINVAL; } memset(sec_info, 0 , sizeof(*sec_info)); drv_ctxt = vcd_get_drv_context(); mutex_lock(&drv_ctxt->dev_mutex); cctxt = drv_ctxt->dev_ctxt.cctxt_list_head; while (cctxt) { if (cctxt->secure && cctxt->decoding) sec_info->secure_dec++; else if (cctxt->secure && !cctxt->decoding) sec_info->secure_enc++; else if (!cctxt->secure && cctxt->decoding) sec_info->non_secure_dec++; else sec_info->non_secure_enc++; count++; cctxt = cctxt->next; } mutex_unlock(&drv_ctxt->dev_mutex); return count; } static int is_session_invalid(u32 decoding, u32 flags) { int is_secure; struct client_security_info sec_info; int client_count = 0; int secure_session_running = 0, non_secure_runnung = 0; is_secure = (flags & VCD_CP_SESSION) ? 1 : 0; client_count = vcd_get_clients_security_info(&sec_info); secure_session_running = (sec_info.secure_enc > 0) || (sec_info.secure_dec > 0); non_secure_runnung = sec_info.non_secure_dec + sec_info.non_secure_enc; if (!is_secure) { if (secure_session_running) { pr_err("non secure session failed secure running\n"); return -EACCES; } } else { if (non_secure_runnung) { pr_err("Secure session failed non secure running\n"); return -EACCES; } } return 0; } u32 vcd_open(s32 driver_handle, u32 decoding, void (*callback) (u32 event, u32 status, void *info, size_t sz, void *handle, void *const client_data), void *client_data, int flags) { u32 rc = 0, num_of_instances = 0; struct vcd_drv_ctxt *drv_ctxt; struct vcd_clnt_ctxt *cctxt; int is_secure = (flags & VCD_CP_SESSION) ? 1 : 0; VCD_MSG_MED("vcd_open:"); if (!callback) { VCD_MSG_ERROR("Bad parameters"); return -EINVAL; } drv_ctxt = vcd_get_drv_context(); cctxt = drv_ctxt->dev_ctxt.cctxt_list_head; while (cctxt) { num_of_instances++; cctxt = cctxt->next; } if (num_of_instances == VIDC_MAX_NUM_CLIENTS) { pr_err(" %s(): Max number of clients reached\n", __func__); return -ENODEV; } rc = is_session_invalid(decoding, flags); if (rc) { VCD_MSG_ERROR("Invalid Session: is_decoder: %d, secure: %d\n", decoding, flags); return rc; } if (is_secure) res_trk_secure_set(); mutex_lock(&drv_ctxt->dev_mutex); if (drv_ctxt->dev_state.state_table->ev_hdlr.open) { rc = drv_ctxt->dev_state.state_table->ev_hdlr. open(drv_ctxt, driver_handle, decoding, callback, client_data); if (rc) { rc = -ENODEV; } } else { VCD_MSG_ERROR("Unsupported API in device state %d", drv_ctxt->dev_state.state); rc = -EPERM; } if (!rc) { cctxt = drv_ctxt->dev_ctxt.cctxt_list_head; cctxt->secure = is_secure; } else if (is_secure) res_trk_secure_unset(); mutex_unlock(&drv_ctxt->dev_mutex); return rc; } EXPORT_SYMBOL(vcd_open); u32 vcd_close(void *handle) { struct vcd_clnt_ctxt *cctxt = (struct vcd_clnt_ctxt *)handle; struct vcd_drv_ctxt *drv_ctxt; u32 rc; int is_secure = 0; VCD_MSG_MED("vcd_close:"); if (!cctxt || cctxt->signature != VCD_SIGNATURE) { VCD_MSG_ERROR("Bad client handle"); return VCD_ERR_BAD_HANDLE; } is_secure = cctxt->secure; drv_ctxt = vcd_get_drv_context(); mutex_lock(&drv_ctxt->dev_mutex); if (drv_ctxt->dev_state.state_table->ev_hdlr.close) { rc = drv_ctxt->dev_state.state_table->ev_hdlr. close(drv_ctxt, cctxt); } else { VCD_MSG_ERROR("Unsupported API in device state %d", drv_ctxt->dev_state.state); rc = VCD_ERR_BAD_STATE; } mutex_unlock(&drv_ctxt->dev_mutex); if (is_secure) res_trk_secure_unset(); return rc; } EXPORT_SYMBOL(vcd_close); u32 vcd_encode_start(void *handle) { struct vcd_clnt_ctxt *cctxt = (struct vcd_clnt_ctxt *)handle; struct vcd_drv_ctxt *drv_ctxt; u32 rc; VCD_MSG_MED("vcd_encode_start:"); if (!cctxt || cctxt->signature != VCD_SIGNATURE) { VCD_MSG_ERROR("Bad client handle"); return VCD_ERR_BAD_HANDLE; } drv_ctxt = vcd_get_drv_context(); mutex_lock(&drv_ctxt->dev_mutex); if (cctxt->clnt_state.state_table->ev_hdlr.encode_start && drv_ctxt->dev_ctxt.pwr_state != VCD_PWR_STATE_SLEEP) { rc = cctxt->clnt_state.state_table->ev_hdlr. encode_start(cctxt); } else { VCD_MSG_ERROR ("Unsupported API in dev power state %d OR client state %d", drv_ctxt->dev_ctxt.pwr_state, cctxt->clnt_state.state); rc = VCD_ERR_BAD_STATE; } mutex_unlock(&drv_ctxt->dev_mutex); return rc; } EXPORT_SYMBOL(vcd_encode_start); u32 vcd_encode_frame(void *handle, struct vcd_frame_data *input_frame) { struct vcd_clnt_ctxt *cctxt = (struct vcd_clnt_ctxt *)handle; struct vcd_drv_ctxt *drv_ctxt; u32 rc; VCD_MSG_MED("vcd_encode_frame:"); if (!cctxt || cctxt->signature != VCD_SIGNATURE) { VCD_MSG_ERROR("Bad client handle"); return VCD_ERR_BAD_HANDLE; } if (!input_frame) { VCD_MSG_ERROR("Bad parameters"); return VCD_ERR_BAD_POINTER; } drv_ctxt = vcd_get_drv_context(); mutex_lock(&drv_ctxt->dev_mutex); if (cctxt->clnt_state.state_table->ev_hdlr.encode_frame) { rc = cctxt->clnt_state.state_table->ev_hdlr. encode_frame(cctxt, input_frame); } else { VCD_MSG_ERROR("Unsupported API in client state %d", cctxt->clnt_state.state); rc = VCD_ERR_BAD_STATE; } mutex_unlock(&drv_ctxt->dev_mutex); return rc; } EXPORT_SYMBOL(vcd_encode_frame); u32 vcd_decode_start(void *handle, struct vcd_sequence_hdr *seq_hdr) { struct vcd_clnt_ctxt *cctxt = (struct vcd_clnt_ctxt *)handle; struct vcd_drv_ctxt *drv_ctxt; u32 rc; VCD_MSG_MED("vcd_decode_start:"); if (!cctxt || cctxt->signature != VCD_SIGNATURE) { VCD_MSG_ERROR("Bad client handle"); return VCD_ERR_BAD_HANDLE; } drv_ctxt = vcd_get_drv_context(); mutex_lock(&drv_ctxt->dev_mutex); if (cctxt->clnt_state.state_table->ev_hdlr.decode_start && drv_ctxt->dev_ctxt.pwr_state != VCD_PWR_STATE_SLEEP) { rc = cctxt->clnt_state.state_table->ev_hdlr. decode_start(cctxt, seq_hdr); } else { VCD_MSG_ERROR ("Unsupported API in dev power state %d OR client state %d", drv_ctxt->dev_ctxt.pwr_state, cctxt->clnt_state.state); rc = VCD_ERR_BAD_STATE; } mutex_unlock(&drv_ctxt->dev_mutex); return rc; } EXPORT_SYMBOL(vcd_decode_start); u32 vcd_decode_frame(void *handle, struct vcd_frame_data *input_frame) { struct vcd_clnt_ctxt *cctxt = (struct vcd_clnt_ctxt *)handle; struct vcd_drv_ctxt *drv_ctxt; u32 rc; VCD_MSG_MED("vcd_decode_frame:"); if (!cctxt || cctxt->signature != VCD_SIGNATURE) { VCD_MSG_ERROR("Bad client handle"); return VCD_ERR_BAD_HANDLE; } if (!input_frame) { VCD_MSG_ERROR("Bad parameters"); return VCD_ERR_BAD_POINTER; } drv_ctxt = vcd_get_drv_context(); mutex_lock(&drv_ctxt->dev_mutex); if (cctxt->clnt_state.state_table->ev_hdlr.decode_frame) { rc = cctxt->clnt_state.state_table->ev_hdlr. decode_frame(cctxt, input_frame); } else { VCD_MSG_ERROR("Unsupported API in client state %d", cctxt->clnt_state.state); rc = VCD_ERR_BAD_STATE; } mutex_unlock(&drv_ctxt->dev_mutex); return rc; } EXPORT_SYMBOL(vcd_decode_frame); u32 vcd_pause(void *handle) { struct vcd_drv_ctxt *drv_ctxt; struct vcd_clnt_ctxt *cctxt = (struct vcd_clnt_ctxt *)handle; u32 rc; VCD_MSG_MED("vcd_pause:"); if (!cctxt || cctxt->signature != VCD_SIGNATURE) { VCD_MSG_ERROR("Bad client handle"); return VCD_ERR_BAD_HANDLE; } drv_ctxt = vcd_get_drv_context(); mutex_lock(&drv_ctxt->dev_mutex); if (cctxt->clnt_state.state_table->ev_hdlr.pause) { rc = cctxt->clnt_state.state_table->ev_hdlr. pause(cctxt); } else { VCD_MSG_ERROR("Unsupported API in client state %d", cctxt->clnt_state.state); rc = VCD_ERR_BAD_STATE; } mutex_unlock(&drv_ctxt->dev_mutex); return rc; } EXPORT_SYMBOL(vcd_pause); u32 vcd_resume(void *handle) { struct vcd_drv_ctxt *drv_ctxt; struct vcd_clnt_ctxt *cctxt = (struct vcd_clnt_ctxt *)handle; u32 rc; VCD_MSG_MED("vcd_resume:"); if (!cctxt || cctxt->signature != VCD_SIGNATURE) { VCD_MSG_ERROR("Bad client handle"); return VCD_ERR_BAD_HANDLE; } drv_ctxt = vcd_get_drv_context(); mutex_lock(&drv_ctxt->dev_mutex); if (drv_ctxt->dev_state.state_table->ev_hdlr.resume && drv_ctxt->dev_ctxt.pwr_state != VCD_PWR_STATE_SLEEP) { rc = drv_ctxt->dev_state.state_table->ev_hdlr. resume(drv_ctxt, cctxt); } else { VCD_MSG_ERROR ("Unsupported API in dev power state %d OR client state %d", drv_ctxt->dev_ctxt.pwr_state, cctxt->clnt_state.state); rc = VCD_ERR_BAD_STATE; } mutex_unlock(&drv_ctxt->dev_mutex); return rc; } EXPORT_SYMBOL(vcd_resume); u32 vcd_flush(void *handle, u32 mode) { struct vcd_clnt_ctxt *cctxt = (struct vcd_clnt_ctxt *)handle; struct vcd_drv_ctxt *drv_ctxt; u32 rc; VCD_MSG_MED("vcd_flush:"); if (!cctxt || cctxt->signature != VCD_SIGNATURE) { VCD_MSG_ERROR("Bad client handle"); return VCD_ERR_BAD_HANDLE; } drv_ctxt = vcd_get_drv_context(); mutex_lock(&drv_ctxt->dev_mutex); if (cctxt->clnt_state.state_table->ev_hdlr.flush) { rc = cctxt->clnt_state.state_table->ev_hdlr. flush(cctxt, mode); } else { VCD_MSG_ERROR("Unsupported API in client state %d", cctxt->clnt_state.state); rc = VCD_ERR_BAD_STATE; } mutex_unlock(&drv_ctxt->dev_mutex); return rc; } EXPORT_SYMBOL(vcd_flush); u32 vcd_stop(void *handle) { struct vcd_clnt_ctxt *cctxt = (struct vcd_clnt_ctxt *)handle; struct vcd_drv_ctxt *drv_ctxt; u32 rc; VCD_MSG_MED("vcd_stop:"); if (!cctxt || cctxt->signature != VCD_SIGNATURE) { VCD_MSG_ERROR("Bad client handle"); return VCD_ERR_BAD_HANDLE; } drv_ctxt = vcd_get_drv_context(); mutex_lock(&drv_ctxt->dev_mutex); if (cctxt->clnt_state.state_table->ev_hdlr.stop && drv_ctxt->dev_ctxt.pwr_state != VCD_PWR_STATE_SLEEP) { rc = cctxt->clnt_state.state_table->ev_hdlr. stop(cctxt); } else { VCD_MSG_ERROR ("Unsupported API in dev power state %d OR client state %d", drv_ctxt->dev_ctxt.pwr_state, cctxt->clnt_state.state); rc = VCD_ERR_BAD_STATE; } mutex_unlock(&drv_ctxt->dev_mutex); return rc; } EXPORT_SYMBOL(vcd_stop); u32 vcd_set_property(void *handle, struct vcd_property_hdr *prop_hdr, void *prop_val) { struct vcd_clnt_ctxt *cctxt = (struct vcd_clnt_ctxt *)handle; struct vcd_drv_ctxt *drv_ctxt; u32 rc; VCD_MSG_MED("vcd_set_property:"); if (!cctxt || cctxt->signature != VCD_SIGNATURE) { VCD_MSG_ERROR("Bad client handle"); return VCD_ERR_BAD_HANDLE; } if (!prop_hdr || !prop_val) { VCD_MSG_ERROR("Bad parameters"); return VCD_ERR_BAD_POINTER; } drv_ctxt = vcd_get_drv_context(); mutex_lock(&drv_ctxt->dev_mutex); if (cctxt->clnt_state.state_table->ev_hdlr.set_property) { rc = cctxt->clnt_state.state_table->ev_hdlr. set_property(cctxt, prop_hdr, prop_val); } else { VCD_MSG_ERROR("Unsupported API in client state %d", cctxt->clnt_state.state); rc = VCD_ERR_BAD_STATE; } mutex_unlock(&drv_ctxt->dev_mutex); return rc; } EXPORT_SYMBOL(vcd_set_property); u32 vcd_get_property(void *handle, struct vcd_property_hdr *prop_hdr, void *prop_val) { struct vcd_clnt_ctxt *cctxt = (struct vcd_clnt_ctxt *)handle; struct vcd_drv_ctxt *drv_ctxt; u32 rc; VCD_MSG_MED("vcd_get_property:"); if (!cctxt || cctxt->signature != VCD_SIGNATURE) { VCD_MSG_ERROR("Bad client handle"); return VCD_ERR_BAD_HANDLE; } if (!prop_hdr || !prop_val) { VCD_MSG_ERROR("Bad parameters"); return VCD_ERR_BAD_POINTER; } drv_ctxt = vcd_get_drv_context(); mutex_lock(&drv_ctxt->dev_mutex); if (cctxt->clnt_state.state_table->ev_hdlr.get_property) { rc = cctxt->clnt_state.state_table->ev_hdlr. get_property(cctxt, prop_hdr, prop_val); } else { VCD_MSG_ERROR("Unsupported API in client state %d", cctxt->clnt_state.state); rc = VCD_ERR_BAD_STATE; } mutex_unlock(&drv_ctxt->dev_mutex); return rc; } EXPORT_SYMBOL(vcd_get_property); u32 vcd_set_buffer_requirements(void *handle, enum vcd_buffer_type buffer, struct vcd_buffer_requirement *buffer_req) { struct vcd_clnt_ctxt *cctxt = (struct vcd_clnt_ctxt *)handle; struct vcd_drv_ctxt *drv_ctxt; u32 rc; VCD_MSG_MED("vcd_set_buffer_requirements:"); if (!cctxt || cctxt->signature != VCD_SIGNATURE) { VCD_MSG_ERROR("Bad client handle"); return VCD_ERR_BAD_HANDLE; } if (!buffer_req) { VCD_MSG_ERROR("Bad parameters"); return VCD_ERR_BAD_POINTER; } drv_ctxt = vcd_get_drv_context(); mutex_lock(&drv_ctxt->dev_mutex); if (cctxt->clnt_state.state_table->ev_hdlr. set_buffer_requirements) { rc = cctxt->clnt_state.state_table->ev_hdlr. set_buffer_requirements(cctxt, buffer, buffer_req); } else { VCD_MSG_ERROR("Unsupported API in client state %d", cctxt->clnt_state.state); rc = VCD_ERR_BAD_STATE; } mutex_unlock(&drv_ctxt->dev_mutex); return rc; } EXPORT_SYMBOL(vcd_set_buffer_requirements); u32 vcd_get_buffer_requirements(void *handle, enum vcd_buffer_type buffer, struct vcd_buffer_requirement *buffer_req) { struct vcd_clnt_ctxt *cctxt = (struct vcd_clnt_ctxt *)handle; struct vcd_drv_ctxt *drv_ctxt; u32 rc; VCD_MSG_MED("vcd_get_buffer_requirements:"); if (!cctxt || cctxt->signature != VCD_SIGNATURE) { VCD_MSG_ERROR("Bad client handle"); return VCD_ERR_BAD_HANDLE; } if (!buffer_req) { VCD_MSG_ERROR("Bad parameters"); return VCD_ERR_BAD_POINTER; } drv_ctxt = vcd_get_drv_context(); mutex_lock(&drv_ctxt->dev_mutex); if (cctxt->clnt_state.state_table->ev_hdlr. get_buffer_requirements) { rc = cctxt->clnt_state.state_table->ev_hdlr. get_buffer_requirements(cctxt, buffer, buffer_req); } else { VCD_MSG_ERROR("Unsupported API in client state %d", cctxt->clnt_state.state); rc = VCD_ERR_BAD_STATE; } mutex_unlock(&drv_ctxt->dev_mutex); return rc; } EXPORT_SYMBOL(vcd_get_buffer_requirements); u32 vcd_set_buffer(void *handle, enum vcd_buffer_type buffer_type, u8 *buffer, u32 buf_size) { struct vcd_clnt_ctxt *cctxt = (struct vcd_clnt_ctxt *)handle; struct vcd_drv_ctxt *drv_ctxt; u32 rc; VCD_MSG_MED("vcd_set_buffer:"); if (!cctxt || cctxt->signature != VCD_SIGNATURE) { VCD_MSG_ERROR("Bad client handle"); return VCD_ERR_BAD_HANDLE; } if (!buffer || !buf_size) { VCD_MSG_ERROR("Bad parameters"); return VCD_ERR_BAD_POINTER; } drv_ctxt = vcd_get_drv_context(); mutex_lock(&drv_ctxt->dev_mutex); if (cctxt->clnt_state.state_table->ev_hdlr.set_buffer) { rc = cctxt->clnt_state.state_table->ev_hdlr. set_buffer(cctxt, buffer_type, buffer, buf_size); } else { VCD_MSG_ERROR("Unsupported API in client state %d", cctxt->clnt_state.state); rc = VCD_ERR_BAD_STATE; } mutex_unlock(&drv_ctxt->dev_mutex); return rc; } EXPORT_SYMBOL(vcd_set_buffer); u32 vcd_allocate_buffer(void *handle, enum vcd_buffer_type buffer, u32 buf_size, u8 **vir_buf_addr, u8 **phy_buf_addr) { struct vcd_clnt_ctxt *cctxt = (struct vcd_clnt_ctxt *)handle; struct vcd_drv_ctxt *drv_ctxt; u32 rc; VCD_MSG_MED("vcd_allocate_buffer:"); if (!cctxt || cctxt->signature != VCD_SIGNATURE) { VCD_MSG_ERROR("Bad client handle"); return VCD_ERR_BAD_HANDLE; } if (!vir_buf_addr || !phy_buf_addr || !buf_size) { VCD_MSG_ERROR("Bad parameters"); return VCD_ERR_BAD_POINTER; } drv_ctxt = vcd_get_drv_context(); mutex_lock(&drv_ctxt->dev_mutex); if (cctxt->clnt_state.state_table->ev_hdlr.allocate_buffer) { rc = cctxt->clnt_state.state_table->ev_hdlr. allocate_buffer(cctxt, buffer, buf_size, vir_buf_addr, phy_buf_addr); } else { VCD_MSG_ERROR("Unsupported API in client state %d", cctxt->clnt_state.state); rc = VCD_ERR_BAD_STATE; } mutex_unlock(&drv_ctxt->dev_mutex); return rc; } EXPORT_SYMBOL(vcd_allocate_buffer); u32 vcd_free_buffer(void *handle, enum vcd_buffer_type buffer_type, u8 *buffer) { struct vcd_clnt_ctxt *cctxt = (struct vcd_clnt_ctxt *)handle; struct vcd_drv_ctxt *drv_ctxt; u32 rc; VCD_MSG_MED("vcd_free_buffer:"); if (!cctxt || cctxt->signature != VCD_SIGNATURE) { VCD_MSG_ERROR("Bad client handle"); return VCD_ERR_BAD_HANDLE; } drv_ctxt = vcd_get_drv_context(); mutex_lock(&drv_ctxt->dev_mutex); if (cctxt->clnt_state.state_table->ev_hdlr.free_buffer) { rc = cctxt->clnt_state.state_table->ev_hdlr. free_buffer(cctxt, buffer_type, buffer); } else { VCD_MSG_ERROR("Unsupported API in client state %d", cctxt->clnt_state.state); rc = VCD_ERR_BAD_STATE; } mutex_unlock(&drv_ctxt->dev_mutex); return rc; } EXPORT_SYMBOL(vcd_free_buffer); u32 vcd_fill_output_buffer(void *handle, struct vcd_frame_data *buffer) { struct vcd_clnt_ctxt *cctxt = (struct vcd_clnt_ctxt *)handle; struct vcd_drv_ctxt *drv_ctxt; u32 rc; VCD_MSG_MED("vcd_fill_output_buffer:"); if (!cctxt || cctxt->signature != VCD_SIGNATURE) { VCD_MSG_ERROR("Bad client handle"); return VCD_ERR_BAD_HANDLE; } if (!buffer) { VCD_MSG_ERROR("Bad parameters"); return VCD_ERR_BAD_POINTER; } drv_ctxt = vcd_get_drv_context(); mutex_lock(&drv_ctxt->dev_mutex); if (cctxt->clnt_state.state_table->ev_hdlr.fill_output_buffer) { rc = cctxt->clnt_state.state_table->ev_hdlr. fill_output_buffer(cctxt, buffer); } else { VCD_MSG_ERROR("Unsupported API in client state %d", cctxt->clnt_state.state); rc = VCD_ERR_BAD_STATE; } mutex_unlock(&drv_ctxt->dev_mutex); return rc; } EXPORT_SYMBOL(vcd_fill_output_buffer); u32 vcd_set_device_power(s32 driver_handle, enum vcd_power_state pwr_state) { u32 rc = VCD_S_SUCCESS; struct vcd_drv_ctxt *drv_ctxt; VCD_MSG_MED("vcd_set_device_power:"); drv_ctxt = vcd_get_drv_context(); mutex_lock(&drv_ctxt->dev_mutex); if (drv_ctxt->dev_state.state_table->ev_hdlr.set_dev_pwr) { rc = drv_ctxt->dev_state.state_table->ev_hdlr. set_dev_pwr(drv_ctxt, pwr_state); } else { VCD_MSG_ERROR("Unsupported API in device state %d", drv_ctxt->dev_state.state); rc = VCD_ERR_BAD_STATE; } mutex_unlock(&drv_ctxt->dev_mutex); return rc; } EXPORT_SYMBOL(vcd_set_device_power); void vcd_read_and_clear_interrupt(void) { VCD_MSG_LOW("vcd_read_and_clear_interrupt:"); ddl_read_and_clear_interrupt(); } void vcd_response_handler(void) { struct vcd_drv_ctxt *drv_ctxt; VCD_MSG_LOW("vcd_response_handler:"); drv_ctxt = vcd_get_drv_context(); mutex_lock(&drv_ctxt->dev_mutex); if (!ddl_process_core_response()) { VCD_MSG_HIGH ("ddl_process_core_response indicated no further" "processing"); mutex_unlock(&drv_ctxt->dev_mutex); return; } if (drv_ctxt->dev_ctxt.command_continue) vcd_continue(); mutex_unlock(&drv_ctxt->dev_mutex); } EXPORT_SYMBOL(vcd_response_handler); u8 vcd_get_num_of_clients(void) { struct vcd_drv_ctxt *drv_ctxt; struct vcd_clnt_ctxt *cctxt; u8 count = 0; VCD_MSG_LOW("vcd_get_num_of_clients:"); drv_ctxt = vcd_get_drv_context(); mutex_lock(&drv_ctxt->dev_mutex); cctxt = drv_ctxt->dev_ctxt.cctxt_list_head; while (cctxt) { count++; cctxt = cctxt->next; } mutex_unlock(&drv_ctxt->dev_mutex); return count; } EXPORT_SYMBOL(vcd_get_num_of_clients); u32 vcd_get_ion_status(void) { return res_trk_get_enable_ion(); } EXPORT_SYMBOL(vcd_get_ion_status); struct ion_client *vcd_get_ion_client(void) { return res_trk_get_ion_client(); } EXPORT_SYMBOL(vcd_get_ion_client);