| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477 | /****************************************************************************** * Orange Shell * Copyright 2015, 飞联. * * File Name  : Orange.c * Description: 一个简单的shell. *          命令字符长度建议>=3,否则太容易匹配成功,导致输入异常时亦匹配到命令 * * modification history * -------------------- * V1.1, 18-mar-2016, 胡达科 modify: 查找命令匹配时的命令长度从输入长度改为系统命令长度 * V1.0, 08-may-2015, Simon written * -------------------- ******************************************************************************/#include <stdio.h>#include <string.h>#include <stdarg.h>#include <ctype.h>#include "hw_cfg.h"#include "mbox.h"#include "device.h"#include "orange.h"#include "uart.h"#include "TermAttr.h"Orange_Shell_t Shell;Orange_Syscall_t *_syscall_table_begin  = NULL;Orange_Syscall_t *_syscall_table_end    = NULL;extern const int OSymTab$$Base;extern const int OSymTab$$Limit;static uint8_t Orange_InitFlag = 0;static Dev_Err_t Orange_RxInd(Dev_t dev, uint32_t size){    Mbox_Post(Shell.rx_mb, size);    return DEV_OK;}/****************************************************************************** * Orange_SysFuncInit - 系统注册命令代码块初始化 * * Input: *  -begin, 代码块开始地址 *  -end, 代码块结束地址 * Output: * Returns: * modification history * -------------------- * 08-may-2015, Simon written * -------------------- ******************************************************************************/static void Orange_SysFuncInit(const void* begin, const void* end){    _syscall_table_begin = (Orange_Syscall_t*) begin;    _syscall_table_end = (Orange_Syscall_t*) end;}void Orange_SetDev(const char* dev_id){    Dev_t dev = NULL;    if(!Orange_InitFlag)    {        Orange_InitFlag = 1;        Orange_SysFuncInit(&OSymTab$$Base, &OSymTab$$Limit);        Shell.rx_mb = Mbox_Create(50);    }    dev = Dev_Find(dev_id);    if (dev != NULL && Dev_Open(dev, DEVICE_OFLAG_RDWR) == DEV_OK)    {        if (Shell.device != NULL)        {            /* close old finsh device */            Dev_Close(Shell.device);        }        Shell.device = dev;        Dev_SetRxIndicate(dev, Orange_RxInd);    }    #ifdef DEBUG_VERSION    else    {        printf("Orange: can not find device:%u\n", dev_id);    }    #endif}void Orange_Printf(const char *fmt, ...){    va_list args;    uint32_t length;    static char log_buf[512];    if(Shell.device == NULL)        return;    va_start(args, fmt);    /* the return value of vsnprintf is the number of bytes that would be     * written to buffer had if the size of the buffer been sufficiently     * large excluding the terminating null byte. If the output string     * would be larger than the rt_log_buf, we have to adjust the output     * length. */    length = vsnprintf(log_buf, sizeof(log_buf) - 1, fmt, args);    if (length > 512 - 1)        length = 512 - 1;    if (Shell.device != NULL)        Dev_Write(Shell.device, 0, log_buf, length);    va_end(args);}/****************************************************************************** * Orange_Strncmp - 字符串比较, 忽略字母大小写比较 * * Input: *  -str1, 字符串1 *  -str2, 字符串2 *  -count, 字符串比较长度 * Output: * Returns: 如果字符串前count个字符相等则返回0, 如果str1<str2则返回值<0, *          如果str1>str2则返回值>0. * modification history * -------------------- * 08-may-2015, Simon written * -------------------- ******************************************************************************/int Orange_Strncmp(const char *str1, const char *str2, int count){    register signed char __res = 0;    char cs, ct;    while (count)    {        cs = tolower(*str1);        ct = tolower(*str2);        if ((__res = cs - ct) != 0 || !cs)            break;        str1++;        str2++;        count--;    }    return __res;}/****************************************************************************** * Orange_GetToken - 从字符串中获取代号, 如获取命令关键字、实参等, 以空格为分隔 * 符截取空格前的代号 * * Input: line, 输入字符串 * Output: * Returns: 返回字符串代号 * modification history * -------------------- * 08-may-2015, Simon written * -------------------- ******************************************************************************/static char *Orange_GetToken(char *line){    unsigned char i = 0;    if (line[0] == '\0' || line[0] == '\r' || line[0] == '\n')        return NULL;    while(line[i] !=' ' && line[i] != '\t' && line[i] != '\r' && line[i] != '\n' && line[i] != '\0')        i++;    line[i] = '\0';    return line;}/****************************************************************************** * Orange_SyscallLookup - 查找系统注册命令 * * Input: name, 命令关键字字符串 * Output: * Returns: 返回系统注册命令结构体 * modification history * -------------------- * 08-may-2015, Simon written * -------------------- ******************************************************************************/static Orange_Syscall_t* Orange_SyscallLookup(char* name){    Orange_Syscall_t* index;    int str_len = 0;    str_len = strlen(name) - 1;    if(name[str_len] == '?')    {        if(str_len == 0)        {            strcpy(name, "help");        }    }    for (index = _syscall_table_begin; index < _syscall_table_end; index ++)    {        /*由于电脑串口引发输入字符串异常,使用输入字符串长度匹配产生匹配错误        如: t_mobile-> t     即可匹配*/        if (Orange_Strncmp(index->name, name, strlen(index->name)) == 0)        {            if(strlen(index->name) == strlen(name))                return index;            else if((name[strlen(name) - 1] == '?' && (strlen(name) - strlen(index->name) == 1))                || (name[strlen(name) - 1] == '=' && (strlen(name) - strlen(index->name) == 1)))            {                return index;            }        }    }    return NULL;}/****************************************************************************** * Orange_SyscallExcute - 查找并执行指令,返回结果 * * Input: ch, 命令行 * Output: 执行结果 0:不响应命令 1:设置成功 2:指令查询 -1:设置失败 -2:无此命令 * Returns: * modification history * -------------------- * 25-sep-2015, czd written * -------------------- ******************************************************************************/int Orange_SyscallExcute(char *ch,Orange_Syscall_t ** SysCallResult){    char *argv[11] = {0};    Orange_Syscall_t *sys_call = NULL;    int i,ret=0;    argv[0] = Orange_GetToken(ch);    sys_call = Orange_SyscallLookup(argv[0]);    if( SysCallResult != NULL )        *SysCallResult = sys_call;    if(sys_call)    {        for(i = 0; i < 10; i++)        {            argv[i + 1] = Orange_GetToken(&argv[i][strlen(argv[i]) + 1]);            if(argv[i + 1] == NULL)                break;            if(strlen(argv[i + 1]) > 100)                break;        }        if(argv[0][strlen(argv[0]) - 1] == '?')            return 2;        if(argv[0][strlen(argv[0]) - 1] == '=')        {            char *pargv = &argv[0][strlen(argv[0]) - 1];            ret = sys_call->func(&pargv);            return ret;        }        else        {            ret = sys_call->func(&argv[1]);            return ret;        }    }    else    {        return -2;    }}/****************************************************************************** * Orange_RunLine - 命令运行处理 * * Input: ch, 命令行 * Output: * Returns: * modification history * -------------------- * 08-may-2015, Simon written * -------------------- ******************************************************************************/static void Orange_RunLine(char *ch){    char *pbuf = NULL;    Orange_Syscall_t *sys_call = NULL;    int ret=0;    if(!Shell.echo_mode)    {        pbuf = strstr(ch, "shell on");        if(pbuf)        {            Shell.echo_mode = 1;            Orange_Printf("\r\n");        }        return;    }    else    {        pbuf = strstr(ch, "shell off");        if(pbuf)        {            Shell.echo_mode = 0;            return;        }    }    ret = Orange_SyscallExcute(ch , &sys_call); //返回值 0:不响应命令 1:设置成功 2:指令查询 -1:设置失败 -2:无此命令    switch( ret )        {            case 0 :                break;            case 1 :                Orange_Printf("Config OK!\r\n");                break;            case 2 :                Orange_Printf("\t%-16s -- %s\r\n", sys_call->name, sys_call->desc);                break;            case -1:                Orange_Printf("Config Failed!\r\n");                break;            case -2 :                Orange_Printf("Bad Command!\r\n");                break ;            default :                break ;        }}/****************************************************************************** * OrangeShell - shell入口函数 * * Input: *  -chs, 输入的字符串 *  -size, 输入的字符串长度 * Output: * Returns: * modification history * -------------------- * 08-may-2015, Simon written * -------------------- ******************************************************************************/void Orange_Shell(void){    char ch;    uint32_t size = 0;    char buf[ORANGE_CMD_SIZE];    char *chs = buf;    /* Init */    if(!Orange_InitFlag)    {        Orange_InitFlag = 1;        Orange_SysFuncInit(&OSymTab$$Base, &OSymTab$$Limit);        Shell.rx_mb = Mbox_Create(50);    }    /* Process */    {        if(Mbox_Pend(Shell.rx_mb, &size) == MBOX_OK)        {            if(size >= ORANGE_CMD_SIZE)            {                Orange_Printf("CMD Exceed!\r\n");                while(size--)                    Dev_Read(Shell.device, 0, chs, 1);                return;            }            size =  Dev_Read(Shell.device, 0, chs, size);        }        /* read one character from device */        while (size)        {            ch = *chs;            size--;            chs++;            /* handle CR key */            if (ch == '\r')            {                if (size)                {                    ch = *chs;                    size--;                    chs++;                }                else                    ch = '\r';            }            /* handle backspace key */            if (ch == 0x7f || ch == 0x08)            {                if(Shell.line_position != 0 && Shell.echo_mode)                {                    Orange_Printf("%c %c", ch, ch);                }                if(Shell.line_position <= 0)                    Shell.line_position = 0;                else                    Shell.line_position --;                Shell.line[Shell.line_position] = 0;                continue;            }            /* handle end of line, break */            if (ch == '\r' || ch == '\n')            {                Shell.line[Shell.line_position] = '\0';                if(Shell.echo_mode)                    Orange_Printf("\r\n");                if (Shell.line_position != 0)                    Orange_RunLine(Shell.line);                if(Shell.echo_mode)                    Orange_Printf(ORANGE_PROMPT);                memset(Shell.line, 0, sizeof(Shell.line));                Shell.line_position = 0;                continue;            }            /* it's a large line, discard it */            if (Shell.line_position >= ORANGE_CMD_SIZE)                Shell.line_position = 0;            /* normal character */            Shell.line[Shell.line_position] = ch;            ch = 0;            if(Shell.echo_mode)                Orange_Printf("%c", Shell.line[Shell.line_position]);            Shell.line_position ++;        } /* end of device read */    }}/****************************************************************************** * Orange_GetParam - 获取字符串中的参数 * Input: src:字符串数组的首地址;param_no:获取第n个参数 * Output: * Returns: 返回获取到的参数 * Description: * modification history * -------------------- * 14-jul-2015, czj written * -------------------- ******************************************************************************/char *Orange_GetParam(char *src, uint8_t param_no){    char *tmp = src;    if(!src)    {        return NULL;    }    if(!param_no)        return NULL;    while(--param_no)    {        tmp = tmp + strlen(tmp) + 1;    }    return tmp;}int Orange_List(void){    {        Orange_Syscall_t *index;        for (index = _syscall_table_begin; index < _syscall_table_end; index ++)        {            Orange_Printf("  %-30s -- %s\r\n", index->name, index->desc);        }    }    return 0;}ORANGE_FUNCTION_EXPORT(Orange_List, help, "list all symbol in system. e.g.help");
 |