Top secrets sources NedoPC zxusbnet

Rev

Blame | Last modification | View Log | Download | RSS feed | ?url?

#include <stdio.h>
#include <string.h>
#include "socket.h"
#include "w5300.h"

#define SWAP16(A)               ((((A << 8 ) & 0xFF00)) | ((A >> 8)& 0x00FF))

uint16   iinchip_source_port;
uint8    check_sendok_flag[MAX_SOCK_NUM];

uint8 socket(SOCKET s, uint8 protocol, uint16 port, uint16 flag)
{
        IINCHIP_WRITE(Sn_MR0(s), (uint8)((protocol | flag) >> 8));
        IINCHIP_WRITE(Sn_MR1(s), (uint8)((protocol | flag) & 0xff));
        if (port != 0)
        {
                IINCHIP_WRITE(Sn_PORTR0(s),(uint8)((port & 0xff00) >> 8));
                IINCHIP_WRITE(Sn_PORTR1(s),(uint8)(port & 0x00ff));
        }
        else
        {
                iinchip_source_port++;     // if don't set the source port, set local_port number.
                IINCHIP_WRITE(Sn_PORTR0(s),(uint8)((iinchip_source_port & 0xff00) >> 8));
                IINCHIP_WRITE((Sn_PORTR1(s)),(uint8)(iinchip_source_port & 0x00ff));
        }
        setSn_CR(s, Sn_CR_OPEN);      // open s-th SOCKET

        check_sendok_flag[s] = 1;     // initialize the sendok flag.

        #ifdef __DEF_IINCHIP_DBG__
                printf("%d : Sn_MR=0x%04x,Sn_PORTR=0x%04x(%04d),Sn_SSR=%04x\r\n",s,IINCHIP_READ(Sn_MR(s)),(uint16)((IINCHIP_READ(Sn_PORTR0(s)) << 8) + IINCHIP_READ(Sn_PORTR1(s))),(uint16)((IINCHIP_READ(Sn_PORTR0(s)) << 8) + IINCHIP_READ(Sn_PORTR1(s))),getSn_SSR(s));
        #endif
        return 1;  
}

void     close(SOCKET s)
{
        // M_08082008 : It is fixed the problem that Sn_SSR cannot be changed a undefined value to the defined value.
        //              Refer to Errata of W5300
        //Check if the transmit data is remained or not.
        if( ((getSn_MR(s)& 0x0F) == Sn_MR_TCP) && (getSn_TX_FSR(s) != getIINCHIP_TxMAX(s)) )
        {
                uint16 loop_cnt =0;
                while(getSn_TX_FSR(s) != getIINCHIP_TxMAX(s))
                {
                        if(loop_cnt++ > 10)
                        {
                                uint8 destip[4];
                                // M_11252008 : modify dest ip address
                                //getSIPR(destip);
                                destip[0] = 0;destip[1] = 0;destip[2] = 0;destip[3] = 1;
                                socket(s,Sn_MR_UDP,0x3000,0);
                                sendto(s,(uint8*)"x",1,destip,0x3000); // send the dummy data to an unknown destination(0.0.0.1).
                                break; // M_11252008 : added break statement
                        }
                wait_10ms(10);
                }
        };
        setSn_IR(s ,0x00FF);          // Clear the remained interrupt bits.
        setSn_CR(s ,Sn_CR_CLOSE);     // Close s-th SOCKET    
}


