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