Statistics
| Branch: | Revision:

root / arduino-1.0 / libraries / Ethernet / utility / socket.cpp @ 58d82c77

History | View | Annotate | Download (8.95 KB)

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
 */
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
}
400