Mod aaa-12 增加 proc 模块, 增加对象管理模块
RCA: SOL: 修改人:huangxin 检视人:huangxin
This commit is contained in:
parent
8838a6af19
commit
0d5d059d7c
|
@ -0,0 +1,12 @@
|
||||||
|
ifneq ($(KERNELRELEASE), )
|
||||||
|
obj-m := procapi.o
|
||||||
|
procapi-objs += proc_api.o cJSON/cJSON.o
|
||||||
|
else
|
||||||
|
#KDIR ?= /opt/fsl-kernel/x86/linux-4.9.140
|
||||||
|
KDIR ?= /home/hx/raspberrypi/linux
|
||||||
|
#PWD := $(shell pwd)
|
||||||
|
all:
|
||||||
|
make -C $(KDIR) M=$(PWD) modules
|
||||||
|
clean:
|
||||||
|
make -C $(KDIR) M=$(PWD) clean
|
||||||
|
endif
|
|
@ -0,0 +1,56 @@
|
||||||
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
|
||||||
|
#include "proc_api.h"
|
||||||
|
#include "obj_api.h"
|
||||||
|
|
||||||
|
#define VERSION ("obj0.0.0.2")
|
||||||
|
|
||||||
|
const char* obj_version(void)
|
||||||
|
{
|
||||||
|
return VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
void object_init(void)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
PCMHI_OBJECT obj, tmp;
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
memset(&obj_array[i], 0, sizeof(CMHI_OBJECT));
|
||||||
|
sprintf(obj_array[i].name, "obj_%02d", i);
|
||||||
|
atomic_add(i, &obj_array[i].ref_count);
|
||||||
|
HASH_ADD_STR(g_objects, name, &obj_array[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
HASH_ITER(hh, g_objects, obj, tmp)
|
||||||
|
{
|
||||||
|
int val = atomic_read(&(obj->ref_count));
|
||||||
|
printk(KERN_ERR "Name = %s, ref_count = %d\n", obj->name, val);
|
||||||
|
HASH_DEL(g_objects, obj);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static int object_module_init(void)
|
||||||
|
{
|
||||||
|
printk(KERN_ALERT "Hello ISG objects manager version: %s\n", VERSION);
|
||||||
|
|
||||||
|
/* if(proc_api_register(&g_ProcApi) != ERR_DBGFS_NO_ERROR) {
|
||||||
|
printk(KERN_ERR "Regisetr %s Error\n", g_ProcApi.dir_name);
|
||||||
|
} */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
module_init(object_module_init);
|
||||||
|
|
||||||
|
static void __exit object_module_exit(void)
|
||||||
|
{
|
||||||
|
printk(KERN_ALERT "Bye ISG objects manager version: %s\n", VERSION);
|
||||||
|
// proc_api_unregister(&g_ProcApi);
|
||||||
|
}
|
||||||
|
module_exit(object_module_exit);
|
||||||
|
#endif // __KERNEL__
|
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef _OBJ_API_H
|
||||||
|
#define _OBJ_API_H
|
||||||
|
#ifdef __KERNEL__
|
||||||
|
#include <asm/atomic.h>
|
||||||
|
#include <linux/semaphore.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "uthash.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
OBJ_TYPE_ADDR = 0,
|
||||||
|
OBJ_TYPE_SERVER,
|
||||||
|
OBJ_TYPE_DATETIME
|
||||||
|
} OBJ_TYPES;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char name[MAX_NAME_LEN];
|
||||||
|
OBJ_TYPES type;
|
||||||
|
void* data;
|
||||||
|
atomic_t ref_count;
|
||||||
|
struct semaphore lock;
|
||||||
|
struct list_head list;
|
||||||
|
} CMHI_OBJECT, *PCMHI_OBJECT;
|
||||||
|
|
||||||
|
const char* obj_version(void);
|
||||||
|
void object_init(void);
|
||||||
|
#endif
|
||||||
|
#endif
|
|
@ -0,0 +1,12 @@
|
||||||
|
ifneq ($(KERNELRELEASE), )
|
||||||
|
obj-m := procapi.o
|
||||||
|
procapi-objs += proc_api.o cJSON/cJSON.o
|
||||||
|
else
|
||||||
|
#KDIR ?= /opt/fsl-kernel/x86/linux-4.9.140
|
||||||
|
KDIR ?= /home/hx/raspberrypi/linux
|
||||||
|
#PWD := $(shell pwd)
|
||||||
|
all:
|
||||||
|
make -C $(KDIR) M=$(PWD) modules
|
||||||
|
clean:
|
||||||
|
make -C $(KDIR) M=$(PWD) clean
|
||||||
|
endif
|
|
@ -0,0 +1,9 @@
|
||||||
|
#ifndef _COMMON_H
|
||||||
|
#define _COMMON_H
|
||||||
|
|
||||||
|
#define DEBUG_CODE_LINE() (printk(KERN_ERR "%s(%d)\n", __FUNCTION__, __LINE__))
|
||||||
|
|
||||||
|
|
||||||
|
#define MAX_NAME_LEN (32)
|
||||||
|
#define MAX_PATH (256)
|
||||||
|
#endif
|
|
@ -0,0 +1,471 @@
|
||||||
|
#ifdef __KERNEL__
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/proc_fs.h>
|
||||||
|
#include <linux/seq_file.h>
|
||||||
|
#include <linux/uaccess.h>
|
||||||
|
#include <asm/bitops.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
|
|
||||||
|
#include "proc_api.h"
|
||||||
|
|
||||||
|
#define MAX_COMMAND_LEN (256)
|
||||||
|
#define MAX_CMD_LEN (32)
|
||||||
|
#define MAX_PARAMS_LEN (128)
|
||||||
|
|
||||||
|
#define TOLOWER(x) ((x) | 0x20)
|
||||||
|
#ifndef MAX
|
||||||
|
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define HELP_BITS (31)
|
||||||
|
#define IOCTL_BITS (30)
|
||||||
|
|
||||||
|
#define PROC_API_DIR_NAME ("isgobj")
|
||||||
|
#define PROC_API_DBG_DIR ("api")
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char key[MAX_PATH];
|
||||||
|
char dir_name[MAX_NAME_LEN];
|
||||||
|
PDBGFS_PRIV data;
|
||||||
|
struct proc_dir_entry* entry;
|
||||||
|
UT_hash_handle hh;
|
||||||
|
} PROC_INFO, *PPROC_INFO;
|
||||||
|
|
||||||
|
static const struct file_operations g_DbgSeq_fops;
|
||||||
|
static struct proc_dir_entry* g_DebugProcFS;
|
||||||
|
|
||||||
|
static DEFINE_RWLOCK(g_proc_lock);
|
||||||
|
static PPROC_INFO g_proc_items = NULL;
|
||||||
|
|
||||||
|
static int proc_api_show(struct seq_file* seq, void* token)
|
||||||
|
{
|
||||||
|
PPROC_INFO pInfo = NULL, tmp = NULL;
|
||||||
|
int i = 0;
|
||||||
|
seq_printf(seq, "Total API items: %u\n", HASH_COUNT(g_proc_items));
|
||||||
|
seq_printf(seq, "API root direcotry: /proc/%s/\n", PROC_API_DIR_NAME);
|
||||||
|
seq_puts(seq, "-------------------------------------"
|
||||||
|
"-------------------------------------\n");
|
||||||
|
seq_puts(seq, "| ID | Direcotry | Name | Show | IOCtrl | Help |\n");
|
||||||
|
seq_puts(seq, "|------------------------------------"
|
||||||
|
"------------------------------------|\n");
|
||||||
|
|
||||||
|
read_lock(&g_proc_lock);
|
||||||
|
HASH_ITER(hh, g_proc_items, pInfo, tmp) {
|
||||||
|
seq_printf(seq, "| %03d | %14s | %14s | %1s | %1s | %1s |\n",
|
||||||
|
i++,
|
||||||
|
pInfo->dir_name ? pInfo->dir_name : "",
|
||||||
|
pInfo->data->name,
|
||||||
|
pInfo->data->show ? "*" : "-",
|
||||||
|
pInfo->data->ioctl ? "*" : "-",
|
||||||
|
pInfo->data->help ? "*" : "-");
|
||||||
|
}
|
||||||
|
read_unlock(&g_proc_lock);
|
||||||
|
|
||||||
|
seq_puts(seq, "-------------------------------------"
|
||||||
|
"-------------------------------------\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int proc_api_ioctl(struct seq_file* seq, void* token)
|
||||||
|
{
|
||||||
|
PDBGFS_PRIV priv = (PDBGFS_PRIV)(seq->private);
|
||||||
|
|
||||||
|
seq_printf(seq, "Run Command [%s] with (%s)\n", priv->cmd, priv->cmd_data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int proc_api_help(struct seq_file* seq, void* token)
|
||||||
|
{
|
||||||
|
PDBGFS_PRIV priv = (PDBGFS_PRIV)(seq->private);
|
||||||
|
seq_puts(seq, "==============Options Helps=============\n");
|
||||||
|
seq_printf(seq, "usage: echo \"<params>\" > /proc/%s/%s/%s\n",
|
||||||
|
PROC_API_DIR_NAME, PROC_API_DBG_DIR, priv->name);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DBGFS_PRIV g_DbgConfig[] = {
|
||||||
|
{
|
||||||
|
"info", 0, 0L, NULL, NULL,
|
||||||
|
proc_api_show, proc_api_ioctl, proc_api_help
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static PROC_API g_ProcApi = {
|
||||||
|
PROC_API_DBG_DIR, g_DbgConfig, sizeof(g_DbgConfig) / sizeof(g_DbgConfig[0]),
|
||||||
|
};
|
||||||
|
|
||||||
|
static int proc_api_init(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void proc_api_uninit(const char* proc_dir_name)
|
||||||
|
{
|
||||||
|
remove_proc_entry(proc_dir_name, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int proc_api_register(PPROC_API pv)
|
||||||
|
{
|
||||||
|
struct proc_dir_entry* pdir;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if(pv == NULL || pv->data == NULL || pv->num_data <= 0) {
|
||||||
|
return ERR_PARA_OUTOFRANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pv->dir_name && strlen(pv->dir_name) > 0) {
|
||||||
|
pdir = proc_mkdir(pv->dir_name, g_DebugProcFS);
|
||||||
|
} else {
|
||||||
|
pdir = g_DebugProcFS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// printk(KERN_ERR "Register: %s number %d of %s\n", pv->dir_name, pv->num_data, pv->data->name);
|
||||||
|
|
||||||
|
for(i = 0; i < pv->num_data; i++) {
|
||||||
|
PPROC_INFO pInfo = (PPROC_INFO)kmalloc(sizeof(PROC_INFO), GFP_KERNEL);
|
||||||
|
|
||||||
|
if(pInfo == NULL) {
|
||||||
|
printk(KERN_ERR "Malloc Error\n");
|
||||||
|
return ERR_MALLOC_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(pInfo, 0, sizeof(PROC_INFO));
|
||||||
|
|
||||||
|
if(!proc_create_data(pv->data[i].name, 0x644, pdir, &g_DbgSeq_fops, &pv->data[i])) {
|
||||||
|
printk(KERN_ERR "proc_create_data Error\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pv->dir_name && strlen(pv->dir_name) > 0) {
|
||||||
|
strcpy(pInfo->dir_name, pv->dir_name);
|
||||||
|
sprintf(pInfo->key, "%s%s", pv->dir_name, pv->data[i].name);
|
||||||
|
} else {
|
||||||
|
sprintf(pInfo->key, "%s", pv->data[i].name);
|
||||||
|
}
|
||||||
|
|
||||||
|
pInfo->entry = pdir;
|
||||||
|
pInfo->data = &pv->data[i];
|
||||||
|
write_lock(&g_proc_lock);
|
||||||
|
HASH_ADD_STR(g_proc_items, key, pInfo);
|
||||||
|
write_unlock(&g_proc_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_DBGFS_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int proc_api_unregister(PPROC_API pv)
|
||||||
|
{
|
||||||
|
PPROC_INFO pInfo = NULL;
|
||||||
|
char key[MAX_PATH];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if(pv == NULL || pv->data == NULL || pv->num_data <= 0) {
|
||||||
|
return ERR_PARA_OUTOFRANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < pv->num_data; i++) {
|
||||||
|
memset(key, 0, MAX_PATH);
|
||||||
|
|
||||||
|
if(pv->dir_name && strlen(pv->dir_name) > 0) {
|
||||||
|
sprintf(key, "%s%s", pv->dir_name, pv->data[i].name);
|
||||||
|
} else {
|
||||||
|
sprintf(key, "%s", pv->data[i].name);
|
||||||
|
}
|
||||||
|
|
||||||
|
HASH_FIND_STR(g_proc_items, key, pInfo);
|
||||||
|
|
||||||
|
if(pInfo) {
|
||||||
|
write_lock(&g_proc_lock);
|
||||||
|
HASH_DEL(g_proc_items, pInfo);
|
||||||
|
write_unlock(&g_proc_lock);
|
||||||
|
remove_proc_entry(pv->data[i].name, pInfo->entry);
|
||||||
|
kfree(pInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pv->dir_name && strlen(pv->dir_name) > 0) {
|
||||||
|
remove_proc_subtree(pv->dir_name, g_DebugProcFS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_DBGFS_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int proc_seq_open(struct inode* inode, struct file* file)
|
||||||
|
{
|
||||||
|
PDBGFS_PRIV priv = (PDBGFS_PRIV)(PDE_DATA(inode));
|
||||||
|
|
||||||
|
if(test_bit(HELP_BITS, &priv->mask) && priv->help) {
|
||||||
|
clear_bit(HELP_BITS, &priv->mask);
|
||||||
|
return single_open(file, priv->help, priv);
|
||||||
|
} else if(test_bit(IOCTL_BITS, &priv->mask) && priv->ioctl) {
|
||||||
|
clear_bit(IOCTL_BITS, &priv->mask);
|
||||||
|
return single_open(file, priv->ioctl, priv);
|
||||||
|
} else {
|
||||||
|
return single_open(file, priv->show, priv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int proc_seq_release(struct inode* inode, struct file* file)
|
||||||
|
{
|
||||||
|
return single_release(inode, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_value_base(unsigned char* pBuf)
|
||||||
|
{
|
||||||
|
int strLen = pBuf ? strlen(pBuf) : -1;
|
||||||
|
|
||||||
|
if(pBuf) {
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
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 get_string_value(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 get_int_value(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(kstrtol(token, get_value_base(token), (long*)¶mValue) != 0) {
|
||||||
|
printk(KERN_ERR "strict_strtol [%s] Error\n", token);
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return paramValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int process_input_content(struct seq_file* seq, unsigned char* pBuf, PDBGFS_PRIV pv)
|
||||||
|
{
|
||||||
|
int strLen = pBuf ? strlen(pBuf) - 1 : -1;
|
||||||
|
char tmpBuf[MAX_COMMAND_LEN], cmdBuf[MAX_CMD_LEN], paramBuf[MAX_PARAMS_LEN];
|
||||||
|
int i = 0;
|
||||||
|
int bIsCmd = 0;
|
||||||
|
|
||||||
|
if(strlen <= 0){
|
||||||
|
return -ERR_PARA_OUTOFRANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(tmpBuf, 0, MAX_COMMAND_LEN);
|
||||||
|
memset(cmdBuf, 0, MAX_CMD_LEN);
|
||||||
|
memset(paramBuf, 0, MAX_PARAMS_LEN);
|
||||||
|
|
||||||
|
if(pBuf == NULL && pv == NULL) {
|
||||||
|
return -ERR_PARA_OUTOFRANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(tmpBuf, pBuf);
|
||||||
|
|
||||||
|
for(i = 0; i < strLen; i++) {
|
||||||
|
if(tmpBuf[i] == ' ') {
|
||||||
|
strncpy(cmdBuf, tmpBuf, i);
|
||||||
|
strncpy(paramBuf, &tmpBuf[i + 1], MAX(strLen - i - 1, 0));
|
||||||
|
bIsCmd = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!bIsCmd) {
|
||||||
|
if(kstrtoul(pBuf, get_value_base(pBuf), (long unsigned int*)&pv->params)) {
|
||||||
|
printk(KERN_ERR "strict_strtoul [%s] base %d Error\n", pBuf, get_value_base(pBuf));
|
||||||
|
return -ERR_DBGFS_WRITEOPTS;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(pv->ioctl != NULL) {
|
||||||
|
if(pv->cmd != NULL) {
|
||||||
|
kfree(pv->cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pv->cmd_data) {
|
||||||
|
kfree(pv->cmd_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strlen(cmdBuf) > 0) {
|
||||||
|
pv->cmd = kmalloc(strlen(cmdBuf) + 1, GFP_KERNEL);
|
||||||
|
|
||||||
|
if(pv->cmd == NULL) {
|
||||||
|
printk(KERN_ERR "Malloc %u Error\n", strlen(cmdBuf) + 1);
|
||||||
|
return -ERR_MALLOC_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(pv->cmd, cmdBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strlen(paramBuf) > 0) {
|
||||||
|
pv->cmd_data = kmalloc(strlen(paramBuf) + 1, GFP_KERNEL);
|
||||||
|
|
||||||
|
if(pv->cmd_data == NULL) {
|
||||||
|
printk(KERN_ERR "Malloc %u Error\n", strlen(paramBuf) + 1);
|
||||||
|
return -ERR_MALLOC_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(pv->cmd_data, paramBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
set_bit(IOCTL_BITS, &pv->mask);
|
||||||
|
printk(KERN_INFO "%s do %s command with %s\n", pv->name, pv->cmd, pv->cmd_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_DBGFS_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_PARA_OUTOFRANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ssize_t proc_seq_option_write(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)) {
|
||||||
|
printk(KERN_ERR "Input Params Error:count = %d, max size = %d\n", count,
|
||||||
|
sizeof(buf));
|
||||||
|
return -ERR_PARA_OUTOFRANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(copy_from_user(buf, userbuf, count)) {
|
||||||
|
printk(KERN_ERR "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) {
|
||||||
|
set_bit(HELP_BITS, &pv->mask);
|
||||||
|
//pv->help((struct seq_file*)file->private_data, pv);
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[count] = 0x00;
|
||||||
|
|
||||||
|
if(!process_input_content(seq, buf, pv) == ERR_DBGFS_NO_ERROR) {
|
||||||
|
printk(KERN_ERR "Input [%s] Process Error\n", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations g_DbgSeq_fops = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.open = proc_seq_open,
|
||||||
|
.read = seq_read,
|
||||||
|
.write = proc_seq_option_write,
|
||||||
|
.llseek = seq_lseek,
|
||||||
|
.release = proc_seq_release,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define VERSION ("v0.0.0.2")
|
||||||
|
|
||||||
|
static int api_module_init(void)
|
||||||
|
{
|
||||||
|
printk(KERN_ALERT "Hello ISG PROC API version: %s\n", VERSION);
|
||||||
|
proc_api_init(PROC_API_DIR_NAME);
|
||||||
|
|
||||||
|
if(proc_api_register(&g_ProcApi) != ERR_DBGFS_NO_ERROR) {
|
||||||
|
printk(KERN_ERR "Regisetr %s Error\n", g_ProcApi.dir_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
module_init(api_module_init);
|
||||||
|
|
||||||
|
static void __exit api_module_exit(void)
|
||||||
|
{
|
||||||
|
printk(KERN_ALERT "Bye ISG PROC API version: %s\n", VERSION);
|
||||||
|
proc_api_unregister(&g_ProcApi);
|
||||||
|
|
||||||
|
proc_api_uninit(PROC_API_DIR_NAME);
|
||||||
|
}
|
||||||
|
module_exit(api_module_exit);
|
||||||
|
|
||||||
|
EXPORT_SYMBOL(proc_api_register);
|
||||||
|
EXPORT_SYMBOL(proc_api_unregister);
|
||||||
|
EXPORT_SYMBOL(get_int_value);
|
||||||
|
EXPORT_SYMBOL(get_string_value);
|
||||||
|
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
MODULE_VERSION("0.1");
|
||||||
|
#endif
|
|
@ -0,0 +1,41 @@
|
||||||
|
#ifndef _PROC_API_H
|
||||||
|
#define _PROC_API_H
|
||||||
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
|
#include <asm/atomic.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ERR_DBGFS_NO_ERROR = 0,
|
||||||
|
ERR_PARA_OUTOFRANGE,
|
||||||
|
ERR_MALLOC_MEMORY,
|
||||||
|
ERR_DBGFS_INIT,
|
||||||
|
ERR_DBGFS_REGISTER,
|
||||||
|
ERR_DBGFS_UNREGISTER,
|
||||||
|
ERR_DBGFS_WRITEOPTS
|
||||||
|
} PROC_ERRCODE;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char* name;
|
||||||
|
unsigned int params;
|
||||||
|
unsigned long mask;
|
||||||
|
char* cmd;
|
||||||
|
char* cmd_data;
|
||||||
|
int (* show)(struct seq_file*, void*);
|
||||||
|
int (* ioctl)(struct seq_file*, void*);
|
||||||
|
int (* help)(struct seq_file*, void*);
|
||||||
|
} DBGFS_PRIV, *PDBGFS_PRIV;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char* dir_name;
|
||||||
|
PDBGFS_PRIV data;
|
||||||
|
int num_data;
|
||||||
|
} PROC_API, *PPROC_API;
|
||||||
|
|
||||||
|
int proc_api_register(PPROC_API pv);
|
||||||
|
int proc_api_unregister(PPROC_API pv);
|
||||||
|
int get_int_value(unsigned char* pBuf, int index);
|
||||||
|
int get_string_value(unsigned char* pBuf, int index, unsigned char* pValue, unsigned int maxBytes);
|
||||||
|
#endif
|
||||||
|
#endif
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue