Wiznet W5500 driver and TCP/UDP loopback

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers socket.c Source File

socket.c

00001 /* Wiznet W5500 Library
00002  * Copyright (c) 2013, WIZnet Co., LTD.
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include "socket.h"
00018 
00019 #define SOCK_ANY_PORT_NUM  0xC000;
00020 
00021 static uint16_t sock_any_port = SOCK_ANY_PORT_NUM;
00022 static uint16_t sock_io_mode = 0;
00023 static uint16_t sock_is_sending = 0;
00024 static uint16_t sock_remained_size[_WIZCHIP_SOCK_NUM_] = {0,0,};
00025 
00026 #define CHECK_SOCKNUM()   \
00027    do{                    \
00028       if(sn > _WIZCHIP_SOCK_NUM_) return SOCKERR_SOCKNUM;   \
00029    }while(0);             \
00030 
00031 #define CHECK_SOCKMODE(mode)  \
00032    do{                     \
00033       if((getSn_MR(sn) & 0x0F) != mode) return SOCKERR_SOCKMODE;  \
00034    }while(0);              \
00035 
00036 #define CHECK_SOCKINIT()   \
00037    do{                     \
00038       if((getSn_SR(sn) != SOCK_INIT)) return SOCKERR_SOCKINIT; \
00039    }while(0);              \
00040 
00041 #define CHECK_SOCKDATA()   \
00042    do{                     \
00043       if(len == 0) return SOCKERR_DATALEN;   \
00044    }while(0);              \
00045 
00046 
00047 
00048 int8_t socket(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag)
00049 {
00050     CHECK_SOCKNUM();
00051     switch(protocol)
00052     {
00053       case Sn_MR_TCP :
00054       case Sn_MR_UDP :
00055       case Sn_MR_MACRAW :
00056          break;
00057       default :
00058          return SOCKERR_SOCKMODE;
00059     }
00060     if((flag & 0x06) != 0) return SOCKERR_SOCKFLAG;
00061        
00062     if(flag != 0)
00063     {
00064     switch(protocol)
00065     {
00066        case Sn_MR_TCP:
00067           if((flag & (SF_TCP_NODELAY|SF_IO_NONBLOCK))==0) return SOCKERR_SOCKFLAG;
00068           break;
00069        case Sn_MR_UDP:
00070           if(flag & SF_IGMP_VER2)
00071           {
00072              if((flag & SF_MULTI_ENABLE)==0) return SOCKERR_SOCKFLAG;
00073           }
00074               if(flag & SF_UNI_BLOCK)
00075               {
00076                  if((flag & SF_MULTI_ENABLE) == 0) return SOCKERR_SOCKFLAG;
00077               }
00078           break;
00079        default:
00080           break;
00081     }
00082    }
00083     close(sn);
00084     setSn_MR(sn, (protocol | (flag & 0xF0)));
00085     if(!port)
00086     {
00087        port = sock_any_port++;
00088        if(sock_any_port == 0xFFF0) sock_any_port = SOCK_ANY_PORT_NUM;
00089     }
00090    setSn_PORT(sn,port); 
00091    setSn_CR(sn,Sn_CR_OPEN);
00092    while(getSn_CR(sn));
00093     sock_io_mode |= ((flag & SF_IO_NONBLOCK) << sn);   
00094    sock_is_sending &= ~(1<<sn);
00095    sock_remained_size[sn] = 0;
00096    while(getSn_SR(sn) == SOCK_CLOSED);
00097    return (int8_t)sn;
00098 }      
00099 
00100 int8_t close(uint8_t sn)
00101 {
00102     CHECK_SOCKNUM();
00103     
00104     setSn_CR(sn,Sn_CR_CLOSE);
00105    /* wait to process the command... */
00106     while( getSn_CR(sn) );
00107     /* clear all interrupt of the socket. */
00108     setSn_IR(sn, 0xFF);
00109     sock_is_sending &= ~(1<<sn);
00110     sock_remained_size[sn] = 0;
00111     while(getSn_SR(sn) != SOCK_CLOSED);
00112     return SOCK_OK;
00113 }
00114 
00115 int8_t listen(uint8_t sn)
00116 {
00117     CHECK_SOCKNUM();
00118    CHECK_SOCKMODE(Sn_MR_TCP);
00119     CHECK_SOCKINIT();
00120     setSn_CR(sn,Sn_CR_LISTEN);
00121     while(getSn_CR(sn));
00122    while(getSn_SR(sn) != SOCK_LISTEN)
00123    {
00124       if(getSn_CR(sn) == SOCK_CLOSED)
00125       {
00126          close(sn);
00127          return SOCKERR_SOCKCLOSED;
00128       }
00129    }
00130    return SOCK_OK;
00131 }
00132 
00133 
00134 int8_t connect(uint8_t sn, uint8_t * addr, uint16_t port)
00135 {
00136    CHECK_SOCKNUM();
00137    CHECK_SOCKMODE(Sn_MR_TCP);
00138    CHECK_SOCKINIT();
00139     if( *((uint32_t*)addr) == 0xFFFFFFFF || *((uint32_t*)addr) == 0) return SOCKERR_IPINVALID;
00140     if(port == 0) return SOCKERR_PORTZERO;
00141     setSn_DIPR(sn,addr);
00142     setSn_DPORT(sn,port);
00143 //  setSUBR();   // set the subnet mask register
00144     setSn_CR(sn,Sn_CR_CONNECT);
00145    while(getSn_CR(sn));
00146    if(sock_io_mode & (1<<sn)) return SOCK_BUSY;
00147    while(getSn_SR(sn) != SOCK_ESTABLISHED)
00148    {   
00149         if (getSn_IR(sn) & Sn_IR_TIMEOUT)
00150         {
00151             setSn_IR(sn, Sn_IR_TIMEOUT);
00152          return SOCKERR_TIMEOUT;
00153         }
00154     }
00155 //  clearSUBR();   // clear the subnet mask again and keep it because of the ARP errata of W5100
00156    return SOCK_OK;
00157 }
00158 
00159 int8_t disconnect(uint8_t sn)
00160 {
00161    CHECK_SOCKNUM();
00162    CHECK_SOCKMODE(Sn_MR_TCP);
00163     setSn_CR(sn,Sn_CR_DISCON);
00164     /* wait to process the command... */
00165     while(getSn_CR(sn));
00166     sock_is_sending &= ~(1<<sn);
00167    if(sock_io_mode & (1<<sn)) return SOCK_BUSY;
00168     while(getSn_SR(sn) != SOCK_CLOSED)
00169     {
00170        if(getSn_IR(sn) & Sn_IR_TIMEOUT)
00171        {
00172           close(sn);
00173           return SOCKERR_TIMEOUT;
00174        }
00175     }
00176     return SOCK_OK;
00177 }
00178 
00179 int32_t send(uint8_t sn, uint8_t * buf, uint16_t len)
00180 {
00181    uint8_t tmp=0;
00182    uint16_t freesize=0;
00183    
00184    CHECK_SOCKNUM();
00185    CHECK_SOCKMODE(Sn_MR_TCP);
00186    CHECK_SOCKDATA();
00187    tmp = getSn_SR(sn);
00188    if(tmp != SOCK_ESTABLISHED && tmp != SOCK_CLOSE_WAIT) return SOCKERR_SOCKSTATUS;
00189    if( sock_is_sending & (1<<sn) )
00190    {
00191       tmp = getSn_IR(sn);
00192       if(tmp & Sn_IR_SENDOK)
00193       {
00194          setSn_IR(sn, Sn_IR_SENDOK);
00195          sock_is_sending &= ~(1<<sn);         
00196       }
00197       else if(tmp & Sn_IR_TIMEOUT)
00198       {
00199          close(sn);
00200          return SOCKERR_TIMEOUT;
00201       }
00202       else return SOCK_BUSY;
00203    }
00204    freesize = getSn_TxMAX(sn);
00205    if (len > freesize) len = freesize; // check size not to exceed MAX size.
00206    while(1)
00207    {
00208       freesize = getSn_TX_FSR(sn);
00209       tmp = getSn_SR(sn);
00210       if ((tmp != SOCK_ESTABLISHED) && (tmp != SOCK_CLOSE_WAIT))
00211       {
00212          close(sn);
00213          return SOCKERR_SOCKSTATUS;
00214       }
00215       if( (sock_io_mode & (1<<sn)) && (len > freesize) ) return SOCK_BUSY;
00216       if(len <= freesize) break;
00217    }
00218    wiz_send_data(sn, buf, len);
00219    setSn_CR(sn,Sn_CR_SEND);
00220    /* wait to process the command... */
00221    while(getSn_CR(sn));
00222    sock_is_sending |= (1 << sn);
00223    /*
00224    if(sock_io_mode & (1<<sn)) return len;
00225    while( ((tmp = getSn_IR(sn)) & Sn_IR_SENDOK) !=Sn_IR_SENDOK )
00226    {
00227       if(tmp & Sn_IR_TIMEOUT)
00228       {
00229          close(sn);
00230          return SOCKERR_TIMEOUT;
00231       }
00232    }
00233    setSn_IR(sn, Sn_IR_SENDOK);
00234    */
00235    return len;
00236 }
00237 
00238 
00239 int32_t recv(uint8_t sn, uint8_t * buf, uint16_t len)
00240 {
00241    uint8_t  tmp = 0;
00242    uint16_t recvsize = 0;
00243    CHECK_SOCKNUM();
00244    CHECK_SOCKMODE(Sn_MR_TCP);
00245    CHECK_SOCKDATA();
00246    
00247    recvsize = getSn_RxMAX(sn);
00248    if(recvsize < len) len = recvsize;
00249    while(1)
00250    {
00251       recvsize = getSn_RX_RSR(sn);
00252       tmp = getSn_SR(sn);
00253       if (tmp != SOCK_ESTABLISHED)
00254       {
00255          if(tmp == SOCK_CLOSE_WAIT)
00256          {
00257             if(recvsize != 0) break;
00258             else if(getSn_TX_FSR(sn) == getSn_TxMAX(sn))
00259             {
00260                close(sn);
00261                return SOCKERR_SOCKSTATUS;
00262             }
00263          }
00264          else
00265          {
00266             close(sn);
00267             return SOCKERR_SOCKSTATUS;
00268          }
00269       }
00270       if((sock_io_mode & (1<<sn)) && (recvsize == 0)) return SOCK_BUSY;
00271       if(recvsize != 0) break;
00272    };
00273    if(recvsize < len) len = recvsize;
00274    wiz_recv_data(sn, buf, len);
00275    setSn_CR(sn,Sn_CR_RECV);
00276    while(getSn_CR(sn));
00277    return len;
00278 }
00279 
00280 int32_t sendto(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port)
00281 {
00282    uint8_t tmp = 0;
00283    uint16_t freesize = 0;
00284    CHECK_SOCKNUM();
00285    //CHECK_SOCKMODE(Sn_MR_UDP);
00286    switch(getSn_MR(sn) & 0x0F)
00287    {
00288       case Sn_MR_UDP:
00289       case Sn_MR_MACRAW:
00290          break;
00291       default:
00292          return SOCKERR_SOCKMODE;
00293    }
00294    CHECK_SOCKDATA();
00295    if(*((uint32_t*)addr) == 0) return SOCKERR_IPINVALID;
00296    if(port == 0)               return SOCKERR_PORTZERO;
00297    tmp = getSn_SR(sn);
00298    if(tmp != SOCK_MACRAW && tmp != SOCK_UDP) return SOCKERR_SOCKSTATUS;
00299 
00300    if( sock_is_sending & (1<<sn) )
00301    {
00302       tmp = getSn_IR(sn);
00303       if(tmp & Sn_IR_SENDOK)
00304       {
00305          setSn_IR(sn, Sn_IR_SENDOK);
00306          sock_is_sending &= ~(1<<sn);
00307       }
00308       else if(tmp & Sn_IR_TIMEOUT)
00309       {
00310          close(sn);
00311          return SOCKERR_TIMEOUT;
00312       }
00313       else return SOCK_BUSY;
00314    }
00315       
00316    setSn_DIPR(sn,addr);
00317    setSn_DPORT(sn,port);      
00318    freesize = getSn_TxMAX(sn);
00319    if (len > freesize) len = freesize; // check size not to exceed MAX size.
00320    while(1)
00321    {
00322       freesize = getSn_TX_FSR(sn);
00323       if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED;
00324       if( (sock_io_mode & (1<<sn)) && (len > freesize) ) return SOCK_BUSY;
00325       if(len <= freesize) break;
00326    };
00327     wiz_send_data(sn, buf, len);
00328 // setSUBR();    // set the subnet mask register
00329     setSn_CR(sn,Sn_CR_SEND);
00330     /* wait to process the command... */
00331     while(getSn_CR(sn));
00332     sock_is_sending |= (1<<sn);
00333     #if 0
00334     if(sock_io_mode & (1<<sn)) return len;
00335    while ( ((tmp = getSn_IR(sn)) & Sn_IR_SENDOK) != Sn_IR_SENDOK ) 
00336    {
00337       if(tmp & Sn_IR_TIMEOUT)
00338     {
00339          setSn_IR(sn, (Sn_IR_SENDOK | Sn_IR_TIMEOUT)); /* clear SEND_OK & TIMEOUT */
00340          return SOCKERR_TIMEOUT;
00341     }
00342    }
00343 // clearSUBR();    // clear the subnet mask again and keep it because of the ARP errata of W5100
00344     setSn_IR(sn, Sn_IR_SENDOK);
00345     #endif
00346     return len;
00347 }
00348 
00349 
00350 
00351 int32_t recvfrom(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port, uint8_t* packinfo)
00352 {
00353    uint8_t  mr;
00354    uint8_t  head[8];
00355     uint16_t pack_len=0;
00356 
00357    CHECK_SOCKNUM();
00358    //CHECK_SOCKMODE(Sn_MR_UDP);
00359    switch((mr=getSn_MR(sn)) & 0x0F)
00360    {
00361       case Sn_MR_UDP:
00362       case Sn_MR_MACRAW:
00363          break;
00364       default:
00365          return SOCKERR_SOCKMODE;
00366    }
00367    CHECK_SOCKDATA();
00368    if(sock_remained_size[sn] == 0)
00369    {
00370       while(1)
00371       {
00372          pack_len = getSn_RX_RSR(sn);
00373          if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED;
00374          if( (sock_io_mode & (1<<sn)) && (pack_len == 0) ) return SOCK_BUSY;
00375          if(pack_len != 0) break;
00376       };
00377    }
00378    *packinfo = 0x00;   
00379     switch (mr & 0x07)
00380     {
00381        case Sn_MR_UDP :
00382           if(sock_remained_size[sn] == 0)
00383           {
00384             wiz_recv_data(sn, head, 8);
00385             setSn_CR(sn,Sn_CR_RECV);
00386             while(getSn_CR(sn));
00387             // read peer's IP address, port number & packet length
00388                 addr[0] = head[0];
00389             addr[1] = head[1];
00390             addr[2] = head[2];
00391             addr[3] = head[3];
00392             *port = head[4];
00393             *port = (*port << 8) + head[5];
00394             sock_remained_size[sn] = head[6];
00395             sock_remained_size[sn] = (sock_remained_size[sn] << 8) + head[7];
00396             *packinfo = 0x80;
00397        }
00398             if(len < sock_remained_size[sn]) pack_len = len;
00399             else pack_len = sock_remained_size[sn];
00400             //
00401             // Need to packet length check (default 1472)
00402             //
00403         wiz_recv_data(sn, buf, pack_len); // data copy.
00404             break;
00405        case Sn_MR_MACRAW :
00406           if(sock_remained_size[sn] == 0)
00407           {
00408             wiz_recv_data(sn, head, 2);
00409             setSn_CR(sn,Sn_CR_RECV);
00410             while(getSn_CR(sn));
00411             // read peer's IP address, port number & packet length
00412                 sock_remained_size[sn] = head[0];
00413             sock_remained_size[sn] = (sock_remained_size[sn] <<8) + head[1];
00414             if(sock_remained_size[sn] > 1514) 
00415             {
00416                close(sn);
00417                return SOCKFATAL_PACKLEN;
00418             }
00419        }
00420             if(len < sock_remained_size[sn]) pack_len = len;
00421             else pack_len = sock_remained_size[sn];
00422             wiz_recv_data(sn,buf,pack_len);
00423            break;
00424       default:
00425          wiz_recv_ignore(sn, pack_len); // data copy.
00426          sock_remained_size[sn] = pack_len;
00427          break;
00428    }
00429     setSn_CR(sn,Sn_CR_RECV);
00430     /* wait to process the command... */
00431     while(getSn_CR(sn)) ;
00432     sock_remained_size[sn] -= pack_len;
00433     if(sock_remained_size[sn] != 0) *packinfo |= 0x01;
00434     return pack_len;
00435 }
00436 
00437 
00438 int8_t  ctlsocket(uint8_t sn, ctlsock_type cstype, void* arg)
00439 {
00440    uint8_t tmp = 0;
00441    CHECK_SOCKNUM();
00442    switch(cstype)
00443    {
00444       case CS_SET_IOMODE:
00445          tmp = *((uint8_t*)arg);
00446          if(tmp == SOCK_IO_NONBLOCK)  sock_io_mode |= (1<<sn);
00447          else if(tmp == SOCK_IO_BLOCK) sock_io_mode &= ~(1<<sn);
00448          else return SOCKERR_ARG;
00449          break;
00450       case CS_GET_IOMODE:   
00451          *((uint8_t*)arg) = (sock_io_mode >> sn) & 0x0001;
00452          break;
00453       case CS_GET_MAXTXBUF:
00454          *((uint16_t*)arg) = getSn_TxMAX(sn);
00455          break;
00456       case CS_GET_MAXRXBUF:    
00457          *((uint16_t*)arg) = getSn_RxMAX(sn);
00458          break;
00459       case CS_CLR_INTERRUPT:
00460          if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG;
00461          setSn_IR(sn,*(uint8_t*)arg);
00462          break;
00463       case CS_GET_INTERRUPT:
00464          *((uint8_t*)arg) = getSn_IR(sn);
00465          break;
00466       case CS_SET_INTMASK:  
00467          if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG;
00468          setSn_IMR(sn,*(uint8_t*)arg);
00469          break;
00470       case CS_GET_INTMASK:   
00471          *((uint8_t*)arg) = getSn_IMR(sn);
00472       default:
00473          return SOCKERR_ARG;
00474    }
00475    return SOCK_OK;
00476 }
00477 
00478 int8_t  setsockopt(uint8_t sn, sockopt_type sotype, void* arg)
00479 {
00480   
00481    CHECK_SOCKNUM();
00482    switch(sotype)
00483    {
00484       case SO_TTL:
00485          setSn_TTL(sn,*(uint8_t*)arg);
00486          break;
00487       case SO_TOS:
00488          setSn_TOS(sn,*(uint8_t*)arg);
00489          break;
00490       case SO_MSS:
00491          setSn_MSSR(sn,*(uint16_t*)arg);
00492          break;
00493       case SO_DESTIP:
00494          setSn_DIPR(sn, (uint8_t*)arg);
00495          break;
00496       case SO_DESTPORT:
00497          setSn_DPORT(sn, *(uint16_t*)arg);
00498          break;
00499       case SO_KEEPALIVESEND:
00500          CHECK_SOCKMODE(Sn_MR_TCP);
00501             if(getSn_KPALVTR(sn) != 0) return SOCKERR_SOCKOPT;
00502             setSn_CR(sn,Sn_CR_SEND_KEEP);
00503             while(getSn_CR(sn) != 0)
00504             {
00505                 if (getSn_IR(sn) & Sn_IR_TIMEOUT)
00506                 {
00507                     setSn_IR(sn, Sn_IR_TIMEOUT);
00508                   return SOCKERR_TIMEOUT;
00509                 }
00510             }
00511          break;
00512       case SO_KEEPALIVEAUTO:
00513          CHECK_SOCKMODE(Sn_MR_TCP);
00514          setSn_KPALVTR(sn,*(uint8_t*)arg);
00515          break;
00516       default:
00517          return SOCKERR_ARG;
00518    }   
00519    return SOCK_OK;
00520 }
00521 
00522 int8_t  getsockopt(uint8_t sn, sockopt_type sotype, void* arg)
00523 {
00524    CHECK_SOCKNUM();
00525    switch(sotype)
00526    {
00527       case SO_FLAG:
00528          *(uint8_t*)arg = getSn_MR(sn) & 0xF0;
00529          break;
00530       case SO_TTL:
00531          *(uint8_t*) arg = getSn_TTL(sn);
00532          break;
00533       case SO_TOS:
00534          *(uint8_t*) arg = getSn_TOS(sn);
00535          break;
00536       case SO_MSS:   
00537          *(uint8_t*) arg = getSn_MSSR(sn);
00538       case SO_DESTIP:
00539          getSn_DIPR(sn, (uint8_t*)arg);
00540          break;
00541       case SO_DESTPORT:  
00542          *(uint16_t*) arg = getSn_DPORT(sn);
00543          break;
00544       case SO_KEEPALIVEAUTO:
00545          CHECK_SOCKMODE(Sn_MR_TCP);
00546          *(uint16_t*) arg = getSn_KPALVTR(sn);
00547          break;
00548       case SO_SENDBUF:
00549          *(uint16_t*) arg = getSn_TX_FSR(sn);
00550       case SO_RECVBUF:
00551          *(uint16_t*) arg = getSn_RX_RSR(sn);
00552       case SO_STATUS:
00553          *(uint8_t*) arg = getSn_SR(sn);
00554          break;
00555       case SO_REMAINSIZE:
00556          if(getSn_MR(sn) == Sn_MR_TCP)
00557             *(uint16_t*)arg = getSn_RX_RSR(sn);
00558          else
00559             *(uint16_t*)arg = sock_remained_size[sn];
00560          break;
00561       default:
00562          return SOCKERR_SOCKOPT;
00563    }
00564    return SOCK_OK;
00565 }