293 lines
5.9 KiB
C
293 lines
5.9 KiB
C
#ifdef __KERNEL__
|
|
#include "debug_info.h"
|
|
#include "log.h"
|
|
|
|
#define TOLOWER(x) ((x) | 0x20)
|
|
|
|
static const struct file_operations g_DbgSeq_fops;
|
|
|
|
static struct proc_dir_entry* g_DebugProcFS;
|
|
|
|
int InitDebugInfoProc(const char* proc_dir_name)
|
|
{
|
|
if(proc_dir_name)
|
|
{
|
|
g_DebugProcFS = proc_mkdir(proc_dir_name, NULL);
|
|
|
|
if(g_DebugProcFS != NULL)
|
|
{
|
|
return ERR_DBGFS_NO_ERROR;
|
|
}
|
|
}
|
|
|
|
return ERR_DBGFS_INIT;
|
|
}
|
|
|
|
void DeInitDebugInfoProc(void)
|
|
{
|
|
remove_proc_entry(g_DebugProcFS->name, NULL);
|
|
}
|
|
|
|
int DebugFsRegister(PDBGFS_PRIV pv)
|
|
{
|
|
struct proc_dir_entry* file;
|
|
|
|
if(pv == NULL)
|
|
{
|
|
return ERR_PARA_OUTOFRANGE;
|
|
}
|
|
|
|
file = create_proc_entry(pv->name, 0, g_DebugProcFS);
|
|
|
|
if(!file)
|
|
{
|
|
return ERR_DBGFS_REGISTER;
|
|
}
|
|
else
|
|
{
|
|
file->proc_fops = &g_DbgSeq_fops;
|
|
file->data = pv;
|
|
}
|
|
|
|
return ERR_DBGFS_NO_ERROR;
|
|
}
|
|
|
|
int DebugFsUnRegister(PDBGFS_PRIV pv)
|
|
{
|
|
|
|
if(strlen(pv->name) > 0)
|
|
{
|
|
remove_proc_entry(pv->name, g_DebugProcFS);
|
|
return ERR_DBGFS_NO_ERROR;
|
|
}
|
|
|
|
return ERR_DBGFS_UNREGISTER;
|
|
}
|
|
|
|
static int DbgSeqOpen(struct inode* inode, struct file* file)
|
|
{
|
|
PDBGFS_PRIV priv = (PDBGFS_PRIV)(PDE(inode)->data);
|
|
|
|
return single_open(file, priv->show, priv);
|
|
}
|
|
|
|
static int DbgSeqRelease(struct inode* inode, struct file* file)
|
|
{
|
|
return single_release(inode, file);
|
|
}
|
|
|
|
static int GetValueBase(unsigned char* pBuf)
|
|
{
|
|
int i = 0;
|
|
int strLen = strlen(pBuf);
|
|
|
|
if(pBuf)
|
|
{
|
|
if(pBuf[0] == '0' && pBuf[1] == 'x')
|
|
{
|
|
return 16;
|
|
}
|
|
|
|
for(i = 0; i < strLen; i++)
|
|
{
|
|
if(TOLOWER(pBuf[i]) >= 'a' && TOLOWER(pBuf[i]) <= 'f')
|
|
{
|
|
return 16;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 10;
|
|
}
|
|
|
|
int GetStringParamValue(unsigned char* pBuf, int index, unsigned char* pValue, unsigned int maxBytes)
|
|
{
|
|
char tmpBuf[128];
|
|
char* token;
|
|
char* s = tmpBuf;
|
|
int paramIndex = 0;
|
|
|
|
if(pBuf == NULL || index < 0 || pValue == NULL)
|
|
{
|
|
return ERR_PARA_OUTOFRANGE;
|
|
}
|
|
|
|
memset(pValue, 0, maxBytes);
|
|
|
|
strcpy(tmpBuf, pBuf);
|
|
|
|
for(token = strsep(&s, " ");
|
|
token != NULL;
|
|
token = strsep(&s, " "))
|
|
{
|
|
if(token != NULL)
|
|
{
|
|
if(index != paramIndex)
|
|
{
|
|
paramIndex += 1;
|
|
continue;
|
|
}
|
|
|
|
strcpy(pValue, token);
|
|
|
|
return ERR_DBGFS_NO_ERROR;
|
|
}
|
|
}
|
|
|
|
return ERR_DBGFS_WRITEOPTS;
|
|
}
|
|
|
|
|
|
int GetIntParamValue(unsigned char* pBuf, int index)
|
|
{
|
|
char tmpBuf[128];
|
|
char* token;
|
|
char* s = tmpBuf;
|
|
int paramIndex = 0;
|
|
int paramValue = -1;
|
|
|
|
if(pBuf == NULL || index < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
strcpy(tmpBuf, pBuf);
|
|
|
|
for(token = strsep(&s, " ");
|
|
token != NULL;
|
|
token = strsep(&s, " "))
|
|
{
|
|
if(token != NULL)
|
|
{
|
|
if(index != paramIndex)
|
|
{
|
|
paramIndex += 1;
|
|
continue;
|
|
}
|
|
|
|
if(strict_strtol(token, GetValueBase(token), (long*)¶mValue))
|
|
{
|
|
LOG_EX(LOG_Error, "strict_strtol [%s] Error\n", token);
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
return paramValue;
|
|
}
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
static int ProcessInputContent(struct seq_file* seq, unsigned char* pBuf, PDBGFS_PRIV pv)
|
|
{
|
|
int strLen = strlen(pBuf) - 1;
|
|
char tmpBuf[MAX_CMD_LEN], cmdBuf[32], paramBuf[64];
|
|
int i = 0;
|
|
int bIsCmd = FALSE;
|
|
|
|
memset(tmpBuf, 0, MAX_CMD_LEN);
|
|
memset(cmdBuf, 0, 32);
|
|
memset(paramBuf, 0, 64);
|
|
|
|
strcpy(tmpBuf, pBuf);
|
|
|
|
if(pBuf == NULL && pv == NULL)
|
|
{
|
|
return ERR_PARA_OUTOFRANGE;
|
|
}
|
|
|
|
for(i = 0; i < strLen; i++)
|
|
{
|
|
if(tmpBuf[i] == ' ')
|
|
{
|
|
strncpy(cmdBuf, tmpBuf, i);
|
|
strncpy(paramBuf, &tmpBuf[i + 1], MAX(strLen - i - 1, 0));
|
|
bIsCmd = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!bIsCmd)
|
|
{
|
|
if(strict_strtoul(pBuf, GetValueBase(pBuf), (long unsigned int*)&pv->params))
|
|
{
|
|
LOG_EX(LOG_Error, "strict_strtoul [%s] base %d Error\n", pBuf, GetValueBase(pBuf));
|
|
return -ERR_DBGFS_WRITEOPTS;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(pv->ioctl != NULL)
|
|
{
|
|
pv->ioctl(seq, cmdBuf, paramBuf);
|
|
}
|
|
}
|
|
|
|
return ERR_PARA_OUTOFRANGE;
|
|
}
|
|
|
|
|
|
static ssize_t DgbSeqOptionsWrite(struct file* file, const char __user* userbuf,
|
|
size_t count, loff_t* data)
|
|
{
|
|
char buf[64];
|
|
struct seq_file* seq = (struct seq_file*)file->private_data;
|
|
PDBGFS_PRIV pv = (PDBGFS_PRIV)seq->private;
|
|
|
|
if(count >= sizeof(buf))
|
|
{
|
|
LOG_EX(LOG_Error, "Input Params Error:count = %d, max size = %d\n", count,
|
|
sizeof(buf));
|
|
return -ERR_PARA_OUTOFRANGE;
|
|
}
|
|
|
|
if(copy_from_user(buf, userbuf, count))
|
|
{
|
|
LOG_EX(LOG_Error, "Copy Data To Kernel Error\n");
|
|
return -ERR_DBGFS_WRITEOPTS;
|
|
}
|
|
|
|
if(buf[0] == 'h' &&
|
|
buf[1] == 'e' &&
|
|
buf[2] == 'l' &&
|
|
buf[3] == 'p')
|
|
{
|
|
if(pv->help != NULL)
|
|
{
|
|
pv->help((struct seq_file*)file->private_data, pv);
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
buf[count] = 0x00;
|
|
|
|
if(ProcessInputContent(seq, buf, pv) == ERR_PARA_OUTOFRANGE)
|
|
{
|
|
// LOG_EX(LOG_Debug, "Process [%s] Options Cmd[%s] Params [%u(hex:%08X)]\n",
|
|
// pv->name,
|
|
// (strlen(pv->cmd) <= 0) ? "NA" : pv->cmd,
|
|
// pv->params, pv->params);
|
|
}
|
|
else
|
|
{
|
|
LOG_EX(LOG_Error, "Input [%s] Process Error\n", buf);
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
static const struct file_operations g_DbgSeq_fops =
|
|
{
|
|
.owner = THIS_MODULE,
|
|
.open = DbgSeqOpen,
|
|
.read = seq_read,
|
|
.write = DgbSeqOptionsWrite,
|
|
.llseek = seq_lseek,
|
|
.release = DbgSeqRelease,
|
|
};
|
|
|
|
#endif
|