BSD style socket API for W5500.

Dependencies:   W5500

Fork of Ethernet by Raphael Kwon

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers socket.c Source File

socket.c

Go to the documentation of this file.
00001 //*****************************************************************************
00002 //
00003 //! \file socket.c
00004 //! \brief SOCKET APIs Implements file.
00005 //! \details SOCKET APIs like as Berkeley Socket APIs. 
00006 //! \version 1.0.0.0
00007 //! \date 2013/10/01
00008 //! \par  Revision history
00009 //!       <2013/10/01> 1st Release
00010 //! \author MidnightCow
00011 //! \copyright
00012 //!
00013 //! Copyright (c)  2013, WIZnet Co., LTD.
00014 //! All rights reserved.
00015 //! 
00016 //! Redistribution and use in source and binary forms, with or without 
00017 //! modification, are permitted provided that the following conditions 
00018 //! are met: 
00019 //! 
00020 //!     * Redistributions of source code must retain the above copyright 
00021 //! notice, this list of conditions and the following disclaimer. 
00022 //!     * Redistributions in binary form must reproduce the above copyright
00023 //! notice, this list of conditions and the following disclaimer in the
00024 //! documentation and/or other materials provided with the distribution. 
00025 //!     * Neither the name of the <ORGANIZATION> nor the names of its 
00026 //! contributors may be used to endorse or promote products derived 
00027 //! from this software without specific prior written permission. 
00028 //! 
00029 //! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00030 //! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
00031 //! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00032 //! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
00033 //! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
00034 //! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
00035 //! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00036 //! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
00037 //! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
00038 //! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
00039 //! THE POSSIBILITY OF SUCH DAMAGE.
00040 //
00041 //*****************************************************************************
00042 #include "socket.h"
00043 
00044 #define SOCK_ANY_PORT_NUM  0xC000;
00045 
00046 static uint16_t sock_any_port = SOCK_ANY_PORT_NUM;
00047 static uint16_t sock_io_mode = 0;
00048 static uint16_t sock_is_sending = 0;
00049 static uint16_t sock_remained_size[_WIZCHIP_SOCK_NUM_] = {0,0,};
00050 
00051 #define CHECK_SOCKNUM()   \
00052    do{                    \
00053       if(sn > _WIZCHIP_SOCK_NUM_) return SOCKERR_SOCKNUM;   \
00054    }while(0);             \
00055 
00056 #define CHECK_SOCKMODE(mode)  \
00057    do{                     \
00058       if((getSn_MR(sn) & 0x0F) != mode) return SOCKERR_SOCKMODE;  \
00059    }while(0);              \
00060 
00061 #define CHECK_SOCKINIT()   \
00062    do{                     \
00063       if((getSn_SR(sn) != SOCK_INIT)) return SOCKERR_SOCKINIT; \
00064    }while(0);              \
00065 
00066 #define CHECK_SOCKDATA()   \
00067    do{                     \
00068       if(len == 0) return SOCKERR_DATALEN;   \
00069    }while(0);              \
00070 
00071 
00072 
00073 int8_t socket(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag)
00074 {
00075     CHECK_SOCKNUM();
00076     switch(protocol)
00077     {
00078       case Sn_MR_TCP :
00079       case Sn_MR_UDP :
00080       case Sn_MR_MACRAW :
00081          break;
00082    #if ( _WIZCHIP_ < 5200 )
00083       case Sn_MR_IPRAW :
00084       case Sn_MR_PPPoE :
00085          break;
00086    #endif
00087       default :
00088          return SOCKERR_SOCKMODE;
00089     }
00090     if((flag & 0x06) != 0) return SOCKERR_SOCKFLAG;
00091 #if _WIZCHIP_ == 5200
00092    if(flag & 0x10) return SOCKERR_SOCKFLAG;
00093 #endif
00094        
00095     if(flag != 0)
00096     {
00097     switch(protocol)
00098     {
00099        case Sn_MR_TCP:
00100           if((flag & (SF_TCP_NODELAY|SF_IO_NONBLOCK))==0) return SOCKERR_SOCKFLAG;
00101           break;
00102        case Sn_MR_UDP:
00103           if(flag & SF_IGMP_VER2)
00104           {
00105              if((flag & SF_MULTI_ENABLE)==0) return SOCKERR_SOCKFLAG;
00106           }
00107           #if _WIZCHIP_ == 5500
00108               if(flag & SF_UNI_BLOCK)
00109               {
00110                  if((flag & SF_MULTI_ENABLE) == 0) return SOCKERR_SOCKFLAG;
00111               }
00112           #endif
00113           break;
00114        default:
00115           break;
00116     }
00117    }
00118     close(sn);
00119     setSn_MR(sn, (protocol | (flag & 0xF0)));
00120     if(!port)
00121     {
00122        port = sock_any_port++;
00123        if(sock_any_port == 0xFFF0) sock_any_port = SOCK_ANY_PORT_NUM;
00124     }
00125    setSn_PORT(sn,port); 
00126    setSn_CR(sn,Sn_CR_OPEN);
00127    while(getSn_CR(sn));
00128     sock_io_mode |= ((flag & SF_IO_NONBLOCK) << sn);   
00129    sock_is_sending &= ~(1<<sn);
00130    sock_remained_size[sn] = 0;
00131    while(getSn_SR(sn) == SOCK_CLOSED);
00132    return (int8_t)sn;
00133 }      
00134 
00135 int8_t close(uint8_t sn)
00136 {
00137     CHECK_SOCKNUM();
00138     
00139     setSn_CR(sn,Sn_CR_CLOSE);
00140    /* wait to process the command... */
00141     while( getSn_CR(sn) );
00142     /* clear all interrupt of the socket. */
00143     setSn_IR(sn, 0xFF);
00144     sock_is_sending &= ~(1<<sn);
00145     sock_remained_size[sn] = 0;
00146     while(getSn_SR(sn) != SOCK_CLOSED);
00147     return SOCK_OK;
00148 }
00149 
00150 int8_t listen(uint8_t sn)
00151 {
00152     CHECK_SOCKNUM();
00153    CHECK_SOCKMODE(Sn_MR_TCP);
00154     CHECK_SOCKINIT();
00155     setSn_CR(sn,Sn_CR_LISTEN);
00156     while(getSn_CR(sn));
00157    while(getSn_SR(sn) != SOCK_LISTEN)
00158    {
00159       if(getSn_CR(sn) == SOCK_CLOSED)
00160       {
00161          close(sn);
00162          return SOCKERR_SOCKCLOSED;
00163       }
00164    }
00165    return SOCK_OK;
00166 }
00167 
00168 
00169 int8_t connect(uint8_t sn, uint8_t * addr, uint16_t port)
00170 {
00171    CHECK_SOCKNUM();
00172    CHECK_SOCKMODE(Sn_MR_TCP);
00173    CHECK_SOCKINIT();
00174     if( *((uint32_t*)addr) == 0xFFFFFFFF || *((uint32_t*)addr) == 0) return SOCKERR_IPINVALID;
00175     if(port == 0) return SOCKERR_PORTZERO;
00176     setSn_DIPR(sn,addr);
00177     setSn_DPORT(sn,port);
00178 //  setSUBR();   // set the subnet mask register
00179     setSn_CR(sn,Sn_CR_CONNECT);
00180    while(getSn_CR(sn));
00181    if(sock_io_mode & (1<<sn)) return SOCK_BUSY;
00182    while(getSn_SR(sn) != SOCK_ESTABLISHED)
00183    {   
00184         if (getSn_IR(sn) & Sn_IR_TIMEOUT)
00185         {
00186             setSn_IR(sn, Sn_IR_TIMEOUT);
00187          return SOCKERR_TIMEOUT;
00188         }
00189     }
00190 //  clearSUBR();   // clear the subnet mask again and keep it because of the ARP errata of W5100
00191    return SOCK_OK;
00192 }
00193 
00194 int8_t disconnect(uint8_t sn)
00195 {
00196    CHECK_SOCKNUM();
00197    CHECK_SOCKMODE(Sn_MR_TCP);
00198     setSn_CR(sn,Sn_CR_DISCON);
00199     /* wait to process the command... */
00200     while(getSn_CR(sn));
00201     sock_is_sending &= ~(1<<sn);
00202    if(sock_io_mode & (1<<sn)) return SOCK_BUSY;
00203     while(getSn_SR(sn) != SOCK_CLOSED)
00204     {
00205        if(getSn_IR(sn) & Sn_IR_TIMEOUT)
00206        {
00207           close(sn);
00208           return SOCKERR_TIMEOUT;
00209        }
00210     }
00211     return SOCK_OK;
00212 }
00213 
00214 int32_t send(uint8_t sn, uint8_t * buf, uint16_t len)
00215 {
00216    uint8_t tmp=0;
00217    uint16_t freesize=0;
00218    
00219    CHECK_SOCKNUM();
00220    CHECK_SOCKMODE(Sn_MR_TCP);
00221    CHECK_SOCKDATA();
00222    tmp = getSn_SR(sn);
00223    if(tmp != SOCK_ESTABLISHED && tmp != SOCK_CLOSE_WAIT) return SOCKERR_SOCKSTATUS;
00224    if( sock_is_sending & (1<<sn) )
00225    {
00226       tmp = getSn_IR(sn);
00227       if(tmp & Sn_IR_SENDOK)
00228       {
00229          setSn_IR(sn, Sn_IR_SENDOK);
00230          sock_is_sending &= ~(1<<sn);         
00231       }
00232       else if(tmp & Sn_IR_TIMEOUT)
00233       {
00234          close(sn);
00235          return SOCKERR_TIMEOUT;
00236       }
00237       else return SOCK_BUSY;
00238    }
00239    freesize = getSn_TxMAX(sn);
00240    if (len > freesize) len = freesize; // check size not to exceed MAX size.
00241    while(1)
00242    {
00243       freesize = getSn_TX_FSR(sn);
00244       tmp = getSn_SR(sn);
00245       if ((tmp != SOCK_ESTABLISHED) && (tmp != SOCK_CLOSE_WAIT))
00246       {
00247          close(sn);
00248          return SOCKERR_SOCKSTATUS;
00249       }
00250       if( (sock_io_mode & (1<<sn)) && (len > freesize) ) return SOCK_BUSY;
00251       if(len <= freesize) break;
00252    }
00253    wiz_send_data(sn, buf, len);
00254    setSn_CR(sn,Sn_CR_SEND);
00255    /* wait to process the command... */
00256    while(getSn_CR(sn));
00257    sock_is_sending |= (1 << sn);
00258    /*
00259    if(sock_io_mode & (1<<sn)) return len;
00260    while( ((tmp = getSn_IR(sn)) & Sn_IR_SENDOK) !=Sn_IR_SENDOK )
00261    {
00262       if(tmp & Sn_IR_TIMEOUT)
00263       {
00264          close(sn);
00265          return SOCKERR_TIMEOUT;
00266       }
00267    }
00268    setSn_IR(sn, Sn_IR_SENDOK);
00269    */
00270    return len;
00271 }
00272 
00273 
00274 int32_t recv(uint8_t sn, uint8_t * buf, uint16_t len)
00275 {
00276    uint8_t  tmp = 0;
00277    uint16_t recvsize = 0;
00278    CHECK_SOCKNUM();
00279    CHECK_SOCKMODE(Sn_MR_TCP);
00280    CHECK_SOCKDATA();
00281    
00282    recvsize = getSn_RxMAX(sn);
00283    if(recvsize < len) len = recvsize;
00284    while(1)
00285    {
00286       recvsize = getSn_RX_RSR(sn);
00287       tmp = getSn_SR(sn);
00288       if (tmp != SOCK_ESTABLISHED)
00289       {
00290          if(tmp == SOCK_CLOSE_WAIT)
00291          {
00292             if(recvsize != 0) break;
00293             else if(getSn_TX_FSR(sn) == getSn_TxMAX(sn))
00294             {
00295                close(sn);
00296                return SOCKERR_SOCKSTATUS;
00297             }
00298          }
00299          else
00300          {
00301             close(sn);
00302             return SOCKERR_SOCKSTATUS;
00303          }
00304       }
00305       if((sock_io_mode & (1<<sn)) && (recvsize == 0)) return SOCK_BUSY;
00306       if(recvsize != 0) break;
00307    };
00308    if(recvsize < len) len = recvsize;
00309    wiz_recv_data(sn, buf, len);
00310    setSn_CR(sn,Sn_CR_RECV);
00311    while(getSn_CR(sn));
00312    return len;
00313 }
00314 
00315 int32_t sendto(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port)
00316 {
00317    uint8_t tmp = 0;
00318    uint16_t freesize = 0;
00319    CHECK_SOCKNUM();
00320    //CHECK_SOCKMODE(Sn_MR_UDP);
00321    switch(getSn_MR(sn) & 0x0F)
00322    {
00323       case Sn_MR_UDP:
00324       case Sn_MR_MACRAW:
00325          break;
00326       default:
00327          return SOCKERR_SOCKMODE;
00328    }
00329    CHECK_SOCKDATA();
00330    if(*((uint32_t*)addr) == 0) return SOCKERR_IPINVALID;
00331    if(port == 0)               return SOCKERR_PORTZERO;
00332    tmp = getSn_SR(sn);
00333    if(tmp != SOCK_MACRAW && tmp != SOCK_UDP) return SOCKERR_SOCKSTATUS;
00334 
00335    if( sock_is_sending & (1<<sn) )
00336    {
00337       tmp = getSn_IR(sn);
00338       if(tmp & Sn_IR_SENDOK)
00339       {
00340          setSn_IR(sn, Sn_IR_SENDOK);
00341          sock_is_sending &= ~(1<<sn);
00342       }
00343       else if(tmp & Sn_IR_TIMEOUT)
00344       {
00345          close(sn);
00346          return SOCKERR_TIMEOUT;
00347       }
00348       else return SOCK_BUSY;
00349    }
00350       
00351    setSn_DIPR(sn,addr);
00352    setSn_DPORT(sn,port);      
00353    freesize = getSn_TxMAX(sn);
00354    if (len > freesize) len = freesize; // check size not to exceed MAX size.
00355    while(1)
00356    {
00357       freesize = getSn_TX_FSR(sn);
00358       if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED;
00359       if( (sock_io_mode & (1<<sn)) && (len > freesize) ) return SOCK_BUSY;
00360       if(len <= freesize) break;
00361    };
00362     wiz_send_data(sn, buf, len);
00363 // setSUBR();    // set the subnet mask register
00364     setSn_CR(sn,Sn_CR_SEND);
00365     /* wait to process the command... */
00366     while(getSn_CR(sn));
00367     sock_is_sending |= (1<<sn);
00368     #if 0
00369     if(sock_io_mode & (1<<sn)) return len;
00370    while ( ((tmp = getSn_IR(sn)) & Sn_IR_SENDOK) != Sn_IR_SENDOK ) 
00371    {
00372       if(tmp & Sn_IR_TIMEOUT)
00373     {
00374          setSn_IR(sn, (Sn_IR_SENDOK | Sn_IR_TIMEOUT)); /* clear SEND_OK & TIMEOUT */
00375          return SOCKERR_TIMEOUT;
00376     }
00377    }
00378 // clearSUBR();    // clear the subnet mask again and keep it because of the ARP errata of W5100
00379     setSn_IR(sn, Sn_IR_SENDOK);
00380     #endif
00381     return len;
00382 }
00383 
00384 
00385 
00386 int32_t recvfrom(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port, uint8_t* packinfo)
00387 {
00388    uint8_t  mr;
00389    uint8_t  head[8];
00390     uint16_t pack_len=0;
00391 
00392    CHECK_SOCKNUM();
00393    //CHECK_SOCKMODE(Sn_MR_UDP);
00394    switch((mr=getSn_MR(sn)) & 0x0F)
00395    {
00396       case Sn_MR_UDP:
00397       case Sn_MR_MACRAW:
00398          break;
00399    #if ( _WIZCHIP_ < 5200 )         
00400       case Sn_MR_IPRAW:
00401       case Sn_MR_PPPoE:
00402          break;
00403    #endif
00404       default:
00405          return SOCKERR_SOCKMODE;
00406    }
00407    CHECK_SOCKDATA();
00408    if(sock_remained_size[sn] == 0)
00409    {
00410       while(1)
00411       {
00412          pack_len = getSn_RX_RSR(sn);
00413          if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED;
00414          if( (sock_io_mode & (1<<sn)) && (pack_len == 0) ) return SOCK_BUSY;
00415          if(pack_len != 0) break;
00416       };
00417    }
00418    *packinfo = 0x00;   
00419     switch (mr & 0x07)
00420     {
00421        case Sn_MR_UDP :
00422           if(sock_remained_size[sn] == 0)
00423           {
00424             wiz_recv_data(sn, head, 8);
00425             setSn_CR(sn,Sn_CR_RECV);
00426             while(getSn_CR(sn));
00427             // read peer's IP address, port number & packet length
00428                 addr[0] = head[0];
00429             addr[1] = head[1];
00430             addr[2] = head[2];
00431             addr[3] = head[3];
00432             *port = head[4];
00433             *port = (*port << 8) + head[5];
00434             sock_remained_size[sn] = head[6];
00435             sock_remained_size[sn] = (sock_remained_size[sn] << 8) + head[7];
00436             *packinfo = 0x80;
00437        }
00438             if(len < sock_remained_size[sn]) pack_len = len;
00439             else pack_len = sock_remained_size[sn];
00440             //
00441             // Need to packet length check (default 1472)
00442             //
00443         wiz_recv_data(sn, buf, pack_len); // data copy.
00444             break;
00445        case Sn_MR_MACRAW :
00446           if(sock_remained_size[sn] == 0)
00447           {
00448             wiz_recv_data(sn, head, 2);
00449             setSn_CR(sn,Sn_CR_RECV);
00450             while(getSn_CR(sn));
00451             // read peer's IP address, port number & packet length
00452                 sock_remained_size[sn] = head[0];
00453             sock_remained_size[sn] = (sock_remained_size[sn] <<8) + head[1];
00454             if(sock_remained_size[sn] > 1514) 
00455             {
00456                close(sn);
00457                return SOCKFATAL_PACKLEN;
00458             }
00459        }
00460             if(len < sock_remained_size[sn]) pack_len = len;
00461             else pack_len = sock_remained_size[sn];
00462             wiz_recv_data(sn,buf,pack_len);
00463            break;
00464    #if ( _WIZCHIP_ < 5200 )
00465         case Sn_MR_IPRAW:
00466            if(sock_remained_size[sn] == 0)
00467            {
00468             wiz_recv_data(sn, head, 6);
00469             setSn_CR(sn,Sn_CR_RECV);
00470             while(getSn_CR(sn));
00471             addr[0] = head[0];
00472             addr[1] = head[1];
00473             addr[2] = head[2];
00474             addr[3] = head[3];
00475             sock_remained_size[sn] = head[4];
00476             sock_remaiend_size[sn] = (sock_remained_size[sn] << 8) + head[5];
00477             *packinfo = 0x80;
00478          }
00479             //
00480             // Need to packet length check
00481             //
00482             if(len < sock_remained_size[sn]) pack_len = len;
00483             else pack_len = sock_remained_size[sn];
00484         wiz_recv_data(sn, buf, pack_len); // data copy.
00485             break;
00486    #endif
00487       default:
00488          wiz_recv_ignore(sn, pack_len); // data copy.
00489          sock_remained_size[sn] = pack_len;
00490          break;
00491    }
00492     setSn_CR(sn,Sn_CR_RECV);
00493     /* wait to process the command... */
00494     while(getSn_CR(sn)) ;
00495     sock_remained_size[sn] -= pack_len;
00496     if(sock_remained_size[sn] != 0) *packinfo |= 0x01;
00497     return pack_len;
00498 }
00499 
00500 
00501 int8_t  ctlsocket(uint8_t sn, ctlsock_type cstype, void* arg)
00502 {
00503    uint8_t tmp = 0;
00504    CHECK_SOCKNUM();
00505    switch(cstype)
00506    {
00507       case CS_SET_IOMODE:
00508          tmp = *((uint8_t*)arg);
00509          if(tmp == SOCK_IO_NONBLOCK)  sock_io_mode |= (1<<sn);
00510          else if(tmp == SOCK_IO_BLOCK) sock_io_mode &= ~(1<<sn);
00511          else return SOCKERR_ARG;
00512          break;
00513       case CS_GET_IOMODE:   
00514          *((uint8_t*)arg) = (sock_io_mode >> sn) & 0x0001;
00515          break;
00516       case CS_GET_MAXTXBUF:
00517          *((uint16_t*)arg) = getSn_TxMAX(sn);
00518          break;
00519       case CS_GET_MAXRXBUF:    
00520          *((uint16_t*)arg) = getSn_RxMAX(sn);
00521          break;
00522       case CS_CLR_INTERRUPT:
00523          if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG;
00524          setSn_IR(sn,*(uint8_t*)arg);
00525          break;
00526       case CS_GET_INTERRUPT:
00527          *((uint8_t*)arg) = getSn_IR(sn);
00528          break;
00529       case CS_SET_INTMASK:  
00530          if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG;
00531          setSn_IMR(sn,*(uint8_t*)arg);
00532          break;
00533       case CS_GET_INTMASK:   
00534          *((uint8_t*)arg) = getSn_IMR(sn);
00535       default:
00536          return SOCKERR_ARG;
00537    }
00538    return SOCK_OK;
00539 }
00540 
00541 int8_t  setsockopt(uint8_t sn, sockopt_type sotype, void* arg)
00542 {
00543    uint8_t tmp;
00544    CHECK_SOCKNUM();
00545    switch(sotype)
00546    {
00547       case SO_TTL:
00548          setSn_TTL(sn,*(uint8_t*)arg);
00549          break;
00550       case SO_TOS:
00551          setSn_TOS(sn,*(uint8_t*)arg);
00552          break;
00553       case SO_MSS:
00554          setSn_MSSR(sn,*(uint16_t*)arg);
00555          break;
00556       case SO_DESTIP:
00557          setSn_DIPR(sn, (uint8_t*)arg);
00558          break;
00559       case SO_DESTPORT:
00560          setSn_DPORT(sn, *(uint16_t*)arg);
00561          break;
00562 #if _WIZCHIP_ != 5100
00563       case SO_KEEPALIVESEND:
00564          CHECK_SOCKMODE(Sn_MR_TCP);
00565          #if _WIZCHIP_ > 5200
00566             if(getSn_KPALVTR(sn) != 0) return SOCKERR_SOCKOPT;
00567          #endif
00568             setSn_CR(sn,Sn_CR_SEND_KEEP);
00569             while((tmp = getSn_CR(sn)) != 0)
00570             {
00571                 if (getSn_IR(sn) & Sn_IR_TIMEOUT)
00572                 {
00573                     setSn_IR(sn, Sn_IR_TIMEOUT);
00574                   return SOCKERR_TIMEOUT;
00575                 }
00576             }
00577          break;
00578    #if _WIZCHIP_ > 5200
00579       case SO_KEEPALIVEAUTO:
00580          CHECK_SOCKMODE(Sn_MR_TCP);
00581          setSn_KPALVTR(sn,*(uint8_t*)arg);
00582          break;
00583    #endif      
00584 #endif   
00585       default:
00586          return SOCKERR_ARG;
00587    }   
00588    return SOCK_OK;
00589 }
00590 
00591 int8_t  getsockopt(uint8_t sn, sockopt_type sotype, void* arg)
00592 {
00593    CHECK_SOCKNUM();
00594    switch(sotype)
00595    {
00596       case SO_FLAG:
00597          *(uint8_t*)arg = getSn_MR(sn) & 0xF0;
00598          break;
00599       case SO_TTL:
00600          *(uint8_t*) arg = getSn_TTL(sn);
00601          break;
00602       case SO_TOS:
00603          *(uint8_t*) arg = getSn_TOS(sn);
00604          break;
00605       case SO_MSS:   
00606          *(uint8_t*) arg = getSn_MSSR(sn);
00607       case SO_DESTIP:
00608          getSn_DIPR(sn, (uint8_t*)arg);
00609          break;
00610       case SO_DESTPORT:  
00611          *(uint16_t*) arg = getSn_DPORT(sn);
00612          break;
00613    #if _WIZCHIP_ > 5200   
00614       case SO_KEEPALIVEAUTO:
00615          CHECK_SOCKMODE(Sn_MR_TCP);
00616          *(uint16_t*) arg = getSn_KPALVTR(sn);
00617          break;
00618    #endif      
00619       case SO_SENDBUF:
00620          *(uint16_t*) arg = getSn_TX_FSR(sn);
00621       case SO_RECVBUF:
00622          *(uint16_t*) arg = getSn_RX_RSR(sn);
00623       case SO_STATUS:
00624          *(uint8_t*) arg = getSn_SR(sn);
00625          break;
00626       case SO_REMAINSIZE:
00627          if(getSn_MR(sn) == Sn_MR_TCP)
00628             *(uint16_t*)arg = getSn_RX_RSR(sn);
00629          else
00630             *(uint16_t*)arg = sock_remained_size[sn];
00631          break;
00632       default:
00633          return SOCKERR_SOCKOPT;
00634    }
00635    return SOCK_OK;
00636 }