/*
 *            Copyright (c) 1998-2004 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 304                               http://www.netsilicon.com
 *  Waltham, MA 02452                       AmericaSales@netsilicon.com
 *
 *************************************************************************
 *
 *  Description
 *  ====================================================================
 *  This file is an example of changing ACE parameters.
 *
 * 8/2/04	RL	This is a sample of stopping ACE, reconfiguring
 *			  	the protocols, restarting ACE. It include a user interface
 *				for the serial port, allowing the user to make a few choices
 *				regarding protocol and IP options.   
 *             
 *
 */

#include <stdio.h>
#include <tx_api.h>
#include <hservapi.h>
#include <sysAccess.h>
#include <ace_params.h>
#include <boardParams.h>

#define MAX_IPADDRESS_LENGTH    15

// prototypes

int 	kbGetIpAddress (char *ipAddrDesc, unsigned long *ipAddress);
void 	printIpAddress(char *buffer, unsigned long ip);
int  	checkIpAddress(char *buffer);
unsigned long kbGetHexValue(char * buffer);

//	Global variables for this module

void	printMACPair(unsigned char M);


void    readLine(char * buf);
void	getNVParams();

//	Global variables for this module


aceProtoStartInfo   	staticIPStartInfo = {ACE_PROT_STATIC, 0, 0, ACE_CONT_IF_GOT_ADDRESS};
aceProtoStartInfo   	autoIPStartInfo = {ACE_PROT_AUTOIP, 0, 0, ACE_CONT_IF_GOT_ADDRESS};

aceConfigInfo       	ACEFromNV;
unsigned long			ipaddr, subnetMask, defGW;

aceConfigInterfaceInfo	* ace_intfc;

configAceStaticInfo 	* staticIPInfo;
configAceStaticInfo		* staticIPInfo2;
configAceAutoipInfo 	* autoIPInfo;
configAceDhcpInfo   	* dhcpInfo;
configAcePingArpInfo 	* pingArpInfo;
configAceBootpInfo		* bootPInfo;
configAceRarpInfo		* rarpInfo;
devBoardParamsType  params;
 