uint8    connect(SOCKET s, uint8 * addr, uint16 port)
{
        if
        (
                ((addr[0] == 0xFF) && (addr[1] == 0xFF) && (addr[2] == 0xFF) && (addr[3] == 0xFF)) ||
                ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) ||
                (port == 0x00)
        )
        {
                #ifdef __DEF_IINCHIP_DBG__
                        printf("%d : Fail[invalid ip,port]\r\n",s);
                #endif
                return 0;
        }

        // set destination IP
        IINCHIP_WRITE(Sn_DIPR0(s),addr[0]);
        IINCHIP_WRITE(Sn_DIPR1(s),addr[1]);
        IINCHIP_WRITE(Sn_DIPR2(s),addr[2]);
        IINCHIP_WRITE(Sn_DIPR3(s),addr[3]);
        // set destination port number
        IINCHIP_WRITE(Sn_DPORTR0(s),(((uint8)(port >> 8))));
        IINCHIP_WRITE(Sn_DPORTR1(s),(((uint8)port & 0xff)));
        // Connect
        ApplySubnet();
        setSn_CR(s,Sn_CR_CONNECT);
       
       
        while( IINCHIP_READ(Sn_SSR(s)) != SOCK_SYNSENT )
        {
                if(IINCHIP_READ(Sn_SSR(s)) == SOCK_ESTABLISHED)
                {
                        break;
                }
                if(getSn_IR(s) & Sn_IR_TIMEOUT)
                {
                        setSn_IR(s,(Sn_IR_TIMEOUT));
                        break;
                }
        }
       
               
        ClearSubnet();

        return 1;  
}

void     disconnect(SOCKET s)
{
        setSn_CR(s,Sn_CR_DISCON);     // Disconnect
}

uint8    listen(SOCKET s)
{
        if (getSn_SSR(s) != SOCK_INIT)
        {
                #ifdef __DEF_IINCHIP_DBG__
                        printf("%d : SOCKET is not created!\r\n",s);
                #endif
                return 0;
        }
        setSn_CR(s,Sn_CR_LISTEN);     // listen

        return 1;
}  
 
uint32   send(SOCKET s, uint8 * buf, uint32 len)
{
        uint8 status=0;
        uint32 ret=0;
        uint32 freesize=0;
        #ifdef __DEF_IINCHIP_DBG__
                uint32 loopcnt = 0;

                printf("%d : send()\r\n",s);
        #endif

        ret = len;
        if (len > getIINCHIP_TxMAX(s)) ret = getIINCHIP_TxMAX(s); // check size not to exceed MAX size.

   

        /*
        * \note if you want to use non blocking function, <b>"do{}while(freesize < ret)"</b> code block
        * can be replaced with the below code. \n
        * \code
        *       while((freesize = getSn_TX_FSR(s))==0);
        *       ret = freesize;
        * \endcode
        */

        // -----------------------
        // NOTE : CODE BLOCK START
        do                                  
        {
                freesize = getSn_TX_FSR(s);
                status = getSn_SSR(s);
                #ifdef __DEF_IINCHIP_DBG__
                        printf("%d : freesize=%ld\r\n",s,freesize);
                if(loopcnt++ > 0x0010000)
                {
                        printf("%d : freesize=%ld,status=%04x\r\n",s,freesize,status);
                        printf("%d:Send Size=%08lx(%d)\r\n",s,ret,ret);
                        printf("MR=%04x\r\n",*((vuint16*)MR));
                        loopcnt = 0;
                }
                #endif
                if ((status != SOCK_ESTABLISHED) && (status != SOCK_CLOSE_WAIT)) return 0;
        } while (freesize < ret);
        // NOTE : CODE BLOCK END
        // ---------------------
   
        if(ret & 0x01) wiz_write_buf(s, buf, (ret+1));
        else wiz_write_buf(s,buf,ret);                   // copy data

        #ifdef __DEF_IINCHIP_DBG__
                loopcnt=0;
        #endif  

        if(!check_sendok_flag[s])                 // if first send, skip.
        {
                while (!(getSn_IR(s) & Sn_IR_SENDOK))  // wait previous SEND command completion.
                {
                #ifdef __DEF_IINCHIP_DBG__

                if(loopcnt++ > 0x010000)
                {
                        printf("%d:Sn_SSR(%02x)\r\n",s,status);
                        printf("%d:Send Size=%08lx(%d)\r\n",s,ret,ret);
                        printf("MR=%02x%02x\r\n",*((vuint8*)MR0),*((vuint8*)MR1));
                        loopcnt = 0;
                }
                #endif
                if (getSn_SSR(s) == SOCK_CLOSED)    // check timeout or abnormal closed.
                {
                        #ifdef __DEF_IINCHIP_DBG__
                                printf("%d : Send Fail. SOCK_CLOSED.\r\n",s);
                        #endif
                       
                        return 0;
                }
                }
                setSn_IR(s, Sn_IR_SENDOK);             // clear Sn_IR_SENDOK      
        }
        else check_sendok_flag[s] = 0;

        // send
        setSn_TX_WRSR(s,ret);  
        setSn_CR(s,Sn_CR_SEND);
   
        return ret;
}

