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