source: rtos_arduino/trunk/arduino_lib/libraries/Ethernet2/src/utility/socket.cpp@ 136

Last change on this file since 136 was 136, checked in by ertl-honda, 8 years ago

ライブラリとOS及びベーシックなサンプルの追加.

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