/********************************************************************************** File: wiznet_tcp.c Description: This file contains the implementation of the tcp protocol for wiznet w5100 chip Release History: Author Date Remarks Version Omer Miranda 20-01-2014 Created 1.0 ***********************************************************************************/ /* *********************************************************************************** Include Files *********************************************************************************** */ #include "wiznet_tcp.h" #include "globaldefs.h" #include "./WMP/GlobExt.h" #include "./WMP/ExternalFuncs.h" /* *********************************************************************************** Globals *********************************************************************************** */ static uint16_t ushLocalPort; /********************************************************************************** Function Name: socket Purpose: This function initializes the channel in particular mode, sets the port number and waits for W5100 done. Input: Socket number. Protocol type. Port number. Options for the socket. Return value: 1 for sucess else 0. Change History: Author Date Remarks Omer Miranda 20-01-2014 Created ***********************************************************************************/ uint8_t socket(SOCKET s, uint8_t ucharProtocol, uint16_t ushPort, uint8_t ucharFlag) { uint8_t ucharStatus; if ((ucharProtocol == Sn_MR_TCP)) { close(s); /* Set the socket mode register for TCP protocol*/ write_wiznet_reg(Sn_MR(s),ucharProtocol | ucharFlag); if (ushPort != 0) { /* Set the socket source port register */ write_wiznet_reg(Sn_PORT0(s),(uint8_t)((ushPort & 0xff00) >> 8)); write_wiznet_reg((Sn_PORT0(s) + 1),(uint8_t)(ushPort & 0x00ff)); } else { /* Set the socket source port register */ ushLocalPort++; /* if source port not given, then set local_port number.*/ write_wiznet_reg(Sn_PORT0(s),(uint8_t)((ushLocalPort & 0xff00) >> 8)); write_wiznet_reg((Sn_PORT0(s) + 1),(uint8_t)(ushLocalPort & 0x00ff)); } /* Open the configured port in the configured protocol */ write_wiznet_reg(Sn_CR(s),Sn_CR_OPEN); /* run sockinit Sn_CR */ /* wait to process the command... */ while( read_wiznet_reg(Sn_CR(s)) ); /* ------- */ ucharStatus = 1; } else { ucharStatus = 0; } return ucharStatus; } /********************************************************************************** Function Name: close Purpose: This function closes the "s" socket Input: Socket number. Return value: None. Change History: Author Date Remarks Omer Miranda 20-01-2014 Created ***********************************************************************************/ void close(SOCKET s) { write_wiznet_reg(Sn_CR(s),Sn_CR_CLOSE); /* wait to process the command... */ while( read_wiznet_reg(Sn_CR(s)) ); /* clear interrupt */ #ifdef __DEF_IINCHIP_INT__ /* m2008.01 [bj] : all clear */ putISR(s, 0x00); #else /* m2008.01 [bj] : all clear */ write_wiznet_reg(Sn_IR(s), 0xFF); #endif } /********************************************************************************** Function Name: connect Purpose: This function establises the connection for the channel in Active (client) mode. This function waits untill the connection is established. Input: Socket number. Destination IP address array. Destination Port number. Return value: Returns 1 for success else 0. Change History: Author Date Remarks Omer Miranda 20-01-2014 Created ***********************************************************************************/ uint8_t connect(SOCKET s, uint8_t* p_ucharAddr, uint16_t ushPort) { uint8_t ucharStatus; if(((p_ucharAddr[0] == 0xFF) && (p_ucharAddr[1] == 0xFF) && (p_ucharAddr[2] == 0xFF) && (p_ucharAddr[3] == 0xFF)) || ((p_ucharAddr[0] == 0x00) && (p_ucharAddr[1] == 0x00) && (p_ucharAddr[2] == 0x00) && (p_ucharAddr[3] == 0x00)) || (ushPort == 0x00)) { ucharStatus = 0; } else { ucharStatus = 1; /* set destination IP */ write_wiznet_reg(Sn_DIPR0(s), p_ucharAddr[0]); write_wiznet_reg((Sn_DIPR0(s) + 1), p_ucharAddr[1]); write_wiznet_reg((Sn_DIPR0(s) + 2), p_ucharAddr[2]); write_wiznet_reg((Sn_DIPR0(s) + 3), p_ucharAddr[3]); write_wiznet_reg(Sn_DPORT0(s), (uint8_t)((ushPort & 0xff00) >> 8)); write_wiznet_reg((Sn_DPORT0(s) + 1),(uint8_t)(ushPort & 0x00ff)); /* set/clear subnet for ARP Errata */ //setSUBR(); clearSUBR(); write_wiznet_reg(Sn_CR(s),Sn_CR_CONNECT); /* wait for completion */ while ( read_wiznet_reg(Sn_CR(s)) ); /* check the SYN packet sending... */ while ( read_wiznet_reg(Sn_SR(s)) != SOCK_SYNSENT ) { if(read_wiznet_reg(Sn_SR(s)) == SOCK_ESTABLISHED) { break; } if (getSn_IR(s) & Sn_IR_TIMEOUT) { write_wiznet_reg(Sn_IR(s), (Sn_IR_TIMEOUT)); // clear TIMEOUT Interrupt ucharStatus = 0; break; } } //clearSUBR(); setSUBR(); } return ucharStatus; } /********************************************************************************** Function Name: disconnect Purpose: Disconnect the socket "s". Input: Socket number. Return value: None. Change History: Author Date Remarks Omer Miranda 20-01-2014 Created ***********************************************************************************/ void disconnect(SOCKET s) { write_wiznet_reg(Sn_CR(s),Sn_CR_DISCON); /* wait to process the command... */ while( read_wiznet_reg(Sn_CR(s)) ); } /********************************************************************************** Function Name: listen Purpose: This function establises connection for the specified channel in passive (server) mode. This function waits for the connection request from the peer. Input: Socket number. Return value: Returns 1 for success else 0. Change History: Author Date Remarks Omer Miranda 20-01-2014 Created ***********************************************************************************/ uint8_t listen(SOCKET s) { uint8_t ucharStatus; ucharStatus = getSn_SR(0); if (ucharStatus == SOCK_INIT) { write_wiznet_reg(Sn_CR(s),Sn_CR_LISTEN); /* wait to process the command... */ while( read_wiznet_reg(Sn_CR(s)) ); /* ------- */ ucharStatus = getSn_SR(0); if(ucharStatus == SOCK_LISTEN) { ucharStatus = 0; } else { close(s); ucharStatus = 1; } } else { close(s); ucharStatus = 1; } return ucharStatus; } /********************************************************************************** Function Name: send Purpose: This function is used to send the data in TCP mode. Input: Socket number. Pointer to data. Number of bytes to send Return value: Returns 1 for success else 0. Change History: Author Date Remarks Omer Miranda 20-01-2014 Created ***********************************************************************************/ uint16_t send(SOCKET s, const uint8_t* p_ucharDataBuf, uint16_t ushLen) { uint8_t ucharStatus=0; uint16_t ushRet=0; uint16_t ushFreeSize=0; if (ushLen > getW5100_TxMAX(s)) { ushRet = getW5100_TxMAX(s); // check size not to exceed MAX size. } else { ushRet = ushLen; } // if freebuf is available, start. do { ushFreeSize = getSn_TX_FSR(s); ucharStatus = read_wiznet_reg(Sn_SR(s)); if ((ucharStatus != SOCK_ESTABLISHED) && (ucharStatus != SOCK_CLOSE_WAIT)) { ushRet = 0; break; } } while (ushFreeSize < ushRet); // copy data send_data_processing(s, (uint8_t *)p_ucharDataBuf, ushRet); write_wiznet_reg(Sn_CR(s),Sn_CR_SEND); /* wait to process the command... */ while( read_wiznet_reg(Sn_CR(s)) ); /* ------- */ #ifdef __DEF_IINCHIP_INT__ while ( (getISR(s) & Sn_IR_SEND_OK) != Sn_IR_SEND_OK ) #else while ( (read_wiznet_reg(Sn_IR(s)) & Sn_IR_SEND_OK) != Sn_IR_SEND_OK ) #endif { /* m2008.01 [bj] : reduce code */ if ( read_wiznet_reg(Sn_SR(s)) == SOCK_CLOSED ) { close(s); return 0; } } /* +2008.01 bj */ #ifdef __DEF_IINCHIP_INT__ putISR(s, getISR(s) & (~Sn_IR_SEND_OK)); #else write_wiznet_reg(Sn_IR(s), Sn_IR_SEND_OK); #endif return ushRet; } /********************************************************************************** Function Name: recv Purpose: This function is an application I/F function which is used to receive the data in TCP mode. It continues to wait for data as much as the application wants to receive.. Input: Socket number. Pointer to data. Number of bytes to receive Return value: received data size for success else 0. Change History: Author Date Remarks Omer Miranda 20-01-2014 Created ***********************************************************************************/ uint16_t recv(SOCKET s, uint8_t* p_ucharDataBuf, uint16_t ushLen) { uint16_t ushStatus=0; if ( ushLen > 0 ) { recv_data_processing(s, p_ucharDataBuf, ushLen); write_wiznet_reg(Sn_CR(s),Sn_CR_RECV); /* +20071122[chungs]:wait to process the command... */ while( read_wiznet_reg(Sn_CR(s)) ); /* ------- */ ushStatus = ushLen; } return ushStatus; }