uint32   recv(SOCKET s, uint8 * buf, uint32 len)
{
        uint16 pack_size=0;
        vint16 mr = getMR();

        #ifdef __DEF_IINCHIP_DBG__
                printf("%d : recv()\r\n",s);
        #endif

        if(IINCHIP_READ(Sn_MR0(s)) & Sn_MR_ALIGN)
        {
                wiz_read_buf(s, buf, len);
                setSn_CR(s,Sn_CR_RECV);
                return len;
        }

        wiz_read_buf(s,(uint8*)&pack_size,2);        // extract the PACKET-INFO(DATA packet length)
 
        #ifdef LITTLE_ENDIAN
                if(mr & MR_FS) pack_size = pack_size;
                else pack_size = SWAP16(pack_size);
        #else
                if(mr & MR_FS) pack_size = SWAP16(pack_size);
                else pack_size = pack_size;
        #endif

        #ifdef __DEF_IINCHIP_DBG__  
                printf("%d:pack_size=%d\r\n",s,pack_size);
        #endif

        len = pack_size;
        if(pack_size & 0x01) len += 1;

        wiz_read_buf(s, buf, len);     // copy data  

        setSn_CR(s,Sn_CR_RECV);                      // recv

   /*
   * \warning  send a packet for updating window size. This code block must be only used when W5300 do only receiving data.
   */

   // ------------------------
   // WARNING CODE BLOCK START
   
   // M_15052008 : Replace Sn_CR_SEND with Sn_CR_SEND_KEEP.
   //if(!(getSn_IR(s) & Sn_IR_SENDOK))
   //{
   //   setSn_TX_WRSR(s,0);                    // size = 0
   //   setSn_CR(s,Sn_CR_SEND);                // send
   //   while(!(getSn_IR(s) & Sn_IR_SENDOK));  // wait SEND command completion
   //   setSn_IR(s,Sn_IR_SENDOK);              // clear Sn_IR_SENDOK bit
   //}
   
   // M_04072008 : Replace Sn_CR_SEND_KEEP with Sn_CR_SEND.
   //if(getSn_RX_RSR(s) == 0)                     // send the window-update packet when the window size is full
   //{
   //   uint8 keep_time = 0;
   //   if((keep_time=getSn_KPALVTR(s)) != 0x00) setSn_KPALVTR(s,0x00); // disables the auto-keep-alive-process
   //   setSn_CR(s,Sn_CR_SEND_KEEP);              // send a keep-alive packet by command
   //   setSn_KPALVTR(s,keep_time);               // restore the previous keep-alive-timer value
   //}


//   if(getSn_RX_RSR(s) == 0)                     // check if the window size is full or not
//   { /* Sn_RX_RSR can be compared with another value instead of ??0??,
//      according to the host performance of receiving data */
//      setSn_TX_WRSR(s,1);                       // size : 1 byte dummy size
//      IINCHIP_WRITE(Sn_TX_FIFOR0(s),0x00);     // write dummy data into tx memory
//      IINCHIP_WRITE(Sn_TX_FIFOR1(s),0x00);
//      setSn_CR(s,Sn_CR_SEND);                   // send                        
//      while(!(getSn_IR(s) & Sn_IR_SENDOK));     // wait SEND command completion
//      setSn_IR(s,Sn_IR_SENDOK);                 // clear Sn_IR_SENDOK bit      
//   }                                                                        


   // WARNING CODE BLOCK END
   // ----------------------
   
   return (uint32)pack_size;
}

