static ssize_t ged_dvfs_tuning_mode_write_entry(const char __user *pszBuffer, size_t uiCount, loff_t uiPosition, void *pvData) { #define GED_HAL_DEBUGFS_SIZE 64 char acBuffer[GED_HAL_DEBUGFS_SIZE]; if ((0 < uiCount) && (uiCount < GED_HAL_DEBUGFS_SIZE)) { if (0 == ged_copy_from_user(acBuffer, pszBuffer, uiCount)) { GED_DVFS_TUNING_MODE eTuningMode; acBuffer[uiCount] = '\0'; if (sscanf(acBuffer, "%u", &eTuningMode) == 1) { if( GED_DVFS_DEFAULT<=eTuningMode && eTuningMode<=GED_DVFS_PERFORMANCE) ged_dvfs_set_tuning_mode(eTuningMode); } //else if (...) //for other commands //{ //} } } return uiCount; }
static long ged_dispatch(GED_BRIDGE_PACKAGE *psBridgePackageKM) { int ret = -EFAULT; void *pvInt, *pvOut; typedef int (ged_bridge_func_type)(void*, void*); ged_bridge_func_type* pFunc = NULL; if ((psBridgePackageKM->i32InBufferSize >=0) && (psBridgePackageKM->i32OutBufferSize >=0) && (psBridgePackageKM->i32InBufferSize + psBridgePackageKM->i32OutBufferSize < GED_IOCTL_PARAM_BUF_SIZE)) { pvInt = gvIOCTLParamBuf; pvOut = (void*)((char*)pvInt + (uintptr_t)psBridgePackageKM->i32InBufferSize); if (psBridgePackageKM->i32InBufferSize > 0) { if (0 != ged_copy_from_user(pvInt, psBridgePackageKM->pvParamIn, psBridgePackageKM->i32InBufferSize)) { GED_LOGE("ged_copy_from_user fail\n"); return ret; } } // we will change the below switch into a function pointer mapping table in the future switch(GED_GET_BRIDGE_ID(psBridgePackageKM->ui32FunctionID)) { case GED_BRIDGE_COMMAND_LOG_BUF_GET: pFunc = (ged_bridge_func_type*)ged_bridge_log_buf_get; break; case GED_BRIDGE_COMMAND_LOG_BUF_WRITE: pFunc = (ged_bridge_func_type*)ged_bridge_log_buf_write; break; case GED_BRIDGE_COMMAND_LOG_BUF_RESET: pFunc = (ged_bridge_func_type*)ged_bridge_log_buf_reset; break; case GED_BRIDGE_COMMAND_BOOST_GPU_FREQ: pFunc = (ged_bridge_func_type*)ged_bridge_boost_gpu_freq; break; case GED_BRIDGE_COMMAND_MONITOR_3D_FENCE: pFunc = (ged_bridge_func_type*)ged_bridge_monitor_3D_fence; break; default: GED_LOGE("Unknown Bridge ID: %u\n", GED_GET_BRIDGE_ID(psBridgePackageKM->ui32FunctionID)); break; } if (pFunc) { ret = pFunc(pvInt, pvOut); } if (psBridgePackageKM->i32OutBufferSize > 0) { if (0 != ged_copy_to_user(psBridgePackageKM->pvParamOut, pvOut, psBridgePackageKM->i32OutBufferSize)) { return ret; } } } return ret; }
static long ged_ioctl(struct file *pFile, unsigned int ioctlCmd, unsigned long arg) { int ret = -EFAULT; GED_BRIDGE_PACKAGE *psBridgePackageKM, *psBridgePackageUM = (GED_BRIDGE_PACKAGE*)arg; GED_BRIDGE_PACKAGE sBridgePackageKM; if (down_interruptible(&ged_dal_sem) < 0) { GED_LOGE("Fail to down ged_dal_sem\n"); return -ERESTARTSYS; } psBridgePackageKM = &sBridgePackageKM; if (0 != ged_copy_from_user(psBridgePackageKM, psBridgePackageUM, sizeof(GED_BRIDGE_PACKAGE))) { GED_LOGE("Fail to ged_copy_from_user\n"); goto unlock_and_return; } ret = ged_dispatch(psBridgePackageKM); unlock_and_return: up(&ged_dal_sem); return ret; }
//----------------------------------------------------------------------------- static ssize_t ged_custom_upbound_gpu_freq_write_entry(const char __user *pszBuffer, size_t uiCount, loff_t uiPosition, void *pvData) { #define GED_HAL_DEBUGFS_SIZE 64 char acBuffer[GED_HAL_DEBUGFS_SIZE]; int i32Value; if ((0 < uiCount) && (uiCount < GED_HAL_DEBUGFS_SIZE)) { if (0 == ged_copy_from_user(acBuffer, pszBuffer, uiCount)) { acBuffer[uiCount] = '\0'; if (sscanf(acBuffer, "%d", &i32Value) == 1) { if (i32Value < 0) i32Value = 0; mtk_custom_upbound_gpu_freq(i32Value); } //else if (...) //for other commands //{ //} } } return uiCount; }
static ssize_t ged_fps_ub_write(const char __user *pszBuffer, size_t uiCount, loff_t uiPosition, void *pvData) { char str_num[MAX_FPS_DIGITS + 1]; if (0 == ged_copy_from_user(str_num, pszBuffer, MAX_FPS_DIGITS)) { str_num[MAX_FPS_DIGITS] = 0; _fps_upper_bound = simple_strtol(str_num, NULL, 10); ged_dvfs_probe_signal(GED_FPS_CHANGE_SIGNAL_EVENT); printk("GED: fps is set to %d", _fps_upper_bound); } return uiCount; }
//ged_dvfs_vsync_offset_level_set static ssize_t ged_vsync_offset_level_write_entry( const char __user *pszBuffer, size_t uiCount, loff_t uiPosition, void *pvData) { #define GED_HAL_DEBUGFS_SIZE 64 #define NUM_TOKEN 2 /* * This proc node accept only: [CMD] [NUM] * for ex: "touch 1" * */ char acBuffer[GED_HAL_DEBUGFS_SIZE]; int aint32Indx[NUM_TOKEN]; char* pcCMD; char* pcValue; int i; int i32VsyncOffsetLevel; int ret; if (!((0 < uiCount) && (uiCount < GED_HAL_DEBUGFS_SIZE - 1))) return 0; if (ged_copy_from_user(acBuffer, pszBuffer, uiCount)) return 0; acBuffer[uiCount] = '\n'; acBuffer[uiCount+1] = 0; i=tokenizer(acBuffer, uiCount, aint32Indx, NUM_TOKEN); GED_LOGE("i=%d",i); if(i==NUM_TOKEN) { pcCMD = acBuffer+aint32Indx[0]; pcValue = acBuffer+aint32Indx[1]; if(strcmp(pcCMD,"set_vsync_offset")==0) { ret = kstrtoint(pcValue, 0, &i32VsyncOffsetLevel); ged_dvfs_vsync_offset_level_set(i32VsyncOffsetLevel); } } return 0; }
static int __ged_log_buf_write(GED_LOG_BUF *psGEDLogBuf, const char __user *pszBuffer, int i32Count) { int cnt; char buf[256]; if (!psGEDLogBuf) { return 0; } cnt = (i32Count >= 256) ? 255 : i32Count; ged_copy_from_user(buf, pszBuffer, cnt); __ged_log_buf_print(psGEDLogBuf, buf); return cnt; }
static long ged_ioctl_compat(struct file *pFile, unsigned int ioctlCmd, unsigned long arg) { typedef struct GED_BRIDGE_PACKAGE_32_TAG { unsigned int ui32FunctionID; int i32Size; unsigned int ui32ParamIn; int i32InBufferSize; unsigned int ui32ParamOut; int i32OutBufferSize; } GED_BRIDGE_PACKAGE_32; int ret = -EFAULT; GED_BRIDGE_PACKAGE sBridgePackageKM64; GED_BRIDGE_PACKAGE_32 sBridgePackageKM32; GED_BRIDGE_PACKAGE_32 *psBridgePackageKM32 = &sBridgePackageKM32; GED_BRIDGE_PACKAGE_32 *psBridgePackageUM32 = (GED_BRIDGE_PACKAGE_32*)arg; if (down_interruptible(&ged_dal_sem) < 0) { GED_LOGE("Fail to down ged_dal_sem\n"); return -ERESTARTSYS; } if (0 != ged_copy_from_user(psBridgePackageKM32, psBridgePackageUM32, sizeof(GED_BRIDGE_PACKAGE_32))) { GED_LOGE("Fail to ged_copy_from_user\n"); goto unlock_and_return; } sBridgePackageKM64.ui32FunctionID = psBridgePackageKM32->ui32FunctionID; sBridgePackageKM64.i32Size = sizeof(GED_BRIDGE_PACKAGE); sBridgePackageKM64.pvParamIn = (void*) ((size_t) psBridgePackageKM32->ui32ParamIn); sBridgePackageKM64.pvParamOut = (void*) ((size_t) psBridgePackageKM32->ui32ParamOut); sBridgePackageKM64.i32InBufferSize = psBridgePackageKM32->i32InBufferSize; sBridgePackageKM64.i32OutBufferSize = psBridgePackageKM32->i32OutBufferSize; ret = ged_dispatch(&sBridgePackageKM64); unlock_and_return: up(&ged_dal_sem); return ret; }
static ssize_t ged_vsync_offset_enable_write_entry(const char __user *pszBuffer, size_t uiCount, loff_t uiPosition, void *pvData) { #define GED_HAL_DEBUGFS_SIZE 64 #define NUM_TOKEN 2 /* * This proc node accept only: [CMD] [NUM] * for ex: "touch 1" * */ char acBuffer[GED_HAL_DEBUGFS_SIZE]; int aint32Indx[NUM_TOKEN]; char* pcCMD; char* pcValue; int i; if ((0 < uiCount) && (uiCount < GED_HAL_DEBUGFS_SIZE)) { if (0 == ged_copy_from_user(acBuffer, pszBuffer, uiCount)) { acBuffer[uiCount] = '\0'; i=tokenizer(acBuffer, uiCount, aint32Indx, NUM_TOKEN); if(i==NUM_TOKEN) { pcCMD = acBuffer+aint32Indx[0]; pcValue = acBuffer+aint32Indx[1]; #ifdef ENABLE_COMMON_DVFS if(strcmp(pcCMD,"touch_down")==0) { if ( (*pcValue)=='1'|| (*pcValue) =='0') { if( (*pcValue) -'0'==0) // touch up ged_dvfs_vsync_offset_event_switch(GED_DVFS_VSYNC_OFFSET_TOUCH_EVENT , false); else // touch down ged_dvfs_vsync_offset_event_switch(GED_DVFS_VSYNC_OFFSET_TOUCH_EVENT , true); } } else if(strcmp(pcCMD,"enable_WFD")==0) { if ( (*pcValue) =='1'|| (*pcValue) =='0') { if( (*pcValue) -'0'==0) // WFD turn-off ged_dvfs_vsync_offset_event_switch(GED_DVFS_VSYNC_OFFSET_WFD_EVENT , false); else // WFD turn-on ged_dvfs_vsync_offset_event_switch(GED_DVFS_VSYNC_OFFSET_WFD_EVENT , true); } } else #endif if(strcmp(pcCMD,"enable_debug")==0) { if ( (*pcValue) =='1'|| (*pcValue) =='0'||(*pcValue) =='2') { if( (*pcValue) -'0'==1) // force off { ged_dvfs_vsync_offset_event_switch(GED_DVFS_VSYNC_OFFSET_FORCE_OFF , true); bForce = GED_FALSE; } else if( (*pcValue) -'0'==2) // force on { ged_dvfs_vsync_offset_event_switch(GED_DVFS_VSYNC_OFFSET_FORCE_ON , true); bForce = GED_TRUE; } else // turn-off debug ged_dvfs_vsync_offset_event_switch(GED_DVFS_VSYNC_OFFSET_DEBUG_CLEAR_EVENT , true); } } else if(strcmp(pcCMD, "gas") == 0) { if ( (*pcValue) =='1'|| (*pcValue) =='0') { if( (*pcValue) -'0'==0) ged_dvfs_vsync_offset_event_switch(GED_DVFS_VSYNC_OFFSET_GAS_EVENT, false); else ged_dvfs_vsync_offset_event_switch(GED_DVFS_VSYNC_OFFSET_GAS_EVENT, true); } } else { GED_LOGE("unknow command:%s %c",pcCMD,*pcValue); } } } } return uiCount; }