QuakeGod
2023-02-01 c5764186c3ec23eb954463495b8fbd77e32b268c
提交 | 用户 | age
85d591 1 //*****************************************************************************
Q 2 //
3 //! \file socket.c
4 //! \brief SOCKET APIs Implements file.
5 //! \details SOCKET APIs like as Berkeley Socket APIs. 
6 //! \version 1.0.3
7 //! \date 2013/10/21
8 //! \par  Revision history
9 //!       <2014/05/01> V1.0.3. Refer to M20140501
10 //!         1. Implicit type casting -> Explicit type casting.
11 //!         2. replace 0x01 with PACK_REMAINED in recvfrom()
12 //!         3. Validation a destination ip in connect() & sendto(): 
13 //!            It occurs a fatal error on converting unint32 address if uint8* addr parameter is not aligned by 4byte address.
14 //!            Copy 4 byte addr value into temporary uint32 variable and then compares it.
15 //!       <2013/12/20> V1.0.2 Refer to M20131220
16 //!                    Remove Warning.
17 //!       <2013/11/04> V1.0.1 2nd Release. Refer to "20131104".
18 //!                    In sendto(), Add to clear timeout interrupt status (Sn_IR_TIMEOUT)
19 //!       <2013/10/21> 1st Release
20 //! \author MidnightCow
21 //! \copyright
22 //!
23 //! Copyright (c)  2013, WIZnet Co., LTD.
24 //! All rights reserved.
25 //! 
26 //! Redistribution and use in source and binary forms, with or without 
27 //! modification, are permitted provided that the following conditions 
28 //! are met: 
29 //! 
30 //!     * Redistributions of source code must retain the above copyright 
31 //! notice, this list of conditions and the following disclaimer. 
32 //!     * Redistributions in binary form must reproduce the above copyright
33 //! notice, this list of conditions and the following disclaimer in the
34 //! documentation and/or other materials provided with the distribution. 
35 //!     * Neither the name of the <ORGANIZATION> nor the names of its 
36 //! contributors may be used to endorse or promote products derived 
37 //! from this software without specific prior written permission. 
38 //! 
39 //! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
40 //! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
41 //! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
42 //! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
43 //! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
44 //! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
45 //! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
46 //! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
47 //! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
48 //! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
49 //! THE POSSIBILITY OF SUCH DAMAGE.
50 //
51 //*****************************************************************************
52 #include "socket.h"
53
54 #define SOCK_ANY_PORT_NUM  0xC000;
55
56 static uint16_t sock_any_port = SOCK_ANY_PORT_NUM;
57 static uint16_t sock_io_mode = 0;
58 static uint16_t sock_is_sending = 0;
59 static uint16_t sock_remained_size[_WIZCHIP_SOCK_NUM_] = {0,0,};
60 static uint8_t  sock_pack_info[_WIZCHIP_SOCK_NUM_] = {0,};
61
62 #if _WIZCHIP_ == 5200
63    static uint16_t sock_next_rd[_WIZCHIP_SOCK_NUM_] ={0,};
64 #endif
65
66 #define CHECK_SOCKNUM()   \
67    do{                    \
68       if(sn > _WIZCHIP_SOCK_NUM_) return SOCKERR_SOCKNUM;   \
69    }while(0);             \
70
71 #define CHECK_SOCKMODE(mode)  \
72    do{                     \
73       if((getSn_MR(sn) & 0x0F) != mode) return SOCKERR_SOCKMODE;  \
74    }while(0);              \
75
76 #define CHECK_SOCKINIT()   \
77    do{                     \
78       if((getSn_SR(sn) != SOCK_INIT)) return SOCKERR_SOCKINIT; \
79    }while(0);              \
80
81 #define CHECK_SOCKDATA()   \
82    do{                     \
83       if(len == 0) return SOCKERR_DATALEN;   \
84    }while(0);              \
85
86
87
88 int8_t socket(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag)
89 {
90     CHECK_SOCKNUM();
91     switch(protocol)
92     {
93       case Sn_MR_TCP :
94       case Sn_MR_UDP :
95       case Sn_MR_MACRAW :
96          break;
97    #if ( _WIZCHIP_ < 5200 )
98       case Sn_MR_IPRAW :
99       case Sn_MR_PPPoE :
100          break;
101    #endif
102       default :
103          return SOCKERR_SOCKMODE;
104     }
105     if((flag & 0x06) != 0) return SOCKERR_SOCKFLAG;
106 #if _WIZCHIP_ == 5200
107    if(flag & 0x10) return SOCKERR_SOCKFLAG;
108 #endif
109        
110     if(flag != 0)
111     {
112        switch(protocol)
113        {
114           case Sn_MR_TCP:
115              if((flag & (SF_TCP_NODELAY|SF_IO_NONBLOCK))==0) return SOCKERR_SOCKFLAG;
116              break;
117           case Sn_MR_UDP:
118              if(flag & SF_IGMP_VER2)
119              {
120                 if((flag & SF_MULTI_ENABLE)==0) return SOCKERR_SOCKFLAG;
121              }
122              #if _WIZCHIP_ == 5500
123                 if(flag & SF_UNI_BLOCK)
124                 {
125                    if((flag & SF_MULTI_ENABLE) == 0) return SOCKERR_SOCKFLAG;
126                 }
127              #endif
128              break;
129           default:
130              break;
131        }
132    }
133     close(sn);
134     setSn_MR(sn, (protocol | (flag & 0xF0)));
135     if(!port)
136     {
137        port = sock_any_port++;
138        if(sock_any_port == 0xFFF0) sock_any_port = SOCK_ANY_PORT_NUM;
139     }
140    setSn_PORT(sn,port);    
141    setSn_CR(sn,Sn_CR_OPEN);
142    while(getSn_CR(sn));
143     sock_io_mode |= ((flag & SF_IO_NONBLOCK) << sn);   
144    sock_is_sending &= ~(1<<sn);
145    sock_remained_size[sn] = 0;
146    sock_pack_info[sn] = 0;
147    while(getSn_SR(sn) == SOCK_CLOSED);
148    return (int8_t)sn;
149 }       
150
151 int8_t close(uint8_t sn)
152 {
153     CHECK_SOCKNUM();
154     
155     setSn_CR(sn,Sn_CR_CLOSE);
156    /* wait to process the command... */
157     while( getSn_CR(sn) );
158     /* clear all interrupt of the socket. */
159     setSn_IR(sn, 0xFF);
160     sock_is_sending &= ~(1<<sn);
161     sock_remained_size[sn] = 0;
162     sock_pack_info[sn] = 0;
163     while(getSn_SR(sn) != SOCK_CLOSED);
164     return SOCK_OK;
165 }
166
167 int8_t listen(uint8_t sn)
168 {
169     CHECK_SOCKNUM();
170    CHECK_SOCKMODE(Sn_MR_TCP);
171     CHECK_SOCKINIT();
172     setSn_CR(sn,Sn_CR_LISTEN);
173     while(getSn_CR(sn));
174    while(getSn_SR(sn) != SOCK_LISTEN)
175    {
176       if(getSn_CR(sn) == SOCK_CLOSED)
177       {
178          close(sn);
179          return SOCKERR_SOCKCLOSED;
180       }
181    }
182    return SOCK_OK;
183 }
184
185
186 int8_t connect(uint8_t sn, uint8_t * addr, uint16_t port)
187 {
188    CHECK_SOCKNUM();
189    CHECK_SOCKMODE(Sn_MR_TCP);
190    CHECK_SOCKINIT();
191    //M20140501 : For avoiding fatal error on memory align mismatched
192    //if( *((uint32_t*)addr) == 0xFFFFFFFF || *((uint32_t*)addr) == 0) return SOCKERR_IPINVALID;
193    {
194       uint32_t taddr;
195       taddr = ((uint32_t)addr[0] & 0x000000FF);
196       taddr = (taddr << 8) + ((uint32_t)addr[1] & 0x000000FF);
197       taddr = (taddr << 8) + ((uint32_t)addr[2] & 0x000000FF);
198       taddr = (taddr << 8) + ((uint32_t)addr[0] & 0x000000FF);
199       if( taddr == 0xFFFFFFFF || taddr == 0) return SOCKERR_IPINVALID;
200    }
201    //
202     
203     if(port == 0) return SOCKERR_PORTZERO;
204     setSn_DIPR(sn,addr);
205     setSn_DPORT(sn,port);
206    #if _WIZCHIP_ == 5200   // for W5200 ARP errata 
207       setSUBR(0);
208    #endif
209     setSn_CR(sn,Sn_CR_CONNECT);
210    while(getSn_CR(sn));
211    if(sock_io_mode & (1<<sn)) return SOCK_BUSY;
212    while(getSn_SR(sn) != SOCK_ESTABLISHED)
213    {   
214         if (getSn_IR(sn) & Sn_IR_TIMEOUT)
215         {
216             setSn_IR(sn, Sn_IR_TIMEOUT);
217          #if _WIZCHIP_ == 5200   // for W5200 ARP errata 
218             setSUBR((uint8_t*)"\x00\x00\x00\x00");
219          #endif
220          return SOCKERR_TIMEOUT;
221         }
222     }
223    #if _WIZCHIP_ == 5200   // for W5200 ARP errata 
224       setSUBR((uint8_t*)"\x00\x00\x00\x00");
225    #endif
226    
227    return SOCK_OK;
228 }
229
230 int8_t disconnect(uint8_t sn)
231 {
232    CHECK_SOCKNUM();
233    CHECK_SOCKMODE(Sn_MR_TCP);
234     setSn_CR(sn,Sn_CR_DISCON);
235     /* wait to process the command... */
236     while(getSn_CR(sn));
237     sock_is_sending &= ~(1<<sn);
238    if(sock_io_mode & (1<<sn)) return SOCK_BUSY;
239     while(getSn_SR(sn) != SOCK_CLOSED)
240     {
241        if(getSn_IR(sn) & Sn_IR_TIMEOUT)
242        {
243           close(sn);
244           return SOCKERR_TIMEOUT;
245        }
246     }
247     return SOCK_OK;
248 }
249
250 int32_t send(uint8_t sn, uint8_t * buf, uint16_t len)
251 {
252    uint8_t tmp=0;
253    uint16_t freesize=0;
254    
255    CHECK_SOCKNUM();
256    CHECK_SOCKMODE(Sn_MR_TCP);
257    CHECK_SOCKDATA();
258    tmp = getSn_SR(sn);
259    if(tmp != SOCK_ESTABLISHED && tmp != SOCK_CLOSE_WAIT) return SOCKERR_SOCKSTATUS;
260    if( sock_is_sending & (1<<sn) )
261    {
262       tmp = getSn_IR(sn);
263       if(tmp & Sn_IR_SENDOK)
264       {
265          setSn_IR(sn, Sn_IR_SENDOK);
266          #if _WZICHIP_ == 5200
267             if(getSn_TX_RD(sn) != sock_next_rd[sn])
268             {
269                setSn_CR(sn,Sn_CR_SEND);
270                while(getSn_CR(sn));
271                return SOCKERR_BUSY;
272             }
273          #endif
274          sock_is_sending &= ~(1<<sn);         
275       }
276       else if(tmp & Sn_IR_TIMEOUT)
277       {
278          close(sn);
279          return SOCKERR_TIMEOUT;
280       }
281       else return SOCK_BUSY;
282    }
283    freesize = getSn_TxMAX(sn);
284    if (len > freesize) len = freesize; // check size not to exceed MAX size.
285    while(1)
286    {
287       freesize = getSn_TX_FSR(sn);
288       tmp = getSn_SR(sn);
289       if ((tmp != SOCK_ESTABLISHED) && (tmp != SOCK_CLOSE_WAIT))
290       {
291          close(sn);
292          return SOCKERR_SOCKSTATUS;
293       }
294       if( (sock_io_mode & (1<<sn)) && (len > freesize) ) return SOCK_BUSY;
295       if(len <= freesize) break;
296    }
297    wiz_send_data(sn, buf, len);
298    #if _WIZCHIP_ == 5200
299       sock_next_rd[sn] = getSn_TX_RD(sn) + len;
300    #endif
301    setSn_CR(sn,Sn_CR_SEND);
302    /* wait to process the command... */
303    while(getSn_CR(sn));
304    sock_is_sending |= (1 << sn);
305    return len;
306 }
307
308
309 int32_t recv(uint8_t sn, uint8_t * buf, uint16_t len)
310 {
311    uint8_t  tmp = 0;
312    uint16_t recvsize = 0;
313    CHECK_SOCKNUM();
314    CHECK_SOCKMODE(Sn_MR_TCP);
315    CHECK_SOCKDATA();
316    
317    recvsize = getSn_RxMAX(sn);
318    if(recvsize < len) len = recvsize;
319    while(1)
320    {
321       recvsize = getSn_RX_RSR(sn);
322       tmp = getSn_SR(sn);
323       if (tmp != SOCK_ESTABLISHED)
324       {
325          if(tmp == SOCK_CLOSE_WAIT)
326          {
327             if(recvsize != 0) break;
328             else if(getSn_TX_FSR(sn) == getSn_TxMAX(sn))
329             {
330                close(sn);
331                return SOCKERR_SOCKSTATUS;
332             }
333          }
334          else
335          {
336             close(sn);
337             return SOCKERR_SOCKSTATUS;
338          }
339       }
340       if((sock_io_mode & (1<<sn)) && (recvsize == 0)) return SOCK_BUSY;
341       if(recvsize != 0) break;
342    };
343    if(recvsize < len) len = recvsize;
344    wiz_recv_data(sn, buf, len);
345    setSn_CR(sn,Sn_CR_RECV);
346    while(getSn_CR(sn));
347    return len;
348 }
349
350 int32_t sendto(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port)
351 {
352    uint8_t tmp = 0;
353    uint16_t freesize = 0;
354    CHECK_SOCKNUM();
355    switch(getSn_MR(sn) & 0x0F)
356    {
357       case Sn_MR_UDP:
358       case Sn_MR_MACRAW:
359          break;
360       default:
361          return SOCKERR_SOCKMODE;
362    }
363    CHECK_SOCKDATA();
364    //M20140501 : For avoiding fatal error on memory align mismatched
365    //if(*((uint32_t*)addr) == 0) return SOCKERR_IPINVALID;
366    {
367       uint32_t taddr;
368       taddr = ((uint32_t)addr[0]) & 0x000000FF;
369       taddr = (taddr << 8) + ((uint32_t)addr[1] & 0x000000FF);
370       taddr = (taddr << 8) + ((uint32_t)addr[2] & 0x000000FF);
371       taddr = (taddr << 8) + ((uint32_t)addr[3] & 0x000000FF);
372    }
373    //
374    if(*((uint32_t*)addr) == 0) return SOCKERR_IPINVALID;
375    if(port == 0)               return SOCKERR_PORTZERO;
376    tmp = getSn_SR(sn);
377    if(tmp != SOCK_MACRAW && tmp != SOCK_UDP) return SOCKERR_SOCKSTATUS;
378       
379    setSn_DIPR(sn,addr);
380    setSn_DPORT(sn,port);      
381    freesize = getSn_TxMAX(sn);
382    if (len > freesize) len = freesize; // check size not to exceed MAX size.
383    while(1)
384    {
385       freesize = getSn_TX_FSR(sn);
386       if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED;
387       if( (sock_io_mode & (1<<sn)) && (len > freesize) ) return SOCK_BUSY;
388       if(len <= freesize) break;
389    };
390     wiz_send_data(sn, buf, len);
391
392    #if _WIZCHIP_ == 5200   // for W5200 ARP errata 
393       setSUBR(0);
394    #endif
395
396     setSn_CR(sn,Sn_CR_SEND);
397     /* wait to process the command... */
398     while(getSn_CR(sn));
399    #if _WIZCHIP_ == 5200   // for W5200 ARP errata 
400       setSUBR((uint8_t*)"\x00\x00\x00\x00");
401    #endif
402    while(1)
403    {
404       tmp = getSn_IR(sn);
405       if(tmp & Sn_IR_SENDOK)
406       {
407          setSn_IR(sn, Sn_IR_SENDOK);
408          break;
409       }
410       //M:20131104
411       //else if(tmp & Sn_IR_TIMEOUT) return SOCKERR_TIMEOUT;
412       else if(tmp & Sn_IR_TIMEOUT)
413       {
414          setSn_IR(sn, Sn_IR_TIMEOUT);
415          return SOCKERR_TIMEOUT;
416       }
417       ////////////
418    }
419     return len;
420 }
421
422
423
424 int32_t recvfrom(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port)
425 {
426    uint8_t  mr;
427    uint8_t  head[8];
428     uint16_t pack_len=0;
429
430    CHECK_SOCKNUM();
431    //CHECK_SOCKMODE(Sn_MR_UDP);
432    switch((mr=getSn_MR(sn)) & 0x0F)
433    {
434       case Sn_MR_UDP:
435       case Sn_MR_MACRAW:
436          break;
437    #if ( _WIZCHIP_ < 5200 )         
438       case Sn_MR_IPRAW:
439       case Sn_MR_PPPoE:
440          break;
441    #endif
442       default:
443          return SOCKERR_SOCKMODE;
444    }
445    CHECK_SOCKDATA();
446    if(sock_remained_size[sn] == 0)
447    {
448       while(1)
449       {
450          pack_len = getSn_RX_RSR(sn);
451          if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED;
452          if( (sock_io_mode & (1<<sn)) && (pack_len == 0) ) return SOCK_BUSY;
453          if(pack_len != 0) break;
454       };
455    }
456    sock_pack_info[sn] = PACK_COMPLETED;
457     switch (mr & 0x07)
458     {
459        case Sn_MR_UDP :
460           if(sock_remained_size[sn] == 0)
461           {
462                wiz_recv_data(sn, head, 8);
463                setSn_CR(sn,Sn_CR_RECV);
464                while(getSn_CR(sn));
465                // read peer's IP address, port number & packet length
466                 addr[0] = head[0];
467                addr[1] = head[1];
468                addr[2] = head[2];
469                addr[3] = head[3];
470                *port = head[4];
471                *port = (*port << 8) + head[5];
472                sock_remained_size[sn] = head[6];
473                sock_remained_size[sn] = (sock_remained_size[sn] << 8) + head[7];
474                sock_pack_info[sn] = PACK_FIRST;
475           }
476             if(len < sock_remained_size[sn]) pack_len = len;
477             else pack_len = sock_remained_size[sn];
478             //
479             // Need to packet length check (default 1472)
480             //
481            wiz_recv_data(sn, buf, pack_len); // data copy.
482             break;
483        case Sn_MR_MACRAW :
484           if(sock_remained_size[sn] == 0)
485           {
486                wiz_recv_data(sn, head, 2);
487                setSn_CR(sn,Sn_CR_RECV);
488                while(getSn_CR(sn));
489                // read peer's IP address, port number & packet length
490                 sock_remained_size[sn] = head[0];
491                sock_remained_size[sn] = (sock_remained_size[sn] <<8) + head[1];
492                if(sock_remained_size[sn] > 1514) 
493                {
494                   close(sn);
495                   return SOCKFATAL_PACKLEN;
496                }
497                sock_pack_info[sn] = PACK_FIRST;
498           }
499             if(len < sock_remained_size[sn]) pack_len = len;
500             else pack_len = sock_remained_size[sn];
501             wiz_recv_data(sn,buf,pack_len);
502            break;
503    #if ( _WIZCHIP_ < 5200 )
504         case Sn_MR_IPRAW:
505            if(sock_remained_size[sn] == 0)
506            {
507                wiz_recv_data(sn, head, 6);
508                setSn_CR(sn,Sn_CR_RECV);
509                while(getSn_CR(sn));
510                addr[0] = head[0];
511                addr[1] = head[1];
512                addr[2] = head[2];
513                addr[3] = head[3];
514                sock_remained_size[sn] = head[4];
515                sock_remaiend_size[sn] = (sock_remained_size[sn] << 8) + head[5];
516                sock_pack_info[sn] = PACK_FIRST;
517          }
518             //
519             // Need to packet length check
520             //
521             if(len < sock_remained_size[sn]) pack_len = len;
522             else pack_len = sock_remained_size[sn];
523            wiz_recv_data(sn, buf, pack_len); // data copy.
524             break;
525    #endif
526       default:
527          wiz_recv_ignore(sn, pack_len); // data copy.
528          sock_remained_size[sn] = pack_len;
529          break;
530    }
531     setSn_CR(sn,Sn_CR_RECV);
532     /* wait to process the command... */
533     while(getSn_CR(sn)) ;
534     sock_remained_size[sn] -= pack_len;
535     //M20140501 : replace 0x01 with PACK_REMAINED
536     //if(sock_remained_size[sn] != 0) sock_pack_info[sn] |= 0x01;
537     if(sock_remained_size[sn] != 0) sock_pack_info[sn] |= PACK_REMAINED;
538    //
539      return pack_len;
540 }
541
542
543 int8_t  ctlsocket(uint8_t sn, ctlsock_type cstype, void* arg)
544 {
545    uint8_t tmp = 0;
546    CHECK_SOCKNUM();
547    switch(cstype)
548    {
549       case CS_SET_IOMODE:
550          tmp = *((uint8_t*)arg);
551          if(tmp == SOCK_IO_NONBLOCK)  sock_io_mode |= (1<<sn);
552          else if(tmp == SOCK_IO_BLOCK) sock_io_mode &= ~(1<<sn);
553          else return SOCKERR_ARG;
554          break;
555       case CS_GET_IOMODE:   
556          //M20140501 : implict type casting -> explict type casting
557          //*((uint8_t*)arg) = (sock_io_mode >> sn) & 0x0001;
558          *((uint8_t*)arg) = (uint8_t)((sock_io_mode >> sn) & 0x0001);
559          //
560          break;
561       case CS_GET_MAXTXBUF:
562          *((uint16_t*)arg) = getSn_TxMAX(sn);
563          break;
564       case CS_GET_MAXRXBUF:    
565          *((uint16_t*)arg) = getSn_RxMAX(sn);
566          break;
567       case CS_CLR_INTERRUPT:
568          if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG;
569          setSn_IR(sn,*(uint8_t*)arg);
570          break;
571       case CS_GET_INTERRUPT:
572          *((uint8_t*)arg) = getSn_IR(sn);
573          break;
574       case CS_SET_INTMASK:  
575          if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG;
576          setSn_IMR(sn,*(uint8_t*)arg);
577          break;
578       case CS_GET_INTMASK:   
579          *((uint8_t*)arg) = getSn_IMR(sn);
580       default:
581          return SOCKERR_ARG;
582    }
583    return SOCK_OK;
584 }
585
586 int8_t  setsockopt(uint8_t sn, sockopt_type sotype, void* arg)
587 {
588  // M20131220 : Remove warning
589  //uint8_t tmp;
590    CHECK_SOCKNUM();
591    switch(sotype)
592    {
593       case SO_TTL:
594          setSn_TTL(sn,*(uint8_t*)arg);
595          break;
596       case SO_TOS:
597          setSn_TOS(sn,*(uint8_t*)arg);
598          break;
599       case SO_MSS:
600          setSn_MSSR(sn,*(uint16_t*)arg);
601          break;
602       case SO_DESTIP:
603          setSn_DIPR(sn, (uint8_t*)arg);
604          break;
605       case SO_DESTPORT:
606          setSn_DPORT(sn, *(uint16_t*)arg);
607          break;
608 #if _WIZCHIP_ != 5100
609       case SO_KEEPALIVESEND:
610          CHECK_SOCKMODE(Sn_MR_TCP);
611          #if _WIZCHIP_ > 5200
612             if(getSn_KPALVTR(sn) != 0) return SOCKERR_SOCKOPT;
613          #endif
614             setSn_CR(sn,Sn_CR_SEND_KEEP);
615             while(getSn_CR(sn) != 0)
616             {
617                // M20131220
618                  //if ((tmp = getSn_IR(sn)) & Sn_IR_TIMEOUT)
619                if (getSn_IR(sn) & Sn_IR_TIMEOUT)
620                  {
621                      setSn_IR(sn, Sn_IR_TIMEOUT);
622                   return SOCKERR_TIMEOUT;
623                  }
624             }
625          break;
626    #if _WIZCHIP_ > 5200
627       case SO_KEEPALIVEAUTO:
628          CHECK_SOCKMODE(Sn_MR_TCP);
629          setSn_KPALVTR(sn,*(uint8_t*)arg);
630          break;
631    #endif      
632 #endif   
633       default:
634          return SOCKERR_ARG;
635    }   
636    return SOCK_OK;
637 }
638
639 int8_t  getsockopt(uint8_t sn, sockopt_type sotype, void* arg)
640 {
641    CHECK_SOCKNUM();
642    switch(sotype)
643    {
644       case SO_FLAG:
645          *(uint8_t*)arg = getSn_MR(sn) & 0xF0;
646          break;
647       case SO_TTL:
648          *(uint8_t*) arg = getSn_TTL(sn);
649          break;
650       case SO_TOS:
651          *(uint8_t*) arg = getSn_TOS(sn);
652          break;
653       case SO_MSS:   
654          *(uint8_t*) arg = getSn_MSSR(sn);
655       case SO_DESTIP:
656          getSn_DIPR(sn, (uint8_t*)arg);
657          break;
658       case SO_DESTPORT:  
659          *(uint16_t*) arg = getSn_DPORT(sn);
660          break;
661    #if _WIZCHIP_ > 5200   
662       case SO_KEEPALIVEAUTO:
663          CHECK_SOCKMODE(Sn_MR_TCP);
664          *(uint16_t*) arg = getSn_KPALVTR(sn);
665          break;
666    #endif      
667       case SO_SENDBUF:
668          *(uint16_t*) arg = getSn_TX_FSR(sn);
669       case SO_RECVBUF:
670          *(uint16_t*) arg = getSn_RX_RSR(sn);
671       case SO_STATUS:
672          *(uint8_t*) arg = getSn_SR(sn);
673          break;
674       case SO_REMAINSIZE:
675          if(getSn_MR(sn) == Sn_MR_TCP)
676             *(uint16_t*)arg = getSn_RX_RSR(sn);
677          else
678             *(uint16_t*)arg = sock_remained_size[sn];
679          break;
680       case SO_PACKINFO:
681          CHECK_SOCKMODE(Sn_MR_TCP);
682          *(uint8_t*)arg = sock_pack_info[sn];
683          break;
684       default:
685          return SOCKERR_SOCKOPT;
686    }
687    return SOCK_OK;
688 }