uint32   sendto(SOCKET s, uint8 * buf, uint32 len, uint8 * addr, uint16 port)
{
        uint8 status=0;
        uint8 isr=0;
        uint32 ret=0;

        #ifdef __DEF_IINCHIP_DBG__
                printf("%d : sendto():%d.%d.%d.%d(%d), len=%d\r\n",s, addr[0], addr[1], addr[2], addr[3] , port, len);
        #endif

        if
        (
          ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) ||
          ((port == 0x00)) ||(len == 0)
        )
        {
                #ifdef __DEF_IINCHIP_DBG__
                         printf("%d : Fail[%d.%d.%d.%d, %.d, %d]\r\n",s, addr[0], addr[1], addr[2], addr[3] , port, len);
                #endif
                return 0;
        }
   
   
        if (len > getIINCHIP_TxMAX(s)) ret = getIINCHIP_TxMAX(s); // check size not to exceed MAX size.
        else ret = len;

        // set destination IP address
        IINCHIP_WRITE(Sn_DIPR0(s),addr[0]);
        IINCHIP_WRITE(Sn_DIPR1(s),addr[1]);
        IINCHIP_WRITE(Sn_DIPR2(s),addr[2]);
        IINCHIP_WRITE(Sn_DIPR3(s),addr[3]);
        // set destination port number
        IINCHIP_WRITE(Sn_DPORTR0(s),((uint8)(port >> 8)));
        IINCHIP_WRITE(Sn_DPORTR1(s),((uint8)(port & 0xff)));

        wiz_write_buf(s, buf, ret+(ret & 0x01));                               // copy data
        // send
        setSn_TX_WRSR(s,ret);
        ApplySubnet();
        setSn_CR(s, Sn_CR_SEND);

        while (!((isr = getSn_IR(s)) & Sn_IR_SENDOK))            // wait SEND command completion
        {
                status = getSn_SSR(s);                                // warning ---------------------------------------
                if ((status == SOCK_CLOSED) || (isr & Sn_IR_TIMEOUT)) // Sn_IR_TIMEOUT causes the decrement of Sn_TX_FSR
                {                                                     // -----------------------------------------------
                        #ifdef __DEF_IINCHIP_DBG__
                                printf("%d: send fail.status=0x%02x,isr=%02x\r\n",s,status,isr);
                        #endif
                        setSn_IR(s,Sn_IR_TIMEOUT);
                        return 0;
                }
        }

        setSn_IR(s, Sn_IR_SENDOK); // Clear Sn_IR_SENDOK
        ClearSubnet();
   
        #ifdef __DEF_IINCHIP_DBG__          
                printf("%d : send()end\r\n",s);
        #endif      

        return ret;  
}