void    aceTest()
{
	char            buffer[128];
	int             result = -1;

	// mode selection - codes the user's choice into enum.
	typedef enum
	{
		DEFAULT_MODE,
		STATIC_MODE,
		AUTOIP_MODE,
		DHCP_MODE,
		RARP_MODE,
		PING_ARP_MODE,
	}IPADDR_MODE;

	IPADDR_MODE AddressMode = STATIC_MODE;

	// some default values

	unsigned long	gatewayIP = 0x0a34010f;			// 10.52.1.15
	unsigned long	localIP = 0x0a343117;			// 10.52.49.23
	unsigned long	subnetMask = 0xfffff800;		// 255.255.248.0
	unsigned long	autoip_start_addr = 0x0a343119;	// 10.52.49.25

	/////////////////////////////////////////////////////////
	// Some ACE variables and structures
	/////////////////////////////////////////////////////////

	aceProtoStartInfo   staticIPStartInfo = {ACE_PROT_STATIC, 0, 0, ACE_CONT_IF_GOT_ADDRESS};
	aceProtoStartInfo   autoIPStartInfo = {ACE_PROT_AUTOIP, 0, 0, ACE_ALWAYS_SHUTDOWN};
	aceProtoStartInfo	dhcpStartInfo = {ACE_PROT_DHCP, 0, 0, ACE_CONT_IF_GOT_ADDRESS}; 
	aceProtoStartInfo	rarpStartInfo = {ACE_PROT_RARP, 0, 0, ACE_CONT_IF_GOT_ADDRESS};
	aceProtoStartInfo	bootPStartInfo = {ACE_PROT_BOOTP, 0, 0, ACE_CONT_IF_GOT_ADDRESS}; 
 

	char ipAddrDesc[16];
	unsigned long ipAddress;

	////////////////////////////////////////////////////////////
	// First get a copy of the ACE Configuration from NVRAM.
	// This function displays some parameters on the screen
	// (via printf).
	////////////////////////////////////////////////////////////

	getNVParams();

	printf("\naceTest() - select ace mode by typing one of the following:\n");
	printf("autoip\nstatic\ndhcp\nnone\n");
	printf("What is your selection?");
	readLine(&buffer[0]);

	if(buffer[0] == "\0")
		printf("Empty line, default mode is static IP\n");
	else
    {
		if(strncmp(&buffer[0], "static", 4) == 0)
		{
			printf("Static ip mode selected, type in the IP address to use> ");
			NAWait(1000);
			AddressMode = STATIC_MODE;
			if(kbGetIpAddress (&ipAddrDesc, &ipAddress) == 1)
				localIP = ipAddress;
			else
			{
				printf("Bad IP address - I will not take it pffffffft!\n");
				return;
			}
		}
		else
		{
			if(strncmp(&buffer[0], "autoip", 4) == 0)
			{
				printf("AutoIP mode selected type in the IP address to use>");
				NAWait(1000);
				AddressMode = AUTOIP_MODE;
				if(kbGetIpAddress (&ipAddrDesc, &ipAddress) == 1)
					localIP = ipAddress;
				else
				{
					printf("Bad IP address - I will not take it pffffffft!\n");
					return;
				}
				printf("Specify autoIP start delay>");
				autoIPStartInfo.delay_before_start = kbGetHexValue(&buffer[0]);
			}
			else
			{
				if(strncmp(&buffer[0], "dhcp", 4) == 0)
				{
					printf("DHCP Mode selected\n");
					AddressMode = DHCP_MODE;
				}
				else
				{
					AddressMode = DEFAULT_MODE;
					printf("None selected, skipping Ace Setup\n");
				}
			}
		}
	}


	if(AddressMode == DEFAULT_MODE)
		return;


	/////////////////////////////////////////////////////
	// ACE reconfiguration sample
	/////////////////////////////////////////////////////


	if(AddressMode == AUTOIP_MODE || AddressMode == STATIC_MODE)
		aceStop("eth0");
	else
		printf("Unsupported mode selected - aborting.\n");

	/////////////////////////////////////////////////////////
	// Change the parameters (ACE parameters) in the NVRAM
	// using the aceParams API.
	/////////////////////////////////////////////////////////

	if(AddressMode == STATIC_MODE)
	{
		printf("aceTest() Static mode\n");

		// Get the info from: params.aceConfig.ace_interface_info[0].static_config
		// and save it in a configAceStaticInfo structure.
		// This is for debug only. The values in this structure 
		// are not used. The other staticIPInfo structure is filled below
		// and contains teh data used to configure ACE static IP.

//		result = customizeAceGetStaticConfig("eth0", staticIPInfo2);

		// Now set the Static IP parameters the way we want them.
		// First a little initialization...

		staticIPInfo->auto_assign = TRUE;
		strcpy(staticIPInfo->domain_name,"");
		staticIPInfo->gateway = gatewayIP;
		staticIPInfo->ip_address = localIP;
		staticIPInfo->isConfigValid = TRUE;
		staticIPInfo->isEnabled = TRUE;
//		staticIPInfo->name_server_address[0] = 0;
		staticIPInfo->startInfo = staticIPStartInfo;
		staticIPInfo->subnet_mask = subnetMask;

		result = customizeAceSetStaticConfig("eth0", staticIPInfo);
		if(result != BP_SUCCESS)
		{
			printf("STATIC IP MODE: Failed to set static config info - bye-bye\n");
			exit(-6);
		}
		else
		{
			printf("STATIC IP MODE: IP = %x, GW = %x, Mask = %x\n", staticIPInfo->ip_address,
				   staticIPInfo->gateway, staticIPInfo->subnet_mask);
		}

		// falls through to ace start call at the bottom ...
	}

	///////////////////////////////////////////
	// For auto ip selection.

	if(AddressMode == AUTOIP_MODE)
	{
		printf("AutoIP mode - setting parameters.\n");

		// First get the static ip config
		// and disable it.

		autoIPInfo->isConfigValid = TRUE;
		autoIPInfo->isEnabled = TRUE;
		autoIPInfo->startInfo = autoIPStartInfo;
//		autoIPInfo->autoip_local_addr = BP_AUTOIP_START_WITH_RANDOM_IP_ADDRESS;
		autoIPInfo->autoip_local_addr = localIP;
//		autoIPInfo->autoip_local_addr = autoip_start_addr;


		result = customizeAceSetAutoipConfig("eth0", autoIPInfo);
		if(result != BP_SUCCESS)
		{
			printf("AUTO IP MODE: Failed to set auto ip config info - bye-bye\n");
			exit(-10);
		}
		else
		{
			printf("AUTO IP MODE: Starting with ");
			if(autoIPInfo->autoip_local_addr == BP_AUTOIP_START_WITH_RANDOM_IP_ADDRESS)
				printf("random ip address\n");
			else
				printf("%x\n", autoIPInfo->autoip_local_addr);
		}
	}

	if(AddressMode == DHCP_MODE)
	{
		printf("DHCP mode - setting parameters.\n");

		dhcpInfo->isConfigValid = TRUE;
		dhcpInfo->isEnabled = TRUE;
		dhcpInfo->startInfo = dhcpStartInfo;

		/*
		 *	Disable autoip and static ip to ensure dhcp is tried.
		 *	also disable RARP, PingARP and BootP
		 */

		autoIPInfo->isEnabled = FALSE;
		staticIPInfo->isEnabled = FALSE;
		rarpInfo->isEnabled = FALSE;
		bootPInfo->isEnabled = FALSE;


		// Save all these modified parameters to NVRAM (one protocol at a time)

		customizeAceSetAutoipConfig("eth0", autoIPInfo);
		customizeAceSetStaticConfig("eth0", staticIPInfo);
		customizeAceSetDhcpConfig("eth0", dhcpInfo);
		customizeAceSetRarpConfig("eth0", rarpInfo);
		customizeAceSetBootpConfig("eth0", bootPInfo);

		printf("DHCP implemented - ACE restarting with new parameters.\n");

		getNVParams();
	}

	/////////////////////////////////////////////////////////
	// Once the parameters are set up, start ACE.
	/////////////////////////////////////////////////////////

	printf("starting ACE\n");
	customizeStartAce();	// starts ACE with the parameters in the NVRAM.

	NAWait(10000);
	customizeGetIPParameters(&ipaddr, &subnetMask, &defGW);
	printf("Checked parameters after 10 second delay:\n");
	printf("IP Address = %x, Mask = %x, Gateway = %x\n", ipaddr, subnetMask, defGW);

}

