W5500
socket.c
Go to the documentation of this file.
1 //*****************************************************************************
2 //
40 //
41 //*****************************************************************************
42 #include "socket.h"
43 
44 #define SOCK_ANY_PORT_NUM 0xC000;
45 
46 static uint16_t sock_any_port = SOCK_ANY_PORT_NUM;
47 
48 #define CHECK_SOCKNUM() \
49  do{ \
50  if(sn > _WIZCHIP_SOCK_NUM_) return SOCKERR_SOCKNUM; \
51  }while(0); \
52 
53 #define CHECK_SOCKMODE(mode) \
54  do{ \
55  if((getSn_MR(sn) & 0x0F) != mode) return SOCKERR_SOCKMODE; \
56  }while(0); \
57 
58 #define CHECK_SOCKINIT() \
59  do{ \
60  if((getSn_SR(sn) != SOCK_INIT)) return SOCKERR_SOCKINIT; \
61  }while(0); \
62 
63 #define CHECK_SOCKDATA() \
64  do{ \
65  if(len == 0) return SOCKERR_DATALEN; \
66  }while(0); \
67 
68 
75 int8_t socket(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag)
76 {
77  CHECK_SOCKNUM();
78  switch(protocol)
79  {
80  case Sn_MR_TCP :
81  case Sn_MR_UDP :
82  case Sn_MR_MACRAW :
83  break;
84  #if ( _WIZCHIP_ < 5200 )
85  case Sn_MR_IPRAW :
86  case Sn_MR_PPPoE :
87  break;
88  #endif
89  default :
90  return SOCKERR_SOCKMODE;
91  }
92  close(sn);
93  setSn_MR(sn, (protocol | (flag & 0xF0)));
94  if(!port)
95  {
96  port = sock_any_port++;
97  if(sock_any_port == 0xFFF0) sock_any_port = SOCK_ANY_PORT_NUM;
98  }
99  setSn_PORT(sn,port);
100  setSn_CR(sn,Sn_CR_OPEN);
101  while(getSn_CR(sn));
102  return (int8_t)sn;
103 }
104 
110 int8_t close(uint8_t sn)
111 {
112  CHECK_SOCKNUM();
113 
114  setSn_CR(sn,Sn_CR_CLOSE);
115  /* wait to process the command... */
116  while( getSn_CR(sn) );
117  /* clear all interrupt of the socket. */
118  setSn_IR(sn, 0xFF);
119  return SOCKOK_SUCC;
120 }
121 
122 
131 int8_t listen(uint8_t sn)
132 {
133  CHECK_SOCKNUM();
135  CHECK_SOCKINIT();
137  while(getSn_CR(sn));
138  while(getSn_SR(sn) != SOCK_LISTEN)
139  {
140  if(getSn_CR(sn) == SOCK_CLOSED)
141  {
142  close(sn);
143  return SOCKERR_SOCKCLOSED;
144  }
145  }
146  return SOCKOK_SUCC;
147 }
148 
149 
161 int8_t connect(uint8_t sn, uint8_t * addr, uint16_t port)
162 {
163  CHECK_SOCKNUM();
165  CHECK_SOCKINIT();
166  if( *((uint32_t*)addr) == 0xFFFFFFFF || *((uint32_t*)addr) == 0) return SOCKERR_IPINVALID;
167  if(port == 0) return SOCKERR_PORTZERO;
168  setSn_DIPR(sn,addr);
169  setSn_DPORT(sn,port);
170 // setSUBR(); // set the subnet mask register
172  while(getSn_CR(sn));
173  while(getSn_SR(sn) != SOCK_ESTABLISHED)
174  {
175  if (getSn_IR(sn) & Sn_IR_TIMEOUT)
176  {
177  setSn_IR(sn, Sn_IR_TIMEOUT);
178  return SOCKERR_TIMEOUT;
179  }
180  }
181 // clearSUBR(); // clear the subnet mask again and keep it because of the ARP errata of W5100
182  return SOCKOK_SUCC;
183 }
184 
185 
186 
194 int8_t disconnect(uint8_t sn)
195 {
196  CHECK_SOCKNUM();
199  /* wait to process the command... */
200  while(getSn_CR(sn));
201  while(getSn_SR(sn) != SOCK_CLOSED)
202  {
203  if(getSn_IR(sn) & Sn_IR_TIMEOUT)
204  {
205  close(sn);
206  return SOCKERR_TIMEOUT;
207  }
208  }
209  return SOCKOK_SUCC;
210 }
211 
212 
221 int32_t send(uint8_t sn, uint8_t * buf, uint16_t len)
222 {
223  uint8_t tmp=0;
224  uint16_t freesize=0;
225 
226  CHECK_SOCKNUM();
228  CHECK_SOCKDATA();
229  tmp = getSn_SR(sn);
230  if(tmp != SOCK_ESTABLISHED && tmp != SOCK_CLOSE_WAIT) return SOCKERR_SOCKSTATUS;
231  freesize = getSn_TXBUF_SIZE(sn) << 10;
232  if (len > freesize) len = freesize; // check size not to exceed MAX size.
233  do
234  {
235  freesize = getSn_TX_FSR(sn);
236  tmp = getSn_SR(sn);
237  if ((tmp != SOCK_ESTABLISHED) && (tmp != SOCK_CLOSE_WAIT))
238  {
239  close(sn);
240  return SOCKERR_SOCKSTATUS;
241  }
242  } while (freesize < len);
243  wiz_send_data(sn, buf, len);
244 
245  setSn_CR(sn,Sn_CR_SEND);
246  /* wait to process the command... */
247  while(getSn_CR(sn));
248  while( ((tmp = getSn_IR(sn)) & Sn_IR_SENDOK) !=Sn_IR_SENDOK )
249  {
250  if(tmp & Sn_IR_TIMEOUT)
251  {
252  close(sn);
253  return SOCKERR_TIMEOUT;
254  }
255  }
256  setSn_IR(sn, Sn_IR_SENDOK);
257  return len;
258 }
259 
260 
267 int32_t recv(uint8_t sn, uint8_t * buf, uint16_t len)
268 {
269  uint8_t tmp = 0;
270  uint16_t recvsize = 0;
271  CHECK_SOCKNUM();
273  CHECK_SOCKDATA();
274 
275  recvsize = getSn_RXBUF_SIZE(sn) << 10;
276  if(recvsize < len) len = recvsize;
277  do
278  {
279  recvsize = getSn_RX_RSR(sn);
280  tmp = getSn_SR(sn);
281  if ((tmp != SOCK_ESTABLISHED) && (tmp != SOCK_CLOSE_WAIT))
282  {
283  close(sn);
284  return SOCKERR_SOCKSTATUS;
285  }
286  }while(recvsize < len);
287  wiz_recv_data(sn, buf, len);
288  setSn_CR(sn,Sn_CR_RECV);
289  while(getSn_CR(sn));
290  return len;
291 }
292 
305 int32_t sendto(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port)
306 {
307  uint8_t tmp = 0;
308  uint16_t freesize = 0;
309  CHECK_SOCKNUM();
310  //CHECK_SOCKMODE(Sn_MR_UDP);
311  switch(getSn_MR(sn) & 0x0F)
312  {
313  case Sn_MR_UDP:
314  case Sn_MR_MACRAW:
315  break;
316  default:
317  return SOCKERR_SOCKMODE;
318  }
319 
320  CHECK_SOCKDATA();
321  if(*((uint32_t*)addr) == 0) return SOCKERR_IPINVALID;
322  if(port == 0) return SOCKERR_PORTZERO;
323  tmp = getSn_SR(sn);
324  if(tmp != SOCK_INIT && tmp != SOCK_UDP) return SOCKERR_SOCKSTATUS;
325  setSn_DIPR(sn,addr);
326  setSn_DPORT(sn,port);
327 
328  freesize = getSn_TXBUF_SIZE(sn) << 10;
329  if (len > freesize) len = freesize; // check size not to exceed MAX size.
330  do
331  {
332  freesize = getSn_TX_FSR(sn);
333  if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED;
334  }while(freesize < len);
335  wiz_send_data(sn, buf, len);
336 // setSUBR(); // set the subnet mask register
337  setSn_CR(sn,Sn_CR_SEND);
338  /* wait to process the command... */
339  while(getSn_CR(sn));
340  while ( ((tmp = getSn_IR(sn)) & Sn_IR_SENDOK) != Sn_IR_SENDOK )
341  {
342  if(tmp & Sn_IR_TIMEOUT)
343  {
344  setSn_IR(sn, (Sn_IR_SENDOK | Sn_IR_TIMEOUT)); /* clear SEND_OK & TIMEOUT */
345  return SOCKERR_TIMEOUT;
346  }
347  }
348 // clearSUBR(); // clear the subnet mask again and keep it because of the ARP errata of W5100
349  setSn_IR(sn, Sn_IR_SENDOK);
350  return len;
351 }
352 
353 
360 int32_t recvfrom(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port)
361 {
362  uint8_t mr = 0;
363  uint8_t head[8];
364  uint16_t pack_len=0;
365 
366  CHECK_SOCKNUM();
367  //CHECK_SOCKMODE(Sn_MR_UDP);
368  switch((mr=getSn_MR(sn)) & 0x0F)
369  {
370  case Sn_MR_UDP:
371  case Sn_MR_MACRAW:
372  break;
373  #if ( _WIZCHIP_ < 5200 )
374  case Sn_MR_IPRAW:
375  case Sn_MR_PPPoE:
376  break;
377  #endif
378  default:
379  return SOCKERR_SOCKMODE;
380  }
381  CHECK_SOCKDATA();
382  do
383  {
384  pack_len = getSn_RX_RSR(sn);
385  if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED;
386  }while(pack_len < len);
387 
388  switch (mr & 0x07)
389  {
390  case Sn_MR_UDP :
391  wiz_recv_data(sn, head, 8);
392  setSn_CR(sn,Sn_CR_RECV);
393  while(getSn_CR(sn));
394  // read peer's IP address, port number & packet length
395  addr[0] = head[0];
396  addr[1] = head[1];
397  addr[2] = head[2];
398  addr[3] = head[3];
399  *port = head[4];
400  *port = (*port << 8) + head[5];
401  pack_len = head[6];
402  pack_len = (pack_len << 8) + head[7];
403  //
404  // Need to packet length check (default 1472)
405  //
406  wiz_recv_data(sn, buf, pack_len); // data copy.
407  break;
408  case Sn_MR_MACRAW :
409  wiz_recv_data(sn, head, 2);
410  setSn_CR(sn,Sn_CR_RECV);
411  while(getSn_CR(sn));
412  // read peer's IP address, port number & packet length
413  pack_len = head[0];
414  pack_len = (pack_len<<8) + head[1];
415  if(pack_len > 1514)
416  {
417  close(sn);
418  return SOCKFATAL_PACKLEN;
419  }
420  wiz_recv_data(sn,buf,pack_len);
421  break;
422  #if ( _WIZCHIP_ < 5200 )
423  case Sn_MR_IPRAW:
424  wiz_recv_data(sn, head, 6);
425  setSn_CR(sn,Sn_CR_RECV);
426  while(getSn_CR(sn));
427  addr[0] = head[0];
428  addr[1] = head[1];
429  addr[2] = head[2];
430  addr[3] = head[3];
431  pack_len = head[4];
432  pack_len = (pack_len << 8) + head[5];
433  //
434  // Need to packet length check
435  //
436  wiz_recv_data(sn, buf, pack_len); // data copy.
437  break;
438  #endif
439  default:
440  wiz_recv_data(sn, buf, pack_len); // data copy.
441  break;
442  }
443  setSn_CR(sn,Sn_CR_RECV);
444  /* wait to process the command... */
445  while(getSn_CR(sn)) ;
446  return pack_len;
447 }
448 
449