Socket APIs
socket.c
Go to the documentation of this file.
1 //*****************************************************************************
2 //
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();
171  CHECK_SOCKINIT();
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();
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
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();
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();
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();
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  }
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:
611  #if _WIZCHIP_ > 5200
612  if(getSn_KPALVTR(sn) != 0) return SOCKERR_SOCKOPT;
613  #endif
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:
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:
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:
682  *(uint8_t*)arg = sock_pack_info[sn];
683  break;
684  default:
685  return SOCKERR_SOCKOPT;
686  }
687  return SOCK_OK;
688 }