Ejemplo n.º 1
0
/**
 * Send the given byte to the USART. It is added to the transmit buffer, and asynchronously
 * transmitted.
 *
 * @param c     Byte to write out on the serial port
 */
void serPutByte(BYTE c) {
    //Check if buffer is full.
    #ifdef SER_WAIT_FOR_TXBUF
    //Wait until a byte is transmitted by the interrupt routine and buffer has place again.
    while (busIsTxBufFull(BUSID)) {
        FAST_USER_PROCESS();
    }
    #else
    if (busIsTxBufFull(BUSID)) {
        serStat |= SER1_TXBUF_OVERRUN;
        return;
    }
    #endif

    //Enter critical section
    DISBALE_INTERRUPTS();

    //If we are not currently TXing, the TX buffer will be empty. No need to transmit via buffer,
    //just write direct to TXREG
    if ( !PIE1_TXIE)
    {
        TXREG = c;      //Send byte
        PIE1_TXIE = 1;  //Indicate that we are currently TXing
        ENABLE_INTERRUPTS();
    }
    //We are currently TXing. This means that the TXIF will soon be set after the current byte
    //has been transmitted, and the TX buffer will be checked for any unsent data. Add current
    //byte to TX buffer.
    else {
        //Add byte to TX buffer, and update buffer pointers
        busPutByteTxBuf(BUFID, c);
        
        ENABLE_INTERRUPTS();
    }
}
Ejemplo n.º 2
0
/**
 * Set a specified byte in the APP_CONFIG configuration structure to a given value.
 * This function will only update the EEPROM if the given new value is different from the
 * current old value. This saves the EEPROM, and increases it's live!
 * 
 * IMPORTANT - EEADRH must be set before calling this function! This configures the EEPROM page.
 *
 * @param offset Contains the offset in the APP_CONFIG structure of the byte to get
 *
 * @return Returns the requested byte
 */
void _appcfgPutc(WORD offset) {
    BYTE newValue;

    newValue = EEDATA;  //Store new value
    
    //Set address
    EEADR = (BYTE)offset;
    EEADRH = (BYTE)(offset >> 8);
    
    //Wait if something is currently being written
    while(EECON1_WR) FAST_USER_PROCESS();

    /////////////////////////////////////////////////
    //Only write to EEPROM if new value is different from old value - this saves the EEPROM!

    //Configure for EEPROM reading, EEPGD=0, CFGS=0
    EECON1 &= 0x3F;

    EECON1_RD = 1;  //After setting this bit, the data is available on next cycle. Is cleared by hardware.
    
    //If new value is the same as the old value, return
    if (EEDATA == newValue) {
        return;
    }


    /////////////////////////////////////////////////
    //Write new value to EEPROM
    EEDATA = newValue;      //New value to be written

    //Configure for EEPROM writing, EEPGD=0, CFGS=0, FREE=0
    EECON1 &= 0x2F;

    EECON1_WREN = 1;        //Write enable
    EECON2      = 0x55;
    EECON2      = 0xAA;
    EECON1_WR   = 1;
    Nop();
    //Wait for write to finish
    while(EECON1_WR) FAST_USER_PROCESS();
    EECON1_WREN = 0;

    return;
}
Ejemplo n.º 3
0
/**
 * Delays for the given time.
 * @param ms Time to delay = given time x 1ms
 */
void DelayMs(unsigned char ms)
{
    #if defined(HITECH_C18)
        while (ms--)
        {
            Delay10us(99);
            FAST_USER_PROCESS();
        }
    #elif defined(MCHP_C18)
        while (ms--)
        {
            #if (CLOCK_FREQ == 40000000)
                Delay1KTCYx(8); //Delay 1ms
            #elif (CLOCK_FREQ == 20000000)
                Delay1KTCYx(4); //Delay 1ms
            #endif
            FAST_USER_PROCESS();
        }
    #endif
}
Ejemplo n.º 4
0
/**
 * Get a specified byte from the APP_CONFIG configuration structure
 *
 * @param offset Contains the offset in the APP_CONFIG structure of the byte to get
 *
 * @return Returns the requested byte
 */
BYTE appcfgGetc(WORD offset) {
    //Set address
    EEADR = (BYTE)offset;
    EEADRH = (BYTE)(offset >> 8);

    //Wait if something is currently being written
    while(EECON1_WR) FAST_USER_PROCESS();

    //Configure for EEPROM reading, EEPGD=0, CFGS=0
    EECON1 &= 0x3F;

    EECON1_RD = 1;  //After setting this bit, the data is available on next cycle. Is cleared by hardware.
    return EEDATA;
}
Ejemplo n.º 5
0
/**
 * Read single byte from I2C bus
 *
 * @param ack Indicates if a ACK is sent after reading the byte. During sequencial read
 * the master will usually send an ACK after each byte read except the last byte. Not
 * sending the ack will indicate to the slave that this is the end of sequential read
 *
 * @return Contents of SSPBUF register
 */
unsigned char i2cGetByte(BOOL ack)
{
    SSPCON2_RCEN = 1;         	// enable master for 1 byte reception

    //At this stage, the slave can use clock streching to give it more time to collect the requested data.
    while ( !SSPSTAT_BF ) FAST_USER_PROCESS();  // wait until byte received
	while ( SSPCON2_RCEN );                     // check that receive sequence is over

    //Send ACK or NACK
    SSPCON2_ACKDT = ack ? 0 : 1;	//Send ACK when 0 and NACK when 1
    SSPCON2_ACKEN = 1;
    while(SSPCON2_ACKEN);           // Wait till finished
    
    return ( SSPBUF );      	// return with read byte
}
Ejemplo n.º 6
0
/**
 * This function transmit all data from the active UDP socket.
 *
 * @preCondition    UDPPut() is already called and desired UDP socket
 *                  is set as an active socket by calling
 *                  UDPIsPutReady().
 *
 * @return          All and any data associated with active UDP socket
 *                  buffer is marked as ready for transmission.
 *
 */
