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