Chinaunix首页 | 论坛 | 博客
  • 博客访问: 866201
  • 博文数量: 190
  • 博客积分: 7021
  • 博客等级: 少将
  • 技术积分: 1752
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-17 19:26
文章分类

全部博文(190)

文章存档

2014年(9)

2011年(32)

2010年(149)

我的朋友

分类: LINUX

2010-05-21 15:05:45

早在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) |
0

上一篇:VIVI中私有数据的管理

下一篇:boot_or_vivi(1)

给主人留下些什么吧!~~