root/branches/follower/libw5100/src/libw5100/socket.c

Revision 140, 11.9 KB (checked in by follower, 11 months ago)

Add author, license and copyright details. (Which weren't permitted in competition entry source.)

Line 
1/*
2
3@file       socket.c
4@brief  setting chip register for socket
5
6   Original Author:
7
8      WIZnet Inc.
9
10*/
11#include <avr/io.h>
12#include <avr/interrupt.h>
13
14#include "types.h"
15
16#ifdef __DEF_IINCHIP_DBG__
17#include <stdio.h>
18#endif
19
20
21#include "w5100.h"
22#include "socket.h"
23
24static uint16 local_port;
25
26
27/**
28@brief  This Socket function initialize the channel in perticular mode, and set the port and wait for W5100 done it.
29@return     1 for sucess else 0.
30*/ 
31uint8 socket(
32    SOCKET s,       /**< for socket number */
33    uint8 protocol,     /**< for socket protocol */
34    uint16 port,        /**< the source port for the socket */
35    uint8 flag      /**< the option for the socket */
36    )
37{
38    uint8 ret;
39#ifdef __DEF_IINCHIP_DBG__
40    printf("socket()\r\n");
41#endif
42    if ((protocol == Sn_MR_TCP) || (protocol == Sn_MR_UDP) || (protocol == Sn_MR_IPRAW) || (protocol == Sn_MR_MACRAW) || (protocol == Sn_MR_PPPOE))
43    {
44        close(s);
45        IINCHIP_WRITE(Sn_MR(s),protocol | flag);
46        if (port != 0) {
47            IINCHIP_WRITE(Sn_PORT0(s),(uint8)((port & 0xff00) >> 8));
48            IINCHIP_WRITE((Sn_PORT0(s) + 1),(uint8)(port & 0x00ff));
49        } else {
50            local_port++; // if don't set the source port, set local_port number.
51            IINCHIP_WRITE(Sn_PORT0(s),(uint8)((local_port & 0xff00) >> 8));
52            IINCHIP_WRITE((Sn_PORT0(s) + 1),(uint8)(local_port & 0x00ff));
53        }
54        IINCHIP_WRITE(Sn_CR(s),Sn_CR_OPEN); // run sockinit Sn_CR
55        ret = 1;
56    }
57    else
58    {
59        ret = 0;
60    }
61#ifdef __DEF_IINCHIP_DBG__
62    printf("Sn_SR = %.2x , Protocol = %.2x\r\n", IINCHIP_READ(Sn_SR(s)), IINCHIP_READ(Sn_MR(s)));
63#endif
64    return ret;
65}
66
67
68/**
69@brief  This function close the socket and parameter is "s" which represent the socket number
70*/ 
71void close(SOCKET s)
72{
73#ifdef __DEF_IINCHIP_DBG__
74    printf("close()\r\n");
75#endif
76    IINCHIP_WRITE(Sn_CR(s),Sn_CR_CLOSE);
77}
78
79
80/**
81@brief  This function established  the connection for the channel in passive (server) mode. This function waits for the request from the peer.
82@return 1 for success else 0.
83*/ 
84uint8 listen(
85    SOCKET s    /**< the socket number */
86    )
87{
88    uint8 ret;
89#ifdef __DEF_IINCHIP_DBG__
90    printf("listen()\r\n");
91#endif
92    if (IINCHIP_READ(Sn_SR(s)) == SOCK_INIT)
93    {
94        IINCHIP_WRITE(Sn_CR(s),Sn_CR_LISTEN);
95        ret = 1;
96    }
97    else
98    {
99        ret = 0;
100#ifdef __DEF_IINCHIP_DBG__
101    printf("Fail[invalid ip,port]\r\n");
102#endif
103    }
104    return ret;
105}
106
107
108/**
109@brief  This function established  the connection for the channel in Active (client) mode.
110        This function waits for the untill the connection is established.
111       
112@return 1 for success else 0.
113*/ 
114uint8 connect(SOCKET s, uint8 * addr, uint16 port)
115{
116    uint8 ret;
117#ifdef __DEF_IINCHIP_DBG__
118    printf("connect()\r\n");
119#endif
120    if 
121        (
122            ((addr[0] == 0xFF) && (addr[1] == 0xFF) && (addr[2] == 0xFF) && (addr[3] == 0xFF)) ||
123            ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) ||
124            (port == 0x00) 
125        ) 
126    {
127        ret = 0;
128#ifdef __DEF_IINCHIP_DBG__
129    printf("Fail[invalid ip,port]\r\n");
130#endif
131    }
132    else
133    {
134
135        ret = 1;
136        // set destination IP
137        IINCHIP_WRITE(Sn_DIPR0(s),addr[0]);
138        IINCHIP_WRITE((Sn_DIPR0(s) + 1),addr[1]);
139        IINCHIP_WRITE((Sn_DIPR0(s) + 2),addr[2]);
140        IINCHIP_WRITE((Sn_DIPR0(s) + 3),addr[3]);
141        IINCHIP_WRITE(Sn_DPORT0(s),(uint8)((port & 0xff00) >> 8));
142        IINCHIP_WRITE((Sn_DPORT0(s) + 1),(uint8)(port & 0x00ff));
143        IINCHIP_WRITE(Sn_CR(s),Sn_CR_CONNECT);
144        // wait for completion
145        while (IINCHIP_READ(Sn_CR(s)))
146        {
147            if (IINCHIP_READ(Sn_SR(s)) == SOCK_CLOSED)
148            {
149#ifdef __DEF_IINCHIP_DBG__
150            printf("SOCK_CLOSED.\r\n");
151#endif
152                ret = 0; break;
153            }
154        }
155    }
156
157    return ret;
158}
159
160
161
162/**
163@brief  This function used for disconnect the socket and parameter is "s" which represent the socket number
164@return 1 for success else 0.
165*/ 
166void disconnect(SOCKET s)
167{
168#ifdef __DEF_IINCHIP_DBG__
169    printf("disconnect()\r\n");
170#endif
171    IINCHIP_WRITE(Sn_CR(s),Sn_CR_DISCON);
172}
173
174
175/**
176@brief  This function used to send the data in TCP mode
177@return 1 for success else 0.
178*/ 
179uint16 send(
180    SOCKET s,       /**< the socket index */
181    const uint8 * buf,  /**< a pointer to data */
182    uint16 len      /**< the data size to be send */
183    )
184{
185    uint8 status=0;
186    uint16 ret=0;
187    uint16 freesize=0;
188#ifdef __DEF_IINCHIP_DBG__
189    printf("send()\r\n");
190#endif
191
192   if (len > getIINCHIP_TxMAX(s)) ret = getIINCHIP_TxMAX(s); // check size not to exceed MAX size.
193   else ret = len;
194
195   // if freebuf is available, start.
196    do 
197    {
198        freesize = getSn_TX_FSR(s);
199        status = IINCHIP_READ(Sn_SR(s));
200        if ((status != SOCK_ESTABLISHED) && (status != SOCK_CLOSE_WAIT))
201        {
202            ret = 0; 
203            break;
204        }
205#ifdef __DEF_IINCHIP_DBG__
206        printf("socket %d freesize(%d) empty or error\r\n", s, freesize);
207#endif
208    } while (freesize < ret);
209
210      // copy data
211    send_data_processing(s, (uint8 *)buf, ret);
212    IINCHIP_WRITE(Sn_CR(s),Sn_CR_SEND);
213
214    // wait for completion
215    while ( (IINCHIP_READ(Sn_IR(s)) & Sn_IR_SEND_OK) != Sn_IR_SEND_OK )
216    {
217        status = IINCHIP_READ(Sn_SR(s));
218        if (status == SOCK_CLOSED)
219        {
220#ifdef __DEF_IINCHIP_DBG__
221            printf("SOCK_CLOSED.\r\n");
222#endif
223            putISR(s, getISR(s) & (Sn_IR_RECV | Sn_IR_DISCON | Sn_IR_CON));
224            IINCHIP_WRITE(Sn_IR(s), (Sn_IR_SEND_OK | Sn_IR_TIMEOUT));
225            return 0;
226        }
227        }
228        putISR(s, getISR(s) & (~Sn_IR_SEND_OK));
229    IINCHIP_WRITE(Sn_IR(s), Sn_IR_SEND_OK);
230    return ret;
231}
232
233
234/**
235@brief  This function is an application I/F function which is used to receive the data in TCP mode.
236        It continues to wait for data as much as the application wants to receive.
237       
238@return received data size for success else -1.
239*/ 
240uint16 recv(
241    SOCKET s,   /**< socket index */
242    uint8 * buf,    /**< a pointer to copy the data to be received */
243    uint16 len  /**< the data size to be read */
244    )
245{
246    uint16 ret=0;
247#ifdef __DEF_IINCHIP_DBG__
248    printf("recv()\r\n");
249#endif
250
251
252    if ( len > 0 )
253    {
254        recv_data_processing(s, buf, len);
255        IINCHIP_WRITE(Sn_CR(s),Sn_CR_RECV);
256        ret = len;
257    }
258    return ret;
259}
260
261
262/**
263@brief  This function is an application I/F function which is used to send the data for other then TCP mode.
264        Unlike TCP transmission, The peer's destination address and the port is needed.
265       
266@return This function return send data size for success else -1.
267*/ 
268uint16 sendto(
269    SOCKET s,       /**< socket index */
270    const uint8 * buf,  /**< a pointer to the data */
271    uint16 len,         /**< the data size to send */
272    uint8 * addr,       /**< the peer's Destination IP address */
273    uint16 port     /**< the peer's destination port number */
274    )
275{
276    uint8 status=0;
277    uint8 isr=0;
278    uint16 ret=0;
279   
280#ifdef __DEF_IINCHIP_DBG__
281    printf("sendto()\r\n");
282#endif
283   if (len > getIINCHIP_TxMAX(s)) ret = getIINCHIP_TxMAX(s); // check size not to exceed MAX size.
284   else ret = len;
285
286    if
287        (
288            ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) ||
289            ((port == 0x00)) ||(ret == 0)
290        ) 
291    {
292       ;
293#ifdef __DEF_IINCHIP_DBG__
294    printf("%d Fail[%.2x.%.2x.%.2x.%.2x, %.d, %d]\r\n",s, addr[0], addr[1], addr[2], addr[3] , port, len);
295    printf("Fail[invalid ip,port]\r\n");
296#endif
297    }
298    else
299    {
300        IINCHIP_WRITE(Sn_DIPR0(s),addr[0]);
301        IINCHIP_WRITE((Sn_DIPR0(s) + 1),addr[1]);
302        IINCHIP_WRITE((Sn_DIPR0(s) + 2),addr[2]);
303        IINCHIP_WRITE((Sn_DIPR0(s) + 3),addr[3]);
304        IINCHIP_WRITE(Sn_DPORT0(s),(uint8)((port & 0xff00) >> 8));
305        IINCHIP_WRITE((Sn_DPORT0(s) + 1),(uint8)(port & 0x00ff));
306
307            // copy data
308            send_data_processing(s, (uint8 *)buf, ret);
309        IINCHIP_WRITE(Sn_CR(s),Sn_CR_SEND);
310       
311        while ( (IINCHIP_READ(Sn_IR(s)) & Sn_IR_SEND_OK) != Sn_IR_SEND_OK )
312        {
313            status = IINCHIP_READ(Sn_SR(s));
314#ifndef __DEF_IINCHIP_INT__
315            isr = IINCHIP_READ(Sn_IR(s));
316#endif
317            if ((isr & Sn_IR_TIMEOUT) || (getISR(s) & Sn_IR_TIMEOUT))
318            {
319#ifdef __DEF_IINCHIP_DBG__
320                printf("send fail.\r\n");
321#endif
322                putISR(s, getISR(s) & (Sn_IR_RECV | Sn_IR_DISCON | Sn_IR_CON));  /* clear SEND_OK & TIMEOUT in I_STATUS[s] */
323                IINCHIP_WRITE(Sn_IR(s), (Sn_IR_SEND_OK | Sn_IR_TIMEOUT));                       // clear SEND_OK & TIMEOUT in Sn_IR(s)
324                return 0;
325            }
326        }
327        putISR(s, getISR(s) & (~Sn_IR_SEND_OK));
328        IINCHIP_WRITE(Sn_IR(s), Sn_IR_SEND_OK);
329
330    }
331    return ret;
332}
333
334
335/**
336@brief  This function is an application I/F function which is used to receive the data in other then
337    TCP mode. This function is used to receive UDP, IP_RAW and MAC_RAW mode, and handle the header as well.
338   
339@return This function return received data size for success else -1.
340*/ 
341uint16 recvfrom(
342    SOCKET s,   /**< the socket number */
343    uint8 * buf,    /**< a pointer to copy the data to be received */
344    uint16 len,     /**< the data size to read */
345    uint8 * addr,   /**< a pointer to store the peer's IP address */
346    uint16 *port    /**< a pointer to store the peer's port number. */
347    )
348{
349    uint8 head[8];
350    uint16 data_len=0;
351    uint16 ptr=0;
352#ifdef __DEF_IINCHIP_DBG__
353    printf("recvfrom()\r\n");
354#endif
355
356    if ( len > 0 )
357    {
358    ptr = IINCHIP_READ(Sn_RX_RD0(s));
359    ptr = ((ptr & 0x00ff) << 8) + IINCHIP_READ(Sn_RX_RD0(s) + 1);
360#ifdef __DEF_IINCHIP_DBG__
361    printf("ISR_RX: rd_ptr : %.4x\r\n", ptr);
362#endif
363    switch (IINCHIP_READ(Sn_MR(s)) & 0x07)
364    {
365    case Sn_MR_UDP :
366            read_data(s, (uint8 *)ptr, head, 0x08);
367            ptr += 8;
368            // read peer's IP address, port number.
369                addr[0] = head[0];
370            addr[1] = head[1];
371            addr[2] = head[2];
372            addr[3] = head[3];
373            *port = head[4];
374            *port = (*port << 8) + head[5];
375            data_len = head[6];
376            data_len = (data_len << 8) + head[7];
377           
378#ifdef __DEF_IINCHIP_DBG__
379            printf("UDP msg arrived\r\n");
380            printf("source Port : %d\r\n", *port);
381            printf("source IP : %d.%d.%d.%d\r\n", addr[0], addr[1], addr[2], addr[3]);
382#endif
383
384            read_data(s, (uint8 *)ptr, buf, data_len); // data copy.
385            ptr += data_len;
386
387            IINCHIP_WRITE(Sn_RX_RD0(s),(uint8)((ptr & 0xff00) >> 8));
388            IINCHIP_WRITE((Sn_RX_RD0(s) + 1),(uint8)(ptr & 0x00ff));
389            break;
390   
391    case Sn_MR_IPRAW :
392            read_data(s, (uint8 *)ptr, head, 0x06);
393            ptr += 6;
394   
395            addr[0] = head[0];
396            addr[1] = head[1];
397            addr[2] = head[2];
398            addr[3] = head[3];
399            data_len = head[4];
400            data_len = (data_len << 8) + head[5];
401   
402#ifdef __DEF_IINCHIP_DBG__
403            printf("IP RAW msg arrived\r\n");
404            printf("source IP : %d.%d.%d.%d\r\n", addr[0], addr[1], addr[2], addr[3]);
405#endif
406            read_data(s, (uint8 *)ptr, buf, data_len); // data copy.
407            ptr += data_len;
408
409            IINCHIP_WRITE(Sn_RX_RD0(s),(uint8)((ptr & 0xff00) >> 8));
410            IINCHIP_WRITE((Sn_RX_RD0(s) + 1),(uint8)(ptr & 0x00ff));
411            break;
412    case Sn_MR_MACRAW :
413            read_data(s,(uint8*)ptr,head,2);
414            ptr+=2;
415            data_len = head[0];
416            data_len = (data_len<<8) + head[1] - 2;
417
418            read_data(s,(uint8*) ptr,buf,data_len);
419            ptr += data_len;
420            IINCHIP_WRITE(Sn_RX_RD0(s),(uint8)((ptr & 0xff00) >> 8));
421            IINCHIP_WRITE((Sn_RX_RD0(s) + 1),(uint8)(ptr & 0x00ff));
422           
423#ifdef __DEF_IINCHIP_DGB__
424            printf("MAC RAW msg arrived\r\n");
425            printf("dest mac=%.2X.%.2X.%.2X.%.2X.%.2X.%.2X\r\n",buf[0],buf[1],buf[2],buf[3],buf[4],buf[5]);
426            printf("src  mac=%.2X.%.2X.%.2X.%.2X.%.2X.%.2X\r\n",buf[6],buf[7],buf[8],buf[9],buf[10],buf[11]);
427            printf("type    =%.2X%.2X\r\n",buf[12],buf[13]); 
428#endif         
429            break;
430
431    default :
432            break;
433    }
434        IINCHIP_WRITE(Sn_CR(s),Sn_CR_RECV);
435    }
436#ifdef __DEF_IINCHIP_DBG__
437    printf("recvfrom() end ..\r\n");
438#endif
439    return data_len;
440}
441
442
443uint16 igmpsend(SOCKET s, const uint8 * buf, uint16 len)
444{
445    //uint8 status=0;
446    uint8 isr=0;
447    uint16 ret=0;
448   
449#ifdef __DEF_IINCHIP_DBG__
450    printf("igmpsend()\r\n");
451#endif
452   if (len > getIINCHIP_TxMAX(s)) ret = getIINCHIP_TxMAX(s); // check size not to exceed MAX size.
453   else ret = len;
454
455    if  (ret == 0) 
456    {
457        ;
458#ifdef __DEF_IINCHIP_DBG__
459    //printf("%d Fail[%d]\r\n",len);
460#endif
461    }
462    else
463    {
464        // copy data
465        send_data_processing(s, (uint8 *)buf, ret);
466        IINCHIP_WRITE(Sn_CR(s),Sn_CR_SEND);
467     
468            while (IINCHIP_READ(Sn_CR(s)))
469        {
470            // status = IINCHIP_READ(Sn_SR(s));
471#ifndef __DEF_IINCHIP_INT__         
472            isr = IINCHIP_READ(Sn_IR(s));
473#endif
474            if ((getISR(s) & Sn_IR_TIMEOUT) || (isr & Sn_IR_TIMEOUT))
475            {
476#ifdef __DEF_IINCHIP_DBG__
477                printf("igmpsend fail.\r\n");
478#endif
479                putISR(s, getISR(s) & (Sn_IR_RECV | Sn_IR_DISCON | Sn_IR_CON));
480                IINCHIP_WRITE(Sn_IR(s), (Sn_IR_SEND_OK | Sn_IR_TIMEOUT));
481                return 0;
482            }
483        }
484        putISR(s, getISR(s) & (~Sn_IR_SEND_OK));
485        IINCHIP_WRITE(Sn_IR(s), Sn_IR_SEND_OK);
486    }
487    return ret;
488}
Note: See TracBrowser for help on using the browser.