/*
 *		LIFTED FROM DIALOG.C
 *
 *  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
 *
 */ 
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';
}  



/*
 *		LIFTED FROM DIALOG.C
 *
 *  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];
	unsigned long	IPAddr;

	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);
}

/*
 *		LIFTED FROM DIALOG.C
 *
 *  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; 
}  
/*
 *		LIFTED FROM DIALOG.C
 *
 *  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
 *
 */ 
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
} 

/*
 *	unsigned long kbGetHexValue(char * buffer)
 *					
 *	returns the hex value
 */

unsigned long kbGetHexValue(char * buffer)
{
	int				i = 0;
	unsigned long	val = 0xffffffff;
	unsigned char	temp;

	printf("<hex> ");
	readLine(buffer);
	
	while (*buffer != '\0' && i < 9) 
	{ 
		if(*buffer >= 0 && *buffer <= 9)
		{
			val *= 0x10;
			val += *buffer - '0';
		}
		else
		{
			if(*buffer >= 'a' && *buffer <= 'f')
			{
				temp = *buffer - 'a';
				val *= 0x10;
				val += temp;
			}
			else
			{
				if(*buffer >= 'A' && *buffer <= 'F')
				{
					temp = *buffer - 'A';
					val *= 0x10;
					val += temp;
				}
				else // if it's not a decimal digit (0-9), and not a letter a-f or A-F,
				{	// then it's not a valid hex digit so get the hell outta here.

					printf("\nINVALID HEX DIGIT IN THI STRING: %s\n", buffer);
					return(-1); 
								// The caller won't necessarily recognize this as
								// a failure, since it is a legitimate hex number (ffffffff).
				}
			}
		}
		 buffer++;
		 i++;
	}
	return(val);
}