void UDPFlush(void)
{
    UDP_HEADER      h;
    UDP_SOCKET_INFO *p;

    // Wait for TX hardware to become available (finish transmitting 
    // any previous packet)
    while( !IPIsTxReady(TRUE) ) FAST_USER_PROCESS();

    p = &UDPSocketInfo[activeUDPSocket];

    h.SourcePort.Val        = swaps(p->localPort);
    h.DestinationPort.Val   = swaps(p->remotePort);
    h.Length.Val            = (WORD)((WORD)p->TxCount + (WORD)sizeof(UDP_HEADER));
    // Do not swap h.Length yet.  It is needed in IPPutHeader.
    h.Checksum.Val      = 0x00;

    //Makes the given TX Buffer active, and set's the pointer to the first byte after the IP
    //header. This is the first byte of the UDP header. The UDP header follows the IP header.
    IPSetTxBuffer(p->TxBuffer, 0);

    //Load IP header.
    IPPutHeader( &p->remoteNode,
                 IP_PROT_UDP,
                 h.Length.Val );


    //Now swap h.Length.Val
    h.Length.Val        = swaps(h.Length.Val);

    //Now load UDP header.
    IPPutArray((BYTE*)&h, sizeof(h));

    //Update checksum. !!!!!!!!!!!!!!! TO BE IMPLEMENTED !!!!!!!!!!!!!!!!!!!

    //Send data contained in TX Buffer via MAC
    MACFlush();

    // The buffer was reserved with AutoFree, so we can immediately 
    // discard it.  The MAC layer will free it after transmission.
    p->TxBuffer         = INVALID_BUFFER;
    p->TxCount          = 0;

}
Ejemplo n.º 7
0
static void ProcessIO(void)
{
//Convert next ADC channel, and store result in adcChannel array
#if (defined(APP_USE_ADC8) || defined(APP_USE_ADC10)) && (ADC_CHANNELS > 0)
    static BYTE adcChannel; //Current ADC channel. Value from 0 - n

    //We are allowed to update AdcValues[] buffer
    //if (!mainFlags.bits.bFreezeADCBuf)
    {
        //Increment to next ADC channel    
        if ((++adcChannel) >= ADC_CHANNELS)
        {
            adcChannel = 0;
        }

        //Check if current ADC channel (adcChannel) is configured to be ADC channel
        if (adcChannel < ((~ADCON1) & 0x0F))
        {
            //Convert next ADC Channel
            ADCON0 &= ~0x3C;
            ADCON0 |= (adcChannel << 2);

            ADCON0_ADON = 1;    //Switch on ADC
            ADCON0_GO = 1;      //Go
    
            while (ADCON0_GO) FAST_USER_PROCESS(); //Wait for conversion to finish

            #if defined(APP_USE_ADC8)
            AdcValues[adcChannel] = ADRESH;
            #elif defined(APP_USE_ADC10)
            AdcValues[adcChannel] = ((WORD)ADRESH << 8) || ADRESL;
            #endif
        }
        //Not ADC channel, set to 0
        else {
            AdcValues[adcChannel] = 0;
        }
    }
#endif

}
Ejemplo n.º 8
0
/**
 * This FSM checks for new incoming packets, and routes it to appropriate
 * stack components. It also performs timed operations.
 *
 * This function must be called periodically called
 * to make sure that timely response.
 *
 * @preCondition    StackInit() is already called.
 *
 * side affect:     Stack FSM is executed.
 */
