nt9856x/code/vos/drivers/source/kwrap/linux/rtos_os_proc.c
2023-03-28 15:07:53 +08:00

292 lines
6.7 KiB
C
Executable File

#include <linux/semaphore.h>
#include <linux/uaccess.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <stdarg.h>
#include "rtos_os_proc.h"
#define __MODULE__ rtos_proc
#define __DBGLVL__ 8 // 0=FATAL, 1=ERR, 2=WRN, 3=UNIT, 4=FUNC, 5=IND, 6=MSG, 7=VALUE, 8=USER
#define __DBGFLT__ "*"
#include <kwrap/debug.h>
#include <kwrap/flag.h>
#include <kwrap/semaphore.h>
#include <kwrap/task.h>
extern int test_vos(int argc, char** argv);
extern int vos_task_debug_dump(int argc, char** argv);
//============================================================================
// Define
//============================================================================
#define MAX_CMD_LENGTH 64
#define MAX_ARG_NUM 6
/*-----------------------------------------------------------------------------*/
/* Local Global Variables */
/*-----------------------------------------------------------------------------*/
unsigned int rtos_proc_debug_level = NVT_DBG_WRN;
static struct seq_file *g_sfile = NULL;
/*-----------------------------------------------------------------------------*/
/* Interface Functions */
/*-----------------------------------------------------------------------------*/
typedef struct proc_cmd {
char cmd[MAX_CMD_LENGTH];
int (*pfunc)(int argc, char** argv);
} PROC_CMD, *PPROC_CMD;
#define NUM_OF_PROC_CMD (sizeof(cmd_list) / sizeof(PROC_CMD))
static PROC_CMD cmd_list[] = {
{ "test_vos", test_vos},
{ "tskcell", vos_task_debug_dump},
};
DEFINE_SEMAPHORE(vos_proc_lock);
static struct proc_dir_entry *proc_entry_root = NULL;
static int vos_seq_printf(const char *fmt, ...)
{
char buf[512]= {0};
int len;
va_list ap;
va_start(ap, fmt);
len = vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
seq_printf(g_sfile, buf);
return 0;
}
static int cmd_ops_show(struct seq_file *sfile, void *v)
{
return 0;
}
static int cmd_ops_open(struct inode *inode, struct file *file)
{
return single_open(file, cmd_ops_show, NULL);
}
static ssize_t cmd_ops_write(struct file *file, const char __user *buf,
size_t size, loff_t *off)
{
char cmd_line[MAX_CMD_LENGTH];
const char delimiters[] = {' ', '\r', '\n', '\0'};
char *argv[MAX_ARG_NUM] = {0};
unsigned char argc = 0;
char *cmdstr = cmd_line;
unsigned int cmd_idx;
int ret = -EINVAL;
// Note: In fact, size will never be smaller than 1 in proc cmd
// to prevent coverity warning, we still check the size < 1
// e.g. cmd [abcde], size = 6
// e.g. cmd [], size = 1
if (size > MAX_CMD_LENGTH || size < 1) {
DBG_ERR("Invalid cmd size %ld\n", (ULONG)size);
goto ERR_OUT;
}
// copy command string from user space
if (copy_from_user(cmd_line, buf, size))
goto ERR_OUT;
cmd_line[size - 1] = '\0';
DBG_DUMP("VOS_PROC_CMD: [%s], size %ld\n", cmd_line, (ULONG)size);
// parse command string
for (argc = 0; argc < MAX_ARG_NUM; argc++) {
argv[argc] = strsep(&cmdstr, delimiters);
if (argv[argc] == NULL)
break;
}
// dispatch command handler
for (cmd_idx = 0 ; cmd_idx < NUM_OF_PROC_CMD; cmd_idx++) {
if (strncmp(argv[0], cmd_list[cmd_idx].cmd, MAX_CMD_LENGTH) == 0) {
ret = cmd_list[cmd_idx].pfunc(argc - 1, &argv[1]);
break;
}
}
if (cmd_idx >= NUM_OF_PROC_CMD)
goto ERR_INVALID_CMD;
return size;
ERR_INVALID_CMD:
DBG_ERR("Invalid CMD [%s]\n", cmd_line);
ERR_OUT:
return -EINVAL;
}
static struct file_operations cmd_fops = {
.owner = THIS_MODULE,
.open = cmd_ops_open,
.read = seq_read,
.write = cmd_ops_write,
.llseek = seq_lseek,
};
static int help_ops_show(struct seq_file *sfile, void *v)
{
int cmd_idx;
seq_printf(sfile, "Usage1:\r\n cat /proc/nvt_vos/sem (or flag, task)\r\n\r\n");
seq_printf(sfile, "Usage2:\r\n cat [CMD] > /proc/nvt_vos/cmd\r\n\r\n");
seq_printf(sfile, "CMD could be:\r\n");
for (cmd_idx = 0 ; cmd_idx < NUM_OF_PROC_CMD; cmd_idx++) {
seq_printf(sfile, "%s\r\n", cmd_list[cmd_idx].cmd);
}
return 0;
}
static int help_ops_open(struct inode *inode, struct file *file)
{
return single_open(file, help_ops_show, NULL);
}
static struct file_operations help_fops = {
.owner = THIS_MODULE,
.open = help_ops_open,
.read = seq_read,
.llseek = seq_lseek,
};
static int flag_ops_show(struct seq_file *sfile, void *v)
{
down(&vos_proc_lock);
g_sfile = sfile;
vos_flag_dump(vos_seq_printf);
up(&vos_proc_lock);
return 0;
}
static int flag_ops_open(struct inode *inode, struct file *file)
{
return single_open(file, flag_ops_show, NULL);
}
static struct file_operations flag_fops = {
.owner = THIS_MODULE,
.open = flag_ops_open,
.read = seq_read,
.llseek = seq_lseek,
};
static int sem_ops_show(struct seq_file *sfile, void *v)
{
down(&vos_proc_lock);
g_sfile = sfile;
vos_sem_dump(vos_seq_printf, 1);
up(&vos_proc_lock);
return 0;
}
static int sem_ops_open(struct inode *inode, struct file *file)
{
return single_open(file, sem_ops_show, NULL);
}
static struct file_operations sem_fops = {
.owner = THIS_MODULE,
.open = sem_ops_open,
.read = seq_read,
.llseek = seq_lseek,
};
static int task_ops_show(struct seq_file *sfile, void *v)
{
down(&vos_proc_lock);
g_sfile = sfile;
vos_task_dump(vos_seq_printf);
up(&vos_proc_lock);
return 0;
}
static int task_ops_open(struct inode *inode, struct file *file)
{
return single_open(file, task_ops_show, NULL);
}
static struct file_operations task_fops = {
.owner = THIS_MODULE,
.open = task_ops_open,
.read = seq_read,
.llseek = seq_lseek,
};
void rtos_proc_init(void *param)
{
int ret = 0;
proc_entry_root = proc_mkdir("nvt_vos", NULL);
if (proc_entry_root == NULL) {
DBG_ERR("failed to create root\n");
ret = -EINVAL;
goto rtos_proc_init_err;
}
if (NULL == proc_create("cmd", S_IRUGO | S_IXUGO, proc_entry_root, &cmd_fops)) {
DBG_ERR("failed to create cmd\n");
ret = -EINVAL;
goto rtos_proc_init_err;
}
if (NULL == proc_create("help", S_IRUGO | S_IXUGO, proc_entry_root, &help_fops)) {
DBG_ERR("failed to create help\n");
ret = -EINVAL;
goto rtos_proc_init_err;
}
if (NULL == proc_create("flag", S_IRUGO | S_IXUGO, proc_entry_root, &flag_fops)) {
DBG_ERR("failed to create flag\n");
ret = -EINVAL;
goto rtos_proc_init_err;
}
if (NULL == proc_create("sem", S_IRUGO | S_IXUGO, proc_entry_root, &sem_fops)) {
DBG_ERR("failed to create sem\n");
ret = -EINVAL;
goto rtos_proc_init_err;
}
if (NULL == proc_create("task", S_IRUGO | S_IXUGO, proc_entry_root, &task_fops)) {
DBG_ERR("failed to create task\n");
ret = -EINVAL;
goto rtos_proc_init_err;
}
return;
rtos_proc_init_err:
if (proc_entry_root) {
proc_remove(proc_entry_root);
proc_entry_root = NULL;
}
}
void rtos_proc_exit(void)
{
if (proc_entry_root) {
proc_remove(proc_entry_root);
proc_entry_root = NULL;
}
}