/*
 *
 *  Function: void getNVParams()
 *
 *  Description:
 *
 *      This function fetches the ACE configuration parameters from the NVRAM.
 *
 *  Parameters:
 *      
 *		none
 *
 *  Return Values:
 *
 *      none
 *
 */ 

void	getNVParams()
{

	char			MACAddr[16];

//	result = customizeAceGetStaticConfig("eth0", &staticIPInfo);

	customizeReadDevBoardParams(&params);
	customizeGetIPParameters(&ipaddr, &subnetMask, &defGW);

	ACEFromNV = params.aceConfig;
	ace_intfc = &(ACEFromNV.ace_interface_info[0]);
	
	staticIPInfo = &(ace_intfc->static_config);
	autoIPInfo = &(ace_intfc->autoip_config);
	dhcpInfo = &(ace_intfc->dhcp_config);
	pingArpInfo = &(ace_intfc->ping_arp_config);
	bootPInfo = &(ace_intfc->bootp_config);
	rarpInfo = &(ace_intfc->rarp_config);

	printf("getNVParams() - Configuration dump:\n");
	customizeGetMACAddress((BYTE *) &MACAddr[0]);
	printf("static IP info: IP = %x gateway = %x mask = %x\n",staticIPInfo->ip_address,
		   staticIPInfo->gateway, staticIPInfo->subnet_mask);

	printMACAddress((unsigned char *) &MACAddr[0]);


	printf("auto IP info: IP = %x\n", autoIPInfo->autoip_local_addr);

	printf("dhcp info: IP suggested = %x lease time = %x server IP = %x\n", dhcpInfo->suggested_ip_address, dhcpInfo->suggested_lease_time,
		   dhcpInfo->server_ip_address);

	printf("pingArpInfo: start_info.delay = %x\n", pingArpInfo->startInfo.delay_before_start);
	printf("bootPInfo: file = %s   server IP = %x\n", bootPInfo->bootfile_name, bootPInfo->server_ip_address);
	printf("rarpInfo: rexint = %x\n", rarpInfo->rarp_rexint);
}

/*
 *
 *  Function: void printfMACAddress()
 *
 *  Description:
 *
 *      This function displays the MAC address is the familiar format
 *		(each two digit pair separated by a colon). 
 *
 *  Parameters:	M, pointer to an array of digit pairs (the product of
 *				customizeGetMACAddress()) in binary/hex form.
 *      
 *		none
 *
 *  Return Values:
 *
 *      none
 *
 */ 
void	printMACAddress(unsigned char * M)
{
	int				i;
	char	tempM;

	// To print the MAC Address - iterate through the 6 bytes and print
	//	each digit with a colon printed between pairs to create
	// the expected display.

	printf("MAC Address = ");
   	for(i = 0; i < 6; i++)
	{
		tempM = M[i];
		printMACPair(tempM);
		if(i < 5)
			printf(":");
	}
	printf("\n");

}

/*
 *
 *  Function: void printfMACPair()
 *
 *  Description:
 *
 *      This function prints the digit pair representing the 8 bit number passed in. 
 *
 *  Parameters:	M, the binary/hex number representing one sixth of the MAC address.
 *      
 *		none
 *
 *  Return Values:
 *
 *      none
 *
 */ 
void	printMACPair(unsigned char M)
{
	unsigned char	a, b;
	a = (M & 0xf0) >> 4;
	b = (M & 0x0f);
	if(a > 9)
	{
		a -= 10;
		a += 'A';
	}
	else
		a += '0';

	printf("%c", a);
	if(b > 9)
	{
		b -= 10;
		b += 'A';

	}
	else
		b += '0';
	printf("%c",b);

}