void StackTask(void)
{
    static WORD dataCount;
    
#if defined(STACK_USE_ICMP)
    static BYTE data[MAX_ICMP_DATA_LEN];
    static WORD ICMPId;
    static WORD ICMPSeq;
#endif
    IP_ADDR destIP;     //Is filled with the Destination IP address contained in the IP header
    
    union
    {
        BYTE MACFrameType;
        BYTE IPFrameType;
        ICMP_CODE ICMPCode;
    } type;

    BOOL lbContinue;

    do
    {
        lbContinue = FALSE;

        switch(smStack)
        {
        case SM_STACK_IDLE:
        case SM_STACK_MAC:

            //debugPutGenRomStr(2, (ROM char*)"1");     //@mxd:2:%s

            //Check if the MAC RX Buffer has any data, and if it does, read the header.
            //Get the next header from the NIC. The node who sent it's address will be copied to 
            //'remoteNode.MACAddr'.
            //Header was NOT read if MACGetHeader returned FALSE
            if ( !MACGetHeader(&remoteNode.MACAddr, &type.MACFrameType) )
            {
                //debugPutGenRomStr(2, (ROM char*)"2");     //@mxd:2:%s
                
                //MODIFIED DHCP BEGIN
                // ADDED
	            #if defined(STACK_USE_DHCP)
	            // Normally, an application would not include  DHCP module
	            // if it is not enabled. But in case some one wants to disable
	            // DHCP module at run-time, remember to not clear our IP
	            // address if link is removed.
	            if(STACK_IS_DHCP_ENABLED)
	            {
		            if(!MACIsLinked())
		            {
	                    AppConfig.MyIPAddr.v[0] = MY_DEFAULT_IP_ADDR_BYTE1;
                        AppConfig.MyIPAddr.v[1] = MY_DEFAULT_IP_ADDR_BYTE2;
                        AppConfig.MyIPAddr.v[2] = MY_DEFAULT_IP_ADDR_BYTE3;
                        AppConfig.MyIPAddr.v[3] = MY_DEFAULT_IP_ADDR_BYTE4;

                        AppConfig.MyMask.v[0] = MY_DEFAULT_MASK_BYTE1;
                        AppConfig.MyMask.v[1] = MY_DEFAULT_MASK_BYTE2;
                        AppConfig.MyMask.v[2] = MY_DEFAULT_MASK_BYTE3;
                        AppConfig.MyMask.v[3] = MY_DEFAULT_MASK_BYTE4;
    
			            DHCPFlags.bits.bDHCPServerDetected = FALSE;

                        stackFlags.bits.bInConfigMode = TRUE;

			            DHCPReset();
		            }
	
		            // DHCP must be called all the time even after IP configuration is
		            // discovered.
		            // DHCP has to account lease expiration time and renew the configuration
		            // time.
		            DHCPTask();
		
		            if(DHCPIsBound())
			            stackFlags.bits.bInConfigMode = FALSE;
	            }
	            #endif
                //MODIFIED DHCP END


                //MODIFIED DHCP BEGIN
                // Removed
                /*
                #if defined(STACK_USE_DHCP)
                    // Normally, an application would not include DHCP module
                    // if it is not enabled. But in case some one wants to disable
                    // DHCP module at run-time, remember to not clear our IP
                    // address if link is removed.
                    //Set our IP to 0.0.0.0 if all the following are TRUE:
                    // - DHCP is enabled
                    // - MAC is not linked yet (or cable is unplugged)
                    if (STACK_IS_DHCP_ENABLED)
                    {
                        if ( !MACIsLinked() )
                        {
                            //debugPutGenRomStr(2, (ROM char*)"3");     //@mxd:2:%s

                            #if (DEBUG_STACKTSK >= LOG_INFO)
                            //debugPutMsg(1); //@mxd:1:DHCP Enabled but MAC not linked yet - set IP to 0.0.0.0
                            #endif
                            
                            //if (stackFlags.bits.bInConfigMode) {
                                //IP address must be 0.0.0.0 before DHCP has obtained a valid IP address
                                MY_IP_BYTE1 = 0;
                                MY_IP_BYTE2 = 0;
                                MY_IP_BYTE3 = 0;
                                MY_IP_BYTE4 = 0;
                            //}

                            stackFlags.bits.bInConfigMode = TRUE;
                            DHCPReset();
                        }
                    }
                #endif
                */
                //MODIFIED DHCP END

                break;      //case SM_STACK_IDLE:  AND   case SM_STACK_MAC:
            }

            //debugPutGenRomStr(2, (ROM char*)"4");     //@mxd:2:%s

            lbContinue = TRUE;
            if ( type.MACFrameType == MAC_IP ) {
                smStack = SM_STACK_IP;
                #if (DEBUG_STACKTSK >= LOG_DEBUG)
                debugPutMsg(2); //@mxd:2:Reading MAC IP header
                #endif
            }
            else if ( type.MACFrameType == MAC_ARP ) {
                smStack = SM_STACK_ARP;
                #if (DEBUG_STACKTSK >= LOG_DEBUG)
                debugPutMsg(3); //@mxd:3:Reading MAC ARP header
                #endif
            }
            else {
                MACDiscardRx(); //Discard the contents of the current RX buffer
                #if (DEBUG_STACKTSK >= LOG_WARN)
                debugPutMsg(4); //@mxd:4:Unknown MAC header read, MAC Frame Type = 0x%x
                debugPutByteHex(type.MACFrameType);
                #endif
            }
            break;      //case SM_STACK_IDLE:  AND   case SM_STACK_MAC:

        case SM_STACK_ARP:
            if ( ARPProcess() )
                smStack = SM_STACK_IDLE;
            //lbContinue = FALSE;   //Removed in latest Microchip TCP/IP stack
            break;

        case SM_STACK_IP:
            if ( IPGetHeader(&destIP,  /* Get Destination IP Address as received in IP header */
                             &remoteNode,
                             &type.IPFrameType,
                             &dataCount) )
            {
                lbContinue = TRUE;
                if ( type.IPFrameType == IP_PROT_ICMP )
                {
                    smStack = SM_STACK_ICMP;

#if defined(STACK_USE_IP_GLEANING)
                    if(stackFlags.bits.bInConfigMode && STACK_IS_DHCP_ENABLED)
                    {
                        // Accoriding to "IP Gleaning" procedure,
                        // when we receive an ICMP packet with a valid
                        // IP address while we are still in configuration
                        // mode, accept that address as ours and conclude
                        // configuration mode.
                        if ( destIP.Val != 0xffffffff )
                        {
                            stackFlags.bits.bInConfigMode    = FALSE;
                            MY_IP_BYTE1                 = destIP.v[0];
                            MY_IP_BYTE2                 = destIP.v[1];
                            MY_IP_BYTE3                 = destIP.v[2];
                            MY_IP_BYTE4                 = destIP.v[3];
                            myDHCPBindCount--;
                        }
                    }
#endif
                }

#if defined(STACK_USE_TCP)
                else if ( type.IPFrameType == IP_PROT_TCP )
                    smStack = SM_STACK_TCP;
#endif

#if defined(STACK_USE_UDP)
                else if ( type.IPFrameType == IP_PROT_UDP )
                    smStack = SM_STACK_UDP;
#endif

                else    // Unknown/unsupported higher level protocol
                {
                    lbContinue = FALSE;
                    MACDiscardRx(); //Discard the contents of the current RX buffer

                    smStack = SM_STACK_IDLE;
                }
            }
            else    // Improper IP header version or checksum
            {
                MACDiscardRx(); //Discard the contents of the current RX buffer
                smStack = SM_STACK_IDLE;
            }
            break;      //case SM_STACK_IP:

#if defined(STACK_USE_UDP)
        case SM_STACK_UDP:
            if ( UDPProcess(&remoteNode, &destIP, dataCount) )
                smStack = SM_STACK_IDLE;
            //lbContinue = FALSE;   //Removed in latest Microchip TCP/IP stack
            break;      //case SM_STACK_UDP:
#endif

#if defined(STACK_USE_TCP)
        case SM_STACK_TCP:
            if ( TCPProcess(&remoteNode, &destIP, dataCount) )  //Will return TRUE if TCPProcess finished it's task, else FALSE
                smStack = SM_STACK_IDLE;
            //lbContinue = FALSE;   //Removed in latest Microchip TCP/IP stack
            break;      //case SM_STACK_TCP:
#endif

        case SM_STACK_ICMP:
            smStack = SM_STACK_IDLE;

#if defined(STACK_USE_ICMP)
            if ( dataCount <= (MAX_ICMP_DATA_LEN+9) )
            {
                if ( ICMPGet(&type.ICMPCode,
                             data,
                             (BYTE*)&dataCount,
                             &ICMPId,
                             &ICMPSeq) )
                {
                    if ( type.ICMPCode == ICMP_ECHO_REQUEST )
                    {
                        lbContinue = TRUE;
                        smStack = SM_STACK_ICMP_REPLY;
                    }
                }
            }
#endif
            MACDiscardRx(); //Discard the contents of the current RX buffer
            break;          //case SM_STACK_ICMP:

#if defined(STACK_USE_ICMP)
        case SM_STACK_ICMP_REPLY:
            if ( ICMPIsTxReady() )
            {
                ICMPPut(&remoteNode,
                        ICMP_ECHO_REPLY,
                        data,
                        (BYTE)dataCount,
                        ICMPId,
                        ICMPSeq);

                smStack = SM_STACK_IDLE;
            }
            break;          //case SM_STACK_ICMP_REPLY:
#endif

        }       //switch(smStack)

        FAST_USER_PROCESS();
    } while(lbContinue);

#if defined(STACK_USE_TCP)
    // Perform timed TCP FSM.
    TCPTick();
#endif


//MODIFIED DHCP BEGIN
// Removed this
//#if defined(STACK_USE_DHCP)
    /*
     * DHCP must be called all the time even after IP configuration is
     * discovered.
     * DHCP has to account lease expiration time and renew the configuration
     * time.
     */
//    DHCPTask();

//    if(DHCPIsBound())
//        stackFlags.bits.bInConfigMode = FALSE;

//#endif

    //debugPutGenRomStr(2, (ROM char*)"MACTask");     //@mxd:2:%s

    //Perform routine MAC tasks
    MACTask();
}
Ejemplo n.º 9
0
/*********************************************************************
 * Function:        void AnnounceIP(void)
 *
 * PreCondition:    Stack is initialized()
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        AnnounceIP opens a UDP socket and transmits a 
 *                    broadcast packet to port 30303.  If a computer is
 *                    on the same subnet and a utility is looking for 
 *                    packets on the UDP port, it will receive the 
 *                    broadcast.  For this application, it is used to 
 *                    announce the change of this board's IP address.
 *                    The messages can be viewed with the MCHPDetect.exe
 *                    program.
 *
 * Note:            A UDP socket must be available before this 
 *                    function is called.  It is freed at the end of 
 *                    the function.  MAX_UDP_SOCKETS may need to be 
 *                    increased if other modules use UDP sockets.
 ********************************************************************/
