console.c revision 981801b95b81e6d1c7a2085967406e86af0f08fc
1/*
2 * console.c
3 *
4 * Copyright 2001-2009 Texas Instruments, Inc. - http://www.ti.com/
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 *     http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19/****************************************************************************
20*
21*   MODULE:  console.c
22*
23*   PURPOSE:
24*
25*   DESCRIPTION:
26*   ============
27*
28*
29****************************************************************************/
30
31/* includes */
32/************/
33#include "cu_osapi.h"
34#include "console.h"
35#include "cu_cmd.h"
36
37/* defines */
38/***********/
39#define INBUF_LENGTH            2100
40#define MAX_NAME_LEN        64
41#define MAX_HELP_LEN        40
42#define MAX_PARM_LEN        20
43#define ALIAS_LEN           1
44
45#define TOKEN_UP           ".."
46#define TOKEN_ROOT         "/"
47#define TOKEN_BREAK        "#"
48#define TOKEN_HELP         "?"
49#define TOKEN_DIRHELP      "help"
50
51/* local types */
52/***************/
53
54typedef enum
55{
56    Dir,
57    Token
58} ConEntry_type_t;
59
60/* Token types */
61typedef enum
62{
63    EmptyToken,
64    UpToken,
65    RootToken,
66    BreakToken,
67    HelpToken,
68    DirHelpToken,
69    NameToken
70} TokenType_t;
71
72
73/* Monitor token structure */
74typedef struct ConEntry_t
75{
76    struct ConEntry_t   *next;
77    S8                  name[MAX_NAME_LEN+1];    /* Entry name */
78    S8                  help[MAX_HELP_LEN+1];    /* Help string */
79    PS8                 alias;                  /* Alias - always in upper case*/
80    ConEntry_type_t     sel;                   /* Entry selector */
81
82    union
83    {
84        struct
85        {
86            struct ConEntry_t   *upper;            /* Upper directory */
87            struct ConEntry_t   *first;            /* First entry */
88        } dir;
89        struct t_Token
90        {
91            FuncToken_t    f_tokenFunc;            /* Token handler */
92            S32            totalParams;
93            ConParm_t      *parm;                  /* Parameters array with totalParams size */
94            PS8            *name;                 /* Parameter name with totalParams size */
95        } token;
96    } u;
97} ConEntry_t;
98
99/* Module control block */
100typedef struct Console_t
101{
102    THandle hCuCmd;
103
104    S32 isDeviceOpen;
105
106    ConEntry_t *p_mon_root;
107    ConEntry_t *p_cur_dir;
108    PS8         p_inbuf;
109    volatile S32 stop_UI_Monitor;
110} Console_t;
111
112/* local variables */
113/*******************/
114
115/* local fucntions */
116/*******************/
117static VOID Console_allocRoot(Console_t* pConsole);
118
119
120/* Remove leading blanks */
121static PS8 Console_ltrim(PS8 s)
122{
123    while( *s == ' ' || *s == '\t' ) s++;
124    return s;
125}
126
127/*
128Make a preliminary analizis of <name> token.
129Returns a token type (Empty, Up, Root, Break, Name)
130*/
131static TokenType_t Console_analizeToken( PS8 name )
132{
133    if (!name[0])
134        return EmptyToken;
135
136    if (!os_strcmp(name, (PS8)TOKEN_UP ) )
137        return UpToken;
138
139    if (!os_strcmp(name, (PS8)TOKEN_ROOT ) )
140        return RootToken;
141
142    if (!os_strcmp(name, (PS8)TOKEN_BREAK ) )
143        return BreakToken;
144
145    if (!os_strcmp(name, (PS8)TOKEN_HELP ) )
146        return HelpToken;
147
148    if (!os_strcmp(name, (PS8)TOKEN_DIRHELP ) )
149        return DirHelpToken;
150
151    return NameToken;
152
153}
154
155/* Compare strings case insensitive */
156static S32 Console_stricmp( PS8 s1, PS8 s2, U16 len )
157{
158    S32  i;
159
160    for( i=0; i<len && s1[i] && s2[i]; i++ )
161    {
162        if (os_tolower(s1[i])  != os_tolower(s2[i] ))
163            break;
164    }
165
166    return ( (len - i) * (s1[i] - s2[i]) );
167}
168
169/* Convert string s to lower case. Return pointer to s */
170static PS8 Console_strlwr( PS8 s )
171{
172    PS8 s0=s;
173
174    while( *s )
175    {
176        *s = (S8)os_tolower(*s );
177        ++s;
178    }
179
180    return s0;
181}
182
183/* free the entries tree */
184static VOID Console_FreeEntry(ConEntry_t *pEntry)
185{
186    ConEntry_t *pEntryTemp,*pEntryTemp1;
187
188    if(pEntry->sel == Dir)
189    {
190        pEntryTemp = pEntry->u.dir.first;
191
192        while (pEntryTemp)
193        {
194            pEntryTemp1 = pEntryTemp->next;
195            Console_FreeEntry(pEntryTemp);
196            pEntryTemp = pEntryTemp1;
197        }
198    }
199
200    /* free the current entry */
201    os_MemoryFree(pEntry);
202}
203
204
205/* Allocate root directory */
206static VOID Console_allocRoot(Console_t* pConsole)
207{
208    /* The very first call. Allocate root structure */
209    if ((pConsole->p_mon_root=(ConEntry_t *)os_MemoryCAlloc(sizeof( ConEntry_t ), 1) ) == NULL)
210    {
211        os_error_printf(CU_MSG_ERROR, (PS8)( "ERROR - Console_allocRoot(): cant allocate root\n") );
212        return;
213    }
214    os_strcpy((PS8)pConsole->p_mon_root->name, (PS8)("\\") );
215    pConsole->p_mon_root->sel = Dir;
216    pConsole->p_cur_dir = pConsole->p_mon_root;
217}
218
219/* Display current directory */
220static VOID Console_displayDir(Console_t* pConsole)
221{
222    S8 out_buf[512];
223    ConEntry_t *p_token;
224    ConEntry_t *p_dir = pConsole->p_cur_dir;
225
226    os_sprintf((PS8)out_buf, (PS8)("%s%s> "), (PS8)(p_dir==pConsole->p_mon_root)? (PS8)("") : (PS8)(".../"), (PS8)p_dir->name );
227    p_token = p_dir->u.dir.first;
228    while( p_token )
229    {
230        if( (os_strlen(out_buf) + os_strlen(p_token->name) + 2)>= sizeof(out_buf) )
231        {
232            os_error_printf(CU_MSG_ERROR, ( (PS8)"ERROR - Console_displayDir(): buffer too small....\n") );
233            break;
234        }
235        os_strcat(out_buf, p_token->name );
236        if ( p_token->sel == Dir )
237            os_strcat((PS8)out_buf, (PS8)("/" ) );
238        p_token = p_token->next;
239        if (p_token)
240            os_strcat((PS8)out_buf, (PS8)(", ") );
241    }
242
243    os_error_printf(CU_MSG_INFO2, (PS8)("%s\n"), (PS8)out_buf );
244}
245
246
247/*
248Cut the first U16 from <p_inbuf>.
249Return the U16 in <name> and updated <p_inbuf>
250*/
251static TokenType_t Console_getWord(Console_t* pConsole, PS8 name, U16 len )
252{
253    U16         i=0;
254    TokenType_t tType;
255
256    pConsole->p_inbuf = Console_ltrim(pConsole->p_inbuf);
257
258    while( *pConsole->p_inbuf && *pConsole->p_inbuf!=' ' && i<len )
259        name[i++] = *(pConsole->p_inbuf++);
260
261    if (i<len)
262        name[i] = 0;
263
264    tType   = Console_analizeToken( name );
265
266    return tType;
267}
268
269static TokenType_t Console_getStrParam(Console_t* pConsole, PS8 buf, ConParm_t *param )
270{
271    TokenType_t tType;
272    U32         i, len = param->hi_val;
273    PS8         end_buf;
274
275    pConsole->p_inbuf = Console_ltrim(pConsole->p_inbuf);
276
277    if( param->flags & CON_PARM_LINE )
278    {
279        os_strcpy(buf, (PS8)pConsole->p_inbuf );
280        pConsole->p_inbuf += os_strlen(pConsole->p_inbuf);
281    }
282    else
283    {
284        if( *pConsole->p_inbuf == '\"' )
285        {
286            end_buf = os_strchr(pConsole->p_inbuf+1, '\"' );
287            if( !end_buf )
288            {
289                os_error_printf(CU_MSG_ERROR, (PS8)("ERROR - invalid string param: '%s'\n"), (PS8)pConsole->p_inbuf );
290                pConsole->p_inbuf += os_strlen(pConsole->p_inbuf);
291                return EmptyToken;
292            }
293            if( (end_buf - pConsole->p_inbuf - 1) > (int)len )
294            {
295                os_error_printf(CU_MSG_ERROR, (PS8)("ERROR - param is too long: '%s'\n"), (PS8)pConsole->p_inbuf );
296                pConsole->p_inbuf += os_strlen(pConsole->p_inbuf);
297                return EmptyToken;
298            }
299            *end_buf = 0;
300            os_strcpy( buf, (PS8)(pConsole->p_inbuf+1 ) );
301            pConsole->p_inbuf = end_buf + 1;
302        }
303        else
304        {
305            for( i=0; *pConsole->p_inbuf && *pConsole->p_inbuf!=' ' && i<len; i++ )
306                buf[i] = *(pConsole->p_inbuf++);
307
308            buf[i] = 0;
309            if( *pConsole->p_inbuf && *pConsole->p_inbuf != ' ' )
310            {
311                os_error_printf(CU_MSG_ERROR, (PS8)("ERROR - param is too long: '%s'\n"), (PS8)( pConsole->p_inbuf-os_strlen( buf) ) );
312                pConsole->p_inbuf += os_strlen(pConsole->p_inbuf);
313                return EmptyToken;
314            }
315        }
316    }
317
318    tType   = Console_analizeToken( buf );
319
320    return tType;
321}
322
323/* Returns number of parameters of the given token
324*/
325static U16 Console_getNParms( ConEntry_t *p_token )
326{
327    U16 i;
328    if ( !p_token->u.token.parm )
329        return 0;
330    for( i=0;
331         (i<p_token->u.token.totalParams) &&
332          p_token->u.token.parm[i].name &&
333          p_token->u.token.parm[i].name[0];
334         i++ )
335        ;
336    return i;
337}
338
339/* Parse p_inbuf string based on parameter descriptions in <p_token>.
340Fill parameter values in <p_token>.
341Returns the number of parameters filled.
342To Do: add a option of one-by-one user input of missing parameters.
343*/
344static S32 Console_parseParms(Console_t* pConsole, ConEntry_t *p_token, U16 *pnParms )
345{
346    U16 nTotalParms = Console_getNParms( p_token );
347    U16 nParms=0;
348    PS8 end_buf = NULL;
349    S8  parm[INBUF_LENGTH];
350    U16 i, print_params = 0;
351    U32 val = 0;
352    S32 sval = 0;
353
354    /* Mark all parameters as don't having an explicit value */
355    for( i=0; i<nTotalParms; i++ )
356        p_token->u.token.parm[i].flags |= CON_PARM_NOVAL;
357
358    /*        -----------------              */
359    pConsole->p_inbuf = Console_ltrim(pConsole->p_inbuf);
360    if( pConsole->p_inbuf[0] == '!' && pConsole->p_inbuf[1] == '!' )
361    {
362        pConsole->p_inbuf += 2; print_params = 1;
363    }
364    /*        -----------------              */
365
366    /* Build a format string */
367    for( i=0; i<nTotalParms; i++ )
368    {
369        if (p_token->u.token.parm[i].flags & (CON_PARM_STRING | CON_PARM_LINE) )
370        {
371            /* For a string parameter value is the string address */
372            /* and hi_val is the string length                   */
373            if (Console_getStrParam(pConsole, parm, &p_token->u.token.parm[i] ) != NameToken)
374                break;
375            if( os_strlen( parm) > p_token->u.token.parm[i].hi_val ||
376                (p_token->u.token.parm[i].low_val && p_token->u.token.parm[i].low_val > os_strlen( parm) ) )
377            {
378                os_error_printf(CU_MSG_ERROR, (PS8)("ERROR - param '%s' must be %ld..%ld chars\n"), (PS8)p_token->u.token.parm[i].name,
379                    (PS8)p_token->u.token.parm[i].low_val, (PS8)p_token->u.token.parm[i].hi_val);
380                return FALSE;
381            }
382            os_strcpy((PS8)(char *)p_token->u.token.parm[i].value, (PS8)parm);
383        }
384        else
385        {
386            if (Console_getWord(pConsole, parm, MAX_PARM_LEN ) != NameToken)
387                break;
388
389            if (p_token->u.token.parm[i].flags & CON_PARM_SIGN)
390            {
391                sval = os_strtol( parm, &end_buf, 0 );
392            }
393            else
394            {
395                val = os_strtoul( parm, &end_buf, 0 );
396            }
397            if( end_buf <= parm )
398                break;
399
400            /* Check value */
401            if (p_token->u.token.parm[i].flags & CON_PARM_RANGE)
402            {
403                if (p_token->u.token.parm[i].flags & CON_PARM_SIGN)
404                {
405                    if ((sval < (S32)p_token->u.token.parm[i].low_val) ||
406                        (sval > (S32)p_token->u.token.parm[i].hi_val) )
407                    {
408                        os_error_printf(CU_MSG_ERROR, (PS8)("%s: %d out of range (%d, %d)\n"),
409                            (PS8)p_token->u.token.parm[i].name, (int)sval,
410                            (int)p_token->u.token.parm[i].low_val, (int)p_token->u.token.parm[i].hi_val );
411                        return FALSE;
412                    }
413
414                }
415                else
416                {
417                    if ((val < p_token->u.token.parm[i].low_val) ||
418                        (val > p_token->u.token.parm[i].hi_val) )
419                    {
420                        os_error_printf(CU_MSG_ERROR , (PS8)("%s: %ld out of range (%ld, %ld)\n"),
421                            (PS8)p_token->u.token.parm[i].name, (PS8)val,
422                            (PS8)p_token->u.token.parm[i].low_val, (PS8)p_token->u.token.parm[i].hi_val );
423                        return FALSE;
424                    }
425                }
426            }
427
428            if (p_token->u.token.parm[i].flags & CON_PARM_SIGN)
429                p_token->u.token.parm[i].value = sval;
430            else
431                p_token->u.token.parm[i].value = val;
432        }
433
434        p_token->u.token.parm[i].flags &= ~CON_PARM_NOVAL;
435        ++nParms;
436    }
437
438    /* Process default values */
439    for( ; i<nTotalParms; i++ )
440    {
441        if ((p_token->u.token.parm[i].flags & CON_PARM_DEFVAL) != 0)
442        {
443            p_token->u.token.parm[i].flags &= ~CON_PARM_NOVAL;
444            ++nParms;
445        }
446        else if (!(p_token->u.token.parm[i].flags & CON_PARM_OPTIONAL) )
447        {
448            /* Mandatory parameter missing */
449            return FALSE;
450        }
451    }
452
453    if( print_params )
454    {
455        os_error_printf((S32)CU_MSG_INFO2, (PS8)("Params: %d\n"), nParms );
456        for (i=0; i<nParms; i++ )
457        {
458            os_error_printf(CU_MSG_INFO2, (PS8)("%d: %s - flags:%d"),
459                i+1, (PS8)p_token->u.token.parm[i].name,
460                p_token->u.token.parm[i].flags);
461
462            if (p_token->u.token.parm[i].flags & CON_PARM_SIGN)
463                os_error_printf(CU_MSG_INFO2, (PS8)("min:%d, max:%d, value:%d "),(PS8)p_token->u.token.parm[i].low_val, (PS8)p_token->u.token.parm[i].hi_val,
464                (PS8)p_token->u.token.parm[i].value);
465            else
466                os_error_printf(CU_MSG_INFO2, (PS8)("min:%ld, max:%ld, value:%ld "),(PS8)p_token->u.token.parm[i].low_val, (PS8)p_token->u.token.parm[i].hi_val,
467                (PS8)p_token->u.token.parm[i].value);
468
469            os_error_printf(CU_MSG_INFO2, (PS8)("(%#lx)"),(PS8)p_token->u.token.parm[i].value );
470
471            if( p_token->u.token.parm[i].flags & (CON_PARM_LINE | CON_PARM_STRING ))
472            {
473                os_error_printf(CU_MSG_INFO2, (PS8)(" - '%s'"), (PS8)(char *) p_token->u.token.parm[i].value );
474            }
475            os_error_printf(CU_MSG_INFO2, (PS8)("\n") );
476        }
477
478    }
479    *pnParms = nParms;
480
481    return TRUE;
482}
483
484/* Serach a token by name in the current directory */
485static ConEntry_t *Console_searchToken( ConEntry_t *p_dir, PS8 name )
486{
487    ConEntry_t *p_token;
488    U16        name_len = (U16)os_strlen( name );
489
490    /* Check alias */
491    p_token = p_dir->u.dir.first;
492    while( p_token )
493    {
494        if (p_token->alias &&
495            (name_len == ALIAS_LEN) &&
496            !Console_stricmp( p_token->alias, name, ALIAS_LEN ) )
497            return p_token;
498        p_token = p_token->next;
499    }
500
501    /* Check name */
502    p_token = p_dir->u.dir.first;
503    while( p_token )
504    {
505        if (!Console_stricmp( p_token->name, name, name_len ) )
506            break;
507        p_token = p_token->next;
508    }
509
510    return p_token;
511}
512
513
514/* Display help for each entry in the current directory */
515VOID  Console_dirHelp(Console_t* pConsole)
516{
517    ConEntry_t *p_token;
518    S8        print_str[80];
519
520    p_token = pConsole->p_cur_dir->u.dir.first;
521
522    while( p_token )
523    {
524        if (p_token->sel == Dir)
525            os_sprintf( print_str, (PS8)"%s: directory\n", (PS8)p_token->name );
526        else
527            os_sprintf( print_str, (PS8)("%s(%d parms): %s\n"),
528            (PS8)p_token->name, Console_getNParms(p_token), p_token->help );
529        os_error_printf(CU_MSG_INFO2,  (PS8)print_str );
530        p_token = p_token->next;
531    }
532
533    os_error_printf(CU_MSG_INFO2, (PS8)("Type ? <name> for command help, \"/\"-root, \"..\"-upper\n") );
534}
535
536
537/* Display help a token */
538static VOID  Console_displayHelp(Console_t* pConsole, ConEntry_t *p_token )
539{
540    S8 bra, ket;
541    U16 nTotalParms = Console_getNParms( p_token );
542    U16 i;
543
544
545    os_error_printf(CU_MSG_INFO2, (PS8)("%s: %s "), (PS8)p_token->help, (PS8)p_token->name );
546    for( i=0; i<nTotalParms; i++ )
547    {
548        if (p_token->u.token.parm[i].flags & CON_PARM_OPTIONAL)
549        {
550            bra = '['; ket=']';
551        }
552        else
553        {
554            bra = '<'; ket='>';
555        }
556        os_error_printf(CU_MSG_INFO2, (PS8)("%c%s"), bra, (PS8)p_token->u.token.parm[i].name );
557        if (p_token->u.token.parm[i].flags & CON_PARM_DEFVAL)
558        {
559            os_error_printf(CU_MSG_INFO2, (PS8)("=%lu"), (PS8)p_token->u.token.parm[i].value);
560        }
561        if (p_token->u.token.parm[i].flags & CON_PARM_RANGE)
562        {
563            os_error_printf(CU_MSG_INFO2, (PS8)(p_token->u.token.parm[i].flags & CON_PARM_SIGN) ? (PS8)(" (%d..%d%s)") : (PS8)(" (%lu..%lu%s)"),
564                (PS8)p_token->u.token.parm[i].low_val,
565                (PS8)p_token->u.token.parm[i].hi_val,
566                (PS8)(p_token->u.token.parm[i].flags & (CON_PARM_STRING | CON_PARM_LINE)) ? (PS8)(" chars") : (PS8)("") );
567
568        }
569        os_error_printf(CU_MSG_INFO2, (PS8)("%c \n"),ket );
570    }
571}
572
573/* Choose unique alias for <name> in <p_dir> */
574/* Currently only single-character aliases are supported */
575static S32 Console_chooseAlias( ConEntry_t *p_dir, ConEntry_t *p_new_token )
576{
577    ConEntry_t *p_token;
578    S32         i;
579    S8          c;
580    PS8         new_alias = NULL;
581
582    /* find alias given from user */
583    for(i=0; p_new_token->name[i]; i++ )
584    {
585        if( os_isupper( p_new_token->name[i]) )
586        {
587            new_alias = &p_new_token->name[i];
588            break;
589        }
590    }
591
592    Console_strlwr( p_new_token->name );
593
594    if( new_alias )
595    {
596        p_token = p_dir->u.dir.first;
597
598        while( p_token )
599        {
600            if (p_token->alias && (os_tolower(*p_token->alias ) == *new_alias) )
601            {
602                os_error_printf(CU_MSG_ERROR, (PS8)("Error - duplicated alias '%c' in <%s> and <%s>**\n"), *new_alias,
603                    (PS8)p_token->name, (PS8)p_new_token->name );
604                return 0;
605            }
606            p_token = p_token->next;
607        }
608        *new_alias = (S8)os_toupper(*new_alias);
609        p_new_token->alias = new_alias;
610        return 1;
611    }
612
613    i = 0;
614    while( p_new_token->name[i] )
615    {
616        c = p_new_token->name[i];
617        p_token = p_dir->u.dir.first;
618
619        while( p_token )
620        {
621            if (p_token->alias &&
622                (os_tolower(*p_token->alias ) == c) )
623                break;
624            p_token = p_token->next;
625        }
626        if (p_token)
627            ++i;
628        else
629        {
630            p_new_token->name[i] = (S8)os_toupper( c );
631            p_new_token->alias   = &p_new_token->name[i];
632            break;
633        }
634    }
635    return 1;
636}
637
638/* Parse the given input string and exit.
639All commands in the input string are executed one by one.
640*/
641static VOID Console_ParseString(Console_t* pConsole, PS8 input_string )
642{
643    ConEntry_t  *p_token;
644    S8          name[MAX_NAME_LEN];
645    TokenType_t tType;
646    U16         nParms;
647
648    if (!pConsole->p_mon_root)
649        return;
650
651    if(!pConsole->isDeviceOpen)
652    {
653        Console_GetDeviceStatus(pConsole);
654        if(!pConsole->isDeviceOpen)
655        {
656            os_error_printf(CU_MSG_ERROR, (PS8)("ERROR - Console_ParseString - Device isn't loaded !!!\n") );
657            return;
658        }
659    }
660
661    if( input_string[os_strlen( input_string)-1] == '\n' )
662    {
663        PS8 s = &input_string[os_strlen( input_string)-1];
664        *s = 0;
665    }
666    pConsole->p_inbuf = input_string;
667    pConsole->stop_UI_Monitor = FALSE;
668
669    /* Interpret empty string as "display directory" */
670    if ( pConsole->p_inbuf && !*pConsole->p_inbuf )
671        Console_displayDir(pConsole);
672
673    while(!pConsole->stop_UI_Monitor && pConsole->p_inbuf && *pConsole->p_inbuf)
674    {
675        tType = Console_getWord(pConsole, name, MAX_NAME_LEN );
676        switch( tType )
677        {
678
679        case NameToken:
680            p_token = Console_searchToken( pConsole->p_cur_dir, name );
681            if (p_token == NULL)
682            {
683                os_error_printf(CU_MSG_ERROR, (PS8)("**Error: '%s'**\n"),name);
684                pConsole->p_inbuf = NULL;
685            }
686            else if (p_token->sel == Dir)
687            {
688                pConsole->p_cur_dir = p_token;
689                Console_displayDir(pConsole);
690            }
691            else
692            {  /* Function token */
693                if (!Console_parseParms(pConsole, p_token, &nParms ))
694                {
695                    Console_displayHelp(pConsole, p_token );
696                }
697                else
698                {
699                    p_token->u.token.f_tokenFunc(pConsole->hCuCmd, p_token->u.token.parm, nParms );
700                }
701            }
702            break;
703
704        case UpToken: /* Go to upper directory */
705            if (pConsole->p_cur_dir->u.dir.upper)
706                pConsole->p_cur_dir = pConsole->p_cur_dir->u.dir.upper;
707            Console_displayDir(pConsole);
708            break;
709
710        case RootToken: /* Go to the root directory */
711            if (pConsole->p_cur_dir->u.dir.upper)
712                pConsole->p_cur_dir = pConsole->p_mon_root;
713            Console_displayDir(pConsole);
714            break;
715
716        case HelpToken: /* Display help */
717            if (( Console_getWord(pConsole, name, MAX_NAME_LEN ) == NameToken ) &&
718                ((p_token = Console_searchToken( pConsole->p_cur_dir, name )) != NULL ) &&
719                (p_token->sel == Token) )
720                Console_displayHelp(pConsole, p_token);
721            else
722                Console_dirHelp(pConsole);
723            break;
724
725        case DirHelpToken:
726            Console_displayDir(pConsole);
727            os_error_printf(CU_MSG_INFO2, (PS8)("Type ? <name> for command help, \"/\"-root, \"..\"-upper\n") );
728            break;
729
730        case BreakToken: /* Clear buffer */
731            pConsole->p_inbuf = NULL;
732            break;
733
734        case EmptyToken:
735            break;
736
737        }
738    }
739}
740
741/* functions */
742/*************/
743
744THandle Console_Create(const PS8 device_name, S32 BypassSupplicant, PS8 pSupplIfFile)
745{
746    Console_t* pConsole = (Console_t*)os_MemoryCAlloc(sizeof(Console_t), sizeof(U8));
747    if(pConsole == NULL)
748    {
749        os_error_printf(CU_MSG_ERROR, (PS8)("Error - Console_Create - cant allocate control block\n") );
750        return NULL;
751    }
752
753    pConsole->hCuCmd = CuCmd_Create(device_name, pConsole, BypassSupplicant, pSupplIfFile);
754    if(pConsole->hCuCmd == NULL)
755    {
756        Console_Destroy(pConsole);
757        return NULL;
758    }
759
760    Console_allocRoot(pConsole);
761
762    pConsole->isDeviceOpen = FALSE;
763
764    return pConsole;
765}
766
767VOID Console_Destroy(THandle hConsole)
768{
769    Console_t* pConsole = (Console_t*)hConsole;
770
771    if(pConsole->hCuCmd)
772    {
773        CuCmd_Destroy(pConsole->hCuCmd);
774    }
775    if (pConsole->p_mon_root)
776    {
777    Console_FreeEntry(pConsole->p_mon_root);
778    }
779    os_MemoryFree(pConsole);
780}
781
782VOID Console_Stop(THandle hConsole)
783{
784    ((Console_t*)hConsole)->stop_UI_Monitor = TRUE;
785}
786
787/* Monitor driver */
788VOID Console_Start(THandle hConsole)
789{
790    Console_t* pConsole = (Console_t*)hConsole;
791    S8  inbuf[INBUF_LENGTH];
792    S32 res;
793
794    if (!pConsole->p_mon_root)
795        return;
796
797    pConsole->stop_UI_Monitor = FALSE;
798    Console_displayDir(pConsole);
799
800    while(!pConsole->stop_UI_Monitor)
801    {
802        /* get input string */
803        res = os_getInputString(inbuf, sizeof(inbuf));
804        if (res == FALSE)
805        {
806            if(pConsole->stop_UI_Monitor)
807            {
808                continue;
809            }
810            else
811            {
812                return;
813            }
814        }
815
816        if(res == OS_GETINPUTSTRING_CONTINUE)
817            continue;
818
819        /* change to NULL terminated strings */
820        if( inbuf[os_strlen(inbuf)-1] == '\n' )
821            inbuf[os_strlen(inbuf)-1] = 0;
822
823        /* parse the string */
824        Console_ParseString(pConsole, inbuf);
825    }
826
827}
828
829VOID Console_GetDeviceStatus(THandle hConsole)
830{
831    Console_t* pConsole = (Console_t*)hConsole;
832
833    if(OK == CuCmd_GetDeviceStatus(pConsole->hCuCmd))
834    {
835        pConsole->isDeviceOpen = TRUE;
836    }
837}
838
839
840/***************************************************************
841
842  Function : consoleAddDirExt
843
844    Description: Add subdirectory
845
846      Parameters: p_root - root directory handle (might be NULL)
847      name   - directory name
848
849        Output:  the new created directory handle
850        =NULL - failure
851***************************************************************/
852THandle Console_AddDirExt(THandle  hConsole,
853                          THandle   hRoot,         /* Upper directory handle. NULL=root */
854                          const PS8  name,          /* New directory name */
855                          const PS8  desc )         /* Optional dir description */
856{
857    Console_t* pConsole = (Console_t*)hConsole;
858    ConEntry_t *p_root = (ConEntry_t *)hRoot;
859    ConEntry_t *p_dir;
860    ConEntry_t **p_e;
861
862    if (!p_root)
863        p_root = pConsole->p_mon_root;
864
865    if(!( p_root && (p_root->sel == Dir)))
866        return NULL;
867
868    if ( (p_dir=(ConEntry_t *)os_MemoryAlloc(sizeof( ConEntry_t )) ) == NULL)
869        return NULL;
870
871    os_memset( p_dir, 0, sizeof( ConEntry_t ) );
872    os_strncpy( p_dir->name, name, MAX_NAME_LEN );
873    os_strncpy( p_dir->help, desc, MAX_HELP_LEN );
874    p_dir->sel = Dir;
875
876    Console_chooseAlias( p_root, p_dir );
877
878    /* Add new directory to the root's list */
879    p_dir->u.dir.upper = p_root;
880    p_e = &(p_root->u.dir.first);
881    while (*p_e)
882        p_e = &((*p_e)->next);
883    *p_e = p_dir;
884
885    return p_dir;
886}
887
888/***************************************************************
889
890  Function : consoleAddToken
891
892    Description: Add token
893
894      Parameters: p_dir  - directory handle (might be NULL=root)
895      name   - token name
896      help   - help string
897      p_func - token handler
898      p_parms- array of parameter descriptions.
899      Must be terminated with {0}.
900      Each parm descriptor is a struct
901      { "myname",         - name
902      10,               - low value
903      20,               - high value
904      0 }               - default value =-1 no default
905      or address for string parameter
906
907        Output:  E_OK - OK
908        !=0 - error
909***************************************************************/
910consoleErr Console_AddToken(  THandle hConsole,
911                                THandle      hDir,
912                                const PS8     name,
913                                const PS8     help,
914                                FuncToken_t   p_func,
915                                ConParm_t     p_parms[] )
916{
917    Console_t* pConsole = (Console_t*)hConsole;
918    ConEntry_t *p_dir = (ConEntry_t *)hDir;
919    ConEntry_t *p_token;
920    ConEntry_t **p_e;
921    U16       i;
922
923    if (!pConsole->p_mon_root)
924      Console_allocRoot(pConsole);
925
926    if (!p_dir)
927      p_dir = pConsole->p_mon_root;
928
929    if(!( p_dir && (p_dir->sel == Dir)))
930        return E_ERROR;
931
932
933    /* Initialize token structure */
934    if((p_token = (ConEntry_t *)os_MemoryCAlloc(1,sizeof(ConEntry_t))) == NULL)
935    {
936     os_error_printf(CU_MSG_ERROR, (PS8)("** no memory **\n") );
937      return E_NOMEMORY;
938    }
939
940
941    /* Copy name */
942    os_strncpy( p_token->name, name, MAX_NAME_LEN );
943    os_strncpy( p_token->help, help, MAX_HELP_LEN );
944    p_token->sel = Token;
945    p_token->u.token.f_tokenFunc = p_func;
946    p_token->u.token.totalParams = 0;
947
948    /* Convert name to lower case and choose alias */
949    Console_chooseAlias( p_dir, p_token );
950
951    /* Copy parameters */
952    if ( p_parms )
953    {
954       ConParm_t     *p_tmpParms = p_parms;
955
956       /* find the number of params */
957       while( p_tmpParms->name && p_tmpParms->name[0] )
958       {
959            p_token->u.token.totalParams++;
960            p_tmpParms++;
961       }
962       /* allocate the parameters info */
963       p_token->u.token.parm = (ConParm_t *)os_MemoryAlloc(p_token->u.token.totalParams * sizeof(ConParm_t));
964       p_token->u.token.name = (PS8*)os_MemoryAlloc(p_token->u.token.totalParams * sizeof(PS8));
965       if ((p_token->u.token.parm == NULL) || (p_token->u.token.name == NULL))
966       {
967            os_error_printf(CU_MSG_ERROR, (PS8)("** no memory for params\n") );
968            os_MemoryFree(p_token);
969            return E_NOMEMORY;
970       }
971       for (i=0; i < p_token->u.token.totalParams; i++)
972       {
973         ConParm_t *p_token_parm = &p_token->u.token.parm[i];
974
975         /* String parameter must have an address */
976         if(p_parms->flags & (CON_PARM_STRING | CON_PARM_LINE))
977         {
978            if ( p_parms->hi_val >= INBUF_LENGTH )
979            {
980               os_error_printf(CU_MSG_ERROR, (PS8)("** buffer too big: %s/%s\n"), p_dir->name, name);
981                os_MemoryFree(p_token->u.token.parm);
982                os_MemoryFree(p_token->u.token.name);
983                os_MemoryFree(p_token);
984                return E_NOMEMORY;
985
986            }
987            if (p_parms->hi_val == 0 || (p_parms->flags & CON_PARM_RANGE) )
988            {
989               os_error_printf(CU_MSG_ERROR, (PS8)("** Bad string param definition: %s/%s\n"), p_dir->name, name );
990                os_MemoryFree(p_token->u.token.parm);
991                os_MemoryFree(p_token->u.token.name);
992                os_MemoryFree(p_token);
993                return E_BADPARM;
994            }
995            p_parms->value = (U32)os_MemoryCAlloc(1,p_parms->hi_val+1);
996            if( !p_parms->value )
997            {
998                os_error_printf(CU_MSG_ERROR, (PS8)("** No memory: %s/%s (max.size=%ld)\n"), p_dir->name, name, p_parms->hi_val );
999                os_MemoryFree(p_token->u.token.parm);
1000                os_MemoryFree(p_token->u.token.name);
1001                os_MemoryFree(p_token);
1002                return E_NOMEMORY;
1003            }
1004        }
1005
1006        /* Copy parameter */
1007        *p_token_parm = *p_parms;
1008        if( p_token_parm->hi_val || p_token_parm->low_val )
1009            p_token_parm->flags |= CON_PARM_RANGE;
1010
1011        p_token->u.token.name[i] = os_MemoryAlloc(os_strlen(p_parms->name));
1012        if (p_token->u.token.name[i] == NULL)
1013        {
1014            os_error_printf(CU_MSG_ERROR, (PS8)("** Error allocate param name\n"));
1015            os_MemoryFree(p_token->u.token.parm);
1016            os_MemoryFree(p_token->u.token.name);
1017            os_MemoryFree(p_token);
1018            return E_NOMEMORY;
1019        }
1020         p_token_parm->name = (PS8)p_token->u.token.name[i];
1021         os_strncpy( p_token->u.token.name[i], p_parms->name, os_strlen(p_parms->name) );
1022         ++p_parms;
1023      } /*end of for loop*/
1024    }
1025
1026    /* Add token to the directory */
1027    p_e = &(p_dir->u.dir.first);
1028    while (*p_e)
1029      p_e = &((*p_e)->next);
1030    *p_e = p_token;
1031
1032    return E_OK;
1033}
1034
1035