uint32   recvfrom(SOCKET s, uint8 * buf, uint32 len, uint8 * addr, uint16  *port)
{
        uint8 head[8];
        uint16 data_len=0;
        uint16 crc[2];
        vint16 mr = getMR();

        #ifdef __DEF_IINCHIP_DBG__
                printf("recvfrom()\r\n");
        #endif

        if ( len > 0 )
        {

                switch (IINCHIP_READ(Sn_MR1(s)) & 0x07)                 // check the mode of s-th SOCKET
                {                                                       // -----------------------------
                case Sn_MR_UDP :                                        // UDP mode

                        wiz_read_buf(s, head, 8);                       // extract the PACKET-INFO
                        // read peer's IP address, port number.

                        if(mr & MR_FS)
                        {
                                addr[0] = head[1];                      // destination IP address
                                addr[1] = head[0];
                                addr[2] = head[3];
                                addr[3] = head[2];
                        }
                        else
                        {
                                addr[0] = head[0];
                                addr[1] = head[1];
                                addr[2] = head[2];
                                addr[3] = head[3];
                        }
                        #ifdef LITTLE_ENDIAN
                                if(mr & MR_FS)
                                {
                                        *port = head[5];                                // destination port number
                                        *port = (*port << 8) + head[4];
                                        data_len = (uint16)head[7];                     // DATA packet length
                                        data_len = (data_len << 8) + head[6];
                                }
                                else
                                {
                                        *port = head[4];                                // destination port number
                                        *port = (*port << 8) + head[5];
                                        data_len = (uint16)head[6];                     // DATA packet length
                                        data_len = (data_len << 8) + head[7];
                                }
                        #else
                                if(mr & MR_FS)
                                {
                                        *port = head[4];
                                        *port = (*port << 8) + head[5];
                                        data_len = (uint16)head[6];                     // DATA packet length
                                        data_len = (data_len << 8) + head[7];
                                }
                                else
                                {
                                        *port = head[5];
                                        *port = (*port << 8) + head[4];
                                        data_len = (uint16)head[7];                     // DATA packet length
                                        data_len = (data_len << 8) + head[6];
                                }
                        #endif

                        #ifdef __DEF_IINCHIP_DBG__
                                printf("UDP msg arrived:%d(0x%04x)\r\n",data_len,data_len);
                                printf("source Port : %d\r\n", *port);
                                printf("source IP : %d.%d.%d.%d\r\n", addr[0], addr[1], addr[2], addr[3]);
                        #endif

                        wiz_read_buf(s, buf, data_len + (data_len & 0x01) );        // data copy.
                        break;

                                                                                        // -----------------------
                case Sn_MR_IPRAW :                                                      // IPRAW mode
                        wiz_read_buf(s, (uint8*)head, 6);                               // extract the PACKET-INFO
                        if((*(vint8*)MR0) & MR_FS)
                        {
                                addr[0] = head[1];                                      // destination IP address
                                addr[1] = head[0];
                                addr[2] = head[3];
                                addr[3] = head[2];
                        }
                        else
                        {
                                addr[0] = head[0];                                      // destination IP address
                                addr[1] = head[1];
                                addr[2] = head[2];
                                addr[3] = head[3];
                        }

                        #ifdef LITTLE_ENDIAN
                                if((*(vint8*)MR0) & MR_FS)
                                {
                                        data_len = (uint16)head[5];                      // DATA packet length
                                        data_len = (data_len << 8) + head[4];
                                }
                                else
                                {
                                        data_len = (uint16)head[4];                     // DATA packet length
                                        data_len = (data_len << 8) + head[5];
                                }
                        #else
                                if((*(vint8*)MR0) & MR_FS)
                                {
                                        data_len = (uint16)head[4];
                                        data_len = (data_len << 8) + head[5];
                                }
                                else
                                {
                                        data_len = (uint16)head[5];
                                        data_len = (data_len << 8) + head[4];
                                }
                        #endif

                        #ifndef __DEF_IINCHIP_DBG__
                                printf("IP RAW msg arrived\r\n");
                                printf("source IP : %d.%d.%d.%d\r\n", addr[0], addr[1], addr[2], addr[3]);
                        #endif

                        wiz_read_buf(s, buf, data_len+(data_len & 0x01));               // data copy.
                        break;                                
               
                                                                                        // -----------------------
                case Sn_MR_MACRAW :                                                     // MACRAW mode
                        wiz_read_buf(s,(uint8*)head,2);                                 // extract the PACKET-INFO
                        #ifdef LITTLE_ENDIAN
                                if((*(vint8*)MR0) & MR_FS)
                                {
                                        data_len = (uint16)head[1];                     // DATA packet length
                                        data_len = (data_len << 8) + head[0];
                                }
                                else
                                {
                                        data_len = (uint16)head[0];
                                        data_len = (data_len << 8) + head[1];
                                }
                        #else
                                if((*(vint8*)MR0) & MR_FS)
                                {
                                        data_len = (uint16)head[0];
                                        data_len = (data_len << 8) + head[1];
                                }
                                else
                                {
                                        data_len = (uint16)head[1];
                                        data_len = (data_len << 8) + head[0];
                                }
                        #endif

                        wiz_read_buf(s, buf, data_len + (data_len & 0x01));        // data copy.
                        wiz_read_buf(s,(uint8*)crc, 4);        // extract CRC data and ignore it.

                        break;
                default :
                        break;
                }
                setSn_CR(s,Sn_CR_RECV);                      // recv
        }
        #ifdef __DEF_IINCHIP_DBG__
                printf("recvfrom() end ..\r\n");
        #endif
   
        return data_len;  
}