void AnnounceIP(void)
{
    UDP_SOCKET    MySocket;
    NODE_INFO    Remote;
    BYTE         i;
    
    // Set the socket's destination to be a broadcast over our IP 
    // subnet
    // Set the MAC destination to be a broadcast
    memset(&Remote, 0xFF, sizeof(Remote));
    
    // Open a UDP socket for outbound transmission
    MySocket = UDPOpen(2860, &Remote, ANNOUNCE_PORT);
    
    // Abort operation if no UDP sockets are available
    // If this ever happens, incrementing MAX_UDP_SOCKETS in 
    // StackTsk.h may help (at the expense of more global memory 
    // resources).
    if( MySocket == INVALID_UDP_SOCKET ) {
        #if (DEBUG_ANNOUNCE >= LOG_ERROR)
        debugPutMsg(1); //@mxd:1:Could not open UDP socket
        #endif

        return;
    }
    
    // Make certain the socket can be written to
    while( !UDPIsPutReady(MySocket) ) FAST_USER_PROCESS();
    
    // Begin sending our MAC address in human readable form.
    // The MAC address theoretically could be obtained from the 
    // packet header when the computer receives our UDP packet, 
    // however, in practice, the OS will abstract away the useful
    // information and it would be difficult to obtain.  It also 
    // would be lost if this broadcast packet were forwarded by a
    // router to a different portion of the network (note that 
    // broadcasts are normally not forwarded by routers).
    for(i=0; i < 15; i++)   //First 15 (0-14) characters are NetBIOS name, 16th character is 0x00
    {
        UDPPut(NETBIOS_NAME_GETCHAR(i));
    }
    UDPPut('\r');
    UDPPut('\n');

    // Convert the MAC address bytes to hex (text) and then send it
    i = 0;
    while(1)
    {
        UDPPut(btohexa_high(AppConfig.MyMACAddr.v[i]));
        UDPPut(btohexa_low(AppConfig.MyMACAddr.v[i]));
        if(++i == 6)
            break;
        UDPPut('-');
    }
    UDPPut('\r');
    UDPPut('\n');

    // Send some other human readable information.
    UDPPut('D');
    UDPPut('H');
    UDPPut('C');
    UDPPut('P');
    UDPPut('/');
    UDPPut('P');
    UDPPut('o');
    UDPPut('w');
    UDPPut('e');
    UDPPut('r');
    UDPPut(' ');
    UDPPut('e');
    UDPPut('v');
    UDPPut('e');
    UDPPut('n');
    UDPPut('t');
    UDPPut(' ');
    UDPPut('o');
    UDPPut('c');
    UDPPut('c');
    UDPPut('u');
    UDPPut('r');
    UDPPut('r');
    UDPPut('e');
    UDPPut('d');
    
    // Send the packet
    UDPFlush();
    
    // Close the socket so it can be used by other modules
    UDPClose(MySocket);
}
Ejemplo n.º 10
0
/**
 * Must be called every couple of ms
 *
 */
