/*
 *            Copyright (c) 1998-2000 by NETsilicon Inc.
 *
 *  This software is copyrighted by and is the sole property of 
 *  NETsilicon.  All rights, title, ownership, or other interests
 *  in the software remain the property of NETsilicon.  This
 *  software may only be used in accordance with the corresponding
 *  license agreement.  Any unauthorized use, duplication, transmission,  
 *  distribution, or disclosure of this software is expressly forbidden.
 *
 *  This Copyright notice may not be removed or modified without prior
 *  written consent of NETsilicon.
 *
 *  NETsilicon, reserves the right to modify this software
 *  without notice.
 *
 *  NETsilicon
 *  411 Waverley Oaks Road                  USA 781.647.1234
 *  Suite 227                               http://www.netsilicon.com
 *  Waltham, MA 02452                       AmericaSales@netsilicon.com
 *
 *************************************************************************
 *
 *     Module Name: dialog.c
 *         Version: 1.00
 *   Original Date: 10/06/99    
 *          Author: Li Zhen
 *   Original Date: 10-Feb-2000
 *          Author: 
 *        Language: Ansi C
 * Compile Options: 
 * Compile defines: 
 *       Libraries: 
 *    Link Options: 
 *
 *    Entry Points: customizeDialog()
 *
 * Description.
 * =======================================================================
 *  This file contains startup dialog routines. THE CODE IN THIS FILE MUST 
 *  BE CUSTOMIZED TO SUPPORT YOUR APPLICATION HARDWARE.  The default 
 *  implementation supports the NET+OS development boards
 *                                                                        
 *                                                                        
 * Edit Date/Ver   Edit Description
 * ==============  ===================================================
 * LZ   02/08/00   added "printf("APPLICATION: %s\r\n", APP_DIALOG_APP_NAME)"
 * LZ   02/16/00   changed "Copyright (c) 1999" to "Copyright (c) 2000"
 * SW   03/06/00   cast return value of getchar() to char avoid a run time error
 * LZ   04/05/00   Added support for little endian.
 * LZ   06/06/00   Added more comments for NVM.
 *                 Added code to handle no NVM case.
 * DXL	07/06/00   netosConfigDialog () return -1 if APP_DIALOG_PORT is not defined 
 * LZ   07/12/00   if !nvParams.useDhcp, then print IP addresses.
 * PMJ  10/18/00   Updated to support dynamic PPP NVRAM parameters.
 * PMJ  10/19/00   Corrected problems with mislabeling of COM1 ports to COM2
 * PMJ  10/26/00   Removed private function NAResolve_MAC in place of public API.
 * NGUR 08/13/01   Add useAppConfh.
 * PMJ  03/20/02   Added root password protection to the system dialog on modification.
 * PMJ  03/22/02   Included dialog capabilities for root password, administrators 
 *                 password, Fixed Key setting and Kerberos parameters.
 * PMJ  03/29/02   Included dialog capabilities for SNTP Servers. 
 * PMJ  04/11/02   Included dialog capabilities for the Kerberos parameters: KDC address,
 *                 username, password, and realmname.   Cleaned up some application 
 *                 issues with the dialog.
 * PMJ  04/23/02   Corrected compiler Warnings.
 * SW   04/30/02   Added GNU support for redirecting std I/O
 * DXL	08/21/002  Use API define for application configuration; 
 *					Removed unneccessary layeers if conditions
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#ifdef NETOS_GNU_TOOLS   /* for GNU only */
#include <sys/fcntl.h>  /* for open */
#endif
#include "tx_api.h"
#include "appconf_api.h"
#include "boardParams.h"
#include "netosIo.h"
#include "netoserr.h"
#include "sysAccess.h"
#include "dialog.h"
#include "NASecurity.h"
#include "bsp.h"

#include "termios.h"

#include "narmapi.h"

#if BSP_WANT_WPA
#include "wpa_api.h"
#endif

static int checkSerialNumber(char *buffer);
static int  checkIpAddress(char *buffer);
static void printIpAddress(char *buffer, unsigned long ip);
static void printMacAddress(char *buffer, BYTE * mac);
static char checkKeyboardInput(unsigned long timeout);
static void readPassword(char * buf);
static void readLine(char * buf);
static int NACloseDialog (void);
static int NAOpenDialog (int flag, devBoardParamsType *nvParamsPtr);
static int NADisplayDialog (devBoardParamsType *nvParamsPtr);
static int NAConfigureDialog (devBoardParamsType *nvParamsPtr);
static int NANetworkDialog (devBoardParamsType *nvParamsPtr);
static int NASecurityDialog (devBoardParamsType *nvParamsPtr);
static int NAHardwareDialog (devBoardParamsType *nvParamsPtr);
static int NAUpdateDialog (devBoardParamsType *nvParamsPtr);
static int kbGetIpAddress (char *ipAddrDesc, unsigned long *ipAddress);
static int kbGetData (char *itemDesc, char *destBuffer, int length, int flag);
static int kbGetReply (char *itemDesc, int flag);
static int kbGetString (char *itemDesc, char *destBuffer, int length, int flag);


#define SERIALNUMBER_LENGTH     8
#define MAX_IPADDRESS_LENGTH    15

#define NADIALOG_VERIFY			0x01
#define NADIALOG_CUSTOM_REPLY	0x02
#define NADIALOG_CUSTOM_DEF_YES	0x04

extern devBoardParamsType defaultParams; 
static int fd;
static unsigned inch, outch, errch;

extern int ioctl(int, int, void *);

#ifdef NETOS_GNU_TOOLS
#include <stdio.h>
#include <unistd.h>
extern void   _EXFUN(__sinit,(struct _reent *));
#define CHECK_INIT(fp) \
  do                                    \
    {                                   \
      if ((fp)->_data == 0)             \
        (fp)->_data = _REENT;           \
      if (!(fp)->_data->__sdidinit)     \
        __sinit ((fp)->_data);          \
    }                                   \
  while (0)
/* need to save cookies, and read/write only */
static void *readFn, *writeFn;
static int _infile, _outfile, _errfile;
#define SAVE_IO_FOR_DIALOG     CHECK_INIT(stdin); CHECK_INIT(stdout); CHECK_INIT(stderr);\
                readFn = stdin->_read; writeFn= stdout->_write;\
        inch = (int)stdin->_cookie; outch=(int)stdout->_cookie;errch=(int)stderr->_cookie;\
		_infile=stdin->_file; _outfile=stdout->_file; _errfile=stderr->_file;

#define RESTORE_IO               stdin->_read = (void*)readFn;stdout->_write= (void*)writeFn;\
        stdin->_cookie=(_PTR)inch; stdout->_cookie=(_PTR)outch;stderr->_cookie=(_PTR)errch;\
		stdin->_file=_infile; stdout->_file=_outfile; stderr->_file=_errfile;
#endif


#define LAST_RESORT_BAUD_RATE   9600


/**
 * Determine if a baud rate is valid.
 *
 * @category Serial_Number  
 * @since 6.0
 *
 * @param baudrate  baudrate to validate
 *
 * @return TRUE     baud rate is valid for dialog
 * @return FALSE    baud rate is not valid for dialog
 */
static BOOLEAN isBaudRateValid(unsigned long baudrate)
{
    return ((baudrate == 1200)||(baudrate == 2400)||(baudrate == 4800) ||(baudrate == 9600)||
           (baudrate == 19200)||(baudrate == 38400)||(baudrate == 57600));
}


/**
 * Get a baudrate that can be used for the dialog.  The selection is as follows.
 *
 * 1.  Use the baudrate passed to us if it is valid.
 * 2.  Next try the value returned by NAGetAppBspBaudRate().
 * 3.  If all else fails, use LAST_RESORT_BAUD_RATE.
 *
 * @category Serial_Number  
 * @since 6.0
 *
 * @param tryThisOneFirst   suggested baud rate
 *
 * @return  baud rate to use for dialog
 */
static unsigned long getUsableBaudrate(unsigned long const tryThisOneFirst)
{
    unsigned long result = LAST_RESORT_BAUD_RATE;
    
    if (isBaudRateValid(tryThisOneFirst))
    {
        result = tryThisOneFirst;
    }
    else if (isBaudRateValid(NAGetAppBspBaudRate()))
    {
        result = NAGetAppBspBaudRate();
    }
    
    return result;
}


#if	BSP_WANT_ETHERNET
/**
 * Determine if the duplex setting is within range.
 *
 * @category Serial_Number  
 * @since 6.0
 *
 * @param   setting     duplex setting to validate
 *
 * @return TRUE         is in range
 * @return FALSE        out of range
 */
