1 //*****************************************************************************
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 
53 #include <string.h>
54 
55 #include "py/mpthread.h"
56 #include "socket.h"
57 
58 #define SOCK_ANY_PORT_NUM  0xC000;
59 
60 static uint16_t sock_any_port = SOCK_ANY_PORT_NUM;
61 static uint16_t sock_io_mode = 0;
62 static uint16_t sock_is_sending = 0;
63 static uint16_t sock_remained_size[_WIZCHIP_SOCK_NUM_] = {0,0,};
64 static uint8_t  sock_pack_info[_WIZCHIP_SOCK_NUM_] = {0,};
65 
66 #if _WIZCHIP_ == 5200
67    static uint16_t sock_next_rd[_WIZCHIP_SOCK_NUM_] ={0,};
68 #endif
69 
70 #define CHECK_SOCKNUM()   \
71    do{                    \
72       if(sn > _WIZCHIP_SOCK_NUM_) return SOCKERR_SOCKNUM;   \
73    }while(0);             \
74 
75 #define CHECK_SOCKMODE(mode)  \
76    do{                     \
77       if((getSn_MR(sn) & 0x0F) != mode) return SOCKERR_SOCKMODE;  \
78    }while(0);              \
79 
80 #define CHECK_SOCKINIT()   \
81    do{                     \
82       if((getSn_SR(sn) != SOCK_INIT)) return SOCKERR_SOCKINIT; \
83    }while(0);              \
84 
85 #define CHECK_SOCKDATA()   \
86    do{                     \
87       if(len == 0) return SOCKERR_DATALEN;   \
88    }while(0);              \
89 
WIZCHIP_EXPORT(socket_reset)90 void WIZCHIP_EXPORT(socket_reset)(void) {
91     sock_any_port = SOCK_ANY_PORT_NUM;
92     sock_io_mode = 0;
93     sock_is_sending = 0;
94     /*
95     memset(sock_remained_size, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint16_t));
96     memset(sock_pack_info, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint8_t));
97     */
98 
99 #if _WIZCHIP_ == 5200
100     memset(sock_next_rd, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint16_t));
101 #endif
102 }
103 
WIZCHIP_EXPORT(socket)104 int8_t WIZCHIP_EXPORT(socket)(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag)
105 {
106 	CHECK_SOCKNUM();
107 	switch(protocol)
108 	{
109       case Sn_MR_TCP :
110       case Sn_MR_UDP :
111       case Sn_MR_MACRAW :
112          break;
113    #if ( _WIZCHIP_ < 5200 )
114       case Sn_MR_IPRAW :
115       case Sn_MR_PPPoE :
116          break;
117    #endif
118       default :
119          return SOCKERR_SOCKMODE;
120 	}
121 	if((flag & 0x06) != 0) return SOCKERR_SOCKFLAG;
122 #if _WIZCHIP_ == 5200
123    if(flag & 0x10) return SOCKERR_SOCKFLAG;
124 #endif
125 
126 	if(flag != 0)
127 	{
128    	switch(protocol)
129    	{
130    	   case Sn_MR_TCP:
131    	      if((flag & (SF_TCP_NODELAY|SF_IO_NONBLOCK))==0) return SOCKERR_SOCKFLAG;
132    	      break;
133    	   case Sn_MR_UDP:
134    	      if(flag & SF_IGMP_VER2)
135    	      {
136    	         if((flag & SF_MULTI_ENABLE)==0) return SOCKERR_SOCKFLAG;
137    	      }
138    	      #if _WIZCHIP_ == 5500
139       	      if(flag & SF_UNI_BLOCK)
140       	      {
141       	         if((flag & SF_MULTI_ENABLE) == 0) return SOCKERR_SOCKFLAG;
142       	      }
143    	      #endif
144    	      break;
145    	   default:
146    	      break;
147    	}
148    }
149 	WIZCHIP_EXPORT(close)(sn);
150 	setSn_MR(sn, (protocol | (flag & 0xF0)));
151 	if(!port)
152 	{
153 	   port = sock_any_port++;
154 	   if(sock_any_port == 0xFFF0) sock_any_port = SOCK_ANY_PORT_NUM;
155 	}
156    setSn_PORT(sn,port);
157    setSn_CR(sn,Sn_CR_OPEN);
158    while(getSn_CR(sn));
159    sock_io_mode |= ((flag & SF_IO_NONBLOCK) << sn);
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 (int8_t)sn;
165 }
166 
WIZCHIP_EXPORT(close)167 int8_t WIZCHIP_EXPORT(close)(uint8_t sn)
168 {
169 	CHECK_SOCKNUM();
170 
171 	setSn_CR(sn,Sn_CR_CLOSE);
172    /* wait to process the command... */
173 	while( getSn_CR(sn) );
174 	/* clear all interrupt of the socket. */
175 	setSn_IR(sn, 0xFF);
176 	sock_is_sending &= ~(1<<sn);
177 	sock_remained_size[sn] = 0;
178 	sock_pack_info[sn] = 0;
179 	while(getSn_SR(sn) != SOCK_CLOSED);
180 	return SOCK_OK;
181 }
182 
WIZCHIP_EXPORT(listen)183 int8_t WIZCHIP_EXPORT(listen)(uint8_t sn)
184 {
185 	CHECK_SOCKNUM();
186    CHECK_SOCKMODE(Sn_MR_TCP);
187 	CHECK_SOCKINIT();
188 	setSn_CR(sn,Sn_CR_LISTEN);
189 	while(getSn_CR(sn));
190    while(getSn_SR(sn) != SOCK_LISTEN)
191    {
192       if(getSn_CR(sn) == SOCK_CLOSED)
193       {
194          WIZCHIP_EXPORT(close)(sn);
195          return SOCKERR_SOCKCLOSED;
196       }
197    }
198    return SOCK_OK;
199 }
200 
201 
WIZCHIP_EXPORT(connect)202 int8_t WIZCHIP_EXPORT(connect)(uint8_t sn, uint8_t * addr, uint16_t port)
203 {
204    CHECK_SOCKNUM();
205    CHECK_SOCKMODE(Sn_MR_TCP);
206    CHECK_SOCKINIT();
207    //M20140501 : For avoiding fatal error on memory align mismatched
208    //if( *((uint32_t*)addr) == 0xFFFFFFFF || *((uint32_t*)addr) == 0) return SOCKERR_IPINVALID;
209    {
210       uint32_t taddr;
211       taddr = ((uint32_t)addr[0] & 0x000000FF);
212       taddr = (taddr << 8) + ((uint32_t)addr[1] & 0x000000FF);
213       taddr = (taddr << 8) + ((uint32_t)addr[2] & 0x000000FF);
214       taddr = (taddr << 8) + ((uint32_t)addr[3] & 0x000000FF);
215       if (taddr == 0xFFFFFFFF || taddr == 0) return SOCKERR_IPINVALID;
216    }
217    //
218 
219 	if(port == 0) return SOCKERR_PORTZERO;
220 	setSn_DIPR(sn,addr);
221 	setSn_DPORT(sn,port);
222    #if _WIZCHIP_ == 5200   // for W5200 ARP errata
223     setSUBR(wizchip_getsubn());
224    #endif
225 	setSn_CR(sn,Sn_CR_CONNECT);
226    while(getSn_CR(sn));
227    if(sock_io_mode & (1<<sn)) return SOCK_BUSY;
228    while(getSn_SR(sn) != SOCK_ESTABLISHED)
229    {
230         if (getSn_SR(sn) == SOCK_CLOSED) {
231             #if _WIZCHIP_ == 5200   // for W5200 ARP errata
232             setSUBR((uint8_t*)"\x00\x00\x00\x00");
233             #endif
234             return SOCKERR_SOCKCLOSED;
235         }
236 		if (getSn_IR(sn) & Sn_IR_TIMEOUT)
237 		{
238 			setSn_IR(sn, Sn_IR_TIMEOUT);
239          #if _WIZCHIP_ == 5200   // for W5200 ARP errata
240             setSUBR((uint8_t*)"\x00\x00\x00\x00");
241          #endif
242          return SOCKERR_TIMEOUT;
243 		}
244         MICROPY_THREAD_YIELD();
245 	}
246    #if _WIZCHIP_ == 5200   // for W5200 ARP errata
247       setSUBR((uint8_t*)"\x00\x00\x00\x00");
248    #endif
249 
250    return SOCK_OK;
251 }
252 
WIZCHIP_EXPORT(disconnect)253 int8_t WIZCHIP_EXPORT(disconnect)(uint8_t sn)
254 {
255    CHECK_SOCKNUM();
256    CHECK_SOCKMODE(Sn_MR_TCP);
257 	setSn_CR(sn,Sn_CR_DISCON);
258 	/* wait to process the command... */
259 	while(getSn_CR(sn));
260 	sock_is_sending &= ~(1<<sn);
261    if(sock_io_mode & (1<<sn)) return SOCK_BUSY;
262 	while(getSn_SR(sn) != SOCK_CLOSED)
263 	{
264 	   if(getSn_IR(sn) & Sn_IR_TIMEOUT)
265 	   {
266 	      WIZCHIP_EXPORT(close)(sn);
267 	      return SOCKERR_TIMEOUT;
268 	   }
269 	}
270 	return SOCK_OK;
271 }
272 
WIZCHIP_EXPORT(send)273 int32_t WIZCHIP_EXPORT(send)(uint8_t sn, uint8_t * buf, uint16_t len)
274 {
275    uint8_t tmp=0;
276    uint16_t freesize=0;
277 
278    CHECK_SOCKNUM();
279    CHECK_SOCKMODE(Sn_MR_TCP);
280    CHECK_SOCKDATA();
281    tmp = getSn_SR(sn);
282    if(tmp != SOCK_ESTABLISHED && tmp != SOCK_CLOSE_WAIT) return SOCKERR_SOCKSTATUS;
283    if( sock_is_sending & (1<<sn) )
284    {
285       tmp = getSn_IR(sn);
286       if(tmp & Sn_IR_SENDOK)
287       {
288          setSn_IR(sn, Sn_IR_SENDOK);
289          #if _WZICHIP_ == 5200
290             if(getSn_TX_RD(sn) != sock_next_rd[sn])
291             {
292                setSn_CR(sn,Sn_CR_SEND);
293                while(getSn_CR(sn));
294                return SOCKERR_BUSY;
295             }
296          #endif
297          sock_is_sending &= ~(1<<sn);
298       }
299       else if(tmp & Sn_IR_TIMEOUT)
300       {
301          WIZCHIP_EXPORT(close)(sn);
302          return SOCKERR_TIMEOUT;
303       }
304       else return SOCK_BUSY;
305    }
306    freesize = getSn_TxMAX(sn);
307    if (len > freesize) len = freesize; // check size not to exceed MAX size.
308    while(1)
309    {
310       freesize = getSn_TX_FSR(sn);
311       tmp = getSn_SR(sn);
312       if ((tmp != SOCK_ESTABLISHED) && (tmp != SOCK_CLOSE_WAIT))
313       {
314          WIZCHIP_EXPORT(close)(sn);
315          return SOCKERR_SOCKSTATUS;
316       }
317       if( (sock_io_mode & (1<<sn)) && (len > freesize) ) return SOCK_BUSY;
318       if(len <= freesize) break;
319       MICROPY_THREAD_YIELD();
320    }
321    wiz_send_data(sn, buf, len);
322    #if _WIZCHIP_ == 5200
323       sock_next_rd[sn] = getSn_TX_RD(sn) + len;
324    #endif
325    setSn_CR(sn,Sn_CR_SEND);
326    /* wait to process the command... */
327    while(getSn_CR(sn));
328    sock_is_sending |= (1 << sn);
329    return len;
330 }
331 
332 
WIZCHIP_EXPORT(recv)333 int32_t WIZCHIP_EXPORT(recv)(uint8_t sn, uint8_t * buf, uint16_t len)
334 {
335    uint8_t  tmp = 0;
336    uint16_t recvsize = 0;
337    CHECK_SOCKNUM();
338    CHECK_SOCKMODE(Sn_MR_TCP);
339    CHECK_SOCKDATA();
340 
341    recvsize = getSn_RxMAX(sn);
342    if(recvsize < len) len = recvsize;
343    while(1)
344    {
345       recvsize = getSn_RX_RSR(sn);
346       tmp = getSn_SR(sn);
347       if (tmp != SOCK_ESTABLISHED)
348       {
349          if(tmp == SOCK_CLOSE_WAIT)
350          {
351             if(recvsize != 0) break;
352             else if(getSn_TX_FSR(sn) == getSn_TxMAX(sn))
353             {
354                // dpgeorge: Getting here seems to be an orderly shutdown of the
355                // socket, and trying to get POSIX behaviour we return 0 because:
356                // "If no messages are available to be received and the peer has per‐
357                //  formed an orderly shutdown, recv() shall return 0".
358                // TODO this return value clashes with SOCK_BUSY in non-blocking mode.
359                WIZCHIP_EXPORT(close)(sn);
360                return 0;
361             }
362          }
363          else
364          {
365             WIZCHIP_EXPORT(close)(sn);
366             return SOCKERR_SOCKSTATUS;
367          }
368       }
369       if((sock_io_mode & (1<<sn)) && (recvsize == 0)) return SOCK_BUSY;
370       if(recvsize != 0) break;
371       MICROPY_THREAD_YIELD();
372    };
373    if(recvsize < len) len = recvsize;
374    wiz_recv_data(sn, buf, len);
375    setSn_CR(sn,Sn_CR_RECV);
376    while(getSn_CR(sn));
377    return len;
378 }
379 
WIZCHIP_EXPORT(sendto)380 int32_t WIZCHIP_EXPORT(sendto)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port)
381 {
382    uint8_t tmp = 0;
383    uint16_t freesize = 0;
384    CHECK_SOCKNUM();
385    switch(getSn_MR(sn) & 0x0F)
386    {
387       case Sn_MR_UDP:
388       case Sn_MR_MACRAW:
389          break;
390       default:
391          return SOCKERR_SOCKMODE;
392    }
393    CHECK_SOCKDATA();
394    //M20140501 : For avoiding fatal error on memory align mismatched
395    //if(*((uint32_t*)addr) == 0) return SOCKERR_IPINVALID;
396    {
397       uint32_t taddr;
398       taddr = ((uint32_t)addr[0]) & 0x000000FF;
399       taddr = (taddr << 8) + ((uint32_t)addr[1] & 0x000000FF);
400       taddr = (taddr << 8) + ((uint32_t)addr[2] & 0x000000FF);
401       taddr = (taddr << 8) + ((uint32_t)addr[3] & 0x000000FF);
402       if (taddr == 0xFFFFFFFF || taddr == 0) return SOCKERR_IPINVALID;
403    }
404    //
405    if(port == 0)               return SOCKERR_PORTZERO;
406    tmp = getSn_SR(sn);
407    if(tmp != SOCK_MACRAW && tmp != SOCK_UDP) return SOCKERR_SOCKSTATUS;
408 
409    setSn_DIPR(sn,addr);
410    setSn_DPORT(sn,port);
411    freesize = getSn_TxMAX(sn);
412    if (len > freesize) len = freesize; // check size not to exceed MAX size.
413    while(1)
414    {
415       freesize = getSn_TX_FSR(sn);
416       if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED;
417       if( (sock_io_mode & (1<<sn)) && (len > freesize) ) return SOCK_BUSY;
418       if(len <= freesize) break;
419       MICROPY_THREAD_YIELD();
420    };
421 	wiz_send_data(sn, buf, len);
422 
423    #if _WIZCHIP_ == 5200   // for W5200 ARP errata
424       setSUBR(wizchip_getsubn());
425    #endif
426 
427 	setSn_CR(sn,Sn_CR_SEND);
428 	/* wait to process the command... */
429 	while(getSn_CR(sn));
430    while(1)
431    {
432       tmp = getSn_IR(sn);
433       if(tmp & Sn_IR_SENDOK)
434       {
435          setSn_IR(sn, Sn_IR_SENDOK);
436          break;
437       }
438       //M:20131104
439       //else if(tmp & Sn_IR_TIMEOUT) return SOCKERR_TIMEOUT;
440       else if(tmp & Sn_IR_TIMEOUT)
441       {
442          setSn_IR(sn, Sn_IR_TIMEOUT);
443    #if _WIZCHIP_ == 5200   // for W5200 ARP errata
444       setSUBR((uint8_t*)"\x00\x00\x00\x00");
445    #endif
446          return SOCKERR_TIMEOUT;
447       }
448       ////////////
449       MICROPY_THREAD_YIELD();
450    }
451    #if _WIZCHIP_ == 5200   // for W5200 ARP errata
452       setSUBR((uint8_t*)"\x00\x00\x00\x00");
453    #endif
454 	return len;
455 }
456 
457 
458 
WIZCHIP_EXPORT(recvfrom)459 int32_t WIZCHIP_EXPORT(recvfrom)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port)
460 {
461    uint8_t  mr;
462    uint8_t  head[8];
463 	uint16_t pack_len=0;
464 
465    CHECK_SOCKNUM();
466    //CHECK_SOCKMODE(Sn_MR_UDP);
467    switch((mr=getSn_MR(sn)) & 0x0F)
468    {
469       case Sn_MR_UDP:
470       case Sn_MR_MACRAW:
471          break;
472    #if ( _WIZCHIP_ < 5200 )
473       case Sn_MR_IPRAW:
474       case Sn_MR_PPPoE:
475          break;
476    #endif
477       default:
478          return SOCKERR_SOCKMODE;
479    }
480    CHECK_SOCKDATA();
481    if(sock_remained_size[sn] == 0)
482    {
483       while(1)
484       {
485          pack_len = getSn_RX_RSR(sn);
486          if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED;
487          if( (sock_io_mode & (1<<sn)) && (pack_len == 0) ) return SOCK_BUSY;
488          if(pack_len != 0) break;
489          MICROPY_THREAD_YIELD();
490       };
491    }
492    sock_pack_info[sn] = PACK_COMPLETED;
493 	switch (mr & 0x07)
494 	{
495 	   case Sn_MR_UDP :
496 	      if(sock_remained_size[sn] == 0)
497 	      {
498    			wiz_recv_data(sn, head, 8);
499    			setSn_CR(sn,Sn_CR_RECV);
500    			while(getSn_CR(sn));
501    			// read peer's IP address, port number & packet length
502     			addr[0] = head[0];
503    			addr[1] = head[1];
504    			addr[2] = head[2];
505    			addr[3] = head[3];
506    			*port = head[4];
507    			*port = (*port << 8) + head[5];
508    			sock_remained_size[sn] = head[6];
509    			sock_remained_size[sn] = (sock_remained_size[sn] << 8) + head[7];
510    			sock_pack_info[sn] = PACK_FIRST;
511    	   }
512 			if(len < sock_remained_size[sn]) pack_len = len;
513 			else pack_len = sock_remained_size[sn];
514 			//
515 			// Need to packet length check (default 1472)
516 			//
517    		wiz_recv_data(sn, buf, pack_len); // data copy.
518 			break;
519 	   case Sn_MR_MACRAW :
520 	      if(sock_remained_size[sn] == 0)
521 	      {
522    			wiz_recv_data(sn, head, 2);
523    			setSn_CR(sn,Sn_CR_RECV);
524    			while(getSn_CR(sn));
525    			// read peer's IP address, port number & packet length
526     			sock_remained_size[sn] = head[0];
527    			sock_remained_size[sn] = (sock_remained_size[sn] <<8) + head[1];
528    			sock_remained_size[sn] -= 2; // len includes 2 len bytes
529    			if(sock_remained_size[sn] > 1514)
530    			{
531    			   WIZCHIP_EXPORT(close)(sn);
532    			   return SOCKFATAL_PACKLEN;
533    			}
534    			sock_pack_info[sn] = PACK_FIRST;
535    	   }
536 			if(len < sock_remained_size[sn]) pack_len = len;
537 			else pack_len = sock_remained_size[sn];
538 			wiz_recv_data(sn,buf,pack_len);
539 		   break;
540    #if ( _WIZCHIP_ < 5200 )
541 		case Sn_MR_IPRAW:
542 		   if(sock_remained_size[sn] == 0)
543 		   {
544    			wiz_recv_data(sn, head, 6);
545    			setSn_CR(sn,Sn_CR_RECV);
546    			while(getSn_CR(sn));
547    			addr[0] = head[0];
548    			addr[1] = head[1];
549    			addr[2] = head[2];
550    			addr[3] = head[3];
551    			sock_remained_size[sn] = head[4];
552    			sock_remaiend_size[sn] = (sock_remained_size[sn] << 8) + head[5];
553    			sock_pack_info[sn] = PACK_FIRST;
554          }
555 			//
556 			// Need to packet length check
557 			//
558 			if(len < sock_remained_size[sn]) pack_len = len;
559 			else pack_len = sock_remained_size[sn];
560    		wiz_recv_data(sn, buf, pack_len); // data copy.
561 			break;
562    #endif
563       default:
564          wiz_recv_ignore(sn, pack_len); // data copy.
565          sock_remained_size[sn] = pack_len;
566          break;
567    }
568 	setSn_CR(sn,Sn_CR_RECV);
569 	/* wait to process the command... */
570 	while(getSn_CR(sn)) ;
571 	sock_remained_size[sn] -= pack_len;
572 	//M20140501 : replace 0x01 with PACK_REMAINED
573 	//if(sock_remained_size[sn] != 0) sock_pack_info[sn] |= 0x01;
574 	if(sock_remained_size[sn] != 0) sock_pack_info[sn] |= PACK_REMAINED;
575    //
576  	return pack_len;
577 }
578 
579 
WIZCHIP_EXPORT(ctlsocket)580 int8_t  WIZCHIP_EXPORT(ctlsocket)(uint8_t sn, ctlsock_type cstype, void* arg)
581 {
582    uint8_t tmp = 0;
583    CHECK_SOCKNUM();
584    switch(cstype)
585    {
586       case CS_SET_IOMODE:
587          tmp = *((uint8_t*)arg);
588          if(tmp == SOCK_IO_NONBLOCK)  sock_io_mode |= (1<<sn);
589          else if(tmp == SOCK_IO_BLOCK) sock_io_mode &= ~(1<<sn);
590          else return SOCKERR_ARG;
591          break;
592       case CS_GET_IOMODE:
593          //M20140501 : implict type casting -> explict type casting
594          //*((uint8_t*)arg) = (sock_io_mode >> sn) & 0x0001;
595          *((uint8_t*)arg) = (uint8_t)((sock_io_mode >> sn) & 0x0001);
596          //
597          break;
598       case CS_GET_MAXTXBUF:
599          *((uint16_t*)arg) = getSn_TxMAX(sn);
600          break;
601       case CS_GET_MAXRXBUF:
602          *((uint16_t*)arg) = getSn_RxMAX(sn);
603          break;
604       case CS_CLR_INTERRUPT:
605          if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG;
606          setSn_IR(sn,*(uint8_t*)arg);
607          break;
608       case CS_GET_INTERRUPT:
609          *((uint8_t*)arg) = getSn_IR(sn);
610          break;
611       case CS_SET_INTMASK:
612          if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG;
613          setSn_IMR(sn,*(uint8_t*)arg);
614          break;
615       case CS_GET_INTMASK:
616          *((uint8_t*)arg) = getSn_IMR(sn);
617       default:
618          return SOCKERR_ARG;
619    }
620    return SOCK_OK;
621 }
622 
WIZCHIP_EXPORT(setsockopt)623 int8_t  WIZCHIP_EXPORT(setsockopt)(uint8_t sn, sockopt_type sotype, void* arg)
624 {
625  // M20131220 : Remove warning
626  //uint8_t tmp;
627    CHECK_SOCKNUM();
628    switch(sotype)
629    {
630       case SO_TTL:
631          setSn_TTL(sn,*(uint8_t*)arg);
632          break;
633       case SO_TOS:
634          setSn_TOS(sn,*(uint8_t*)arg);
635          break;
636       case SO_MSS:
637          setSn_MSSR(sn,*(uint16_t*)arg);
638          break;
639       case SO_DESTIP:
640          setSn_DIPR(sn, (uint8_t*)arg);
641          break;
642       case SO_DESTPORT:
643          setSn_DPORT(sn, *(uint16_t*)arg);
644          break;
645 #if _WIZCHIP_ != 5100
646       case SO_KEEPALIVESEND:
647          CHECK_SOCKMODE(Sn_MR_TCP);
648          #if _WIZCHIP_ > 5200
649             if(getSn_KPALVTR(sn) != 0) return SOCKERR_SOCKOPT;
650          #endif
651             setSn_CR(sn,Sn_CR_SEND_KEEP);
652             while(getSn_CR(sn) != 0)
653             {
654                // M20131220
655          		//if ((tmp = getSn_IR(sn)) & Sn_IR_TIMEOUT)
656                if (getSn_IR(sn) & Sn_IR_TIMEOUT)
657          		{
658          			setSn_IR(sn, Sn_IR_TIMEOUT);
659                   return SOCKERR_TIMEOUT;
660          		}
661             }
662          break;
663    #if _WIZCHIP_ > 5200
664       case SO_KEEPALIVEAUTO:
665          CHECK_SOCKMODE(Sn_MR_TCP);
666          setSn_KPALVTR(sn,*(uint8_t*)arg);
667          break;
668    #endif
669 #endif
670       default:
671          return SOCKERR_ARG;
672    }
673    return SOCK_OK;
674 }
675 
WIZCHIP_EXPORT(getsockopt)676 int8_t  WIZCHIP_EXPORT(getsockopt)(uint8_t sn, sockopt_type sotype, void* arg)
677 {
678    CHECK_SOCKNUM();
679    switch(sotype)
680    {
681       case SO_FLAG:
682          *(uint8_t*)arg = getSn_MR(sn) & 0xF0;
683          break;
684       case SO_TTL:
685          *(uint8_t*) arg = getSn_TTL(sn);
686          break;
687       case SO_TOS:
688          *(uint8_t*) arg = getSn_TOS(sn);
689          break;
690       case SO_MSS:
691          *(uint8_t*) arg = getSn_MSSR(sn);
692       case SO_DESTIP:
693          getSn_DIPR(sn, (uint8_t*)arg);
694          break;
695       case SO_DESTPORT:
696          *(uint16_t*) arg = getSn_DPORT(sn);
697          break;
698    #if _WIZCHIP_ > 5200
699       case SO_KEEPALIVEAUTO:
700          CHECK_SOCKMODE(Sn_MR_TCP);
701          *(uint16_t*) arg = getSn_KPALVTR(sn);
702          break;
703    #endif
704       case SO_SENDBUF:
705          *(uint16_t*) arg = getSn_TX_FSR(sn);
706       case SO_RECVBUF:
707          *(uint16_t*) arg = getSn_RX_RSR(sn);
708       case SO_STATUS:
709          *(uint8_t*) arg = getSn_SR(sn);
710          break;
711       case SO_REMAINSIZE:
712          if(getSn_MR(sn) == Sn_MR_TCP)
713             *(uint16_t*)arg = getSn_RX_RSR(sn);
714          else
715             *(uint16_t*)arg = sock_remained_size[sn];
716          break;
717       case SO_PACKINFO:
718          CHECK_SOCKMODE(Sn_MR_TCP);
719          *(uint8_t*)arg = sock_pack_info[sn];
720          break;
721       default:
722          return SOCKERR_SOCKOPT;
723    }
724    return SOCK_OK;
725 }
726