1 #include "w5100.h"
2 #include "socket.h"
3 
4 static uint16_t local_port;
5 
6 /**
7  * @brief	This Socket function initialize the channel in perticular mode, and set the port and wait for W5100 done it.
8  * @return 	1 for success else 0.
9  */
socket(SOCKET s,uint8_t protocol,uint16_t port,uint8_t flag)10 uint8_t socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag)
11 {
12   if ((protocol == SnMR::TCP) || (protocol == SnMR::UDP) || (protocol == SnMR::IPRAW) || (protocol == SnMR::MACRAW) || (protocol == SnMR::PPPOE))
13   {
14     close(s);
15     SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
16     W5100.writeSnMR(s, protocol | flag);
17     if (port != 0) {
18       W5100.writeSnPORT(s, port);
19     }
20     else {
21       local_port++; // if don't set the source port, set local_port number.
22       W5100.writeSnPORT(s, local_port);
23     }
24 
25     W5100.execCmdSn(s, Sock_OPEN);
26     SPI.endTransaction();
27     return 1;
28   }
29 
30   return 0;
31 }
32 
33 
socketStatus(SOCKET s)34 uint8_t socketStatus(SOCKET s)
35 {
36   SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
37   uint8_t status = W5100.readSnSR(s);
38   SPI.endTransaction();
39   return status;
40 }
41 
42 
43 /**
44  * @brief	This function close the socket and parameter is "s" which represent the socket number
45  */
close(SOCKET s)46 void close(SOCKET s)
47 {
48   SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
49   W5100.execCmdSn(s, Sock_CLOSE);
50   W5100.writeSnIR(s, 0xFF);
51   SPI.endTransaction();
52 }
53 
54 
55 /**
56  * @brief	This function established  the connection for the channel in passive (server) mode. This function waits for the request from the peer.
57  * @return	1 for success else 0.
58  */
listen(SOCKET s)59 uint8_t listen(SOCKET s)
60 {
61   SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
62   if (W5100.readSnSR(s) != SnSR::INIT) {
63     SPI.endTransaction();
64     return 0;
65   }
66   W5100.execCmdSn(s, Sock_LISTEN);
67   SPI.endTransaction();
68   return 1;
69 }
70 
71 
72 /**
73  * @brief	This function established  the connection for the channel in Active (client) mode.
74  * 		This function waits for the untill the connection is established.
75  *
76  * @return	1 for success else 0.
77  */
connect(SOCKET s,uint8_t * addr,uint16_t port)78 uint8_t connect(SOCKET s, uint8_t * addr, uint16_t port)
79 {
80   if
81     (
82   ((addr[0] == 0xFF) && (addr[1] == 0xFF) && (addr[2] == 0xFF) && (addr[3] == 0xFF)) ||
83     ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) ||
84     (port == 0x00)
85     )
86     return 0;
87 
88   // set destination IP
89   SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
90   W5100.writeSnDIPR(s, addr);
91   W5100.writeSnDPORT(s, port);
92   W5100.execCmdSn(s, Sock_CONNECT);
93   SPI.endTransaction();
94 
95   return 1;
96 }
97 
98 
99 
100 /**
101  * @brief	This function used for disconnect the socket and parameter is "s" which represent the socket number
102  * @return	1 for success else 0.
103  */
disconnect(SOCKET s)104 void disconnect(SOCKET s)
105 {
106   SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
107   W5100.execCmdSn(s, Sock_DISCON);
108   SPI.endTransaction();
109 }
110 
111 
112 /**
113  * @brief	This function used to send the data in TCP mode
114  * @return	1 for success else 0.
115  */
send(SOCKET s,const uint8_t * buf,uint16_t len)116 uint16_t send(SOCKET s, const uint8_t * buf, uint16_t len)
117 {
118   uint8_t status=0;
119   uint16_t ret=0;
120   uint16_t freesize=0;
121 
122   if (len > W5100.SSIZE)
123     ret = W5100.SSIZE; // check size not to exceed MAX size.
124   else
125     ret = len;
126 
127   // if freebuf is available, start.
128   do
129   {
130     SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
131     freesize = W5100.getTXFreeSize(s);
132     status = W5100.readSnSR(s);
133     SPI.endTransaction();
134     if ((status != SnSR::ESTABLISHED) && (status != SnSR::CLOSE_WAIT))
135     {
136       ret = 0;
137       break;
138     }
139     yield();
140   }
141   while (freesize < ret);
142 
143   // copy data
144   SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
145   W5100.send_data_processing(s, (uint8_t *)buf, ret);
146   W5100.execCmdSn(s, Sock_SEND);
147 
148   /* +2008.01 bj */
149   while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK )
150   {
151     /* m2008.01 [bj] : reduce code */
152     if ( W5100.readSnSR(s) == SnSR::CLOSED )
153     {
154       SPI.endTransaction();
155       close(s);
156       return 0;
157     }
158     SPI.endTransaction();
159     yield();
160     SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
161   }
162   /* +2008.01 bj */
163   W5100.writeSnIR(s, SnIR::SEND_OK);
164   SPI.endTransaction();
165   return ret;
166 }
167 
168 
169 /**
170  * @brief	This function is an application I/F function which is used to receive the data in TCP mode.
171  * 		It continues to wait for data as much as the application wants to receive.
172  *
173  * @return	received data size for success else -1.
174  */
recv(SOCKET s,uint8_t * buf,int16_t len)175 int16_t recv(SOCKET s, uint8_t *buf, int16_t len)
176 {
177   // Check how much data is available
178   SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
179   int16_t ret = W5100.getRXReceivedSize(s);
180   if ( ret == 0 )
181   {
182     // No data available.
183     uint8_t status = W5100.readSnSR(s);
184     if ( status == SnSR::LISTEN || status == SnSR::CLOSED || status == SnSR::CLOSE_WAIT )
185     {
186       // The remote end has closed its side of the connection, so this is the eof state
187       ret = 0;
188     }
189     else
190     {
191       // The connection is still up, but there's no data waiting to be read
192       ret = -1;
193     }
194   }
195   else if (ret > len)
196   {
197     ret = len;
198   }
199 
200   if ( ret > 0 )
201   {
202     W5100.recv_data_processing(s, buf, ret);
203     W5100.execCmdSn(s, Sock_RECV);
204   }
205   SPI.endTransaction();
206   return ret;
207 }
208 
209 
recvAvailable(SOCKET s)210 int16_t recvAvailable(SOCKET s)
211 {
212   SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
213   int16_t ret = W5100.getRXReceivedSize(s);
214   SPI.endTransaction();
215   return ret;
216 }
217 
218 
219 /**
220  * @brief	Returns the first byte in the receive queue (no checking)
221  *
222  * @return
223  */
peek(SOCKET s,uint8_t * buf)224 uint16_t peek(SOCKET s, uint8_t *buf)
225 {
226   SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
227   W5100.recv_data_processing(s, buf, 1, 1);
228   SPI.endTransaction();
229   return 1;
230 }
231 
232 
233 /**
234  * @brief	This function is an application I/F function which is used to send the data for other then TCP mode.
235  * 		Unlike TCP transmission, The peer's destination address and the port is needed.
236  *
237  * @return	This function return send data size for success else -1.
238  */
sendto(SOCKET s,const uint8_t * buf,uint16_t len,uint8_t * addr,uint16_t port)239 uint16_t sendto(SOCKET s, const uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t port)
240 {
241   uint16_t ret=0;
242 
243   if (len > W5100.SSIZE) ret = W5100.SSIZE; // check size not to exceed MAX size.
244   else ret = len;
245 
246   if
247     (
248   ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) ||
249     ((port == 0x00)) ||(ret == 0)
250     )
251   {
252     /* +2008.01 [bj] : added return value */
253     ret = 0;
254   }
255   else
256   {
257     SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
258     W5100.writeSnDIPR(s, addr);
259     W5100.writeSnDPORT(s, port);
260 
261     // copy data
262     W5100.send_data_processing(s, (uint8_t *)buf, ret);
263     W5100.execCmdSn(s, Sock_SEND);
264 
265     /* +2008.01 bj */
266     while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK )
267     {
268       if (W5100.readSnIR(s) & SnIR::TIMEOUT)
269       {
270         /* +2008.01 [bj]: clear interrupt */
271         W5100.writeSnIR(s, (SnIR::SEND_OK | SnIR::TIMEOUT)); /* clear SEND_OK & TIMEOUT */
272         SPI.endTransaction();
273         return 0;
274       }
275       SPI.endTransaction();
276       yield();
277       SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
278     }
279 
280     /* +2008.01 bj */
281     W5100.writeSnIR(s, SnIR::SEND_OK);
282     SPI.endTransaction();
283   }
284   return ret;
285 }
286 
287 
288 /**
289  * @brief	This function is an application I/F function which is used to receive the data in other then
290  * 	TCP mode. This function is used to receive UDP, IP_RAW and MAC_RAW mode, and handle the header as well.
291  *
292  * @return	This function return received data size for success else -1.
293  */
recvfrom(SOCKET s,uint8_t * buf,uint16_t len,uint8_t * addr,uint16_t * port)294 uint16_t recvfrom(SOCKET s, uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t *port)
295 {
296   uint8_t head[8];
297   uint16_t data_len=0;
298   uint16_t ptr=0;
299 
300   if ( len > 0 )
301   {
302     SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
303     ptr = W5100.readSnRX_RD(s);
304     switch (W5100.readSnMR(s) & 0x07)
305     {
306     case SnMR::UDP :
307       W5100.read_data(s, ptr, head, 0x08);
308       ptr += 8;
309       // read peer's IP address, port number.
310       addr[0] = head[0];
311       addr[1] = head[1];
312       addr[2] = head[2];
313       addr[3] = head[3];
314       *port = head[4];
315       *port = (*port << 8) + head[5];
316       data_len = head[6];
317       data_len = (data_len << 8) + head[7];
318 
319       W5100.read_data(s, ptr, buf, data_len); // data copy.
320       ptr += data_len;
321 
322       W5100.writeSnRX_RD(s, ptr);
323       break;
324 
325     case SnMR::IPRAW :
326       W5100.read_data(s, ptr, head, 0x06);
327       ptr += 6;
328 
329       addr[0] = head[0];
330       addr[1] = head[1];
331       addr[2] = head[2];
332       addr[3] = head[3];
333       data_len = head[4];
334       data_len = (data_len << 8) + head[5];
335 
336       W5100.read_data(s, ptr, buf, data_len); // data copy.
337       ptr += data_len;
338 
339       W5100.writeSnRX_RD(s, ptr);
340       break;
341 
342     case SnMR::MACRAW:
343       W5100.read_data(s, ptr, head, 2);
344       ptr+=2;
345       data_len = head[0];
346       data_len = (data_len<<8) + head[1] - 2;
347 
348       W5100.read_data(s, ptr, buf, data_len);
349       ptr += data_len;
350       W5100.writeSnRX_RD(s, ptr);
351       break;
352 
353     default :
354       break;
355     }
356     W5100.execCmdSn(s, Sock_RECV);
357     SPI.endTransaction();
358   }
359   return data_len;
360 }
361 
362 /**
363  * @brief	Wait for buffered transmission to complete.
364  */
flush(SOCKET s)365 void flush(SOCKET s) {
366   // TODO
367 }
368 
igmpsend(SOCKET s,const uint8_t * buf,uint16_t len)369 uint16_t igmpsend(SOCKET s, const uint8_t * buf, uint16_t len)
370 {
371   uint16_t ret=0;
372 
373   if (len > W5100.SSIZE)
374     ret = W5100.SSIZE; // check size not to exceed MAX size.
375   else
376     ret = len;
377 
378   if (ret == 0)
379     return 0;
380 
381   SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
382   W5100.send_data_processing(s, (uint8_t *)buf, ret);
383   W5100.execCmdSn(s, Sock_SEND);
384 
385   while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK )
386   {
387     if (W5100.readSnIR(s) & SnIR::TIMEOUT)
388     {
389       /* in case of igmp, if send fails, then socket closed */
390       /* if you want change, remove this code. */
391       SPI.endTransaction();
392       close(s);
393       return 0;
394     }
395     SPI.endTransaction();
396     yield();
397     SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
398   }
399 
400   W5100.writeSnIR(s, SnIR::SEND_OK);
401   SPI.endTransaction();
402   return ret;
403 }
404 
bufferData(SOCKET s,uint16_t offset,const uint8_t * buf,uint16_t len)405 uint16_t bufferData(SOCKET s, uint16_t offset, const uint8_t* buf, uint16_t len)
406 {
407   uint16_t ret =0;
408   SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
409   if (len > W5100.getTXFreeSize(s))
410   {
411     ret = W5100.getTXFreeSize(s); // check size not to exceed MAX size.
412   }
413   else
414   {
415     ret = len;
416   }
417   W5100.send_data_processing_offset(s, offset, buf, ret);
418   SPI.endTransaction();
419   return ret;
420 }
421 
startUDP(SOCKET s,uint8_t * addr,uint16_t port)422 int startUDP(SOCKET s, uint8_t* addr, uint16_t port)
423 {
424   if
425     (
426      ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) ||
427      ((port == 0x00))
428     )
429   {
430     return 0;
431   }
432   else
433   {
434     SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
435     W5100.writeSnDIPR(s, addr);
436     W5100.writeSnDPORT(s, port);
437     SPI.endTransaction();
438     return 1;
439   }
440 }
441 
sendUDP(SOCKET s)442 int sendUDP(SOCKET s)
443 {
444   SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
445   W5100.execCmdSn(s, Sock_SEND);
446 
447   /* +2008.01 bj */
448   while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK )
449   {
450     if (W5100.readSnIR(s) & SnIR::TIMEOUT)
451     {
452       /* +2008.01 [bj]: clear interrupt */
453       W5100.writeSnIR(s, (SnIR::SEND_OK|SnIR::TIMEOUT));
454       SPI.endTransaction();
455       return 0;
456     }
457     SPI.endTransaction();
458     yield();
459     SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
460   }
461 
462   /* +2008.01 bj */
463   W5100.writeSnIR(s, SnIR::SEND_OK);
464   SPI.endTransaction();
465 
466   /* Sent ok */
467   return 1;
468 }
469 
470