static BOOLEAN isDuplexValid(bpDuplexLevelType setting)
{
    return ((setting == bpHalfDuplex) || (setting == bpFullDuplex) || (setting == bpDefaultDuplex));
}

        

/**
 * Return a text description of the duplex setting.
 *
 * @category Serial_Number  
 * @since 6.0
 *
 * @param setting       duplex setting to translate to a text string
 *
 * @return "Half Duplex"    half duplex setting
 * @return "Full Duplex"    full duplex setting
 * @return "Default"        use default duplex setting of hub
 * @return "Invalid Duplex Setting" duplex setting is out of range
 */
static char * const getDuplexString(bpDuplexLevelType setting)
{
    char *result = "Invalid Duplex Setting";
    static char * const duplexString[] = {"Half Duplex", "Full Duplex", "phy Default"};
    
    if (isDuplexValid(setting))
    {
        result = duplexString[setting];
    }
    
    return result;
}
#endif	/* BSP_WANT_ETHERNET */



/*
 *
 *  Function: void customizeDialog (void)
 *
 *  Description:
 *
 *      This routine sets up configuration dialog if APP_DIALOG_PORT is defined.
 *
 *  Notes:
 *
 *      THIS CODE MUST BE CUSTOMIZED FOR YOUR BOARD.  The implementation
 *      below is for NET+OS development boards only.
 *
 *  Parameters:
 *
 *      none
 *
 *  Return Values:
 *
 *      none
 *
 */ 

void customizeDialog (void)
{
	int	updated = 0;
 
    	devBoardParamsType *nvParams;

	if (NAGetAppDialogPort () == 0)
	{
 		/* No DIALOG defined */ 
		return;
	}

	nvParams = (devBoardParamsType *)malloc(sizeof(devBoardParamsType));
	if (nvParams == NULL)
		return;

    	/*  
     	 *  customizeReadDevBoardParams() reads the contents of the section of NVRAM that contains
     	 *  the development board's startup parameters if APP_USE_NVRAM flag is set to a nonzero value. 
   	 *  If APP_USE_NVRAM is 0, customizeReadDevBoardParams() reads the default parameters as defined
     	 *  in appconfig.h. customizeReadDevBoardParams() and default data struct are in 
     	 *  customize\boardParams.c.
     	 *
   	 */
	do
	{
	updated =0;
    	customizeReadDevBoardParams (nvParams);

	/* Open Dialog for Blocking Mode */
	NAOpenDialog (0, nvParams);

	/* Display Configuration */
   	NADisplayDialog (nvParams);

	/* Changed configuration? */
	if (NAConfigureDialog (nvParams) == 1)
	{
		updated |= NANetworkDialog (nvParams);
		updated |= NASecurityDialog (nvParams);
		updated |= NAHardwareDialog (nvParams);
		if (updated)
		{
			/* Update Dialog */
			NAUpdateDialog (nvParams);
		}
	}

	/* Close Dialog */
	NACloseDialog ();  
	} while (updated != 0);

	free(nvParams);
}


#if (BSP_SERIAL_NUMBER_FORMAT == BSP_SERIAL_NUMBER_FORMAT_500)

/*
 * Deprecated version of checkSerialNumber that works on 8
 * digit serial numbers.
 */
static int checkSerialNumber(char *buffer)
{
    int i;
  
    i= strlen(buffer);
    if (i != SERIALNUMBER_LENGTH)
    {
        return 0;
    }
    else
    {
        for (i=0; i<SERIALNUMBER_LENGTH; i++)
        {
            if (!(isdigit(buffer[i])))
            {
                return 0;
            }
        }
    }

    return 1;   
} 

#else


/*
 *
 *  Function: static int checkSerialNumber(char *buffer)
 *
 *  Description:
 *
 *      This routine validates the board's serial number.
 *
 *  Notes:
 *
 *      THIS CODE MUST BE CUSTOMIZED FOR YOUR BOARD.  The implementation
 *      below is for NET+OS development boards only.
 *
 *  Parameters:
 *
 *      buffer    points to the string which contains serial number.
 *
 *  Return Values:
 *
 *      0         invalid
 *      1         valid
 *
 */ 
static int checkSerialNumber(char *buffer)
{
    int i;
    int result = 0;
  
    if (((BP_SERIAL_NUMBER_LENGTH + 1) == strlen(buffer)) && (toupper(buffer[0]) == 'S'))
    {
        /*
         * Digi Manufacturing process prefixes serial numbers with a leading
         * S.  Ingore it.
         */
        memmove(buffer, &buffer[1], BP_SERIAL_NUMBER_LENGTH + 1);
    }

    if (BP_SERIAL_NUMBER_LENGTH == strlen(buffer))
    {
        /*
         * Digi serial number must consist of a letter followed by 8 digits.
         */
        if (!isalpha(buffer[0]))
        {
            goto done;
        }
        for (i = 1; i < BP_SERIAL_NUMBER_LENGTH; i++)
        {
            if (!isdigit(buffer[i]))
            {
                goto done;
            }
        }
        result = 1;
    }
    done:
    
    return result;    
} 
#endif

/*
 *
 *  Function: static int  checkIpAddress(char *buffer)
 *
 *  Description:
 *
 *      This routine validates an IP address.
 *
 *  Parameters:
 *
 *      buffer    points to the string which contains an IP address in "a.b.c.d" format.
 *
 *  Return Values:
 *
 *      0         invalid
 *      1         valid
 *
 */ 
static int  checkIpAddress(char *buffer)
{
   unsigned int length,i;
   unsigned int j =0;
   unsigned int val;
      
   
   length = strlen(buffer);
   
   if ( (length > MAX_IPADDRESS_LENGTH))
      return 0;
   else
   {
     for (i=0; i<length; i++)
     {
       
       if (buffer[i] =='.')
           {
             j++;
             if (j > 3)   /* only three '.' allowed */
                return 0;
           }
       else if (!(isdigit(buffer[i]))) /* all input char must be numeric */
           return 0;
     } 
     
     for (i = 0; i < 4; i++)
      {
           if (*buffer != '\0') 
           {
               val = 0;
               while (*buffer != '\0' && *buffer != '.') 
               {  
                    val *= 10;
                    val += *buffer - '0';
                    buffer++;
               }
               if (val > 255)
                  return 0;       /* any field should be less than 256 */
                  
               if (*buffer != '\0') 
                   buffer++;
           } 
       }   
   }
   return 1; 
}  
/*
 *
 *  Function: static void printIpAddress(char *buffer, unsigned long ip)
 *
 *  Description:
 *
 *      This routine print out the board's IP address with descriptions.
 *
 *  Notes:
 *
 *      THIS CODE MUST BE CUSTOMIZED FOR YOUR BOARD SHOULD YOU USE DIFFERENT 
 *      DISPLAY FORMAT. The implementation below is for NET+OS development 
 *      boards only.
 *
 *  Parameters:
 *
 *      buffer    points to the string which contains some descriptions.
 *      ip        ip address
 *
 *  Return Values:
 *
 *      none
 *
 */ 
static void printIpAddress(char *buffer, unsigned long ip)
{
#ifndef _LITTLE_ENDIAN
    printf(buffer, (ip >> 24) & 0xFF,
                   (ip >> 16) & 0xFF,
                   (ip >> 8)  & 0xFF,
                   (ip) & 0xFF);
#else
    printf(buffer, (ip) & 0xFF,
                   (ip >> 8)  & 0xFF,
                   (ip >> 16) & 0xFF,
                   (ip >> 24) & 0xFF);
#endif
} 
/*
 *
 *  Function: static void printMacAddress(char *buffer, char * mac)
 *
 *  Description:
 *
 *      This routine print out the board's MAC address with descriptions.
 *
 *  Notes:
 *
 *      THIS CODE MUST BE CUSTOMIZED FOR YOUR BOARD SHOULD YOU USE DIFFERENT 
 *      DISPLAY FORMAT. The implementation below is for NET+OS development 
 *      boards only.
 *
 *  Parameters:
 *
 *      buffer    points to the string which contains some descriptions.
 *      mac       points to the array which contains the MAC address
 *
 *  Return Values:
 *
 *      none
 *
 */ 
