早在vivi的启动代码的main函数的第六部的时候就有add_command(&flash_cmd)--->
void add_command(user_command_t *cmd),看这个函数之前,现看看vivi中定义的user_command_t结构体
typedef struct user_command{
const char *name; //命令的名字
void (*cmdfunc)(int argc, const char **); //命令对应的名字
struct user_command *next_cmd; //链表指针,指向下一个命令
const char *helpstr; //命令帮助
};
这个结构体中包含了vivi命令的所有信息
/* add user command */
void add_command(user_command_t *cmd)
{
if (head_cmd == NULL) {
head_cmd = tail_cmd = cmd;
} else {
tail_cmd->next_cmd = cmd;
tail_cmd = cmd;
}
/*printk("Registered '%s' command\n", cmd->name);*/
}
|
vivi中命令很多,我们拿出里面一个简单的命令来进行分析,从而对命令有一个整体的把我,全部的命令则去读vivi源代码即可:
我们就拿nand_cmd命令来分析流程。首先是定义一个user_command_t结构的
static user_command_t flash_cmd = {
"flash",
command_flash,
NULL,
"flash [{cmds}] \t\t\t-- Manage Flash Memory"
};
|
定义完了结构体,接下来就是flash命令的具体实现函数:
void command_flash(int argc, const char **argv)
{
//mymtd已经在mtd_init()函数中已经初始化
if (mymtd == NULL) {
printk("Error: Can not find MTD information\n");
return;
}
//在参数不合理的情况下,调用函数command_help
if (argc == 1) {
printk("invalid 'flash' command: too few arguments\n");
command_help(0, NULL);
return;
}
execsubcmd(flash_cmds, argc-1, argv+1);
}
|
首先分析command_help函数:
static void command_help(int argc, const char **argv)
{
print_usage("flash", flash_cmds);
}
|
上面的函数只是做了一个封装,下面才是真正实现功能的函数!
void print_usage(char *strhead, user_subcommand_t *cmds)
{
printk("Usage:\n");
while (cmds->name != NULL) {
if (strhead)
printk("%s ", strhead);
if (*cmds->helpstr)
printk("%s\n", cmds->helpstr);
cmds++;
}
}
|
下面是exevsubsmd()函数
void execsubcmd(user_subcommand_t *cmds, int argc, const char **argv)
{
while (cmds->name != NULL) {
if (strncmp(argv[0], cmds->name, strlen(argv[0])) == 0) {
/*printk("subexeccmd: cmd=%s, argc=%d\n", argv[0], argc);*/
cmds->cmdfunc(argc, argv);
return;
}
cmds++;
}
printk("Could not found '%s' sub-command\n", argv[0]);
}
|
需要注意的地方是:从command_flash()函数传递参数的时候execsubcmd(flash_cmds, argc-1, argv+1)也就是将第一个参数去掉了,执行子命令的函数。然后调用子命令函数来执行相应的操作。
我们来看看flash命令子命令的定义:
typedef struct user_subcommand {
const char *name;
void (*cmdfunc)(int argc, const char **);
const char *helpstr;
} user_subcommand_t;
|
再来看看有多少个子命令:
因为子命令比较多,应此定义了一个结构数组,数组中每一个元素表示一个子命令结构。需要的时候只需要遍历数组找到相应的子命令即可。
static user_subcommand_t flash_cmds[] = {
{
"help",
command_help,
"help"
}, {
"erase",
command_erase,
"erase [] or [ ]"
}, {
"lock",
command_lock,
"lock "
}, {
"unlock",
command_unlock,
"unlock "
}, {
"info",
command_info,
"info"
}, {
NULL,
NULL,
NULL }
};
|
到了这里只需要完成相应的处理函数即可,也就是上面的:
command_lock();
command_unlock();
command_erase();
command_info();........
给出一个具体函数的源代码:command_unlock():
static void command_unlock(int argc, const char **argv)
{
struct mtd_info *mtd = mymtd;
loff_t ofs;
size_t blk_size, len;
if (argc != 3) {
putstr("invalid 'flash unlock' command: too few(many) arguments\r\n");
return;
}
ofs = (loff_t)strtoul(argv[1], NULL, 0, NULL);
len = (size_t)strtoul(argv[2], NULL, 0, NULL);
blk_size = find_erase_size(mtd, ofs, len);
printk("Unlocking blocks 0x%08lx-0x%08lx... ", ofs, ofs+blk_size);
if (mtd->unlock(mtd, ofs, blk_size) < 0)
putstr("failed\r\n");
else
putstr("done\r\n");
}
每个函数实现不同的功能。
在完成了前面的步骤之后,最重要的一步也是最简单的一步,将命令加到命令链表中,调用的是add_command()函数
/* add user command */
void add_command(user_command_t *cmd)
{
if (head_cmd == NULL) {
head_cmd = tail_cmd = cmd;
} else {
tail_cmd->next_cmd = cmd;
tail_cmd = cmd;
}
/*printk("Registered '%s' command\n", cmd->name);*/
}
|
这里看到了,其实增加一个命令流程不难,难的是编写相应的实现函数!
阅读(1263) | 评论(0) | 转发(0) |