D:/DRISSI/arduino-0022/arduino-0022/libraries/Ethernet/utility/socket.cpp
00001 #include "w5100.h"
00002 #include "socket.h"
00003 
00004 static uint16_t local_port;
00005 
00010 uint8_t socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag)
00011 {
00012   uint8_t ret;
00013   if ((protocol == SnMR::TCP) || (protocol == SnMR::UDP) || (protocol == SnMR::IPRAW) || (protocol == SnMR::MACRAW) || (protocol == SnMR::PPPOE))
00014   {
00015     close(s);
00016     W5100.writeSnMR(s, protocol | flag);
00017     if (port != 0) {
00018       W5100.writeSnPORT(s, port);
00019     } 
00020     else {
00021       local_port++; // if don't set the source port, set local_port number.
00022       W5100.writeSnPORT(s, local_port);
00023     }
00024 
00025     W5100.execCmdSn(s, Sock_OPEN);
00026     
00027     return 1;
00028   }
00029 
00030   return 0;
00031 }
00032 
00033 
00037 void close(SOCKET s)
00038 {
00039   W5100.execCmdSn(s, Sock_CLOSE);
00040   W5100.writeSnIR(s, 0xFF);
00041 }
00042 
00043 
00048 uint8_t listen(SOCKET s)
00049 {
00050   if (W5100.readSnSR(s) != SnSR::INIT)
00051     return 0;
00052   W5100.execCmdSn(s, Sock_LISTEN);
00053   return 1;
00054 }
00055 
00056 
00063 uint8_t connect(SOCKET s, uint8_t * addr, uint16_t port)
00064 {
00065   if 
00066     (
00067   ((addr[0] == 0xFF) && (addr[1] == 0xFF) && (addr[2] == 0xFF) && (addr[3] == 0xFF)) ||
00068     ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) ||
00069     (port == 0x00) 
00070     ) 
00071     return 0;
00072 
00073   // set destination IP
00074   W5100.writeSnDIPR(s, addr);
00075   W5100.writeSnDPORT(s, port);
00076   W5100.execCmdSn(s, Sock_CONNECT);
00077 
00078   return 1;
00079 }
00080 
00081 
00082 
00087 void disconnect(SOCKET s)
00088 {
00089   W5100.execCmdSn(s, Sock_DISCON);
00090 }
00091 
00092 
00097 uint16_t send(SOCKET s, const uint8_t * buf, uint16_t len)
00098 {
00099   uint8_t status=0;
00100   uint16_t ret=0;
00101   uint16_t freesize=0;
00102 
00103   if (len > W5100.SSIZE) 
00104     ret = W5100.SSIZE; // check size not to exceed MAX size.
00105   else 
00106     ret = len;
00107 
00108   // if freebuf is available, start.
00109   do 
00110   {
00111     freesize = W5100.getTXFreeSize(s);
00112     status = W5100.readSnSR(s);
00113     if ((status != SnSR::ESTABLISHED) && (status != SnSR::CLOSE_WAIT))
00114     {
00115       ret = 0; 
00116       break;
00117     }
00118   } 
00119   while (freesize < ret);
00120 
00121   // copy data
00122   W5100.send_data_processing(s, (uint8_t *)buf, ret);
00123   W5100.execCmdSn(s, Sock_SEND);
00124 
00125   /* +2008.01 bj */
00126   while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK ) 
00127   {
00128     /* m2008.01 [bj] : reduce code */
00129     if ( W5100.readSnSR(s) == SnSR::CLOSED )
00130     {
00131       close(s);
00132       return 0;
00133     }
00134   }
00135   /* +2008.01 bj */
00136   W5100.writeSnIR(s, SnIR::SEND_OK);
00137   return ret;
00138 }
00139 
00140 
00147 uint16_t recv(SOCKET s, uint8_t *buf, uint16_t len)
00148 {
00149   uint16_t ret=0;
00150 
00151   if ( len > 0 )
00152   {
00153     W5100.recv_data_processing(s, buf, len);
00154     W5100.execCmdSn(s, Sock_RECV);
00155     ret = len;
00156   }
00157   return ret;
00158 }
00159 
00160 
00166 uint16_t peek(SOCKET s, uint8_t *buf)
00167 {
00168   W5100.recv_data_processing(s, buf, 1, 1);
00169 
00170   return 1;
00171 }
00172 
00173 
00180 uint16_t sendto(SOCKET s, const uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t port)
00181 {
00182   uint16_t ret=0;
00183 
00184   if (len > W5100.SSIZE) ret = W5100.SSIZE; // check size not to exceed MAX size.
00185   else ret = len;
00186 
00187   if
00188     (
00189   ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) ||
00190     ((port == 0x00)) ||(ret == 0)
00191     ) 
00192   {
00193     /* +2008.01 [bj] : added return value */
00194     ret = 0;
00195   }
00196   else
00197   {
00198     W5100.writeSnDIPR(s, addr);
00199     W5100.writeSnDPORT(s, port);
00200 
00201     // copy data
00202     W5100.send_data_processing(s, (uint8_t *)buf, ret);
00203     W5100.execCmdSn(s, Sock_SEND);
00204 
00205     /* +2008.01 bj */
00206     while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK ) 
00207     {
00208       if (W5100.readSnIR(s) & SnIR::TIMEOUT)
00209       {
00210         /* +2008.01 [bj]: clear interrupt */
00211         W5100.writeSnIR(s, (SnIR::SEND_OK | SnIR::TIMEOUT)); /* clear SEND_OK & TIMEOUT */
00212         return 0;
00213       }
00214     }
00215 
00216     /* +2008.01 bj */
00217     W5100.writeSnIR(s, SnIR::SEND_OK);
00218   }
00219   return ret;
00220 }
00221 
00222 
00229 uint16_t recvfrom(SOCKET s, uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t *port)
00230 {
00231   uint8_t head[8];
00232   uint16_t data_len=0;
00233   uint16_t ptr=0;
00234 
00235   if ( len > 0 )
00236   {
00237     ptr = W5100.readSnRX_RD(s);
00238     switch (W5100.readSnMR(s) & 0x07)
00239     {
00240     case SnMR::UDP :
00241       W5100.read_data(s, (uint8_t *)ptr, head, 0x08);
00242       ptr += 8;
00243       // read peer's IP address, port number.
00244       addr[0] = head[0];
00245       addr[1] = head[1];
00246       addr[2] = head[2];
00247       addr[3] = head[3];
00248       *port = head[4];
00249       *port = (*port << 8) + head[5];
00250       data_len = head[6];
00251       data_len = (data_len << 8) + head[7];
00252 
00253       W5100.read_data(s, (uint8_t *)ptr, buf, data_len); // data copy.
00254       ptr += data_len;
00255 
00256       W5100.writeSnRX_RD(s, ptr);
00257       break;
00258 
00259     case SnMR::IPRAW :
00260       W5100.read_data(s, (uint8_t *)ptr, head, 0x06);
00261       ptr += 6;
00262 
00263       addr[0] = head[0];
00264       addr[1] = head[1];
00265       addr[2] = head[2];
00266       addr[3] = head[3];
00267       data_len = head[4];
00268       data_len = (data_len << 8) + head[5];
00269 
00270       W5100.read_data(s, (uint8_t *)ptr, buf, data_len); // data copy.
00271       ptr += data_len;
00272 
00273       W5100.writeSnRX_RD(s, ptr);
00274       break;
00275 
00276     case SnMR::MACRAW:
00277       W5100.read_data(s,(uint8_t*)ptr,head,2);
00278       ptr+=2;
00279       data_len = head[0];
00280       data_len = (data_len<<8) + head[1] - 2;
00281 
00282       W5100.read_data(s,(uint8_t*) ptr,buf,data_len);
00283       ptr += data_len;
00284       W5100.writeSnRX_RD(s, ptr);
00285       break;
00286 
00287     default :
00288       break;
00289     }
00290     W5100.execCmdSn(s, Sock_RECV);
00291   }
00292   return data_len;
00293 }
00294 
00295 
00296 uint16_t igmpsend(SOCKET s, const uint8_t * buf, uint16_t len)
00297 {
00298   uint8_t status=0;
00299   uint16_t ret=0;
00300 
00301   if (len > W5100.SSIZE) 
00302     ret = W5100.SSIZE; // check size not to exceed MAX size.
00303   else 
00304     ret = len;
00305 
00306   if (ret == 0)
00307     return 0;
00308 
00309   W5100.send_data_processing(s, (uint8_t *)buf, ret);
00310   W5100.execCmdSn(s, Sock_SEND);
00311 
00312   while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK ) 
00313   {
00314     status = W5100.readSnSR(s);
00315     if (W5100.readSnIR(s) & SnIR::TIMEOUT)
00316     {
00317       /* in case of igmp, if send fails, then socket closed */
00318       /* if you want change, remove this code. */
00319       close(s);
00320       return 0;
00321     }
00322   }
00323 
00324   W5100.writeSnIR(s, SnIR::SEND_OK);
00325   return ret;
00326 }
00327