static void printMacAddress(char *buffer, BYTE * mac)
{
    printf(buffer, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}
/*
 *
 *  Function: static char checkKeyboardInput(unsigned long timeout)
 *
 *  Description:
 *
 *      This routine checks if there is any key being pressed in a certain time period.
 *
 *  Parameters:
 *
 *      timeout   how long before this routine returns if no key is pressed
 *
 *  Return Values:
 *
 *      the value of the pressed key or 0xff if no key is pressed.
 *
 */ 
static char checkKeyboardInput(unsigned long timeout)
{
    int i;
    char rc;
    
      
    for (i=0; i < timeout; i++)
      {
        tx_thread_sleep(BSP_TICKS_PER_SECOND);
        rc=0;
        rc= (char) getchar();
        if ((rc != 0xff) && (rc != '\n'))
           return (rc);
      }
    return (rc);  
}   
/*
 *
 *  Function: static void readLine(char * buf)
 *
 *  Description:
 *
 *      This routine gets one line of the information input from keyboard.
 *      It prints out the information as well.
 *
 *  Parameters:
 *      buf     points to an array to hold the information
 *
 *  Return Values:
 *
 *      none
 *
 */ 
static void readLine(char * buf)
{
  char character;
  int i = 0;
  do
  {
    character = getchar();
    if (character == '\b') 
    {
       if (i > 0)
       {
          putchar(character);
          putchar(0x20);   /*space*/
          putchar(character);
          --i;
       }
    }
    
    else if (character != '\n')
    {
       buf[i] = character;
       putchar(character);
       ++i;
    }
  }
  while (character != '\r');
  putchar('\n');
  
  buf[i-1] = '\0';
}  

/*
 *
 *  Function: static void readPassword(char * buf)
 *
 *  Description:
 *
 *      This routine gets new password input from keyboard.
 *      It prints out "***" while getting informations
 *
 *  Parameters:
 *      buf     points to an array to hold the new password
 *
 *  Return Values:
 *
 *      none
 *
 */ 
static void readPassword(char * buf)
{
    char character;
    int i = 0;
    do
    {
        character = getchar();
        if (character == '\b') 
        {
            if (i > 0)
            {
                putchar(character);
                putchar(0x20);   /*space*/
                putchar(character);
                --i;
            }
        }
        else if ((character != '\r') && (character != '\n'))
        {
            buf[i] = character;
            putchar('*');
            ++i;
        }
    }
    while ((character != '\r') && (character != '\n'));
    putchar('\r');
    putchar('\n');
  
    buf[i] = '\0';
}  
/*
 *
 *  Function: static int kbGetIpAddress (char *ipAddrDesc, unsigned long *ipAddress)
 *
 *  Description:
 *
 *      This routine print out what kind of IP address it needs and gets it from keyboard.
 *
 *  Notes:
 *
 *      THIS CODE MUST BE CUSTOMIZED FOR YOUR BOARD SHOULD YOU USE DIFFERENT 
 *      DISPLAY FORMAT. The implementation below is for NET+OS development 
 *      boards only.
 *
 *  Parameters:
 *
 *      ipAddrDesc    points to the string which contains some descriptions.
 *      ipAddres      points to an unsigned long which holds the old IP address.
 *                    upon return, will hold the new IP address if any.
 *
 *  Return Values:
 *
 *      0             no update, keep the old IP address
 *      1             got a new IP address     
 *
 */ 
static int kbGetIpAddress (char *ipAddrDesc, unsigned long *ipAddress)
{
	int	rc;

    char buffer[128];

	while (1)
    {
		printf ("%s ", ipAddrDesc);
        printIpAddress("IP address [%d.%d.%d.%d]? ", *ipAddress);
        readLine (buffer);
        if (buffer[0] == '\0')
        {
			rc = 0;
			break;
		}

        if(checkIpAddress(buffer))
        {
          	*ipAddress = NAInet_addr(buffer);
			printf ("  %s ", ipAddrDesc);
           	printIpAddress("IP address is %d.%d.%d.%d\r\n", *ipAddress);
			rc = 1;
			break;
        }

        printf("Invalid IP address\r\n");
    }

	return (rc);
}
/*
 *
 *  Function: static int kbGetReply (char *itemDesc, int flag)
 *
 *  Description:
 *
 *      This routine displays those items asking if you would like to update,
 *      and get the answer from keyboard for yes or no
 *
 *  Notes:
 *
 *      THIS CODE MUST BE CUSTOMIZED FOR YOUR BOARD SHOULD YOU USE DIFFERENT 
 *      DISPLAY FORMAT. The implementation below is for NET+OS development 
 *      boards only.
 *
 *  Parameters:
 *
 *      itemDesc    points to the string which contains descriptions of the item.
 *      flag        to indicate how the item description is going to be displayed.
 *
 *  Return Values:
 *
 *      0             no update, keep the old setting
 *      1             yes, need to change the setting    
 *
 */ 
static int kbGetReply (char *itemDesc, int flag)
{
	int	reply;
    char buffer[128];

    //printf("\r\n");

    while (1)
    {
		if (flag & NADIALOG_CUSTOM_REPLY)
		{
	        printf ("%s ", itemDesc);
		}
		else
		{
	        printf ("Would you like to update the %s ", itemDesc);
		}
		if (flag & NADIALOG_CUSTOM_DEF_YES)
		{
	        printf ("[Y]? ");
		}
		else
		{
	        printf ("[N]? ");
		}

        readLine (buffer);
        if (buffer[0] == 'y' || buffer[0] =='Y')
        {
            reply = 1;
            break;
        }
        if (buffer[0] == 'n' || buffer[0] =='N')
        {
            reply = 0;
            break;
        }
		if (buffer[0] == '\0')
		{
			reply = ((flag & NADIALOG_CUSTOM_DEF_YES) != 0);
			break;
		}
    }

	return (reply);
}


#if	BSP_WANT_ETHERNET
/*
 *
 *
 *  Description:
 *
 *      This routine prompts for a duplex level.
 *
 *  Notes:
 *
 *      THIS CODE MUST BE CUSTOMIZED FOR YOUR BOARD SHOULD YOU USE DIFFERENT 
 *      DISPLAY FORMAT. The implementation below is for NET+OS development 
 *      boards only.
 *
 *  Parameters:
 *
 *      desc        points to the string which contains descriptions of the item.
 *      setting     indicates current duplex setting
 *
 *  Return Values:
 *
 *      bpHalfDuplex      half duplex
 *      bpFullDuplex      full duplex  
 *      bpDefaultDuplex   automatically negotiated duplex level
 *
 */ 
static bpDuplexLevelType kbGetDuplex (char *desc, bpDuplexLevelType setting)
{
	bpDuplexLevelType	reply;
    char buffer[128];

    //printf("\r\n");

    while (1)
    {
	    printf ("%s[%s] ", desc, getDuplexString(setting));

        readLine (buffer);
        if (buffer[0] == 'f' || buffer[0] =='F')
        {
            reply = bpFullDuplex;
            break;
        }

        if (buffer[0] == 'h' || buffer[0] =='H') 
        {
            reply = bpHalfDuplex;
            break;
        }
        
        if (buffer[0] == 'd' || buffer[0] =='D') 
        {
            reply = bpDefaultDuplex;
            break;
        }
        
       if (buffer[0] == 0)
        {
            reply = setting;
            break;
        }
    }

	return (reply);
}
#endif /* BSP_WANT_ETHERNET */


/*
 *
 *  Function: static int kbGetData (char *itemDesc, char *destBuffer, int length, int flag)
 *
 *  Description:
 *
 *      This routine displays those items you would like to update,
 *      and get the update information from keyboard.
 *
 *  Notes:
 *
 *      THIS CODE MUST BE CUSTOMIZED FOR YOUR BOARD SHOULD YOU USE DIFFERENT 
 *      DISPLAY FORMAT. The implementation below is for NET+OS development 
 *      boards only.
 *
 *  Parameters:
 *
 *      itemDesc    points to the string which contains descriptions of the item.
 *      destBuffer  points to an array to hold the new information.
 *      length      length boundary of new information
 *      flag        to indicate if we need the new information to be entered again.
 *
 *  Return Values:
 *
 *      0             no update, keep the old setting
 *      1             updated     
 *
 */ 
static int kbGetData (char *itemDesc, char *destBuffer, int length, int flag)
{
	int	rc;

    char srcBuffer_1[128];
    char srcBuffer_2[128];

    while (1)
    {
		printf("Enter the new %s:    ", itemDesc);
        readPassword(srcBuffer_1);
        if (srcBuffer_1[0] == '\0')
        {
			rc = 0;
			break;
		}

        if (strlen(srcBuffer_1) < length)
        {
			if (flag & NADIALOG_VERIFY)
			{
				/* verify input */
		        printf("Re-enter the new %s: ", itemDesc);
   			    readPassword(srcBuffer_2);
			}

       	    if (!(flag & NADIALOG_VERIFY)  || strcmp (srcBuffer_1, srcBuffer_2) == 0)
            {
   	            /*  update destination buffer  */
            	memset (destBuffer, 0, length);
           		strcpy (destBuffer, srcBuffer_1);
				rc = 1;
           		break;
   			}
			
            printf("ERROR: %s entries mismatched.\r\n", itemDesc);
        }
        else
        {
            printf("ERROR: Invalid %s.  Length must be less than %d characters.\r\n", itemDesc, length);
        }
    }

	return (rc);
}

/*
 *
 *  Function: static int kbGetString (char *itemDesc, char *destBuffer, int length, int flag)
 *
 *  Description:
 *
 *      This routine displays those items you would like to update,
 *      and get the update information from keyboard.
 *
 *  Notes:
 *
 *      THIS CODE MUST BE CUSTOMIZED FOR YOUR BOARD SHOULD YOU USE DIFFERENT 
 *      DISPLAY FORMAT. The implementation below is for NET+OS development 
 *      boards only.
 *
 *  Parameters:
 *
 *      itemDesc    points to the string which contains descriptions of the item.
 *      destBuffer  points to an array to hold the new information.
 *      length      length boundary of new information
 *      flag        to indicate if we need the answer to be yes or no,
 *                  or indicate if we need the new information to be entered again.
 *
 *  Return Values:
 *
 *      0             no update, keep the old setting
 *      1             updated     
 *
 */ 
static int kbGetString (char *itemDesc, char *destBuffer, int length, int flag)
{
	int	rc;

	while (1)
	{
		if (kbGetReply (itemDesc, flag))
		{
			if (kbGetData (itemDesc, destBuffer, length, flag))
			{
				rc = 1;
				break;
			}
		}
		else
		{
			/* No update */
			rc = 0;
			break;
		}
	}
	
	return (rc);
}

#if BSP_WANT_WIRELESS

/* Description of each wireless protocol mode */
static const char *wln_modes[] = {
	"Infrastructure", 
	"Ad hoc (join or create)", 
	"Ad hoc (join only)",
	"Any type",
};

/*
 *
 *  Function: static void printWirelessParams (devBoardParamsType *nvParamsPtr)
 *
 *  Description:
 *
 *      This routine prints all wireless parameters.
 *
 *  Parameters:
 *
 *      nvParamsPtr     pointer to structure with development board parameters
 *
 */ 
static void printWirelessParams (devBoardParamsType *nvParamsPtr)
{
	aceConfigInterfaceInfo *interface = customizeAceFindInterfaceConfig(BP_WLN_INTERFACE, &nvParamsPtr->aceConfig);
	if (interface == NULL)
	{
		/* Find an unused config record, but don't overwrite ethernet */
		interface = customizeAceFindUnusedInterfaceConfig(&nvParamsPtr->aceConfig, FALSE);
		if (interface)
			customizeAceGetDefaultInterfaceConfig(BP_WLN_INTERFACE, interface);
	}

	if (interface)
	{
		if ((interface->static_config.isConfigValid) && (interface->static_config.isEnabled))
		{
			printIpAddress("  Wireless IP address is %d.%d.%d.%d\r\n", interface->static_config.ip_address);
			printIpAddress("  Wireless subnet mask is %d.%d.%d.%d\r\n", interface->static_config.subnet_mask);
			printIpAddress("  Wireless IP address of default gateway to other networks is %d.%d.%d.%d\r\n", interface->static_config.gateway);
		}
		else
		{
			printf("  The board will obtain wireless IP configuration parameters from the network.\r\n");
		}
	}

	if (nvParamsPtr->wlnParams.bss_type <= WLN_BSS_ANY) 
		printf("  Wireless protocol mode is %s\r\n", wln_modes[nvParamsPtr->wlnParams.bss_type]);
		
	if (nvParamsPtr->wlnParams.ssid_len == 0)
		printf("  Wireless SSID is (search)\r\n");
	else
		printf("  Wireless SSID is %.*s\r\n", nvParamsPtr->wlnParams.ssid_len, nvParamsPtr->wlnParams.ssid);
	
	if(nvParamsPtr->wlnParams.channel == WLN_CHAN_SCAN)
		printf("  Wireless channel is (search)\r\n");
	else
		printf("  Wireless channel is %d\r\n", nvParamsPtr->wlnParams.channel);
	
	if (nvParamsPtr->wlnParams.security & WLN_SEC_WEP)
		printf("  WEP is enabled\r\n");
	else
		printf("  WEP is disbled\r\n");
#if BSP_WANT_WPA
	if (nvParamsPtr->wlnParams.security & (WLN_SEC_WPA_PSK|WLN_SEC_WPA_AUTH))
		printf("  WPA is enabled\r\n");
	else
		printf("  WPA is disbled\r\n");
#endif
}

/*
 *
 *  Function: static int kbGetNumber (char *descr, int *value, int min, int max)
 *
 *  Description:
 *
 *      This routine gets a number from the keyboard.
 *
 *  Parameters:
 *
 *      descr       description string displayed to user
 *      value       default value and returned result
 *      min         minimum allowed value
 *      max         maximum allowed value
 *
 *  Return Values:
 *
 *      0             no update, value unchanged
 *      1             updated     
 *
 */ 
static int kbGetNumber (char *descr, int *value, int min, int max)
{
    char buffer[128];
	int n, result;

    while (1)
    {
      	printf(descr, *value);
      	readLine(buffer);  
      	if (buffer[0] == '\0')
      		return 0;
      		
	    n = sscanf(buffer, "%d", &result);
      	if (n == 1 && result >= min && result <= max)
      	{
      		*value = result;
			return 1;
		}
		
		printf("Plese enter a number between %d and %d\r\n", min, max);
    }  
}

/*
 *
 *  Function: static int kbGetStringLimit (char *descr, char *value, int min, int max)
 *
 *  Description:
 *
 *      This routine gets a number from the keyboard.
 *
 *  Parameters:
 *
 *      descr       description string displayed to user
 *      value       default value and returned result
 *      min         minimum allowed characters
 *      max         maximum allowed characters
 *
 *  Return Values:
 *
 *      0             no update, value unchanged
 *      1             updated     
 *
 */ 
static int kbGetStringLimit (char *descr, char *value, int min, int max)
{
    char buffer[128];
	int n;

    while (1)
    {
      	printf(descr, value);
      	readLine(buffer);  
	    n = strlen(buffer);
      	if (n == 0)
      		return 0;
      	if (n >= min && n <= max)
      	{
      		strcpy(value, buffer);
			return 1;
		}
		
		printf("Plese enter a string of %d to %d characters\r\n", min, max);
    }  
}

/*
 *
 *  Function: static int kbGetWEPKey (int index, wln_params *params)
 *
 *  Description:
 *
 *      This routine gets a new WEP key from the keyboard.
 *
 *  Parameters:
 *
 *      index       index of key (0-3)
 *      params      points to wireless parameters
 *
 *  Return Values:
 *
 *      0             no update, keep the old setting
 *      1             updated     
 *
 */ 
static int kbGetWEPKey (int index, wln_params *params)
{
    char buffer[128];
	unsigned char key[WLN_WEP104_SIZE];
	int i, n;
	
    while (1)
    {
      	printf("WEP key %d [no change]? ", index);
      	readLine(buffer);  
      	if (buffer[0] == '\0')
      		return 0;
      		
      	for (i = 0; i < WLN_WEP104_SIZE; i++)
      	{
      		if (isxdigit(buffer[2*i]) && isxdigit(buffer[2*i+1]) &&
				sscanf(&buffer[2*i], "%2x", &n) == 1)
					key[i] = n;
			else
      			break;
      	}
      	
      	if (i == WLN_WEP40_SIZE || i == WLN_WEP104_SIZE)
      	{
			params->wep_key_len = i;
      		memcpy(params->wep_key[index], key, i);
      		return 1;
      	}

   		printf("Please enter a 10 or 26 digit hex number\r\n");
    }
}

/*
 *
 *  Function: static int NAWirelessDialog (wln_params *wp)
 *
 *  Description:
 *
 *      This routine gets the new wireless parameters.
 *
 *  Parameters:
 *
 *      wp     pointer to structure with wireless parameters
 *
 *  Return Values:
 *
 *      0:     no updates
 *      1:     some or all network information are updated
 *
 */ 
static int NAWirelessDialog (wln_params *wp)
{
	char buffer[256], buffer2[128];
	int update = 0;
	int i, flag;
	
	uint32 old_sec = wp->security;
	wp->security = 0;
	
    /* BSS type */
    sprintf(buffer, "\r\nWireless network type [%d]?\r\n"
    	"Enter 0 for %s\r\n      1 for %s\r\n      2 for %s\r\n      3 for %s\r\n",
    	wp->bss_type, wln_modes[0], wln_modes[1], wln_modes[2], wln_modes[3]);
    update |= kbGetNumber(buffer, (int *) &wp->bss_type, WLN_BSS_ESS, WLN_BSS_ANY);
	
    /* SSID */
    memcpy(buffer, wp->ssid, wp->ssid_len);
    buffer[wp->ssid_len] = '\0';
	if (kbGetStringLimit("\r\nWireless SSID (enter ANY to search) [%s]? ",
		buffer, 0, WLN_SSID_SIZE))
	{
		int n = strlen(buffer);
		if (strcmp(buffer, "ANY") == 0)
			n = 0;
		
		memcpy (wp->ssid, buffer, n);
		wp->ssid_len = n;
		update = 1;
	}
	
    /* Channel */
    update |= kbGetNumber("Wireless channel (enter 1-14 or 0 to search) [%d]? ", 
    	&wp->channel, WLN_CHAN_SCAN, WLN_CHAN_NUM);
    
    /* Enable WEP */
	flag = NADIALOG_CUSTOM_REPLY;
	if (old_sec & WLN_SEC_WEP)
		flag |= NADIALOG_CUSTOM_DEF_YES;
	if (kbGetReply ("Enable WEP", flag))
	{
		/* Default key */
		update |= kbGetNumber("WEP default key number (0-3) [%d]? ", 
			&wp->wep_key_id, 0, 3);

		/* WEP keys */
		for (i = 0; i < 4; i++)
			update |= kbGetWEPKey(i, wp);
			
		wp->security |= WLN_SEC_WEP;
	}
    	
#if BSP_WANT_WPA
	if (wp->bss_type == WLN_BSS_IBSS || wp->bss_type == WLN_BSS_IBSS_JOIN)
		printf("WPA not supported in ad hoc mode\r\n");
	else
	{
		/* Enable WPA */
		flag = NADIALOG_CUSTOM_REPLY;
		if (old_sec & (WLN_SEC_WPA_PSK|WLN_SEC_WPA_AUTH))
			flag |= NADIALOG_CUSTOM_DEF_YES;
		if (kbGetReply ("Enable WPA", flag))
		{
			/* PSK */
			if (wp->ssid_len == 0)
				printf("Must specify an SSID to use WPA-PSK\r\n");
			else if (kbGetStringLimit("WPA-PSK passphrase [no change]? ", buffer, 8, 63))
			{
				printf("Calculating key (about 30 seconds)...\r\n");
				wpa_passphrase_to_psk (buffer, wp->ssid, wp->ssid_len, wp->wpa_psk);
				update = 1;
			}

			/* Identity */
			update |= kbGetStringLimit("WPA login [%s]? ", 
				wp->identity, 0, WLN_IDENT_SIZE);

			/* Password */
			while (1)
			{
			printf("WPA password [no change]? ");
			readPassword (buffer);
				if (buffer[0] == '\0')
					break;

				printf("Re-enter WPA password: ");
				readPassword (buffer2);
				if (strcmp(buffer, buffer2) == 0)
			{
				strncpy(wp->password, buffer, WLN_PWD_SIZE);
				update = 1;
					break;
				}
				else
					printf("Passwords do not match\r\n");
			}

			wp->security |= WLN_SEC_WPA_PSK|WLN_SEC_WPA_AUTH;
			wp->wpa_encrypt = WLN_ENCR_ANY;
			wp->auth_methods = WLN_AUTH_ANY;
		}
	}
#endif // BSP_WANT_WPA

	if (wp->security == 0)
		wp->security = WLN_SEC_OPEN;
		
   	return update || (wp->security != old_sec);
}
#endif // BSP_WANT_WIRELESS

/*
 *
 *  Function: static int NAOpenDialog (int flag, devBoardParamsType *nvParamsPtr)
 *
 *  Description:
 *
 *      This routine sets up stdin, stdout, and stderr to be redirected
 *      out the APP_DIALOG_PORT if APP_DIALOG_PORT is defined.
 *
 *  Parameters:
 *
 *      flag    	0: NONBLOCK I/O
 *              	1: BLOCK I/O
 *      nvParamsPtr     pointer to structure with development board parameters
 *
 *  Return Values:
 *
 *      channel ID
 *
 */

static int NAOpenDialog (int flag, devBoardParamsType *nvParamsPtr)
{
	int	rc;
	unsigned long baudrate;
	struct termios tios;


#ifndef NETOS_GNU_TOOLS
	/* Save IO */
    inch = stdin->io_channel;
    outch = stdout->io_channel;
    errch = stderr->io_channel;
#else
	SAVE_IO_FOR_DIALOG
#endif

    /* open device */
	if (flag == 0)
	{
    	    fd = open (NAGetAppDialogPort (), (O_RDWR | O_NONBLOCK) );
	}
        else
	{
    	   fd = open (NAGetAppDialogPort (), O_RDWR );
	}
        
    if (fd <0)
    {
        netosFatalError("APP_DIALOG_PORT improperly defined", ERROR_CLASS_BSP, ERROR_BAD_DIALOG_PORT);
        return -1;
    }

#ifndef NETOS_GNU_TOOLS
    stdin->io_channel = fd;
    stdout->io_channel = fd;
    stderr->io_channel = fd;
#else
	CHECK_INIT(stdin);
	CHECK_INIT(stdout);
	CHECK_INIT(stderr);
    
	/* need to override the following so that
	   std I/O will call into DDI */
    stdout->_cookie = (_PTR)fd;
	stdout->_file =fd;
    stdin->_cookie = (_PTR)fd;
	stdin->_file = fd;
    stderr->_cookie = (_PTR)fd;
	stderr->_file = fd;
    stdin->_read = (void*)read;
    stdout->_write = (void*)write;
    stderr->_write = (void*)write;
#endif
	
	baudrate = getUsableBaudrate(nvParamsPtr->baudrate);
	
        tcgetattr(fd, &tios);
        cfsetospeed(&tios, baudrate);
        rc = tcsetattr(fd, TCSANOW, &tios);
     
	if (rc < 0)	
	{
		netosFatalError("error when change baud rate in Dialog.c", ERROR_CLASS_BSP, ERROR_INVALID_DIALOG_BAUDRATE);
	}

    return fd;
}
/*
 *
 *  Function: static int NACloseDialog (void)
 *
 *  Description:
 *
 *      This routine closes APP_DIALOG_PORT if APP_DIALOG_PORT is defined, and
 *      restore stdin, stdout, and stderr.
 *
 *  Parameters:
 *
 *      none
 *
 *  Return Values:
 *
 *      0       success
 *
 */
static int NACloseDialog (void)
{
	#ifndef NETOS_GNU_TOOLS
    	close(stdin->io_channel);

		/* Restore IO */
        stdin->io_channel = inch;
        stdout->io_channel = outch;
        stderr->io_channel = errch;
	#else
       // void *readFn, *writeFn; 

		close (fd);

		RESTORE_IO
	#endif

	return (0);
}

/*
 *
 *  Function: static int NADisplayDialog (devBoardParamsType *nvParamsPtr)
 *
 *  Description:
 *
 *      This routine displays the target configuration and prompts the user
 *      for modifications.
 *
 *  Notes:
 *
 *      THIS CODE MUST BE CUSTOMIZED FOR YOUR BOARD.  The implementation
 *      below is for NET+OS development boards only.
 *
 *  Parameters:
 *
 *      nvParamsPtr     pointer to structure with development board parameters
 *
 *  Return Values:
 *
 *      0:              success
 *
 */ 
static int NADisplayDialog (devBoardParamsType *nvParamsPtr)
{   
    char s[20];  
    BYTE mac_addrp[6];
#if	BSP_WANT_ETHERNET
	aceConfigInterfaceInfo *interface;
#endif

    /*
     * We use to have code here that corrected invalid baudrates and waittimes before 
     * they were displayed.  I removed it since we should display invalid settings 
     * so that users will correct them.
     */
         
    printf("\r\n");
    printf("\r\n");
    printf("\r\n");
    printf("NET+WORKS Version %s\r\n", NETOS_VERSION_NUMBER);
    printf("Copyright (c) 2003, NETsilicon, Inc.\r\n");
    printf("\r\n");
    printf("PLATFORM: %s\r\n", NABspPlatform);
    printf("APPLICATION: %s\r\n", NAGetAppDialogAppName ());
    printf("-----------------------------------------------------------------------------\r\n");
    printf("NETWORK INTERFACE PARAMETERS:\r\n");
    
#if	BSP_WANT_ETHERNET
    interface = customizeAceFindInterfaceConfig(BP_ETH_INTERFACE, &nvParamsPtr->aceConfig);

    if (interface == NULL)
    {
        interface = customizeAceFindUnusedInterfaceConfig(&nvParamsPtr->aceConfig, TRUE);
        customizeAceGetDefaultEthernetConfig(interface, 0);
    }
    if ((interface->static_config.isConfigValid) && (interface->static_config.isEnabled))
    {
        printIpAddress("  Ethernet IP address is %d.%d.%d.%d\r\n", interface->static_config.ip_address);
        printIpAddress("  Ethernet subnet mask is %d.%d.%d.%d\r\n", interface->static_config.subnet_mask);
        printIpAddress("  Ethernet IP address of default gateway to other networks is %d.%d.%d.%d\r\n", interface->static_config.gateway);
    }
    else
    {
	    printf("  The board will obtain ethernet IP configuration parameters from the network.\r\n");
    }
#endif

#if BSP_WANT_WIRELESS
	printWirelessParams(nvParamsPtr);
#endif

/*  New PPP parameters allows backward compatibility with older applications    */

    if (NAGetAppEnablePPP1 ())
    {
        printIpAddress("  IP address on COM1 is %d.%d.%d.%d\r\n", nvParamsPtr->ipAddrPpp1);

        if (nvParamsPtr->ipAddrPpp1peer)
        {
            printIpAddress("  Peer IP address connected to COM1 is %d.%d.%d.%d\r\n", nvParamsPtr->ipAddrPpp1peer);
        }
    }

    if (NAGetAppEnablePPP2 ())
    {
        printIpAddress("  IP address on COM2 is %d.%d.%d.%d\r\n", nvParamsPtr->ipAddrPpp2);

        if (nvParamsPtr->ipAddrPpp2peer)
        {
            printIpAddress("  Peer IP address connected to COM2 is %d.%d.%d.%d\r\n", nvParamsPtr->ipAddrPpp2peer);
        }
    }

    if (NAGetAppUseNetworkTimeProtocol ())
    {
        if (nvParamsPtr->ipAddrSntp1 != 0)
        {
            printIpAddress("  Primary SNTP Server IP address is %d.%d.%d.%d\r\n", nvParamsPtr->ipAddrSntp1);
            if (nvParamsPtr->ipAddrSntp2 != 0)
            {
                printIpAddress("  Secondary SNTP Server IP address is %d.%d.%d.%d\r\n", nvParamsPtr->ipAddrSntp2);
            }
        }
    }

	if (NAGetAppUseKerberos ())
	{
	    printf          ("SECURITY PARAMETERS:\r\n");
    	printIpAddress  ("  Kerberos KDC IP Address is %d.%d.%d.%d\r\n", nvParamsPtr->krbIpAddr);
	    printf          ("  Kerberos realm name is %s\r\n", nvParamsPtr->krbRealmname );
    	printf          ("  Kerberos User name is %s\r\n", nvParamsPtr->krbUsername );
	}


    printf("HARDWARE PARAMETERS:\r\n");   
    printf("  Serial channels will use a baud rate of %lu\r\n",nvParamsPtr->baudrate);

    #if (BSP_SERIAL_NUMBER_FORMAT == BSP_SERIAL_NUMBER_FORMAT_500)
        memcpy(s,  &nvParamsPtr->serialNumber[1],SERIALNUMBER_LENGTH);
        s[SERIALNUMBER_LENGTH]=0;  /*for correct printf %s format*/
    #else
        memcpy(s,  nvParamsPtr->serialNumber,sizeof(nvParamsPtr->serialNumber));
        s[BP_SERIAL_NUMBER_LENGTH]=0;  /*for correct printf %s format*/
    #endif
    printf("  This board's serial number is %s\r\n", s);
    customizeGetMACAddress (mac_addrp);
    printMacAddress("  This board's MAC Address is %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\r\n",mac_addrp);                  
    printf("  After board is reset, start-up code will wait %lu seconds\r\n", nvParamsPtr->waitTime);

#if	BSP_WANT_ETHERNET
    printf("  Default duplex setting for Ethernet connection: %s\r\n", getDuplexString(nvParamsPtr->defaultDuplexLevel));
#endif

    printf("-----------------------------------------------------------------------------\r\n");
	return (0);
}
/*
 *
 *  Function: static int NAConfigureDialog (devBoardParamsType *nvParamsPtr)
 *
 *  Description:
 *
 *      This routine checks if the user intends to make changes, if yes, it will close
 *      the dialog port and reopen it with block mode to wait for the input. It also
 *      authenticates user for the right to change. If the password is incorrect, it allows
 *      user to reenter 3 times before giving up.
 *
 *  Notes:
 *
 *      THIS CODE MUST BE CUSTOMIZED FOR YOUR BOARD.  The implementation
 *      below is for NET+OS development boards only.
 *
 *  Parameters:
 *
 *      nvParamsPtr     pointer to structure with development board parameters
 *
 *  Return Values:
 *
 *      0:              continue without any updates
 *      1:              need to update
 *
 */ 
static int NAConfigureDialog (devBoardParamsType *nvParamsPtr)
{
	int	rc;
	char temp;
    char buffer[128];
    int	notAuthenticated = 1;
    char password[NASYSACC_STRLEN_PASSWORD];

    if (NAGetAppUseNvram ())
    {
        printf("Press any key in %lu seconds to change these settings.\r\n", nvParamsPtr->waitTime);
    }
    printf("\r\n");
    printf("\r\n");
   
   
    /*any key is pressed?*/
    temp = checkKeyboardInput(nvParamsPtr->waitTime);
    if ((temp != 0xff) && (NAGetAppUseNvram ()))
    {
        printf("Press A to Accept the settings, or M to Modify?");
    }
    else
    {
        return 0;          /*time out spared, no modification needed, continue...*/
    }
    
    /*let's close nonblock i/o, use block i/o*/
	NACloseDialog ();
        
	/* Open for Blocking Mode */
    NAOpenDialog (1, nvParamsPtr); 

     
    /*"A" or "a", "M" or "m"* is pressed?*/
    while (1)
    {
        readLine(buffer);
        if (buffer[0] == 'a' || buffer[0] =='A')
        {
            printf("continue...\r\n");
            return 0;         /*no modification needed, user needs to continue...*/
        }

        if (buffer[0] == 'm' || buffer[0] =='M')
        {
            break;
        }

        printf("Press A to Accept the settings, or M to Modify?"); 
    }  

    /*  "M" or "m" is pressed   */
    printf("\r\n");
    rc = NAgetSysAccess ("root", &password[0], NULL);
    if ((rc == NASYSACC_LEVEL_ROOT) && (notAuthenticated))
    {
        for (rc = 0; ; rc ++)
        {
            printf("Enter the root password: ");
            readPassword(buffer);
            if (strcmp(buffer, password) == 0)
            {
                /*  OK - this is an authentic administrator */
                notAuthenticated = 0;
                break;
            }

            if (rc < 3)
            {
                printf("FAILURE: root password incorrect\r\n");
            }
            else
            {
                /*  no modification allowed, continue...*/
                printf("FAILURE: root password incorrect\r\ncontinue...\r\n");
                return 0;
            }
        }
    } 
    
    if (kbGetReply ("Reset configuration to default values", NADIALOG_CUSTOM_REPLY))
    {
        customizeUseDefaultParams(nvParamsPtr);
    }

	return (1);
}

/*
 *
 *  Function: static int NAIPParamDialog (devBoardParamsType *nvParamsPtr, char *ifname, char *prompt)
 *
 *  Description:
 *
 *      This routine gets a new IP parameters.
 *
 *  Parameters:
 *
 *      nvParamsPtr     pointer to structure with development board parameters
 *      ifname        name of interface (BP_ETH_INTERFACE of BP_WLN_INTERFACE)
 *      prompt        string displayed to user
 *
 *  Return Values:
 *
 *      0             no update, keep the old setting
 *      1             updated     
 *
 */ 
static int NAIPParamDialog (devBoardParamsType *nvParamsPtr, char *ifname, char *prompt)
{
	int	updated = 0;
    unsigned long temp;
    static configAceStaticInfo const staticZero = {0};
    static aceProtoStartInfo staticStartInfo = {ACE_PROT_STATIC, 0, 0, ACE_ALWAYS_SHUTDOWN};

    /*
     * Extract the configuration structure from the NVRAM structure.  There should be a configuration
     * settings for the interface.  If not, then reinitialize the structure.
     */
    aceConfigInterfaceInfo *config = customizeAceFindInterfaceConfig(ifname, &nvParamsPtr->aceConfig);
    
    if (config == NULL)
    {
        customizeAceGetDefaultConfig(&nvParamsPtr->aceConfig);
        config = customizeAceFindInterfaceConfig(ifname, &nvParamsPtr->aceConfig);
        updated = TRUE;
    }
    if ((!config->isConfigValid) || (!config->isEnabled))
    {
		customizeAceGetDefaultInterfaceConfig(ifname, config);
        updated = TRUE;
    }
    
	temp = kbGetReply (prompt, NADIALOG_CUSTOM_REPLY |
			(config->static_config.isEnabled ? 0 : NADIALOG_CUSTOM_DEF_YES));
 	if (temp)
 	{
 	    /*
 	     * Disable the static configuration to make ACE get an address from the network.
 	     * The protocols actually used by ACE are determined by the settings stored
 	     * in NVRAM.
 	     */
        config->static_config.isEnabled = FALSE;
        config->static_config.auto_assign = FALSE;
        updated = TRUE;
    }
    else
    {
        if (!config->static_config.isConfigValid)
        {
            config->static_config = staticZero;
        }
        
        /* ip address */
        kbGetIpAddress ("Static", &config->static_config.ip_address);
        
        /* subnet mask */
        kbGetIpAddress ("Subnet Mask", &config->static_config.subnet_mask);
        
        /* gateway mask */
        kbGetIpAddress ("Gateway address", &config->static_config.gateway);
        
        /*
         * Enabling the static configuration will cause ACE to ignore the settings used
         * for DHCP, BOOTP, et al on the same interface.
         */
        config->static_config.isEnabled = TRUE;
        config->static_config.auto_assign = TRUE;
        config->static_config.startInfo = staticStartInfo;
        config->static_config.isConfigValid = TRUE;
        updated = TRUE;
    }

	return (updated);
}

/*
 *
 *  Function: static int NANetworkDialog (devBoardParamsType *nvParamsPtr)
 *
 *  Description:
 *
 *      This routine gets the new network information.
 *
 *  Notes:
 *
 *      THIS CODE MUST BE CUSTOMIZED FOR YOUR BOARD.  The implementation
 *      below is for NET+OS development boards only.
 *
 *  Parameters:
 *
 *      nvParamsPtr     pointer to structure with development board parameters
 *
 *  Return Values:
 *
 *      0:              no updates
 *      1:              some or all network information are updated
 *
 */ 
static int NANetworkDialog (devBoardParamsType *nvParamsPtr)
{
	int	updated = 0;

    /*  Operator has been authenticated */
    printf("\r\n");
    printf("For each of the following questions, you can press <Return> to ");
    printf("select the value shown in braces, or you can enter a new value.\r\n"); 
    printf("\r\n");
    printf("NETWORK INTERFACE PARAMETERS:\r\n\r\n");
    
#if	BSP_WANT_ETHERNET
	updated = NAIPParamDialog(nvParamsPtr, BP_ETH_INTERFACE, 
					"Should ethernet obtain IP settings from the network");
#endif

#if BSP_WANT_WIRELESS
	updated |= NAIPParamDialog(nvParamsPtr, BP_WLN_INTERFACE, 
					"Should wireless obtain IP settings from the network");

	updated |= NAWirelessDialog(&nvParamsPtr->wlnParams);
#endif

    if (NAGetAppEnablePPP1 ())
    {
        /* ppp com1 address */
		updated |= kbGetIpAddress ("COM1 PPP", &nvParamsPtr->ipAddrPpp1);

        /* ppp com1 peer address */
		updated |= kbGetIpAddress ("COM1 PPP Peer", &nvParamsPtr->ipAddrPpp1peer);
    }

    if (NAGetAppEnablePPP2 ())
    {
        /* ppp com2 address */
        updated |= kbGetIpAddress ("COM2 PPP", &nvParamsPtr->ipAddrPpp2);

        /* ppp com2 peer address */
        updated |= kbGetIpAddress ("COM2 PPP Peer", &nvParamsPtr->ipAddrPpp2peer);
    }

	if (NAGetAppUseNetworkTimeProtocol ())
	{
	   	/*  Primary SNTP Server */
		updated |= kbGetIpAddress ("Primary SNTP Server", &nvParamsPtr->ipAddrSntp1);

	    /*  Secondary SNTP Server */
      	if (nvParamsPtr->ipAddrSntp1 != 0)
   	   	{
       		updated |= kbGetIpAddress ("Secondary SNTP Server", &nvParamsPtr->ipAddrSntp2);
   	    }
	}


	return (updated);
}


/*
 *
 *  Function: static int NASecurityDialog (devBoardParamsType *nvParamsPtr)
 *
 *  Description:
 *
 *      This routine gets the new security information.
 *
 *  Notes:
 *
 *      THIS CODE MUST BE CUSTOMIZED FOR YOUR BOARD.  The implementation
 *      below is for NET+OS development boards only.
 *
 *  Parameters:
 *
 *      nvParamsPtr     pointer to structure with development board parameters
 *
 *  Return Values:
 *
 *      0:              no updates
 *      1:              some or all security information are updated
 *
 */ 
static int NASecurityDialog (devBoardParamsType *nvParamsPtr)
{
	int	updated = 0;
	char *valueStr;
	char bufDesc[32];
    char password[NASYSACC_STRLEN_PASSWORD];

	if (NAGetAppRootPassword () || NAGetAppAdministratorsAccount () 
		|| NAGetAppFixedGatewayKey () || NAGetAppUseKerberos ())
	{
	    printf("\r\nSECURITY PARAMETERS:\r\n\r\n");
	}

    /*  root password   */
    if (NAGetAppRootPassword ())
    {
		if (kbGetString ("Root Password", password, NASYSACC_STRLEN_PASSWORD, NADIALOG_VERIFY)) 
		{
           	if (nvParamsPtr->rootPassword[0] == 0)
            {
            	NAsetSysAccess (NASYSACC_DEL, "root", NAGetAppRootPassword (), NASYSACC_LEVEL_ROOT, 0);
            }
            else
            {
                NAsetSysAccess (NASYSACC_DEL, "root", nvParamsPtr->rootPassword, NASYSACC_LEVEL_ROOT, 0);
            }

			NAsetSysAccess (NASYSACC_ADD, "root", password, NASYSACC_LEVEL_ROOT, 0);

            /*  update the nvParams record  */
            memset (nvParamsPtr->rootPassword, 0, sizeof(nvParamsPtr->rootPassword));
            strcpy (nvParamsPtr->rootPassword, password);
			updated = 1;
        }
    }

    /*  administrator account password  */
    if ((valueStr = NAGetAppAdministratorsAccount ()) != NULL)
    {
		sprintf (bufDesc, "Administrator '%s' Password", valueStr);
		updated |= kbGetString (bufDesc, nvParamsPtr->adminPassword, NASYSACC_STRLEN_PASSWORD, NADIALOG_VERIFY);
    }

    /*  fixed Key */
    if (NAGetAppFixedGatewayKey ())
    {
		updated |= kbGetString ("Fixed Key", nvParamsPtr->FixedKey, NASYSACC_STRLEN_PASSWORD, NADIALOG_VERIFY);
    }

    if (NAGetAppUseKerberos ())
    {
        updated |= kbGetIpAddress ("Kerberos KDC", &nvParamsPtr->krbIpAddr);
		updated |= kbGetString ("Kerberos Realm name", nvParamsPtr->krbRealmname, NASEC_MAX_KRB_REALM_NAME_LENGTH, 0);
		updated |= kbGetString ("Kerberos Username", nvParamsPtr->krbUsername, NASEC_MAX_KRB_USERNAME_LENGTH, 0);
		updated |= kbGetString ("Kerberos Password", nvParamsPtr->krbPassword, NASEC_MAX_KRB_PASSWORD_LENGTH, NADIALOG_VERIFY);
    }

	return (updated);
}
/*
 *
 *  Function: static int NAHardwareDialog (devBoardParamsType *nvParamsPtr)
 *
 *  Description:
 *
 *      This routine gets the new hardware related information.
 *
 *  Notes:
 *
 *      THIS CODE MUST BE CUSTOMIZED FOR YOUR BOARD.  The implementation
 *      below is for NET+OS development boards only.
 *
 *  Parameters:
 *
 *      nvParamsPtr     pointer to structure with development board parameters
 *
 *  Return Values:
 *
 *      0:              no updates
 *      1:              some or all hardware related information are updated
 *
 */    
static int NAHardwareDialog (devBoardParamsType *nvParamsPtr)
{
    char s[20];
    int	updated = 0;
    char buffer[128];
    unsigned long baudrate;
#if	BSP_WANT_ETHERNET
    bpDuplexLevelType newDuplex;
#endif

    printf("\r\n");
    printf("HARDWARE PARAMETERS:\r\n");  
    
    /*set the baudrate*/
    printf("\r\n");
    
    while (1)
    {
      	printf("Set the baud rate of Serial channels[%lu]?",nvParamsPtr->baudrate);
      	readLine(buffer);  
      	if (buffer[0] == '\0')
      	{
			baudrate = nvParamsPtr->baudrate;
		}
		else
		{

	        baudrate = atol(buffer);
	    }
       	if (isBaudRateValid(baudrate))    
       	{
           	nvParamsPtr->baudrate = baudrate;
           	printf("  The new baud rate is %lu\r\n",nvParamsPtr->baudrate);
           	printf("  The baud rate will be changed on next power up\r\n");
           	printf("  Please set the baud rate for your terminal accordingly\r\n");
			updated = 1;
           	break;
       	}

      	printf("The baud rate has to be 1200, 2400, 4800, 9600, 19200, 38400, or 57600\r\n");
    }    
     
    #if (BSP_SERIAL_NUMBER_FORMAT == BSP_SERIAL_NUMBER_FORMAT_500)
        printf("\r\n");
        /*set the board's serial number?*/
        printf("Each development board must have a unique serial number\r\n");
        memcpy(s,  &nvParamsPtr->serialNumber[1], SERIALNUMBER_LENGTH);
        s[SERIALNUMBER_LENGTH]=0;  /*for correct printf %s format*/
        while (1)
        {
          	printf("Set the board's serial number[%s]? ", s);
          	readLine(buffer);  
          	if (buffer[0] == '\0')
          	{
    			break;
    	  	}
    
           	if ( checkSerialNumber(buffer))
           	{
              	nvParamsPtr->serialNumber[0] = BP_OLDSTYLE_PREFIX;
              	memcpy(&nvParamsPtr->serialNumber[1], buffer, SERIALNUMBER_LENGTH);
              	nvParamsPtr->serialNumber[BP_SERIAL_NUMBER_LENGTH] = 0;
              	memcpy(s, &nvParamsPtr->serialNumber[1], SERIALNUMBER_LENGTH);
              	s[SERIALNUMBER_LENGTH]=0;  /*for correct printf %s format*/
              	printf("  The board's new serial number is %s\r\n", s);
    			updated = 1;
              	break;
           	}
    
            printf("The board's serial number has to be 00000000-99999999, 8 digits.\r\n");
        }
    #else
        printf("\r\n");
        /*set the board's serial number?*/
        printf("Each development board must have a unique serial number\r\n");
        memcpy(s,  nvParamsPtr->serialNumber,sizeof(nvParamsPtr->serialNumber));
        s[BP_SERIAL_NUMBER_LENGTH]=0;  /*for correct printf %s format*/
        while (1)
        {
          	printf("Set the board's serial number[%s]? ", s);
          	readLine(buffer);  
          	if (buffer[0] == '\0')
          	{
    			break;
    	  	}
    
           	if ( checkSerialNumber(buffer))
           	{
                  	memcpy(nvParamsPtr->serialNumber, buffer ,sizeof(nvParamsPtr->serialNumber));
                  	memcpy(s,  nvParamsPtr->serialNumber,sizeof(nvParamsPtr->serialNumber));
                  	s[BP_SERIAL_NUMBER_LENGTH]=0;  /*for correct printf %s format*/
                  	printf("  The board's new serial number is %s\r\n", s);
        			updated = 1;
                  	break;
           	}
    
            printf("The board's serial number has to be A00000000-Z99999999.\r\n");
            printf("1 alpha character followed by 8 digits.\r\n");
        }
    #endif
   
    #if (BSP_SERIAL_NUMBER_FORMAT != BSP_SERIAL_NUMBER_FORMAT_500)
    printf("\r\n");
    /*set the board's serial number?*/
    printf("Each development board must have a unique Ethernet MAC address.\r\n");
    sprintf(s, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", nvParamsPtr->ethernetMac[0], nvParamsPtr->ethernetMac[1], nvParamsPtr->ethernetMac[2], nvParamsPtr->ethernetMac[3], nvParamsPtr->ethernetMac[4], nvParamsPtr->ethernetMac[5]);
    while (1)
    {
        BYTE macAddress[sizeof nvParamsPtr->ethernetMac];
        
      	printf("Set the board's Ethernet MAC Address[%s]? ", s);
      	readLine(buffer);  
      	if (buffer[0] == '\0')
      	{
			break;
	  	}

       	if ( NAConvertMacAddressString(macAddress, buffer) == BP_SUCCESS)
       	{
          	memcpy(nvParamsPtr->ethernetMac, macAddress, sizeof nvParamsPtr->ethernetMac);
            printMacAddress("  This board's new Ethernet MAC Address is %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\r\n", nvParamsPtr->ethernetMac);                  
			updated = 1;
          	break;
       	}

        printf("An Ethernet MAC address must consist of 6 2-hexdigit \r\n");
        printf("values seperated by colons.\r\n");
    }
    #endif
    
    /*set wait time?*/
    printf("\r\n");
    printf("How long (in seconds) should CPU delay before starting up[%lu]? ", nvParamsPtr->waitTime);
    readLine(buffer);  
    if (buffer[0] != '\0')
	{
    	if(buffer[1] == '\0')
       	{
         	if (buffer[0] < 0x35)
           	{
             	nvParamsPtr->waitTime = 5;
            	printf("The smallest wait time is 5 seconds.\r\n");
           	}
         	else
			{
             	nvParamsPtr->waitTime = buffer[0]-0x30;        
			}
       	}
       	else
		{
         	nvParamsPtr->waitTime = (unsigned long)((buffer[0]-0x30)*10) + (unsigned long)(buffer[1]-0x30);
		}
         
       	printf("  After board is reset, start-up code will wait %lu seconds.\r\n", nvParamsPtr->waitTime);   
		updated = 1;
     }
     
#if	BSP_WANT_ETHERNET
     printf("\n\n");
     printf("Normally the board will automatically negotiate with the network hub\r\n");
     printf("(or switch) to determine the Ethernet duplex setting, however some hubs\r\n");
     printf("do not support autonegotiation.  In this case, the Ethernet driver can force\r\n");
     printf("the PHY to half duplex, force it to full duplex, or allow the PHY to use its\r\n");
     printf("default setting (usually half duplex).\r\n");
     do
     {
        newDuplex = kbGetDuplex ("Default Ethernet duplex setting (Full, Half, or phy Default)?" , nvParamsPtr->defaultDuplexLevel);
        if (isDuplexValid(newDuplex) == FALSE)
        {
            printf("You must select Full duplex, Half duplex, or the PHY's Default setting.\n\n");
        }
     } while (isDuplexValid(newDuplex) == FALSE);

     updated = (newDuplex != nvParamsPtr->defaultDuplexLevel);
     nvParamsPtr->defaultDuplexLevel = newDuplex;
#endif

	return (updated);
}
/*
 *
 *  Function: static int NAHardwareDialog (devBoardParamsType *nvParamsPtr)
 *
 *  Description:
 *
 *      This routine update the board parameters if there is any change.
 *
 *  Notes:
 *
 *      THIS CODE MUST BE CUSTOMIZED FOR YOUR BOARD.  The implementation
 *      below is for NET+OS development boards only.
 *
 *  Parameters:
 *
 *      nvParamsPtr     pointer to structure with development board parameters
 *
 *  Return Values:
 *
 *      0:              board parameters are updated
 *
 */         

static int NAUpdateDialog (devBoardParamsType *nvParamsPtr)     
{
 //   char mac_addrp[6];

   /* 
    * save all the changes in NVMEM
    * if the APP_USE_NVRAM flag is set to 0, just update default parameters.
    * 
    */
	printf("\r\n");
    
    if (NAGetAppUseNvram ())
	{
         printf("Saving the changes in NV memory...");
	}        
    else
	{
         printf("Updating the changes in defaultParams...");
	}
         
    /*  
     *  NAWriteDevBoardParams() writes development board parameters to NVRAM if APP_USE_NVRAM 
     *  flag is set to a nonzero value. If APP_USE_NVRAM is 0, NAReadDevBoardParams() updates 
     *  the default parameters as defined in appconfig.h. NAWriteDevBoardParams() and 
     *   default data struct are in src\narmcore\narmsrln.c.
     */     
    customizeWriteDevBoardParams (nvParamsPtr);

    printf("Done.\n");

    tx_thread_sleep(25); /*to see better*/
	return (0);
}