void busTask(void) {
    BYTE c;
    BYTE bytesRead;
    BYTE busId;
    BYTE linkedMask;

    /////////////////////////////////////////////////
    //UDP 1
    
    //Get bus to link to UDP 1
    busId = appcfgGetc(BUSCFG_UDP1_LINK);

    #if defined(BRD_SBC65EC)    
    //Currently UDP 1 can only be linked to Serial 1, Serial 2 and I2C for SBC65EC
    if ((busId >= BUSID_SER1) && (busId <= BUSID_I2C1) && (udpBus1 != INVALID_UDP_SOCKET)) {
    #else
    //Currently UDP 1 can only be linked to Serial 1 and I2C for SBC68EC
    if ( ((busId == BUSID_SER1) || (busId == BUSID_I2C1)) && (udpBus1 != INVALID_UDP_SOCKET)) {
    #endif
    
        //Is there any data waiting for us on this UDP port?
        if (UDPIsGetReady(udpBus1)) {

            if (busIsEnabled(busId)) {

                //Read bytes
                while (UDPGet(&c)) {

                    //Wait until a byte is transmitted by the interrupt routine and buffer has place again.
                    while (busIsTxBufFull(busId)) {

                        busService(busId);
                        FAST_USER_PROCESS();
                    }
                    //Add byte to TX buffer, and update buffer pointers
                    busPutByteTxBuf(busId, c);
                }

                //Initiate transmitting if not already transmitting
                if (!busIsTxing(busId)) {

                    busService(busId);
                }
            }

            //Discard the socket buffer.
            UDPDiscard();
        }

        //Is there any data to send on UDP port
        if(busRxBufHasData(busId)) {

            if (UDPIsPutReady(udpBus1)) {

                while(busRxBufHasData(busId)) {
                
                    //Read and remove byte from buffer
                    c = busPeekByteRxBuf(busId);
                    busRemoveByteRxBuf(busId);
                    
                    UDPPut(c);
                }
            
                // Now transmit it.
                UDPFlush();
            }
        }
    }


    /////////////////////////////////////////////////
    //UDP 2
    
    //Get bus to link to UDP 2
    busId = appcfgGetc(BUSCFG_UDP2_LINK);

    #if defined(BRD_SBC65EC)    
    //Currently UDP 1 can only be linked to Serial 1, Serial 2 and I2C for SBC65EC
    if ((busId >= BUSID_SER1) && (busId <= BUSID_I2C1) && (udpBus1 != INVALID_UDP_SOCKET)) {
    #else
    //Currently UDP 1 can only be linked to Serial 1 and I2C for SBC68EC
    if ( ((busId == BUSID_SER1) || (busId == BUSID_I2C1)) && (udpBus1 != INVALID_UDP_SOCKET)) {
    #endif
        //Is there any data waiting for us on this UDP port?
        if (UDPIsGetReady(udpBus2)) {

            if (busIsEnabled(busId)) {
                //Read bytes
                while (UDPGet(&c)) {
                    //Wait until a byte is transmitted by the interrupt routine and buffer has place again.
                    while (busIsTxBufFull(busId)) {
                        busService(busId);
                        FAST_USER_PROCESS();
                    }
                    //Add byte to TX buffer, and update buffer pointers
                    busPutByteTxBuf(busId, c);
                }

                //Initiate transmitting if not already transmitting
                if (!busIsTxing(busId)) {
                    busService(busId);
                }
            }

            //Discard the socket buffer.
            UDPDiscard();
        }

        //Is there any data to send on UDP port
        if(busRxBufHasData(busId)) {
            if (UDPIsPutReady(udpBus2)) {

                while(busRxBufHasData(busId)) {
                    //Read and remove byte from buffer
                    c = busPeekByteRxBuf(busId);
                    busRemoveByteRxBuf(busId);
            
                    UDPPut(c);
                }
            
                // Now transmit it.
                UDPFlush();
            }
        }
    }


    /////////////////////////////////////////////////
    //Service all serial buses
    for (busId=0; busId<BUS_COUNT; busId++) {
        busService(busId);
    }
}


/**
 * Service the given bus. If our code has a section where it has to wait for the transmit
 * buffer of a bus to be empties, it should call this function while waiting.
 *
 * @param busId The bus ID of the requested bus. Is a BUSID_XXX variable
 *
 */
void busService(BYTE busId) {
    switch(busId) {
        case BUSID_SER1:
            serService();
        break;
        
        #if defined(BRD_SBC65EC)
        case BUSID_SER2:
            ser2Service();
        break;
        #endif
        
        case BUSID_I2C1:
            i2cBusService();
        break;
        
        case BUSID_SPI1:
            NOP();
        break;
    }
}


/**
 * Gets a byte at the given offset from the Transmit Buffer, without removing it.
 * The byte is NOT removed from the buffer, and the buffer pointers are NOT updated! 
 * The byte at the given offset it returned. The offset is how deep the byte is in
 * the buffer. For example, 0 will return first byte in buffer, 5 will return the 6th
 * byte in the buffer.
 *
 * @preCondition Ensure offset parameter is not larger than current number of bytes
 * contained in buffer. Call busGetTxBufCount() to get current number of bytes in buffer.
 *
 * @param busId The bus ID of the requested bus. Is a BUSID_XXX variable
 * @param offset Offset of byte to return. Is a value from 0-n, where n = (busGetTxBufCount() - 1)
 *
 * @return Returns the byte at the given offset in the given bus's Transmit buffer.
 */
BYTE busPeekByteTxBufAt(BYTE busId, BYTE offset) {
	BYTE ofst;

	ofst = busInfo.buf[busId].getTx + offset;

	//Check if offset wrap around
	if (ofst >= busInfo.buf[busId].txBufSize) {
		ofst = ofst - busInfo.buf[busId].txBufSize;
	}

	return *(busInfo.buf[busId].txBuf + ofst);

}


/**
 * Gets a byte at the given offset from the Receive Buffer, without removing it.
 * The byte is NOT removed from the buffer, and the buffer pointers are NOT updated! 
 * The byte at the given offset it returned. The offset is how deep the byte is in
 * the buffer. For example, 0 will return first byte in buffer, 5 will return the 6th
 * byte in the buffer.
 *
 * @preCondition Ensure offset parameter is not larger than current number of bytes
 * contained in buffer. Call busGetRxBufCount() to get current number of bytes in buffer.
 *
 * @param busId The bus ID of the requested bus. Is a BUSID_XXX variable
 * @param offset Offset of byte to return. Is a value from 0-n, where n = (busGetRxBufCount() - 1)
 *
 * @return Returns the byte at the given offset in the given bus's Receive buffer.
 */
BYTE busPeekByteRxBufAt(BYTE busId, BYTE offset) {
	BYTE ofst;

	ofst = busInfo.buf[busId].getRx + offset;

	//Check if offset wrap around
	if (ofst >= busInfo.buf[busId].rxBufSize) {
		ofst = ofst - busInfo.buf[busId].rxBufSize;
	}

	return *(busInfo.buf[busId].rxBuf + ofst);
}
Ejemplo n.º 11
0
/**
 * This function transmit all data from the active UDP socket.
 *
 * @preCondition    UDPPut() is already called and desired UDP socket
 *                  is set as an active socket by calling
 *                  UDPIsPutReady().
 *
 * @return          All and any data associated with active UDP socket
 *                  buffer is marked as ready for transmission.
 *
 */
void UDPFlush(void)
{
    UDP_HEADER      h;
    UDP_SOCKET_INFO *p;
    WORD csLength;
	DWORD_VAL csChecksum;
    // Wait for TX hardware to become available (finish transmitting 
    // any previous packet)
    while( !IPIsTxReady(TRUE) ) FAST_USER_PROCESS();

    p = &UDPSocketInfo[activeUDPSocket];

    h.SourcePort.Val        = swaps(p->localPort);
    h.DestinationPort.Val   = swaps(p->remotePort);
    h.Length.Val            = (WORD)((WORD)p->TxCount + (WORD)sizeof(UDP_HEADER));
    // Do not swap h.Length yet.  It is needed in IPPutHeader.
    h.Checksum.Val      = 0x00;

    //Makes the given TX Buffer active, and set's the pointer to the first byte after the IP
    //header. This is the first byte of the UDP header. The UDP header follows the IP header.
    IPSetTxBuffer(p->TxBuffer, 0);

    //Load IP header.
    IPPutHeader( &p->remoteNode,
                 IP_PROT_UDP,
                 h.Length.Val );

    // save length before swap for checksum calculation
    csLength			= p->TxCount;

    //Now swap h.Length.Val
    h.Length.Val        = swaps(h.Length.Val);

    //Now load UDP header.
    IPPutArray((BYTE*)&h, sizeof(h));

    //Update checksum. !!!!!!!!!!!!!!! TO BE IMPLEMENTED !!!!!!!!!!!!!!!!!!!
	// Update checksum.
    
	// start the checksum with value for UDP protocol & length from pseudo header (and in the actual packet)
	csChecksum.Val = (WORD)IP_PROT_UDP + (WORD)csLength + sizeof(UDP_HEADER);
	// add in my address and the remoteNode address
	csChecksum.Val += ((WORD)MY_IP_BYTE1 << 8) + MY_IP_BYTE2;
	csChecksum.Val += ((WORD)MY_IP_BYTE3 << 8) + MY_IP_BYTE4;
	csChecksum.Val += ((WORD)p->remoteNode.IPAddr.v[0] << 8) +  ((WORD)p->remoteNode.IPAddr.v[1] ) +
					  ((WORD)p->remoteNode.IPAddr.v[2] << 8) +  ((WORD)p->remoteNode.IPAddr.v[3] );
			

    // set mac pointer to the ip_addr of the source, so all of pseudo header but length is included.
    // length of pseudo header is already included in previous instruction.
    //MACSetRxBuffer( sizeof(IP_HEADER)+sizeof(UDP_HEADER) );
	

	csChecksum.Val += (WORD)p->localPort;
	csChecksum.Val += (WORD)p->remotePort;
	csChecksum.Val += (WORD)csLength + sizeof(UDP_HEADER);

	//IPSetRxBuffer(BASE_TX_ADDR + sizeof(ETHER_HEADER) + sizeof(IP_HEADER) - ( sizeof(IP_ADDR) * 2 ) );
	
    // handled in UdpPut routines
	csChecksum.Val += udpChecksum;

	// add any carry over to the last word
	while((DWORD)csChecksum.word.MSW) {
		csChecksum.Val = (DWORD)csChecksum.word.LSW + (DWORD)csChecksum.word.MSW;
	}	
	// add any carry over from adding the carry over
	//csChecksum.Val = (DWORD)csChecksum.word.LSW + (DWORD)csChecksum.word.MSW;
	
	// invert
	csChecksum.Val = ~csChecksum.Val;
	
	// set write pointer to location of checksum in packet
	//MACSetWritePtr( sizeof(ETHER_HEADER) + sizeof(IP_HEADER) + sizeof(UDP_HEADER) - 2 );
	IPSetTxBuffer(p->TxBuffer,   sizeof(UDP_HEADER) - 2);
	// write the swapped checksum to the packet
	
	
	//MACPut(	csChecksum.v[1] );
	//MACPut(	csChecksum.v[0] );
	MACPut(0);
	MACPut(0);
    //Send data contained in TX Buffer via MAC
    MACFlush();

    // The buffer was reserved with AutoFree, so we can immediately 
    // discard it.  The MAC layer will free it after transmission.
    p->TxBuffer         = INVALID_BUFFER;
    p->TxCount          = 0;

}
Ejemplo n.º 12
0
/**
 *  DHCP PACKET FORMAT AS PER RFC 1541
 *
 *  0                   1                   2                   3
 *   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *   |     op (1)    |   htype (1)   |   hlen (1)    |   hops (1)    |
 *   +---------------+---------------+---------------+---------------+
 *   |                            xid (4)                            |
 *   +-------------------------------+-------------------------------+
 *   |           secs (2)            |           flags (2)           |
 *   +-------------------------------+-------------------------------+
 *   |                          ciaddr  (4)                          |
 *   +---------------------------------------------------------------+
 *   |                          yiaddr  (4)                          |
 *   +---------------------------------------------------------------+
 *   |                          siaddr  (4)                          |
 *   +---------------------------------------------------------------+
 *   |                          giaddr  (4)                          |
 *   +---------------------------------------------------------------+
 *   |                                                               |
 *   |                          chaddr  (16)                         |
 *   |                                                               |
 *   |                                                               |
 *   +---------------------------------------------------------------+
 *   |                                                               |
 *   |                          sname   (64)                         |
 *   +---------------------------------------------------------------+
 *   |                                                               |
 *   |                          file    (128)                        |
 *   +---------------------------------------------------------------+
 *   |                                                               |
 *   |                          options (312)                        |
 *   +---------------------------------------------------------------+
 *
 */
static BYTE _DHCPReceive(void)
{
    BYTE v;
    BYTE i, j;
    BYTE type;
    BOOL lbDone;
    DWORD_VAL tempServerID;
    MAC_ADDR tempMacAddr;


    // Assume unknown message until proven otherwise.
    type = DHCP_UNKNOWN_MESSAGE;

    UDPGet(&v);                             // op

    // Make sure this is BOOT_REPLY.
    if ( v == BOOT_REPLY )
    {
        // Discard htype, hlen, hops, xid, secs, flags, ciaddr.
        for ( i = 0; i < 15u; i++ )
            UDPGet(&v);

        // Check to see if this is the first offer
        if(DHCPState.bits.bOfferReceived)
        {
            // Discard offered IP address, we already have an offer
            for ( i = 0; i < 4u; i++ )
                UDPGet(&v);
        }
        else
        {
            // Save offered IP address until we know for sure that we have it.
            UDPGet(&tempIPAddress.v[0]);
            UDPGet(&tempIPAddress.v[1]);
            UDPGet(&tempIPAddress.v[2]);
            UDPGet(&tempIPAddress.v[3]);
            ValidValues.bits.IPAddress = 1;
        }

        // Ignore siaddr, giaddr
        for ( i = 0; i < 8u; i++ )
            UDPGet(&v);

        // Check to see if chaddr (Client Hardware Address) belongs to us.
        tempMacAddr.v[0] = MY_MAC_BYTE1;
        tempMacAddr.v[1] = MY_MAC_BYTE2;
        tempMacAddr.v[2] = MY_MAC_BYTE3;
        tempMacAddr.v[3] = MY_MAC_BYTE4;
        tempMacAddr.v[4] = MY_MAC_BYTE5;
        tempMacAddr.v[5] = MY_MAC_BYTE6;
        for ( i = 0; i < 6u; i++ )
        {
            UDPGet(&v);
            if ( v != tempMacAddr.v[i])
                goto UDPInvalid;
        }


        // Ignore part of chaddr, sname, file, magic cookie.
        for ( i = 0; i < 206u; i++ )
            UDPGet(&v);

        lbDone = FALSE;
        do
        {
            // Get the Option number
            // Break out eventually in case if this is a malformed 
            // DHCP message, ie: missing DHCP_END_OPTION marker
            if(!UDPGet(&v))
            {
                lbDone = TRUE;
                break;
            }

            switch(v)
            {
            case DHCP_MESSAGE_TYPE:
                UDPGet(&v);                         // Skip len
                // Len must be 1.
                if ( v == 1u )
                {
                    UDPGet(&type);                  // Get type

                    // Throw away the packet if we know we don't need it (ie: another offer when we already have one)
                    if(DHCPState.bits.bOfferReceived && (type == DHCP_OFFER_MESSAGE))
                    {
                        goto UDPInvalid;
                    }
                }
                else
                    goto UDPInvalid;
                break;

            case DHCP_SUBNET_MASK:
                UDPGet(&v);                     // Skip len
                // Len must be 4.
                if ( v == 4u )
                {
                    // Check to see if this is the first offer
                    if(DHCPState.bits.bOfferReceived)
                    {
                        // Discard offered IP mask, we already have an offer
                        for ( i = 0; i < 4u; i++ )
                            UDPGet(&v);
                    }
                    else
                    {
                        UDPGet(&tempMask.v[0]);
                        UDPGet(&tempMask.v[1]);
                        UDPGet(&tempMask.v[2]);
                        UDPGet(&tempMask.v[3]);
                        ValidValues.bits.Mask = 1;
                    }
                }
                else
                    goto UDPInvalid;
                break;

            case DHCP_ROUTER:
                UDPGet(&j);
                // Len must be >= 4.
                if ( j >= 4u )
                {
                    // Check to see if this is the first offer
                    if(DHCPState.bits.bOfferReceived)
                    {
                        // Discard offered Gateway address, we already have an offer
                        for ( i = 0; i < 4u; i++ )
                            UDPGet(&v);
                    }
                    else
                    {
                        UDPGet(&tempGateway.v[0]);
                        UDPGet(&tempGateway.v[1]);
                        UDPGet(&tempGateway.v[2]);
                        UDPGet(&tempGateway.v[3]);
                        ValidValues.bits.Gateway = 1;
                    }
                }
                else
                    goto UDPInvalid;

                // Discard any other router addresses.
                j -= 4;
                while(j--)
                    UDPGet(&v);
                break;

#if defined(STACK_USE_DNS)
            case DHCP_DNS:
                UDPGet(&j);
                // Len must be >= 4.
                if ( j >= 4u )
                {
                    // Check to see if this is the first offer
                    if(DHCPState.bits.bOfferReceived)
                    {
                        // Discard offered DNS server address, we already have an offer
                        for ( i = 0; i < 4u; i++ )
                            UDPGet(&v);
                    }
                    else
                    {
                        UDPGet(&tempDNS.v[0]);
                        UDPGet(&tempDNS.v[1]);
                        UDPGet(&tempDNS.v[2]);
                        UDPGet(&tempDNS.v[3]);
                        ValidValues.bits.DNS = 1;
                    }
                }
                else
                    goto UDPInvalid;

                // Discard any other DNS server addresses
                j -= 4;
                while(j--)
                    UDPGet(&v);
                break;
#endif

//            case DHCP_HOST_NAME:
//                UDPGet(&j);
//                // Len must be >= 4.
//                if(j < 1u)
//                    goto UDPInvalid;
//
//                // Check to see if this is the first offer
//                if(DHCPState.bits.bOfferReceived)
//                {
//                    // Discard offered host name, we already have an offer
//                    while(j--)
//                        UDPGet(&v);
//                }
//                else
//                {
//                    for(i = 0; j, i < sizeof(tempHostName); i++, j--)
//                    {
//                        UDPGet(&tempHostName[i]);
//                    }
//                    while(j--)
//                    {
//                        UDPGet(&v);
//                    }
//                    ValidValues.bits.HostName = 1;
//                }
//
//                break;

            case DHCP_SERVER_IDENTIFIER:
                UDPGet(&v);                         // Get len
                // Len must be 4.
                if ( v == 4u )
                {
                    UDPGet(&tempServerID.v[3]);   // Get the id
                    UDPGet(&tempServerID.v[2]);
                    UDPGet(&tempServerID.v[1]);
                    UDPGet(&tempServerID.v[0]);
                }
                else
                    goto UDPInvalid;
                break;

            case DHCP_END_OPTION:
                lbDone = TRUE;
                break;

            case DHCP_IP_LEASE_TIME:
                UDPGet(&v);                         // Get len
                // Len must be 4.
                if ( v == 4u )
                {
                    // Check to see if this is the first offer
                    if(DHCPState.bits.bOfferReceived)
                    {
                        // Discard offered lease time, we already have an offer
                        for ( i = 0; i < 4u; i++ )
                            UDPGet(&v);
                    }
                    else
                    {
                        UDPGet(&DHCPLeaseTime.v[3]);
                        UDPGet(&DHCPLeaseTime.v[2]);
                        UDPGet(&DHCPLeaseTime.v[1]);
                        UDPGet(&DHCPLeaseTime.v[0]);

                        // Due to possible timing delays, consider actual lease
                        // time less by half hour.
                        if ( DHCPLeaseTime.Val > HALF_HOUR )
                            DHCPLeaseTime.Val = DHCPLeaseTime.Val - HALF_HOUR;
                    }
                }
                else
                    goto UDPInvalid;
                break;

            default:
                // Ignore all unsupport tags.
                UDPGet(&j);                     // Get option len
                while( j-- )                    // Ignore option values
                    UDPGet(&v);
            }
            FAST_USER_PROCESS();
        } while( !lbDone );
    }

    // If this is an OFFER message, remember current server id.
    if ( type == DHCP_OFFER_MESSAGE )
    {
        DHCPServerID.Val = tempServerID.Val;
        DHCPState.bits.bOfferReceived = TRUE;
    }
    else
    {
        // For other types of messages, make sure that received
        // server id matches with our previous one.
        if ( DHCPServerID.Val != tempServerID.Val )
            type = DHCP_UNKNOWN_MESSAGE;
    }

    UDPDiscard();                             // We are done with this packet
    return type;

UDPInvalid:
    UDPDiscard();
    return DHCP_UNKNOWN_MESSAGE;

}
Ejemplo n.º 13
0
/*****************************************************************************
  Function:
	void _DHCPReceive(void)

  Description:
	Receives and parses a DHCP message.

  Precondition:
	A DHCP message is waiting in the UDP buffer.

  Parameters:
	None

  Returns:
  	One of the DCHP_TYPE* contants.
  ***************************************************************************/
static BYTE _DHCPReceive(void)
{
	/*********************************************************************
	        DHCP PACKET FORMAT AS PER RFC 1541
	
	   0                   1                   2                   3
	   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |     op (1)    |   htype (1)   |   hlen (1)    |   hops (1)    |
	   +---------------+---------------+---------------+---------------+
	   |                            xid (4)                            |
	   +-------------------------------+-------------------------------+
	   |           secs (2)            |           flags (2)           |
	   +-------------------------------+-------------------------------+
	   |                          ciaddr  (4)                          |
	   +---------------------------------------------------------------+
	   |                          yiaddr  (4)                          |
	   +---------------------------------------------------------------+
	   |                          siaddr  (4)                          |
	   +---------------------------------------------------------------+
	   |                          giaddr  (4)                          |
	   +---------------------------------------------------------------+
	   |                                                               |
	   |                          chaddr  (16)                         |
	   |                                                               |
	   |                                                               |
	   +---------------------------------------------------------------+
	   |                                                               |
	   |                          sname   (64)                         |
	   +---------------------------------------------------------------+
	   |                                                               |
	   |                          file    (128)                        |
	   +---------------------------------------------------------------+
	   |                                                               |
	   |                          options (312)                        |
	   +---------------------------------------------------------------+
	
	 ********************************************************************/
    BYTE v;
    BYTE i, j;
    BYTE type;
    BOOL lbDone;
    DWORD_VAL tempServerID;


    // Assume unknown message until proven otherwise.
    type = DHCP_UNKNOWN_MESSAGE;

    UDPGet(&v);                             // op
    
    // Make sure this is BOOT_REPLY.
    if ( v == BOOT_REPLY )
    {
        // Discard htype, hlen, hops, xid, secs, flags, ciaddr.
        for ( i = 0; i < 15u; i++ )
            UDPGet(&v);

		// Check to see if this is the first offer
		if(DHCPFlags.bits.bOfferReceived)
		{
	        // Discard offered IP address, we already have an offer
	        for ( i = 0; i < 4u; i++ )
	            UDPGet(&v);
		}
		else
		{
	        // Save offered IP address until we know for sure that we have it.
			UDPGetArray((BYTE*)&tempIPAddress, sizeof(tempIPAddress));
			ValidValues.bits.IPAddress = 1;
		}

        // Ignore siaddr, giaddr
        for ( i = 0; i < 8u; i++ )
            UDPGet(&v);

        // Check to see if chaddr (Client Hardware Address) belongs to us.
        for ( i = 0; i < 6u; i++ )
        {
            UDPGet(&v);
            if ( v != AppConfig.MyMACAddr.v[i])
                goto UDPInvalid;
        }


        // Ignore part of chaddr, sname, file, magic cookie.
        for ( i = 0; i < 206u; i++ )
            UDPGet(&v);

        lbDone = FALSE;
        do
        {
			// Get the Option number
			// Break out eventually in case if this is a malformed 
			// DHCP message, ie: missing DHCP_END_OPTION marker
			if(!UDPGet(&v))
			{
				lbDone = TRUE;
				break;
			}

            switch(v)
            {
            case DHCP_MESSAGE_TYPE:
                UDPGet(&v);                         // Skip len
                // Len must be 1.
                if ( v == 1u )
                {
                    UDPGet(&type);                  // Get type

					// Throw away the packet if we know we don't need it (ie: another offer when we already have one)
					if(DHCPFlags.bits.bOfferReceived && (type == DHCP_OFFER_MESSAGE))
					{
						goto UDPInvalid;
					}
                }
                else
                    goto UDPInvalid;
                break;

            case DHCP_SUBNET_MASK:
                UDPGet(&v);                     // Skip len
                // Len must be 4.
                if ( v == 4u )
                {
					// Check to see if this is the first offer
					if(DHCPFlags.bits.bOfferReceived)
					{
				        // Discard offered IP mask, we already have an offer
				        for ( i = 0; i < 4u; i++ )
				            UDPGet(&v);
					}
					else
					{
						UDPGetArray((BYTE*)&tempMask, sizeof(tempMask));
						ValidValues.bits.Mask = 1;
					}
                }
                else
                    goto UDPInvalid;
                break;

            case DHCP_ROUTER:
                UDPGet(&j);
                // Len must be >= 4.
                if ( j >= 4u )
                {
					// Check to see if this is the first offer
					if(DHCPFlags.bits.bOfferReceived)
					{
				        // Discard offered Gateway address, we already have an offer
				        for ( i = 0; i < 4u; i++ )
				            UDPGet(&v);
					}
					else
					{
						UDPGetArray((BYTE*)&tempGateway, sizeof(tempGateway));
						ValidValues.bits.Gateway = 1;
					}
                }
                else
                    goto UDPInvalid;

                // Discard any other router addresses.
                j -= 4;
                while(j--)
                    UDPGet(&v);
                break;

#if defined(STACK_USE_DNS)
            case DHCP_DNS:
                UDPGet(&j);
                // Len must be >= 4.
                if(j < 4u)
                    goto UDPInvalid;

				// Check to see if this is the first offer
				if(!DHCPFlags.bits.bOfferReceived)
				{
					UDPGetArray((BYTE*)&tempDNS, sizeof(tempDNS));
					ValidValues.bits.DNS = 1;
					j -= 4;
				}

				// Len must be >= 4 for a secondary DNS server address
				if(j >= 4u)
				{
					// Check to see if this is the first offer
					if(!DHCPFlags.bits.bOfferReceived)
					{
						UDPGetArray((BYTE*)&tempDNS2, sizeof(tempDNS2));
						ValidValues.bits.DNS2 = 1;
						j -= 4;
					}
				}

                // Discard any other DNS server addresses
                while(j--)
                    UDPGet(&v);
                break;
#endif

//            case DHCP_HOST_NAME:
//                UDPGet(&j);
//                // Len must be >= 4.
//                if(j < 1u)
//					goto UDPInvalid;
//
//				// Check to see if this is the first offer
//				if(DHCPFlags.bits.bOfferReceived)
//				{
//			        // Discard offered host name, we already have an offer
//	                while(j--)
//	                    UDPGet(&v);
//				}
//				else
//				{
//					for(i = 0; j, i < sizeof(tempHostName); i++, j--)
//					{
//						UDPGet(&tempHostName[i]);
//					}
//					while(j--)
//					{
//						UDPGet(&v);
//					}
//					ValidValues.bits.HostName = 1;
//				}
//
//                break;

            case DHCP_SERVER_IDENTIFIER:
                UDPGet(&v);                         // Get len
                // Len must be 4.
                if ( v == 4u )
                {
                    UDPGet(&tempServerID.v[3]);   // Get the id
                    UDPGet(&tempServerID.v[2]);
                    UDPGet(&tempServerID.v[1]);
                    UDPGet(&tempServerID.v[0]);
                }
                else
                    goto UDPInvalid;
                break;

            case DHCP_END_OPTION:
                lbDone = TRUE;
                break;

            case DHCP_IP_LEASE_TIME:
                UDPGet(&v);                         // Get len
                // Len must be 4.
                if ( v == 4u )
                {
					// Check to see if this is the first offer
					if(DHCPFlags.bits.bOfferReceived)
					{
				        // Discard offered lease time, we already have an offer
				        for ( i = 0; i < 4u; i++ )
				            UDPGet(&v);
					}
					else
					{
	                    UDPGet(&DHCPLeaseTime.v[3]);
	                    UDPGet(&DHCPLeaseTime.v[2]);
	                    UDPGet(&DHCPLeaseTime.v[1]);
	                    UDPGet(&DHCPLeaseTime.v[0]);

	                    // In case if our clock is not as accurate as the remote 
						// DHCP server's clock, let's treat the lease time as only 
						// 96.875% of the value given
						DHCPLeaseTime.Val -= DHCPLeaseTime.Val>>5;
					}
                }
                else
                    goto UDPInvalid;
                break;

            default:
                // Ignore all unsupport tags.
                UDPGet(&j);                     // Get option len
                while( j-- )                    // Ignore option values
                    UDPGet(&v);
            }
            FAST_USER_PROCESS();
        } while( !lbDone );
    }