initial commit
commit
e8d73df01d
Binary file not shown.
@ -0,0 +1,386 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! \file w5100.c
|
||||
//! \brief W5100 HAL Interface.
|
||||
//! \version 1.0.0
|
||||
//! \date 2013/10/21
|
||||
//! \par Revision history
|
||||
//! <2013/10/21> 1st Release
|
||||
//! \author MidnightCow
|
||||
//!
|
||||
//! Copyright (c) 2013, WIZnet Co., LTD.
|
||||
//! All rights reserved.
|
||||
//!
|
||||
//! Redistribution and use in source and binary forms, with or without
|
||||
//! modification, are permitted provided that the following conditions
|
||||
//! are met:
|
||||
//!
|
||||
//! * Redistributions of source code must retain the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer.
|
||||
//! * Redistributions in binary form must reproduce the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer in the
|
||||
//! documentation and/or other materials provided with the distribution.
|
||||
//! * Neither the name of the <ORGANIZATION> nor the names of its
|
||||
//! contributors may be used to endorse or promote products derived
|
||||
//! from this software without specific prior written permission.
|
||||
//!
|
||||
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
//! THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#include "w5100.h"
|
||||
|
||||
#if (_WIZCHIP_ == 5100)
|
||||
/**
|
||||
@brief This function writes the data into W5100 registers.
|
||||
*/
|
||||
void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb )
|
||||
{
|
||||
WIZCHIP_CRITICAL_ENTER();
|
||||
WIZCHIP.CS._select();
|
||||
|
||||
#if( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_))
|
||||
WIZCHIP.IF.SPI._write_byte(0xF0);
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0xFF00) >> 8);
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF) >> 0);
|
||||
WIZCHIP.IF.SPI._write_byte(wb); // Data write (write 1byte data)
|
||||
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_) )
|
||||
//M20150601 : Rename the function for integrating with ioLibrary
|
||||
//WIZCHIP.IF.BUS._write_byte(AddrSel,wb);
|
||||
WIZCHIP.IF.BUS._write_data(AddrSel,wb);
|
||||
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
|
||||
|
||||
//add indirect bus
|
||||
//M20150601 : Rename the function for integrating with ioLibrary
|
||||
//WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0xFF00) >> 8);
|
||||
//WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x00FF));
|
||||
//WIZCHIP.IF.BUS._write_byte(IDM_DR,wb);
|
||||
WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0xFF00) >> 8);
|
||||
WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x00FF));
|
||||
WIZCHIP.IF.BUS._write_data(IDM_DR,wb);
|
||||
#else
|
||||
#error "Unknown _WIZCHIP_IO_MODE_ in W5100. !!!"
|
||||
#endif
|
||||
|
||||
WIZCHIP.CS._deselect();
|
||||
WIZCHIP_CRITICAL_EXIT();
|
||||
}
|
||||
/**
|
||||
@brief This function reads the value from W5100 registers.
|
||||
*/
|
||||
uint8_t WIZCHIP_READ(uint32_t AddrSel)
|
||||
{
|
||||
uint8_t ret;
|
||||
|
||||
WIZCHIP_CRITICAL_ENTER();
|
||||
WIZCHIP.CS._select();
|
||||
|
||||
#if( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_))
|
||||
WIZCHIP.IF.SPI._write_byte(0x0F);
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0xFF00) >> 8);
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF) >> 0);
|
||||
ret = WIZCHIP.IF.SPI._read_byte();
|
||||
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_) )
|
||||
//M20150601 : Rename the function for integrating with ioLibrary
|
||||
//ret = WIZCHIP.IF.BUS._read_byte(AddrSel);
|
||||
ret = WIZCHIP.IF.BUS._read_data(AddrSel);
|
||||
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
|
||||
|
||||
//add indirect bus
|
||||
//M20150601 : Rename the function for integrating with ioLibrary
|
||||
//WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0xFF00) >> 8);
|
||||
//WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x00FF));
|
||||
//ret = WIZCHIP.IF.BUS._read_byte(IDM_DR);
|
||||
WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0xFF00) >> 8);
|
||||
WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x00FF));
|
||||
ret = WIZCHIP.IF.BUS._read_data(IDM_DR);
|
||||
|
||||
#else
|
||||
#error "Unknown _WIZCHIP_IO_MODE_ in W5100. !!!"
|
||||
#endif
|
||||
|
||||
WIZCHIP.CS._deselect();
|
||||
WIZCHIP_CRITICAL_EXIT();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief This function writes into W5100 memory(Buffer)
|
||||
*/
|
||||
void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len)
|
||||
{
|
||||
uint16_t i = 0;
|
||||
|
||||
WIZCHIP_CRITICAL_ENTER();
|
||||
WIZCHIP.CS._select(); //M20150601 : Moved here.
|
||||
|
||||
#if( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_))
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
//M20160715 : Depricated "M20150601 : Remove _select() to top-side"
|
||||
// CS should be controlled every SPI frames
|
||||
WIZCHIP.CS._select();
|
||||
WIZCHIP.IF.SPI._write_byte(0xF0);
|
||||
WIZCHIP.IF.SPI._write_byte((((uint16_t)(AddrSel+i)) & 0xFF00) >> 8);
|
||||
WIZCHIP.IF.SPI._write_byte((((uint16_t)(AddrSel+i)) & 0x00FF) >> 0);
|
||||
WIZCHIP.IF.SPI._write_byte(pBuf[i]); // Data write (write 1byte data)
|
||||
//M20160715 : Depricated "M20150601 : Remove _select() to top-side"
|
||||
WIZCHIP.CS._deselect();
|
||||
}
|
||||
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_) )
|
||||
for(i = 0; i < len; i++)
|
||||
//M20150601 : Rename the function for integrating with ioLibrary
|
||||
// WIZCHIP.IF.BUS._write_byte(AddrSel+i,pBuf[i]);
|
||||
WIZCHIP.IF.BUS._write_data(AddrSel+i,pBuf[i]);
|
||||
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
|
||||
//M20150601 : Rename the function for integrating with ioLibrary
|
||||
/*
|
||||
WIZCHIP_WRITE(MR,WIZCHIP_READ(MR) | MR_AI);
|
||||
WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0xFF00) >> 8);
|
||||
WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x00FF));
|
||||
for(i = 0 ; i < len; i++)
|
||||
WIZCHIP.IF.BUS._write_byte(IDM_DR,pBuf[i]);
|
||||
WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) & ~MR_AI);
|
||||
*/
|
||||
setMR(getMR()|MR_AI);
|
||||
WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0xFF00) >> 8);
|
||||
WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x00FF));
|
||||
for(i = 0 ; i < len; i++)
|
||||
WIZCHIP.IF.BUS._write_data(IDM_DR,pBuf[i]);
|
||||
setMR(getMR() & ~MR_AI);
|
||||
|
||||
#else
|
||||
#error "Unknown _WIZCHIP_IO_MODE_ in W5100. !!!!"
|
||||
#endif
|
||||
|
||||
WIZCHIP.CS._deselect(); //M20150601 : Moved here.
|
||||
WIZCHIP_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
/**
|
||||
@brief This function reads into W5100 memory(Buffer)
|
||||
*/
|
||||
|
||||
void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len)
|
||||
{
|
||||
uint16_t i = 0;
|
||||
WIZCHIP_CRITICAL_ENTER();
|
||||
WIZCHIP.CS._select(); //M20150601 : Moved here.
|
||||
|
||||
#if( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_))
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
//M20160715 : Depricated "M20150601 : Remove _select() to top-side"
|
||||
// CS should be controlled every SPI frames
|
||||
WIZCHIP.CS._select();
|
||||
WIZCHIP.IF.SPI._write_byte(0x0F);
|
||||
WIZCHIP.IF.SPI._write_byte((uint16_t)((AddrSel+i) & 0xFF00) >> 8);
|
||||
WIZCHIP.IF.SPI._write_byte((uint16_t)((AddrSel+i) & 0x00FF) >> 0);
|
||||
pBuf[i] = WIZCHIP.IF.SPI._read_byte();
|
||||
//M20160715 : Depricated "M20150601 : Remove _select() to top-side"
|
||||
WIZCHIP.CS._deselect();
|
||||
}
|
||||
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_) )
|
||||
for(i = 0 ; i < len; i++)
|
||||
//M20150601 : Rename the function for integrating with ioLibrary
|
||||
// pBuf[i] = WIZCHIP.IF.BUS._read_byte(AddrSel+i);
|
||||
pBuf[i] = WIZCHIP.IF.BUS._read_data(AddrSel+i);
|
||||
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
|
||||
//M20150601 : Rename the function for integrating with ioLibrary
|
||||
/*
|
||||
WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) | MR_AI);
|
||||
WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0xFF00) >> 8);
|
||||
WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x00FF));
|
||||
for(i = 0 ; i < len; i++)
|
||||
pBuf[i] = WIZCHIP.IF.BUS._read_byte(IDM_DR);
|
||||
WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) & ~MR_AI);
|
||||
*/
|
||||
setMR(getMR() | MR_AI);
|
||||
WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0xFF00) >> 8);
|
||||
WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x00FF));
|
||||
for(i = 0 ; i < len; i++)
|
||||
pBuf[i] = WIZCHIP.IF.BUS._read_data(IDM_DR);
|
||||
setMR(getMR() & ~MR_AI);
|
||||
|
||||
#else
|
||||
#error "Unknown _WIZCHIP_IO_MODE_ in W5100. !!!!"
|
||||
#endif
|
||||
|
||||
WIZCHIP.CS._deselect(); //M20150601 : Moved Here.
|
||||
WIZCHIP_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
// Socket N regsiter IO function //
|
||||
///////////////////////////////////
|
||||
|
||||
uint16_t getSn_TX_FSR(uint8_t sn)
|
||||
{
|
||||
uint16_t val=0,val1=0;
|
||||
do
|
||||
{
|
||||
val1 = WIZCHIP_READ(Sn_TX_FSR(sn));
|
||||
val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1));
|
||||
if (val1 != 0)
|
||||
{
|
||||
val = WIZCHIP_READ(Sn_TX_FSR(sn));
|
||||
val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1));
|
||||
}
|
||||
}while (val != val1);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
uint16_t getSn_RX_RSR(uint8_t sn)
|
||||
{
|
||||
uint16_t val=0,val1=0;
|
||||
do
|
||||
{
|
||||
val1 = WIZCHIP_READ(Sn_RX_RSR(sn));
|
||||
val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1));
|
||||
if (val1 != 0)
|
||||
{
|
||||
val = WIZCHIP_READ(Sn_RX_RSR(sn));
|
||||
val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1));
|
||||
}
|
||||
}while (val != val1);
|
||||
return val;
|
||||
}
|
||||
|
||||
/////////////////////////////////////
|
||||
// Sn_TXBUF & Sn_RXBUF IO function //
|
||||
/////////////////////////////////////
|
||||
uint32_t getSn_RxBASE(uint8_t sn)
|
||||
{
|
||||
int8_t i;
|
||||
#if ( _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_)
|
||||
uint32_t rxbase = _W5100_IO_BASE_ + _WIZCHIP_IO_RXBUF_;
|
||||
#else
|
||||
uint32_t rxbase = _WIZCHIP_IO_RXBUF_;
|
||||
#endif
|
||||
for(i = 0; i < sn; i++)
|
||||
rxbase += getSn_RxMAX(i);
|
||||
|
||||
return rxbase;
|
||||
}
|
||||
|
||||
uint32_t getSn_TxBASE(uint8_t sn)
|
||||
{
|
||||
int8_t i;
|
||||
#if ( _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_)
|
||||
uint32_t txbase = _W5100_IO_BASE_ + _WIZCHIP_IO_TXBUF_;
|
||||
#else
|
||||
uint32_t txbase = _WIZCHIP_IO_TXBUF_;
|
||||
#endif
|
||||
for(i = 0; i < sn; i++)
|
||||
txbase += getSn_TxMAX(i);
|
||||
return txbase;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief This function is being called by send() and sendto() function also. for copy the data form application buffer to Transmite buffer of the chip.
|
||||
|
||||
This function read the Tx write pointer register and after copy the data in buffer update the Tx write pointer
|
||||
register. User should read upper byte first and lower byte later to get proper value.
|
||||
And this function is being used for copy the data form application buffer to Transmite
|
||||
buffer of the chip. It calculate the actual physical address where one has to write
|
||||
the data in transmite buffer. Here also take care of the condition while it exceed
|
||||
the Tx memory uper-bound of socket.
|
||||
|
||||
*/
|
||||
void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
|
||||
{
|
||||
uint16_t ptr;
|
||||
uint16_t size;
|
||||
uint16_t dst_mask;
|
||||
uint16_t dst_ptr;
|
||||
|
||||
ptr = getSn_TX_WR(sn);
|
||||
|
||||
dst_mask = ptr & getSn_TxMASK(sn);
|
||||
dst_ptr = getSn_TxBASE(sn) + dst_mask;
|
||||
|
||||
if (dst_mask + len > getSn_TxMAX(sn))
|
||||
{
|
||||
size = getSn_TxMAX(sn) - dst_mask;
|
||||
WIZCHIP_WRITE_BUF(dst_ptr, wizdata, size);
|
||||
wizdata += size;
|
||||
size = len - size;
|
||||
dst_ptr = getSn_TxBASE(sn);
|
||||
WIZCHIP_WRITE_BUF(dst_ptr, wizdata, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
WIZCHIP_WRITE_BUF(dst_ptr, wizdata, len);
|
||||
}
|
||||
|
||||
ptr += len;
|
||||
|
||||
setSn_TX_WR(sn, ptr);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief This function is being called by recv() also. This function is being used for copy the data form Receive buffer of the chip to application buffer.
|
||||
|
||||
This function read the Rx read pointer register
|
||||
and after copy the data from receive buffer update the Rx write pointer register.
|
||||
User should read upper byte first and lower byte later to get proper value.
|
||||
It calculate the actual physical address where one has to read
|
||||
the data from Receive buffer. Here also take care of the condition while it exceed
|
||||
the Rx memory uper-bound of socket.
|
||||
*/
|
||||
void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
|
||||
{
|
||||
uint16_t ptr;
|
||||
uint16_t size;
|
||||
uint16_t src_mask;
|
||||
uint16_t src_ptr;
|
||||
|
||||
ptr = getSn_RX_RD(sn);
|
||||
|
||||
src_mask = (uint32_t)ptr & getSn_RxMASK(sn);
|
||||
src_ptr = (getSn_RxBASE(sn) + src_mask);
|
||||
|
||||
|
||||
if( (src_mask + len) > getSn_RxMAX(sn) )
|
||||
{
|
||||
size = getSn_RxMAX(sn) - src_mask;
|
||||
WIZCHIP_READ_BUF((uint32_t)src_ptr, (uint8_t*)wizdata, size);
|
||||
wizdata += size;
|
||||
size = len - size;
|
||||
src_ptr = getSn_RxBASE(sn);
|
||||
WIZCHIP_READ_BUF(src_ptr, (uint8_t*)wizdata, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
WIZCHIP_READ_BUF(src_ptr, (uint8_t*)wizdata, len);
|
||||
}
|
||||
|
||||
ptr += len;
|
||||
|
||||
setSn_RX_RD(sn, ptr);
|
||||
}
|
||||
|
||||
void wiz_recv_ignore(uint8_t sn, uint16_t len)
|
||||
{
|
||||
uint16_t ptr;
|
||||
|
||||
ptr = getSn_RX_RD(sn);
|
||||
|
||||
ptr += len;
|
||||
setSn_RX_RD(sn,ptr);
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,425 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! \file w5100S.c
|
||||
//! \brief W5100S HAL Interface.
|
||||
//! \version 1.0.0
|
||||
//! \date 2018/03/29
|
||||
//! \par Revision history
|
||||
//! <2018/03/29> 1st Release
|
||||
//! \author Peter
|
||||
//!
|
||||
//! Copyright (c) 2013, WIZnet Co., LTD.
|
||||
//! All rights reserved.
|
||||
//!
|
||||
//! Redistribution and use in source and binary forms, with or without
|
||||
//! modification, are permitted provided that the following conditions
|
||||
//! are met:
|
||||
//!
|
||||
//! * Redistributions of source code must retain the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer.
|
||||
//! * Redistributions in binary form must reproduce the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer in the
|
||||
//! documentation and/or other materials provided with the distribution.
|
||||
//! * Neither the name of the <ORGANIZATION> nor the names of its
|
||||
//! contributors may be used to endorse or promote products derived
|
||||
//! from this software without specific prior written permission.
|
||||
//!
|
||||
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
//! THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#include "w5100s.h"
|
||||
|
||||
#if (_WIZCHIP_ == W5100S)
|
||||
/**
|
||||
@brief This function writes the data into W5100S registers.
|
||||
*/
|
||||
void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb )
|
||||
{
|
||||
int i;
|
||||
WIZCHIP_CRITICAL_ENTER();
|
||||
WIZCHIP.CS._select();
|
||||
|
||||
#if( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_))
|
||||
WIZCHIP.IF.SPI._write_byte(0xF0);
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0xFF00) >> 8);
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF) >> 0);
|
||||
WIZCHIP.IF.SPI._write_byte(wb); // Data write (write 1byte data)
|
||||
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_5500_) )
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0xFF00) >> 8);
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF) >> 0);
|
||||
WIZCHIP.IF.SPI._write_byte(0xF0);
|
||||
WIZCHIP.IF.SPI._write_byte(wb); // Data write (write 1byte data)
|
||||
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
|
||||
|
||||
//add indirect bus
|
||||
//M20150601 : Rename the function for integrating with ioLibrary
|
||||
//WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0xFF00) >> 8);
|
||||
//WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x00FF));
|
||||
//WIZCHIP.IF.BUS._write_byte(IDM_DR,wb);
|
||||
WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0xFF00) >> 8);
|
||||
WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x00FF));
|
||||
WIZCHIP.IF.BUS._write_data(IDM_DR,wb);
|
||||
#else
|
||||
#error "Unknown _WIZCHIP_IO_MODE_ in W5100. !!!"
|
||||
#endif
|
||||
|
||||
WIZCHIP.CS._deselect();
|
||||
WIZCHIP_CRITICAL_EXIT();
|
||||
}
|
||||
/**
|
||||
@brief This function reads the value from W5100S registers.
|
||||
*/
|
||||
uint8_t WIZCHIP_READ(uint32_t AddrSel)
|
||||
{
|
||||
uint8_t ret;
|
||||
int i;
|
||||
WIZCHIP_CRITICAL_ENTER();
|
||||
WIZCHIP.CS._select();
|
||||
|
||||
#if( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_))
|
||||
WIZCHIP.IF.SPI._write_byte(0x0F);
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0xFF00) >> 8);
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF) >> 0);
|
||||
ret = WIZCHIP.IF.SPI._read_byte();
|
||||
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_5500_) )
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0xFF00) >> 8);
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF) >> 0);
|
||||
WIZCHIP.IF.SPI._write_byte(0x0F);
|
||||
ret = WIZCHIP.IF.SPI._read_byte();
|
||||
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
|
||||
|
||||
//add indirect bus
|
||||
//M20150601 : Rename the function for integrating with ioLibrary
|
||||
//WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0xFF00) >> 8);
|
||||
//WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x00FF));
|
||||
//ret = WIZCHIP.IF.BUS._read_byte(IDM_DR);
|
||||
WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0xFF00) >> 8);
|
||||
WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x00FF));
|
||||
ret = WIZCHIP.IF.BUS._read_data(IDM_DR);
|
||||
|
||||
#else
|
||||
#error "Unknown _WIZCHIP_IO_MODE_ in W5100S. !!!"
|
||||
#endif
|
||||
|
||||
WIZCHIP.CS._deselect();
|
||||
WIZCHIP_CRITICAL_EXIT();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief This function writes into W5100S memory(Buffer)
|
||||
*/
|
||||
void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len)
|
||||
{
|
||||
uint16_t i = 0;
|
||||
int j,k,l;
|
||||
WIZCHIP_CRITICAL_ENTER();
|
||||
WIZCHIP.CS._select(); //M20150601 : Moved here.
|
||||
|
||||
#if((_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_))
|
||||
|
||||
WIZCHIP.IF.SPI._write_byte(0xF0);
|
||||
WIZCHIP.IF.SPI._write_byte((((uint16_t)(AddrSel+i)) & 0xFF00) >> 8);
|
||||
WIZCHIP.IF.SPI._write_byte((((uint16_t)(AddrSel+i)) & 0x00FF) >> 0);
|
||||
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
WIZCHIP.IF.SPI._write_byte(pBuf[i]); // Data write (write 1byte data)
|
||||
}
|
||||
|
||||
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_5500_) )
|
||||
|
||||
WIZCHIP.IF.SPI._write_byte((((uint16_t)(AddrSel+i)) & 0xFF00) >> 8);
|
||||
WIZCHIP.IF.SPI._write_byte((((uint16_t)(AddrSel+i)) & 0x00FF) >> 0);
|
||||
WIZCHIP.IF.SPI._write_byte(0xF0);
|
||||
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
WIZCHIP.IF.SPI._write_byte(pBuf[i]); // Data write (write 1byte data)
|
||||
}
|
||||
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
|
||||
//M20150601 : Rename the function for integrating with ioLibrary
|
||||
/*
|
||||
WIZCHIP_WRITE(MR,WIZCHIP_READ(MR) | MR_AI);
|
||||
WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0xFF00) >> 8);
|
||||
WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x00FF));
|
||||
for(i = 0 ; i < len; i++)
|
||||
WIZCHIP.IF.BUS._write_byte(IDM_DR,pBuf[i]);
|
||||
WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) & ~MR_AI);
|
||||
*/
|
||||
setMR(getMR()|MR_AI);
|
||||
WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0xFF00) >> 8);
|
||||
WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x00FF));
|
||||
for(i = 0 ; i < len; i++)
|
||||
WIZCHIP.IF.BUS._write_data(IDM_DR,pBuf[i]);
|
||||
setMR(getMR() & ~MR_AI);
|
||||
|
||||
#else
|
||||
#error "Unknown _WIZCHIP_IO_MODE_ in W5100S. !!!!"
|
||||
#endif
|
||||
|
||||
WIZCHIP.CS._deselect(); //M20150601 : Moved here.
|
||||
WIZCHIP_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
/**
|
||||
@brief This function reads into W5100S memory(Buffer)
|
||||
*/
|
||||
|
||||
void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len)
|
||||
{
|
||||
uint16_t i = 0;
|
||||
WIZCHIP_CRITICAL_ENTER();
|
||||
WIZCHIP.CS._select(); //M20150601 : Moved here.
|
||||
|
||||
#if( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_) )
|
||||
|
||||
WIZCHIP.IF.SPI._write_byte(0x0F);
|
||||
WIZCHIP.IF.SPI._write_byte((uint16_t)((AddrSel+i) & 0xFF00) >> 8);
|
||||
WIZCHIP.IF.SPI._write_byte((uint16_t)((AddrSel+i) & 0x00FF) >> 0);
|
||||
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
pBuf[i] = WIZCHIP.IF.SPI._read_byte();
|
||||
}
|
||||
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_5500_) )
|
||||
|
||||
WIZCHIP.IF.SPI._write_byte((uint16_t)((AddrSel+i) & 0xFF00) >> 8);
|
||||
WIZCHIP.IF.SPI._write_byte((uint16_t)((AddrSel+i) & 0x00FF) >> 0);
|
||||
WIZCHIP.IF.SPI._write_byte(0x0F);
|
||||
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
pBuf[i] = WIZCHIP.IF.SPI._read_byte();
|
||||
}
|
||||
|
||||
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
|
||||
//M20150601 : Rename the function for integrating with ioLibrary
|
||||
/*
|
||||
WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) | MR_AI);
|
||||
WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0xFF00) >> 8);
|
||||
WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x00FF));
|
||||
for(i = 0 ; i < len; i++)
|
||||
pBuf[i] = WIZCHIP.IF.BUS._read_byte(IDM_DR);
|
||||
WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) & ~MR_AI);
|
||||
*/
|
||||
setMR(getMR() | MR_AI);
|
||||
WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0xFF00) >> 8);
|
||||
WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x00FF));
|
||||
for(i = 0 ; i < len; i++)
|
||||
pBuf[i] = WIZCHIP.IF.BUS._read_data(IDM_DR);
|
||||
setMR(getMR() & ~MR_AI);
|
||||
|
||||
#else
|
||||
#error "Unknown _WIZCHIP_IO_MODE_ in W5100S. !!!!"
|
||||
#endif
|
||||
|
||||
WIZCHIP.CS._deselect(); //M20150601 : Moved Here.
|
||||
WIZCHIP_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
// Socket N regsiter IO function //
|
||||
///////////////////////////////////
|
||||
|
||||
uint16_t getSn_TX_FSR(uint8_t sn)
|
||||
{
|
||||
uint16_t val=0,val1=0;
|
||||
do
|
||||
{
|
||||
val1 = WIZCHIP_READ(Sn_TX_FSR(sn));
|
||||
val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1));
|
||||
if (val1 != 0)
|
||||
{
|
||||
val = WIZCHIP_READ(Sn_TX_FSR(sn));
|
||||
val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1));
|
||||
}
|
||||
}while (val != val1);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
uint16_t getSn_RX_RSR(uint8_t sn)
|
||||
{
|
||||
uint16_t val=0,val1=0;
|
||||
do
|
||||
{
|
||||
val1 = WIZCHIP_READ(Sn_RX_RSR(sn));
|
||||
val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1));
|
||||
if (val1 != 0)
|
||||
{
|
||||
val = WIZCHIP_READ(Sn_RX_RSR(sn));
|
||||
val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1));
|
||||
}
|
||||
}while (val != val1);
|
||||
return val;
|
||||
}
|
||||
|
||||
/////////////////////////////////////
|
||||
// Sn_TXBUF & Sn_RXBUF IO function //
|
||||
/////////////////////////////////////
|
||||
uint32_t getSn_RxBASE(uint8_t sn)
|
||||
{
|
||||
int8_t i;
|
||||
#if ( _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_)
|
||||
uint32_t rxbase = _W5100S_IO_BASE_ + _WIZCHIP_IO_RXBUF_;
|
||||
#else
|
||||
uint32_t rxbase = _WIZCHIP_IO_RXBUF_;
|
||||
#endif
|
||||
for(i = 0; i < sn; i++)
|
||||
rxbase += getSn_RxMAX(i);
|
||||
|
||||
return rxbase;
|
||||
}
|
||||
|
||||
uint32_t getSn_TxBASE(uint8_t sn)
|
||||
{
|
||||
int8_t i;
|
||||
#if ( _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_)
|
||||
uint32_t txbase = _W5100S_IO_BASE_ + _WIZCHIP_IO_TXBUF_;
|
||||
#else
|
||||
uint32_t txbase = _WIZCHIP_IO_TXBUF_;
|
||||
#endif
|
||||
for(i = 0; i < sn; i++)
|
||||
txbase += getSn_TxMAX(i);
|
||||
return txbase;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief This function is being called by send() and sendto() function also. for copy the data form application buffer to Transmite buffer of the chip.
|
||||
|
||||
This function read the Tx write pointer register and after copy the data in buffer update the Tx write pointer
|
||||
register. User should read upper byte first and lower byte later to get proper value.
|
||||
And this function is being used for copy the data form application buffer to Transmite
|
||||
buffer of the chip. It calculate the actual physical address where one has to write
|
||||
the data in transmite buffer. Here also take care of the condition while it exceed
|
||||
the Tx memory uper-bound of socket.
|
||||
|
||||
*/
|
||||
void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
|
||||
{
|
||||
uint16_t ptr;
|
||||
uint16_t size;
|
||||
uint16_t dst_mask;
|
||||
uint16_t dst_ptr;
|
||||
|
||||
ptr = getSn_TX_WR(sn);
|
||||
|
||||
dst_mask = ptr & getSn_TxMASK(sn);
|
||||
dst_ptr = getSn_TxBASE(sn) + dst_mask;
|
||||
|
||||
if (dst_mask + len > getSn_TxMAX(sn))
|
||||
{
|
||||
size = getSn_TxMAX(sn) - dst_mask;
|
||||
WIZCHIP_WRITE_BUF(dst_ptr, wizdata, size);
|
||||
wizdata += size;
|
||||
size = len - size;
|
||||
dst_ptr = getSn_TxBASE(sn);
|
||||
WIZCHIP_WRITE_BUF(dst_ptr, wizdata, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
WIZCHIP_WRITE_BUF(dst_ptr, wizdata, len);
|
||||
}
|
||||
|
||||
ptr += len;
|
||||
|
||||
setSn_TX_WR(sn, ptr);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief This function is being called by recv() also. This function is being used for copy the data form Receive buffer of the chip to application buffer.
|
||||
|
||||
This function read the Rx read pointer register
|
||||
and after copy the data from receive buffer update the Rx write pointer register.
|
||||
User should read upper byte first and lower byte later to get proper value.
|
||||
It calculate the actual physical address where one has to read
|
||||
the data from Receive buffer. Here also take care of the condition while it exceed
|
||||
the Rx memory uper-bound of socket.
|
||||
*/
|
||||
void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
|
||||
{
|
||||
uint16_t ptr;
|
||||
uint16_t size;
|
||||
uint16_t src_mask;
|
||||
uint16_t src_ptr;
|
||||
|
||||
ptr = getSn_RX_RD(sn);
|
||||
|
||||
src_mask = (uint32_t)ptr & getSn_RxMASK(sn);
|
||||
src_ptr = (getSn_RxBASE(sn) + src_mask);
|
||||
|
||||
|
||||
if( (src_mask + len) > getSn_RxMAX(sn) )
|
||||
{
|
||||
size = getSn_RxMAX(sn) - src_mask;
|
||||
WIZCHIP_READ_BUF((uint32_t)src_ptr, (uint8_t*)wizdata, size);
|
||||
wizdata += size;
|
||||
size = len - size;
|
||||
src_ptr = getSn_RxBASE(sn);
|
||||
WIZCHIP_READ_BUF(src_ptr, (uint8_t*)wizdata, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
WIZCHIP_READ_BUF(src_ptr, (uint8_t*)wizdata, len);
|
||||
}
|
||||
|
||||
ptr += len;
|
||||
|
||||
setSn_RX_RD(sn, ptr);
|
||||
}
|
||||
|
||||
void wiz_recv_ignore(uint8_t sn, uint16_t len)
|
||||
{
|
||||
uint16_t ptr;
|
||||
|
||||
ptr = getSn_RX_RD(sn);
|
||||
|
||||
ptr += len;
|
||||
setSn_RX_RD(sn,ptr);
|
||||
}
|
||||
|
||||
void wiz_mdio_write(uint8_t PHYMDIO_regadr, uint16_t var)
|
||||
{
|
||||
WIZCHIP_WRITE(PHYRAR,PHYMDIO_regadr);
|
||||
WIZCHIP_WRITE(PHYDIR, (uint8_t)(var >> 8));
|
||||
WIZCHIP_WRITE(PHYDIR+1, (uint8_t)(var));
|
||||
WIZCHIP_WRITE(PHYACR, PHYACR_WRITE);
|
||||
while(WIZCHIP_READ(PHYACR)); //wait for command complete
|
||||
}
|
||||
|
||||
uint16_t wiz_mdio_read(uint8_t PHYMDIO_regadr)
|
||||
{
|
||||
WIZCHIP_WRITE(PHYRAR,PHYMDIO_regadr);
|
||||
WIZCHIP_WRITE(PHYACR, PHYACR_READ);
|
||||
while(WIZCHIP_READ(PHYACR)); //wait for command complete
|
||||
return ((uint16_t)WIZCHIP_READ(PHYDOR) << 8) | WIZCHIP_READ(PHYDOR+1);
|
||||
}
|
||||
|
||||
void wiz_delay_ms(uint32_t milliseconds)
|
||||
{
|
||||
uint32_t i;
|
||||
for(i = 0 ; i < milliseconds ; i++)
|
||||
{
|
||||
//Write any values to clear the TCNTCLKR register
|
||||
setTCNTCLKR(0xff);
|
||||
|
||||
// Wait until counter register value reaches 10.(10 = 1ms : TCNTR is 100us tick counter register)
|
||||
while(getTCNTR() < 0x0a){}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,353 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! \file w5200.c
|
||||
//! \brief W5200 HAL Interface.
|
||||
//! \version 1.0.0
|
||||
//! \date 2013/10/21
|
||||
//! \par Revision history
|
||||
//! <2013/10/21> 1st Release
|
||||
//! \author MidnightCow
|
||||
//!
|
||||
//! Copyright (c) 2013, WIZnet Co., LTD.
|
||||
//! All rights reserved.
|
||||
//!
|
||||
//! Redistribution and use in source and binary forms, with or without
|
||||
//! modification, are permitted provided that the following conditions
|
||||
//! are met:
|
||||
//!
|
||||
//! * Redistributions of source code must retain the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer.
|
||||
//! * Redistributions in binary form must reproduce the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer in the
|
||||
//! documentation and/or other materials provided with the distribution.
|
||||
//! * Neither the name of the <ORGANIZATION> nor the names of its
|
||||
//! contributors may be used to endorse or promote products derived
|
||||
//! from this software without specific prior written permission.
|
||||
//!
|
||||
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
//! THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#include "w5200.h"
|
||||
|
||||
#if (_WIZCHIP_ == 5200)
|
||||
/**
|
||||
@brief This function writes the data into W5200 registers.
|
||||
*/
|
||||
void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb )
|
||||
{
|
||||
WIZCHIP_CRITICAL_ENTER();
|
||||
WIZCHIP.CS._select();
|
||||
|
||||
#if( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_))
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8);
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0);
|
||||
WIZCHIP.IF.SPI._write_byte(_W5200_SPI_WRITE_); // Data write command and Write data length upper
|
||||
WIZCHIP.IF.SPI._write_byte(0x01); // Write data length lower
|
||||
WIZCHIP.IF.SPI._write_byte(wb); // Data write (write 1byte data)
|
||||
|
||||
#elif ( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_) )
|
||||
|
||||
//add indirect bus
|
||||
//M20150601 : Rename the function for integrating with W5300
|
||||
//WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0x0000FF00) >> 8);
|
||||
//WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x000000FF));
|
||||
//WIZCHIP.IF.BUS._write_byte(IDM_DR,wb);
|
||||
WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0x0000FF00) >> 8);
|
||||
WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x000000FF));
|
||||
WIZCHIP.IF.BUS._write_data(IDM_DR,wb);
|
||||
|
||||
#else
|
||||
#error "Unknown _WIZCHIP_IO_MODE_ in W5200. !!!"
|
||||
#endif
|
||||
|
||||
WIZCHIP.CS._deselect();
|
||||
WIZCHIP_CRITICAL_EXIT();
|
||||
}
|
||||
/**
|
||||
@brief This function reads the value from W5200 registers.
|
||||
*/
|
||||
uint8_t WIZCHIP_READ(uint32_t AddrSel)
|
||||
{
|
||||
uint8_t ret;
|
||||
|
||||
WIZCHIP_CRITICAL_ENTER();
|
||||
WIZCHIP.CS._select();
|
||||
|
||||
#if( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_))
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8);
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0);
|
||||
WIZCHIP.IF.SPI._write_byte(_W5200_SPI_READ_); // Read data length upper
|
||||
WIZCHIP.IF.SPI._write_byte(0x01); // Data length lower
|
||||
ret = WIZCHIP.IF.SPI._read_byte();
|
||||
|
||||
#elif ( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_) )
|
||||
|
||||
//add indirect bus
|
||||
//M20150601 : Rename the function for integrating with W5300
|
||||
//WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0x0000FF00) >> 8);
|
||||
//WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x000000FF));
|
||||
//ret = WIZCHIP.IF.BUS._read_byte(IDM_DR);
|
||||
WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0x0000FF00) >> 8);
|
||||
WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x000000FF));
|
||||
ret = WIZCHIP.IF.BUS._read_data(IDM_DR);
|
||||
|
||||
#else
|
||||
#error "Unknown _WIZCHIP_IO_MODE_ in W5200. !!!"
|
||||
#endif
|
||||
|
||||
WIZCHIP.CS._deselect();
|
||||
WIZCHIP_CRITICAL_EXIT();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief This function writes into W5200 memory(Buffer)
|
||||
*/
|
||||
void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len)
|
||||
{
|
||||
uint16_t i = 0;
|
||||
WIZCHIP_CRITICAL_ENTER();
|
||||
WIZCHIP.CS._select();
|
||||
|
||||
#if( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_))
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8);
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0);
|
||||
WIZCHIP.IF.SPI._write_byte(_W5200_SPI_WRITE_ | ((len & 0x7F00) >> 8)); // Write data op code and length upper
|
||||
WIZCHIP.IF.SPI._write_byte((len & 0x00FF) >> 0); // length lower
|
||||
for(i = 0; i < len; i++)
|
||||
WIZCHIP.IF.SPI._write_byte(pBuf[i]);
|
||||
|
||||
#elif ( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_) )
|
||||
//M20150601 : Rename the function for integrating with W5300
|
||||
/*
|
||||
WIZCHIP_WRITE(MR,WIZCHIP_READ(MR) | MR_AI);
|
||||
WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0x0000FF00) >> 8);
|
||||
WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x000000FF));
|
||||
for(i = 0 ; i < len; i++)
|
||||
WIZCHIP.IF.BUS._write_byte(IDM_DR,pBuf[i]);
|
||||
WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) & ~MR_AI);
|
||||
*/
|
||||
setMR(getMR() | MR_AI);
|
||||
WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0x0000FF00) >> 8);
|
||||
WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x000000FF));
|
||||
for(i = 0 ; i < len; i++)
|
||||
WIZCHIP.IF.BUS._write_data(IDM_DR,pBuf[i]);
|
||||
WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) & ~MR_AI);
|
||||
#else
|
||||
#error "Unknown _WIZCHIP_IO_MODE_ in W5200. !!!!"
|
||||
#endif
|
||||
|
||||
WIZCHIP.CS._deselect();
|
||||
WIZCHIP_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
/**
|
||||
@brief This function reads into W5200 memory(Buffer)
|
||||
*/
|
||||
void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len)
|
||||
{
|
||||
uint16_t i = 0;
|
||||
WIZCHIP_CRITICAL_ENTER();
|
||||
WIZCHIP.CS._select();
|
||||
|
||||
#if( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_))
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8);
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0);
|
||||
WIZCHIP.IF.SPI._write_byte( _W5200_SPI_READ_ | ((len & 0x7F00) >> 8)); // Write data op code and length upper
|
||||
WIZCHIP.IF.SPI._write_byte((len & 0x00FF) >> 0); // length lower
|
||||
for(i = 0; i < len; i++)
|
||||
pBuf[i] = WIZCHIP.IF.SPI._read_byte();
|
||||
|
||||
#elif ( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_) )
|
||||
//M20150601 : Rename the function for integrating with W5300
|
||||
/*
|
||||
WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) | MR_AI);
|
||||
WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0x0000FF00) >> 8);
|
||||
WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x000000FF));
|
||||
for(i = 0 ; i < len; i++)
|
||||
pBuf[i] = WIZCHIP.IF.BUS._read_byte(IDM_DR);
|
||||
WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) & ~MR_AI);
|
||||
*/
|
||||
setMR(getMR() | MR_AI);
|
||||
WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0x0000FF00) >> 8);
|
||||
WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x000000FF));
|
||||
for(i = 0 ; i < len; i++)
|
||||
pBuf[i] = WIZCHIP.IF.BUS._read_data(IDM_DR);
|
||||
setMR(getMR() & ~MR_AI);
|
||||
#else
|
||||
#error "Unknown _WIZCHIP_IO_MODE_ in W5200. !!!!"
|
||||
#endif
|
||||
|
||||
WIZCHIP.CS._deselect();
|
||||
WIZCHIP_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
// Socket N regsiter IO function //
|
||||
///////////////////////////////////
|
||||
|
||||
uint16_t getSn_TX_FSR(uint8_t sn)
|
||||
{
|
||||
uint16_t val=0,val1=0;
|
||||
do
|
||||
{
|
||||
val1 = WIZCHIP_READ(Sn_TX_FSR(sn));
|
||||
val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1));
|
||||
if (val1 != 0)
|
||||
{
|
||||
val = WIZCHIP_READ(Sn_TX_FSR(sn));
|
||||
val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1));
|
||||
}
|
||||
}while (val != val1);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
uint16_t getSn_RX_RSR(uint8_t sn)
|
||||
{
|
||||
uint16_t val=0,val1=0;
|
||||
do
|
||||
{
|
||||
val1 = WIZCHIP_READ(Sn_RX_RSR(sn));
|
||||
val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1));
|
||||
if (val1 != 0)
|
||||
{
|
||||
val = WIZCHIP_READ(Sn_RX_RSR(sn));
|
||||
val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1));
|
||||
}
|
||||
}while (val != val1);
|
||||
return val;
|
||||
}
|
||||
|
||||
/////////////////////////////////////
|
||||
// Sn_TXBUF & Sn_RXBUF IO function //
|
||||
/////////////////////////////////////
|
||||
|
||||
uint16_t getSn_RxBASE(uint8_t sn)
|
||||
{
|
||||
int8_t i;
|
||||
uint16_t rxbase = _WIZCHIP_IO_RXBUF_;
|
||||
for(i = 0; i < sn; i++)
|
||||
rxbase += getSn_RxMAX(i);
|
||||
return rxbase;
|
||||
}
|
||||
|
||||
uint16_t getSn_TxBASE(uint8_t sn)
|
||||
{
|
||||
int8_t i;
|
||||
uint16_t txbase = _WIZCHIP_IO_TXBUF_;
|
||||
for(i = 0; i < sn; i++)
|
||||
txbase += getSn_TxMAX(i);
|
||||
return txbase;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief This function is being called by send() and sendto() function also. for copy the data form application buffer to Transmite buffer of the chip.
|
||||
|
||||
This function read the Tx write pointer register and after copy the data in buffer update the Tx write pointer
|
||||
register. User should read upper byte first and lower byte later to get proper value.
|
||||
And this function is being used for copy the data form application buffer to Transmite
|
||||
buffer of the chip. It calculate the actual physical address where one has to write
|
||||
the data in transmite buffer. Here also take care of the condition while it exceed
|
||||
the Tx memory uper-bound of socket.
|
||||
|
||||
*/
|
||||
|
||||
void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
|
||||
{
|
||||
|
||||
uint16_t ptr;
|
||||
uint16_t size;
|
||||
uint16_t dst_mask;
|
||||
uint8_t * dst_ptr;
|
||||
|
||||
ptr = getSn_TX_WR(sn);
|
||||
|
||||
|
||||
dst_mask = (uint32_t)ptr & getSn_TxMASK(sn);
|
||||
dst_ptr = (uint8_t*)((uint32_t)getSn_TxBASE(sn) + dst_mask);
|
||||
|
||||
if (dst_mask + len > getSn_TxMAX(sn))
|
||||
{
|
||||
size = getSn_TxMAX(sn) - dst_mask;
|
||||
WIZCHIP_WRITE_BUF((uint32_t)dst_ptr, wizdata, size);
|
||||
wizdata += size;
|
||||
size = len - size;
|
||||
dst_ptr = (uint8_t*)((uint32_t)getSn_TxBASE(sn));
|
||||
WIZCHIP_WRITE_BUF((uint32_t)dst_ptr, wizdata, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
WIZCHIP_WRITE_BUF((uint32_t)dst_ptr, wizdata, len);
|
||||
}
|
||||
|
||||
ptr += len;
|
||||
|
||||
setSn_TX_WR(sn, ptr);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief This function is being called by recv() also. This function is being used for copy the data form Receive buffer of the chip to application buffer.
|
||||
|
||||
This function read the Rx read pointer register
|
||||
and after copy the data from receive buffer update the Rx write pointer register.
|
||||
User should read upper byte first and lower byte later to get proper value.
|
||||
It calculate the actual physical address where one has to read
|
||||
the data from Receive buffer. Here also take care of the condition while it exceed
|
||||
the Rx memory uper-bound of socket.
|
||||
*/
|
||||
void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
|
||||
{
|
||||
uint16_t ptr;
|
||||
uint16_t size;
|
||||
uint16_t src_mask;
|
||||
uint8_t * src_ptr;
|
||||
|
||||
ptr = getSn_RX_RD(sn);
|
||||
|
||||
src_mask = (uint32_t)ptr & getSn_RxMASK(sn);
|
||||
src_ptr = (uint8_t *)((uint32_t)getSn_RxBASE(sn) + src_mask);
|
||||
|
||||
if( (src_mask + len) > getSn_RxMAX(sn) )
|
||||
{
|
||||
size = getSn_RxMAX(sn) - src_mask;
|
||||
WIZCHIP_READ_BUF((uint32_t)src_ptr, (uint8_t*)wizdata, size);
|
||||
wizdata += size;
|
||||
size = len - size;
|
||||
src_ptr = (uint8_t*)((uint32_t)getSn_RxBASE(sn));
|
||||
WIZCHIP_READ_BUF((uint32_t)src_ptr, (uint8_t*)wizdata, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
WIZCHIP_READ_BUF((uint32_t)src_ptr, (uint8_t*)wizdata, len);
|
||||
}
|
||||
|
||||
ptr += len;
|
||||
|
||||
setSn_RX_RD(sn, ptr);
|
||||
}
|
||||
|
||||
void wiz_recv_ignore(uint8_t sn, uint16_t len)
|
||||
{
|
||||
uint16_t ptr;
|
||||
|
||||
ptr = getSn_RX_RD(sn);
|
||||
|
||||
ptr += len;
|
||||
setSn_RX_RD(sn,ptr);
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,225 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! \file w5300.h
|
||||
//! \brief W5300 HAL implement File.
|
||||
//! \version 1.0.0
|
||||
//! \date 2015/05/01
|
||||
//! \par Revision history
|
||||
//! <2015/05/01> 1st Released for integrating with ioLibrary
|
||||
//! Download the latest version directly from GitHub. Please visit the our GitHub repository for ioLibrary.
|
||||
//! >> https://github.com/Wiznet/ioLibrary_Driver
|
||||
//! \author MidnightCow
|
||||
//! \copyright
|
||||
//!
|
||||
//! Copyright (c) 2015, WIZnet Co., LTD.
|
||||
//! All rights reserved.
|
||||
//!
|
||||
//! Redistribution and use in source and binary forms, with or without
|
||||
//! modification, are permitted provided that the following conditions
|
||||
//! are met:
|
||||
//!
|
||||
//! * Redistributions of source code must retain the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer.
|
||||
//! * Redistributions in binary form must reproduce the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer in the
|
||||
//! documentation and/or other materials provided with the distribution.
|
||||
//! * Neither the name of the <ORGANIZATION> nor the names of its
|
||||
//! contributors may be used to endorse or promote products derived
|
||||
//! from this software without specific prior written permission.
|
||||
//!
|
||||
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
//! THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#include <stdint.h>
|
||||
#include "wizchip_conf.h"
|
||||
|
||||
#if _WIZCHIP_ == 5300
|
||||
|
||||
extern uint8_t sock_remained_byte[_WIZCHIP_SOCK_NUM_];
|
||||
extern uint8_t sock_pack_info[_WIZCHIP_SOCK_NUM_];
|
||||
|
||||
|
||||
/***********************
|
||||
* Basic I/O Function *
|
||||
***********************/
|
||||
|
||||
void WIZCHIP_WRITE(uint32_t AddrSel, uint16_t wb )
|
||||
{
|
||||
WIZCHIP_CRITICAL_ENTER();
|
||||
WIZCHIP.CS._select();
|
||||
|
||||
#if ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_) )
|
||||
#if(_WIZCHIP_IO_BUS_WIDTH_ == 8)
|
||||
WIZCHIP.IF.BUS._write_data(AddrSel, (uint8_t)(wb>>8));
|
||||
WIZCHIP.IF.BUS._write_data(WIZCHIP_OFFSET_INC(AddrSel,1),(uint8_t)wb);
|
||||
#elif(_WIZCHIP_IO_BUS_WIDTH_ == 16)
|
||||
WIZCHIP.IF.BUS._write_data(AddrSel, wb);
|
||||
#else
|
||||
#error "Abnoraml _WIZCHIP_IO_BUS_WIDTH_. Should be 8 or 16"
|
||||
#endif
|
||||
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
|
||||
#if(_WIZCHIP_IO_BUS_WIDTH_ == 8)
|
||||
WIZCHIP.IF.BUS._write_data(IDM_AR, (uint8_t)(AddrSel >> 8));
|
||||
WIZCHIP.IF.BUS._write_data(WIZCHIP_OFFSET_INC(IDM_AR,1),(uint8_t)AddrSel);
|
||||
WIZCHIP.IF.BUS._write_data(IDM_DR,(uint8_t)(wb>>8));
|
||||
WIZCHIP.IF.BUS._write_data(WIZCHIP_OFFSET_INC(IDM_DR,1),(uint8_t)wb);
|
||||
#elif(_WIZCHIP_IO_BUS_WIDTH_ == 16)
|
||||
WIZCHIP.IF.BUS._write_data(IDM_AR, (uint16_t)AddrSel);
|
||||
WIZCHIP.IF.BUS._write_data(IDM_DR, wb);
|
||||
#else
|
||||
#error "Abnoraml _WIZCHIP_IO_BUS_WIDTH_. Should be 8 or 16"
|
||||
#endif
|
||||
#else
|
||||
#error "Unknown _WIZCHIP_IO_MODE_ in W5300. !!!"
|
||||
#endif
|
||||
|
||||
WIZCHIP.CS._deselect();
|
||||
WIZCHIP_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
uint16_t WIZCHIP_READ(uint32_t AddrSel)
|
||||
{
|
||||
uint16_t ret;
|
||||
|
||||
WIZCHIP_CRITICAL_ENTER();
|
||||
WIZCHIP.CS._select();
|
||||
|
||||
#if ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_) )
|
||||
#if (_WIZCHIP_IO_BUS_WIDTH_ == 8)
|
||||
ret = (((uint16_t)WIZCHIP.IF.BUS._read_data(AddrSel)) << 8) |
|
||||
(((uint16_t)WIZCHIP.IF.BUS._read_data(WIZCHIP_OFFSET_INC(AddrSel,1))) & 0x00FF) ;
|
||||
#elif(_WIZCHIP_IO_BUS_WIDTH_ == 16)
|
||||
ret = WIZCHIP.IF.BUS._read_data(AddrSel);
|
||||
#else
|
||||
#error "Abnoraml _WIZCHIP_IO_BUS_WIDTH_. Should be 8 or 16"
|
||||
#endif
|
||||
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
|
||||
#if(_WIZCHIP_IO_BUS_WIDTH_ == 8)
|
||||
WIZCHIP.IF.BUS._write_data(IDM_AR, (uint8_t)(AddrSel >> 8));
|
||||
WIZCHIP.IF.BUS._write_data(WIZCHIP_OFFSET_INC(IDM_AR,1),(uint8_t)AddrSel);
|
||||
ret = (((uint16_t)WIZCHIP.IF.BUS._read_data(IDM_DR)) << 8) |
|
||||
(((uint16_t)WIZCHIP.IF.BUS._read_data(WIZCHIP_OFFSET_INC(IDM_DR,1))) & 0x00FF);
|
||||
#elif(_WIZCHIP_IO_BUS_WIDTH_ == 16)
|
||||
WIZCHIP.IF.BUS._write_data(IDM_AR, (uint16_t)AddrSel);
|
||||
ret = WIZCHIP.IF.BUS._read_data(IDM_DR);
|
||||
#else
|
||||
#error "Abnoraml _WIZCHIP_IO_BUS_WIDTH_. Should be 8 or 16"
|
||||
#endif
|
||||
#else
|
||||
#error "Unknown _WIZCHIP_IO_MODE_ in W5300. !!!"
|
||||
#endif
|
||||
|
||||
WIZCHIP.CS._deselect();
|
||||
WIZCHIP_CRITICAL_EXIT();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void setTMSR(uint8_t sn,uint8_t tmsr)
|
||||
{
|
||||
uint16_t tmem;
|
||||
tmem = WIZCHIP_READ(WIZCHIP_OFFSET_INC(TMS01R, (sn & 0xFE)));
|
||||
if(sn & 0x01) tmem = (tmem & 0xFF00) | (((uint16_t)tmsr ) & 0x00FF) ;
|
||||
else tmem = (tmem & 0x00FF) | (((uint16_t)tmsr) << 8) ;
|
||||
WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(TMS01R, (sn & 0xFE)),tmem);
|
||||
}
|
||||
|
||||
uint8_t getTMSR(uint8_t sn)
|
||||
{
|
||||
if(sn & 0x01)
|
||||
return (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(TMS01R, (sn & 0xFE))) & 0x00FF);
|
||||
return (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(TMS01R, (sn & 0xFE))) >> 8);
|
||||
}
|
||||
|
||||
void setRMSR(uint8_t sn,uint8_t rmsr)
|
||||
{
|
||||
uint16_t rmem;
|
||||
rmem = WIZCHIP_READ(WIZCHIP_OFFSET_INC(RMS01R, (sn & 0xFE)));
|
||||
if(sn & 0x01) rmem = (rmem & 0xFF00) | (((uint16_t)rmsr ) & 0x00FF) ;
|
||||
else rmem = (rmem & 0x00FF) | (((uint16_t)rmsr) << 8) ;
|
||||
WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(RMS01R, (sn & 0xFE)),rmem);
|
||||
}
|
||||
|
||||
uint8_t getRMSR(uint8_t sn)
|
||||
{
|
||||
if(sn & 0x01)
|
||||
return (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(RMS01R, (sn & 0xFE))) & 0x00FF);
|
||||
return (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(RMS01R, (sn & 0xFE))) >> 8);
|
||||
}
|
||||
|
||||
uint32_t getSn_TX_FSR(uint8_t sn)
|
||||
{
|
||||
uint32_t free_tx_size=0;
|
||||
uint32_t free_tx_size1=1;
|
||||
while(1)
|
||||
{
|
||||
free_tx_size = (((uint32_t)WIZCHIP_READ(Sn_TX_FSR(sn))) << 16) |
|
||||
(((uint32_t)WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),2))) & 0x0000FFFF); // read
|
||||
if(free_tx_size == free_tx_size1) break; // if first == sencond, Sn_TX_FSR value is valid.
|
||||
free_tx_size1 = free_tx_size; // save second value into first
|
||||
}
|
||||
return free_tx_size;
|
||||
}
|
||||
|
||||
uint32_t getSn_RX_RSR(uint8_t sn)
|
||||
{
|
||||
uint32_t received_rx_size=0;
|
||||
uint32_t received_rx_size1=1;
|
||||
while(1)
|
||||
{
|
||||
received_rx_size = (((uint32_t)WIZCHIP_READ(Sn_RX_RSR(sn))) << 16) |
|
||||
(((uint32_t)WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),2))) & 0x0000FFFF);
|
||||
if(received_rx_size == received_rx_size1) break;
|
||||
received_rx_size1 = received_rx_size; // if first == sencond, Sn_RX_RSR value is valid.
|
||||
} // save second value into first
|
||||
return received_rx_size + (uint32_t)((sock_pack_info[sn] & 0x02) ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint32_t len)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
if(len == 0) return;
|
||||
|
||||
for(i = 0; i < len ; i += 2)
|
||||
setSn_TX_FIFOR(sn, (((uint16_t)wizdata[i]) << 8) | (((uint16_t)wizdata[i+1]) & 0x00FF))
|
||||
}
|
||||
|
||||
void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint32_t len)
|
||||
{
|
||||
uint16_t rd = 0;
|
||||
uint32_t i = 0;
|
||||
|
||||
if(len == 0) return;
|
||||
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
if((i & 0x01)==0)
|
||||
{
|
||||
rd = getSn_RX_FIFOR(sn);
|
||||
wizdata[i] = (uint8_t)(rd >> 8);
|
||||
}
|
||||
else wizdata[i] = (uint8_t)rd; // For checking the memory access violation
|
||||
}
|
||||
sock_remained_byte[sn] = (uint8_t)rd; // back up the remaind fifo byte.
|
||||
}
|
||||
|
||||
void wiz_recv_ignore(uint8_t sn, uint32_t len)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
for(i = 0; i < len ; i += 2) getSn_RX_FIFOR(sn);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,267 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! \file w5500.c
|
||||
//! \brief W5500 HAL Interface.
|
||||
//! \version 1.0.2
|
||||
//! \date 2013/10/21
|
||||
//! \par Revision history
|
||||
//! <2015/02/05> Notice
|
||||
//! The version history is not updated after this point.
|
||||
//! Download the latest version directly from GitHub. Please visit the our GitHub repository for ioLibrary.
|
||||
//! >> https://github.com/Wiznet/ioLibrary_Driver
|
||||
//! <2014/05/01> V1.0.2
|
||||
//! 1. Implicit type casting -> Explicit type casting. Refer to M20140501
|
||||
//! Fixed the problem on porting into under 32bit MCU
|
||||
//! Issued by Mathias ClauBen, wizwiki forum ID Think01 and bobh
|
||||
//! Thank for your interesting and serious advices.
|
||||
//! <2013/12/20> V1.0.1
|
||||
//! 1. Remove warning
|
||||
//! 2. WIZCHIP_READ_BUF WIZCHIP_WRITE_BUF in case _WIZCHIP_IO_MODE_SPI_FDM_
|
||||
//! for loop optimized(removed). refer to M20131220
|
||||
//! <2013/10/21> 1st Release
|
||||
//! \author MidnightCow
|
||||
//! \copyright
|
||||
//!
|
||||
//! Copyright (c) 2013, WIZnet Co., LTD.
|
||||
//! All rights reserved.
|
||||
//!
|
||||
//! Redistribution and use in source and binary forms, with or without
|
||||
//! modification, are permitted provided that the following conditions
|
||||
//! are met:
|
||||
//!
|
||||
//! * Redistributions of source code must retain the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer.
|
||||
//! * Redistributions in binary form must reproduce the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer in the
|
||||
//! documentation and/or other materials provided with the distribution.
|
||||
//! * Neither the name of the <ORGANIZATION> nor the names of its
|
||||
//! contributors may be used to endorse or promote products derived
|
||||
//! from this software without specific prior written permission.
|
||||
//!
|
||||
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
//! THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//*****************************************************************************
|
||||
//#include <stdio.h>
|
||||
#include "w5500.h"
|
||||
|
||||
#define _W5500_SPI_VDM_OP_ 0x00
|
||||
#define _W5500_SPI_FDM_OP_LEN1_ 0x01
|
||||
#define _W5500_SPI_FDM_OP_LEN2_ 0x02
|
||||
#define _W5500_SPI_FDM_OP_LEN4_ 0x03
|
||||
|
||||
#if (_WIZCHIP_ == 5500)
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
uint8_t WIZCHIP_READ(uint32_t AddrSel)
|
||||
{
|
||||
uint8_t ret;
|
||||
uint8_t spi_data[3];
|
||||
|
||||
WIZCHIP_CRITICAL_ENTER();
|
||||
WIZCHIP.CS._select();
|
||||
|
||||
AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_);
|
||||
|
||||
if(!WIZCHIP.IF.SPI._read_burst || !WIZCHIP.IF.SPI._write_burst) // byte operation
|
||||
{
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8);
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0);
|
||||
}
|
||||
else // burst operation
|
||||
{
|
||||
spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
|
||||
spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
|
||||
spi_data[2] = (AddrSel & 0x000000FF) >> 0;
|
||||
WIZCHIP.IF.SPI._write_burst(spi_data, 3);
|
||||
}
|
||||
ret = WIZCHIP.IF.SPI._read_byte();
|
||||
|
||||
WIZCHIP.CS._deselect();
|
||||
WIZCHIP_CRITICAL_EXIT();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb )
|
||||
{
|
||||
uint8_t spi_data[4];
|
||||
|
||||
WIZCHIP_CRITICAL_ENTER();
|
||||
WIZCHIP.CS._select();
|
||||
|
||||
AddrSel |= (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_);
|
||||
|
||||
//if(!WIZCHIP.IF.SPI._read_burst || !WIZCHIP.IF.SPI._write_burst) // byte operation
|
||||
if(!WIZCHIP.IF.SPI._write_burst) // byte operation
|
||||
{
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8);
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0);
|
||||
WIZCHIP.IF.SPI._write_byte(wb);
|
||||
}
|
||||
else // burst operation
|
||||
{
|
||||
spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
|
||||
spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
|
||||
spi_data[2] = (AddrSel & 0x000000FF) >> 0;
|
||||
spi_data[3] = wb;
|
||||
WIZCHIP.IF.SPI._write_burst(spi_data, 4);
|
||||
}
|
||||
|
||||
WIZCHIP.CS._deselect();
|
||||
WIZCHIP_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len)
|
||||
{
|
||||
uint8_t spi_data[3];
|
||||
uint16_t i;
|
||||
|
||||
WIZCHIP_CRITICAL_ENTER();
|
||||
WIZCHIP.CS._select();
|
||||
|
||||
AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_);
|
||||
|
||||
if(!WIZCHIP.IF.SPI._read_burst || !WIZCHIP.IF.SPI._write_burst) // byte operation
|
||||
{
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8);
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0);
|
||||
for(i = 0; i < len; i++)
|
||||
pBuf[i] = WIZCHIP.IF.SPI._read_byte();
|
||||
}
|
||||
else // burst operation
|
||||
{
|
||||
spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
|
||||
spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
|
||||
spi_data[2] = (AddrSel & 0x000000FF) >> 0;
|
||||
WIZCHIP.IF.SPI._write_burst(spi_data, 3);
|
||||
WIZCHIP.IF.SPI._read_burst(pBuf, len);
|
||||
}
|
||||
|
||||
WIZCHIP.CS._deselect();
|
||||
WIZCHIP_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len)
|
||||
{
|
||||
uint8_t spi_data[3];
|
||||
uint16_t i;
|
||||
|
||||
WIZCHIP_CRITICAL_ENTER();
|
||||
WIZCHIP.CS._select();
|
||||
|
||||
AddrSel |= (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_);
|
||||
|
||||
if(!WIZCHIP.IF.SPI._write_burst) // byte operation
|
||||
{
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8);
|
||||
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0);
|
||||
for(i = 0; i < len; i++)
|
||||
WIZCHIP.IF.SPI._write_byte(pBuf[i]);
|
||||
}
|
||||
else // burst operation
|
||||
{
|
||||
spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
|
||||
spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
|
||||
spi_data[2] = (AddrSel & 0x000000FF) >> 0;
|
||||
WIZCHIP.IF.SPI._write_burst(spi_data, 3);
|
||||
WIZCHIP.IF.SPI._write_burst(pBuf, len);
|
||||
}
|
||||
|
||||
WIZCHIP.CS._deselect();
|
||||
WIZCHIP_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
|
||||
uint16_t getSn_TX_FSR(uint8_t sn)
|
||||
{
|
||||
uint16_t val=0,val1=0;
|
||||
|
||||
do
|
||||
{
|
||||
val1 = WIZCHIP_READ(Sn_TX_FSR(sn));
|
||||
val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1));
|
||||
if (val1 != 0)
|
||||
{
|
||||
val = WIZCHIP_READ(Sn_TX_FSR(sn));
|
||||
val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1));
|
||||
}
|
||||
}while (val != val1);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
uint16_t getSn_RX_RSR(uint8_t sn)
|
||||
{
|
||||
uint16_t val=0,val1=0;
|
||||
|
||||
do
|
||||
{
|
||||
val1 = WIZCHIP_READ(Sn_RX_RSR(sn));
|
||||
val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1));
|
||||
if (val1 != 0)
|
||||
{
|
||||
val = WIZCHIP_READ(Sn_RX_RSR(sn));
|
||||
val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1));
|
||||
}
|
||||
}while (val != val1);
|
||||
return val;
|
||||
}
|
||||
|
||||
void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
|
||||
{
|
||||
uint16_t ptr = 0;
|
||||
uint32_t addrsel = 0;
|
||||
|
||||
if(len == 0) return;
|
||||
ptr = getSn_TX_WR(sn);
|
||||
//M20140501 : implict type casting -> explict type casting
|
||||
//addrsel = (ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3);
|
||||
addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3);
|
||||
//
|
||||
WIZCHIP_WRITE_BUF(addrsel,wizdata, len);
|
||||
|
||||
ptr += len;
|
||||
setSn_TX_WR(sn,ptr);
|
||||
}
|
||||
|
||||
void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
|
||||
{
|
||||
uint16_t ptr = 0;
|
||||
uint32_t addrsel = 0;
|
||||
|
||||
if(len == 0) return;
|
||||
ptr = getSn_RX_RD(sn);
|
||||
//M20140501 : implict type casting -> explict type casting
|
||||
//addrsel = ((ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3);
|
||||
addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3);
|
||||
//
|
||||
WIZCHIP_READ_BUF(addrsel, wizdata, len);
|
||||
ptr += len;
|
||||
|
||||
setSn_RX_RD(sn,ptr);
|
||||
}
|
||||
|
||||
|
||||
void wiz_recv_ignore(uint8_t sn, uint16_t len)
|
||||
{
|
||||
uint16_t ptr = 0;
|
||||
|
||||
ptr = getSn_RX_RD(sn);
|
||||
ptr += len;
|
||||
setSn_RX_RD(sn,ptr);
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,931 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! \file socket.c
|
||||
//! \brief SOCKET APIs Implements file.
|
||||
//! \details SOCKET APIs like as Berkeley Socket APIs.
|
||||
//! \version 1.0.3
|
||||
//! \date 2013/10/21
|
||||
//! \par Revision history
|
||||
//! <2015/02/05> Notice
|
||||
//! The version history is not updated after this point.
|
||||
//! Download the latest version directly from GitHub. Please visit the our GitHub repository for ioLibrary.
|
||||
//! >> https://github.com/Wiznet/ioLibrary_Driver
|
||||
//! <2014/05/01> V1.0.3. Refer to M20140501
|
||||
//! 1. Implicit type casting -> Explicit type casting.
|
||||
//! 2. replace 0x01 with PACK_REMAINED in recvfrom()
|
||||
//! 3. Validation a destination ip in connect() & sendto():
|
||||
//! It occurs a fatal error on converting unint32 address if uint8* addr parameter is not aligned by 4byte address.
|
||||
//! Copy 4 byte addr value into temporary uint32 variable and then compares it.
|
||||
//! <2013/12/20> V1.0.2 Refer to M20131220
|
||||
//! Remove Warning.
|
||||
//! <2013/11/04> V1.0.1 2nd Release. Refer to "20131104".
|
||||
//! In sendto(), Add to clear timeout interrupt status (Sn_IR_TIMEOUT)
|
||||
//! <2013/10/21> 1st Release
|
||||
//! \author MidnightCow
|
||||
//! \copyright
|
||||
//!
|
||||
//! Copyright (c) 2013, WIZnet Co., LTD.
|
||||
//! All rights reserved.
|
||||
//!
|
||||
//! Redistribution and use in source and binary forms, with or without
|
||||
//! modification, are permitted provided that the following conditions
|
||||
//! are met:
|
||||
//!
|
||||
//! * Redistributions of source code must retain the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer.
|
||||
//! * Redistributions in binary form must reproduce the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer in the
|
||||
//! documentation and/or other materials provided with the distribution.
|
||||
//! * Neither the name of the <ORGANIZATION> nor the names of its
|
||||
//! contributors may be used to endorse or promote products derived
|
||||
//! from this software without specific prior written permission.
|
||||
//!
|
||||
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
//! THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//*****************************************************************************
|
||||
#include "socket.h"
|
||||
|
||||
//M20150401 : Typing Error
|
||||
//#define SOCK_ANY_PORT_NUM 0xC000;
|
||||
#define SOCK_ANY_PORT_NUM 0xC000
|
||||
|
||||
static uint16_t sock_any_port = SOCK_ANY_PORT_NUM;
|
||||
static uint16_t sock_io_mode = 0;
|
||||
static uint16_t sock_is_sending = 0;
|
||||
|
||||
static uint16_t sock_remained_size[_WIZCHIP_SOCK_NUM_] = {0,0,};
|
||||
|
||||
//M20150601 : For extern decleation
|
||||
//static uint8_t sock_pack_info[_WIZCHIP_SOCK_NUM_] = {0,};
|
||||
uint8_t sock_pack_info[_WIZCHIP_SOCK_NUM_] = {0,};
|
||||
//
|
||||
|
||||
#if _WIZCHIP_ == 5200
|
||||
static uint16_t sock_next_rd[_WIZCHIP_SOCK_NUM_] ={0,};
|
||||
#endif
|
||||
|
||||
//A20150601 : For integrating with W5300
|
||||
#if _WIZCHIP_ == 5300
|
||||
uint8_t sock_remained_byte[_WIZCHIP_SOCK_NUM_] = {0,}; // set by wiz_recv_data()
|
||||
#endif
|
||||
|
||||
|
||||
#define CHECK_SOCKNUM() \
|
||||
do{ \
|
||||
if(sn > _WIZCHIP_SOCK_NUM_) return SOCKERR_SOCKNUM; \
|
||||
}while(0); \
|
||||
|
||||
#define CHECK_SOCKMODE(mode) \
|
||||
do{ \
|
||||
if((getSn_MR(sn) & 0x0F) != mode) return SOCKERR_SOCKMODE; \
|
||||
}while(0); \
|
||||
|
||||
#define CHECK_SOCKINIT() \
|
||||
do{ \
|
||||
if((getSn_SR(sn) != SOCK_INIT)) return SOCKERR_SOCKINIT; \
|
||||
}while(0); \
|
||||
|
||||
#define CHECK_SOCKDATA() \
|
||||
do{ \
|
||||
if(len == 0) return SOCKERR_DATALEN; \
|
||||
}while(0); \
|
||||
|
||||
|
||||
|
||||
int8_t socket(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag)
|
||||
{
|
||||
CHECK_SOCKNUM();
|
||||
switch(protocol)
|
||||
{
|
||||
case Sn_MR_TCP :
|
||||
{
|
||||
//M20150601 : Fixed the warning - taddr will never be NULL
|
||||
/*
|
||||
uint8_t taddr[4];
|
||||
getSIPR(taddr);
|
||||
*/
|
||||
uint32_t taddr;
|
||||
getSIPR((uint8_t*)&taddr);
|
||||
if(taddr == 0) return SOCKERR_SOCKINIT;
|
||||
break;
|
||||
}
|
||||
case Sn_MR_UDP :
|
||||
case Sn_MR_MACRAW :
|
||||
case Sn_MR_IPRAW :
|
||||
break;
|
||||
#if ( _WIZCHIP_ < 5200 )
|
||||
case Sn_MR_PPPoE :
|
||||
break;
|
||||
#endif
|
||||
default :
|
||||
return SOCKERR_SOCKMODE;
|
||||
}
|
||||
//M20150601 : For SF_TCP_ALIGN & W5300
|
||||
//if((flag & 0x06) != 0) return SOCKERR_SOCKFLAG;
|
||||
if((flag & 0x04) != 0) return SOCKERR_SOCKFLAG;
|
||||
#if _WIZCHIP_ == 5200
|
||||
if(flag & 0x10) return SOCKERR_SOCKFLAG;
|
||||
#endif
|
||||
|
||||
if(flag != 0)
|
||||
{
|
||||
switch(protocol)
|
||||
{
|
||||
case Sn_MR_TCP:
|
||||
//M20150601 : For SF_TCP_ALIGN & W5300
|
||||
#if _WIZCHIP_ == 5300
|
||||
if((flag & (SF_TCP_NODELAY|SF_IO_NONBLOCK|SF_TCP_ALIGN))==0) return SOCKERR_SOCKFLAG;
|
||||
#else
|
||||
if((flag & (SF_TCP_NODELAY|SF_IO_NONBLOCK))==0) return SOCKERR_SOCKFLAG;
|
||||
#endif
|
||||
|
||||
break;
|
||||
case Sn_MR_UDP:
|
||||
if(flag & SF_IGMP_VER2)
|
||||
{
|
||||
if((flag & SF_MULTI_ENABLE)==0) return SOCKERR_SOCKFLAG;
|
||||
}
|
||||
#if _WIZCHIP_ == 5500
|
||||
if(flag & SF_UNI_BLOCK)
|
||||
{
|
||||
if((flag & SF_MULTI_ENABLE) == 0) return SOCKERR_SOCKFLAG;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
close(sn);
|
||||
//M20150601
|
||||
#if _WIZCHIP_ == 5300
|
||||
setSn_MR(sn, ((uint16_t)(protocol | (flag & 0xF0))) | (((uint16_t)(flag & 0x02)) << 7) );
|
||||
#else
|
||||
setSn_MR(sn, (protocol | (flag & 0xF0)));
|
||||
#endif
|
||||
if(!port)
|
||||
{
|
||||
port = sock_any_port++;
|
||||
if(sock_any_port == 0xFFF0) sock_any_port = SOCK_ANY_PORT_NUM;
|
||||
}
|
||||
setSn_PORT(sn,port);
|
||||
setSn_CR(sn,Sn_CR_OPEN);
|
||||
while(getSn_CR(sn));
|
||||
//A20150401 : For release the previous sock_io_mode
|
||||
sock_io_mode &= ~(1 <<sn);
|
||||
//
|
||||
sock_io_mode |= ((flag & SF_IO_NONBLOCK) << sn);
|
||||
sock_is_sending &= ~(1<<sn);
|
||||
sock_remained_size[sn] = 0;
|
||||
//M20150601 : repalce 0 with PACK_COMPLETED
|
||||
//sock_pack_info[sn] = 0;
|
||||
sock_pack_info[sn] = PACK_COMPLETED;
|
||||
//
|
||||
while(getSn_SR(sn) == SOCK_CLOSED);
|
||||
return (int8_t)sn;
|
||||
}
|
||||
|
||||
int8_t close(uint8_t sn)
|
||||
{
|
||||
CHECK_SOCKNUM();
|
||||
//A20160426 : Applied the erratum 1 of W5300
|
||||
#if (_WIZCHIP_ == 5300)
|
||||
//M20160503 : Wrong socket parameter. s -> sn
|
||||
//if( ((getSn_MR(s)& 0x0F) == Sn_MR_TCP) && (getSn_TX_FSR(s) != getSn_TxMAX(s)) )
|
||||
if( ((getSn_MR(sn)& 0x0F) == Sn_MR_TCP) && (getSn_TX_FSR(sn) != getSn_TxMAX(sn)) )
|
||||
{
|
||||
uint8_t destip[4] = {0, 0, 0, 1};
|
||||
// TODO
|
||||
// You can wait for completing to sending data;
|
||||
// wait about 1 second;
|
||||
// if you have completed to send data, skip the code of erratum 1
|
||||
// ex> wait_1s();
|
||||
// if (getSn_TX_FSR(s) == getSn_TxMAX(s)) continue;
|
||||
//
|
||||
//M20160503 : The socket() of close() calls close() itself again. It occures a infinite loop - close()->socket()->close()->socket()-> ~
|
||||
//socket(s,Sn_MR_UDP,0x3000,0);
|
||||
//sendto(s,destip,1,destip,0x3000); // send the dummy data to an unknown destination(0.0.0.1).
|
||||
setSn_MR(sn,Sn_MR_UDP);
|
||||
setSn_PORTR(sn, 0x3000);
|
||||
setSn_CR(sn,Sn_CR_OPEN);
|
||||
while(getSn_CR(sn) != 0);
|
||||
while(getSn_SR(sn) != SOCK_UDP);
|
||||
sendto(sn,destip,1,destip,0x3000); // send the dummy data to an unknown destination(0.0.0.1).
|
||||
};
|
||||
#endif
|
||||
setSn_CR(sn,Sn_CR_CLOSE);
|
||||
/* wait to process the command... */
|
||||
while( getSn_CR(sn) );
|
||||
/* clear all interrupt of the socket. */
|
||||
setSn_IR(sn, 0xFF);
|
||||
//A20150401 : Release the sock_io_mode of socket n.
|
||||
sock_io_mode &= ~(1<<sn);
|
||||
//
|
||||
sock_is_sending &= ~(1<<sn);
|
||||
sock_remained_size[sn] = 0;
|
||||
sock_pack_info[sn] = 0;
|
||||
while(getSn_SR(sn) != SOCK_CLOSED);
|
||||
return SOCK_OK;
|
||||
}
|
||||
|
||||
int8_t listen(uint8_t sn)
|
||||
{
|
||||
CHECK_SOCKNUM();
|
||||
CHECK_SOCKMODE(Sn_MR_TCP);
|
||||
CHECK_SOCKINIT();
|
||||
setSn_CR(sn,Sn_CR_LISTEN);
|
||||
while(getSn_CR(sn));
|
||||
while(getSn_SR(sn) != SOCK_LISTEN)
|
||||
{
|
||||
close(sn);
|
||||
return SOCKERR_SOCKCLOSED;
|
||||
}
|
||||
return SOCK_OK;
|
||||
}
|
||||
|
||||
|
||||
int8_t connect(uint8_t sn, uint8_t * addr, uint16_t port)
|
||||
{
|
||||
CHECK_SOCKNUM();
|
||||
CHECK_SOCKMODE(Sn_MR_TCP);
|
||||
CHECK_SOCKINIT();
|
||||
//M20140501 : For avoiding fatal error on memory align mismatched
|
||||
//if( *((uint32_t*)addr) == 0xFFFFFFFF || *((uint32_t*)addr) == 0) return SOCKERR_IPINVALID;
|
||||
{
|
||||
uint32_t taddr;
|
||||
taddr = ((uint32_t)addr[0] & 0x000000FF);
|
||||
taddr = (taddr << 8) + ((uint32_t)addr[1] & 0x000000FF);
|
||||
taddr = (taddr << 8) + ((uint32_t)addr[2] & 0x000000FF);
|
||||
taddr = (taddr << 8) + ((uint32_t)addr[3] & 0x000000FF);
|
||||
if( taddr == 0xFFFFFFFF || taddr == 0) return SOCKERR_IPINVALID;
|
||||
}
|
||||
//
|
||||
|
||||
if(port == 0) return SOCKERR_PORTZERO;
|
||||
setSn_DIPR(sn,addr);
|
||||
setSn_DPORT(sn,port);
|
||||
setSn_CR(sn,Sn_CR_CONNECT);
|
||||
while(getSn_CR(sn));
|
||||
if(sock_io_mode & (1<<sn)) return SOCK_BUSY;
|
||||
while(getSn_SR(sn) != SOCK_ESTABLISHED)
|
||||
{
|
||||
if (getSn_IR(sn) & Sn_IR_TIMEOUT)
|
||||
{
|
||||
setSn_IR(sn, Sn_IR_TIMEOUT);
|
||||
return SOCKERR_TIMEOUT;
|
||||
}
|
||||
|
||||
if (getSn_SR(sn) == SOCK_CLOSED)
|
||||
{
|
||||
return SOCKERR_SOCKCLOSED;
|
||||
}
|
||||
}
|
||||
|
||||
return SOCK_OK;
|
||||
}
|
||||
|
||||
int8_t disconnect(uint8_t sn)
|
||||
{
|
||||
CHECK_SOCKNUM();
|
||||
CHECK_SOCKMODE(Sn_MR_TCP);
|
||||
setSn_CR(sn,Sn_CR_DISCON);
|
||||
/* wait to process the command... */
|
||||
while(getSn_CR(sn));
|
||||
sock_is_sending &= ~(1<<sn);
|
||||
if(sock_io_mode & (1<<sn)) return SOCK_BUSY;
|
||||
while(getSn_SR(sn) != SOCK_CLOSED)
|
||||
{
|
||||
if(getSn_IR(sn) & Sn_IR_TIMEOUT)
|
||||
{
|
||||
close(sn);
|
||||
return SOCKERR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
return SOCK_OK;
|
||||
}
|
||||
|
||||
int32_t send(uint8_t sn, uint8_t * buf, uint16_t len)
|
||||
{
|
||||
uint8_t tmp=0;
|
||||
uint16_t freesize=0;
|
||||
|
||||
CHECK_SOCKNUM();
|
||||
CHECK_SOCKMODE(Sn_MR_TCP);
|
||||
CHECK_SOCKDATA();
|
||||
tmp = getSn_SR(sn);
|
||||
if(tmp != SOCK_ESTABLISHED && tmp != SOCK_CLOSE_WAIT) return SOCKERR_SOCKSTATUS;
|
||||
if( sock_is_sending & (1<<sn) )
|
||||
{
|
||||
tmp = getSn_IR(sn);
|
||||
if(tmp & Sn_IR_SENDOK)
|
||||
{
|
||||
setSn_IR(sn, Sn_IR_SENDOK);
|
||||
//M20150401 : Typing Error
|
||||
//#if _WZICHIP_ == 5200
|
||||
#if _WIZCHIP_ == 5200
|
||||
if(getSn_TX_RD(sn) != sock_next_rd[sn])
|
||||
{
|
||||
setSn_CR(sn,Sn_CR_SEND);
|
||||
while(getSn_CR(sn));
|
||||
return SOCK_BUSY;
|
||||
}
|
||||
#endif
|
||||
sock_is_sending &= ~(1<<sn);
|
||||
}
|
||||
else if(tmp & Sn_IR_TIMEOUT)
|
||||
{
|
||||
close(sn);
|
||||
return SOCKERR_TIMEOUT;
|
||||
}
|
||||
else return SOCK_BUSY;
|
||||
}
|
||||
freesize = getSn_TxMAX(sn);
|
||||
if (len > freesize) len = freesize; // check size not to exceed MAX size.
|
||||
while(1)
|
||||
{
|
||||
freesize = getSn_TX_FSR(sn);
|
||||
tmp = getSn_SR(sn);
|
||||
if ((tmp != SOCK_ESTABLISHED) && (tmp != SOCK_CLOSE_WAIT))
|
||||
{
|
||||
close(sn);
|
||||
return SOCKERR_SOCKSTATUS;
|
||||
}
|
||||
if( (sock_io_mode & (1<<sn)) && (len > freesize) ) return SOCK_BUSY;
|
||||
if(len <= freesize) break;
|
||||
}
|
||||
wiz_send_data(sn, buf, len);
|
||||
#if _WIZCHIP_ == 5200
|
||||
sock_next_rd[sn] = getSn_TX_RD(sn) + len;
|
||||
#endif
|
||||
|
||||
#if _WIZCHIP_ == 5300
|
||||
setSn_TX_WRSR(sn,len);
|
||||
#endif
|
||||
|
||||
setSn_CR(sn,Sn_CR_SEND);
|
||||
/* wait to process the command... */
|
||||
while(getSn_CR(sn));
|
||||
sock_is_sending |= (1 << sn);
|
||||
//M20150409 : Explicit Type Casting
|
||||
//return len;
|
||||
return (int32_t)len;
|
||||
}
|
||||
|
||||
|
||||
int32_t recv(uint8_t sn, uint8_t * buf, uint16_t len)
|
||||
{
|
||||
uint8_t tmp = 0;
|
||||
uint16_t recvsize = 0;
|
||||
//A20150601 : For integarating with W5300
|
||||
#if _WIZCHIP_ == 5300
|
||||
uint8_t head[2];
|
||||
uint16_t mr;
|
||||
#endif
|
||||
//
|
||||
CHECK_SOCKNUM();
|
||||
CHECK_SOCKMODE(Sn_MR_TCP);
|
||||
CHECK_SOCKDATA();
|
||||
|
||||
recvsize = getSn_RxMAX(sn);
|
||||
if(recvsize < len) len = recvsize;
|
||||
|
||||
//A20150601 : For Integrating with W5300
|
||||
#if _WIZCHIP_ == 5300
|
||||
//sock_pack_info[sn] = PACK_COMPLETED; // for clear
|
||||
if(sock_remained_size[sn] == 0)
|
||||
{
|
||||
#endif
|
||||
//
|
||||
while(1)
|
||||
{
|
||||
recvsize = getSn_RX_RSR(sn);
|
||||
tmp = getSn_SR(sn);
|
||||
if (tmp != SOCK_ESTABLISHED)
|
||||
{
|
||||
if(tmp == SOCK_CLOSE_WAIT)
|
||||
{
|
||||
if(recvsize != 0) break;
|
||||
else if(getSn_TX_FSR(sn) == getSn_TxMAX(sn))
|
||||
{
|
||||
close(sn);
|
||||
return SOCKERR_SOCKSTATUS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
close(sn);
|
||||
return SOCKERR_SOCKSTATUS;
|
||||
}
|
||||
}
|
||||
if((sock_io_mode & (1<<sn)) && (recvsize == 0)) return SOCK_BUSY;
|
||||
if(recvsize != 0) break;
|
||||
};
|
||||
#if _WIZCHIP_ == 5300
|
||||
}
|
||||
#endif
|
||||
|
||||
//A20150601 : For integrating with W5300
|
||||
#if _WIZCHIP_ == 5300
|
||||
if((sock_remained_size[sn] == 0) || (getSn_MR(sn) & Sn_MR_ALIGN))
|
||||
{
|
||||
mr = getMR();
|
||||
if((getSn_MR(sn) & Sn_MR_ALIGN)==0)
|
||||
{
|
||||
wiz_recv_data(sn,head,2);
|
||||
if(mr & MR_FS)
|
||||
recvsize = (((uint16_t)head[1]) << 8) | ((uint16_t)head[0]);
|
||||
else
|
||||
recvsize = (((uint16_t)head[0]) << 8) | ((uint16_t)head[1]);
|
||||
sock_pack_info[sn] = PACK_FIRST;
|
||||
}
|
||||
sock_remained_size[sn] = recvsize;
|
||||
}
|
||||
if(len > sock_remained_size[sn]) len = sock_remained_size[sn];
|
||||
recvsize = len;
|
||||
if(sock_pack_info[sn] & PACK_FIFOBYTE)
|
||||
{
|
||||
*buf = sock_remained_byte[sn];
|
||||
buf++;
|
||||
sock_pack_info[sn] &= ~(PACK_FIFOBYTE);
|
||||
recvsize -= 1;
|
||||
sock_remained_size[sn] -= 1;
|
||||
}
|
||||
if(recvsize != 0)
|
||||
{
|
||||
wiz_recv_data(sn, buf, recvsize);
|
||||
setSn_CR(sn,Sn_CR_RECV);
|
||||
while(getSn_CR(sn));
|
||||
}
|
||||
sock_remained_size[sn] -= recvsize;
|
||||
if(sock_remained_size[sn] != 0)
|
||||
{
|
||||
sock_pack_info[sn] |= PACK_REMAINED;
|
||||
if(recvsize & 0x1) sock_pack_info[sn] |= PACK_FIFOBYTE;
|
||||
}
|
||||
else sock_pack_info[sn] = PACK_COMPLETED;
|
||||
if(getSn_MR(sn) & Sn_MR_ALIGN) sock_remained_size[sn] = 0;
|
||||
//len = recvsize;
|
||||
#else
|
||||
if(recvsize < len) len = recvsize;
|
||||
wiz_recv_data(sn, buf, len);
|
||||
setSn_CR(sn,Sn_CR_RECV);
|
||||
while(getSn_CR(sn));
|
||||
#endif
|
||||
|
||||
//M20150409 : Explicit Type Casting
|
||||
//return len;
|
||||
return (int32_t)len;
|
||||
}
|
||||
|
||||
int32_t sendto(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port)
|
||||
{
|
||||
uint8_t tmp = 0;
|
||||
uint16_t freesize = 0;
|
||||
uint32_t taddr;
|
||||
|
||||
CHECK_SOCKNUM();
|
||||
switch(getSn_MR(sn) & 0x0F)
|
||||
{
|
||||
case Sn_MR_UDP:
|
||||
case Sn_MR_MACRAW:
|
||||
// break;
|
||||
// #if ( _WIZCHIP_ < 5200 )
|
||||
case Sn_MR_IPRAW:
|
||||
break;
|
||||
// #endif
|
||||
default:
|
||||
return SOCKERR_SOCKMODE;
|
||||
}
|
||||
CHECK_SOCKDATA();
|
||||
//M20140501 : For avoiding fatal error on memory align mismatched
|
||||
//if(*((uint32_t*)addr) == 0) return SOCKERR_IPINVALID;
|
||||
//{
|
||||
//uint32_t taddr;
|
||||
taddr = ((uint32_t)addr[0]) & 0x000000FF;
|
||||
taddr = (taddr << 8) + ((uint32_t)addr[1] & 0x000000FF);
|
||||
taddr = (taddr << 8) + ((uint32_t)addr[2] & 0x000000FF);
|
||||
taddr = (taddr << 8) + ((uint32_t)addr[3] & 0x000000FF);
|
||||
//}
|
||||
//
|
||||
//if(*((uint32_t*)addr) == 0) return SOCKERR_IPINVALID;
|
||||
if((taddr == 0) && ((getSn_MR(sn)&Sn_MR_MACRAW) != Sn_MR_MACRAW)) return SOCKERR_IPINVALID;
|
||||
if((port == 0) && ((getSn_MR(sn)&Sn_MR_MACRAW) != Sn_MR_MACRAW)) return SOCKERR_PORTZERO;
|
||||
tmp = getSn_SR(sn);
|
||||
//#if ( _WIZCHIP_ < 5200 )
|
||||
if((tmp != SOCK_MACRAW) && (tmp != SOCK_UDP) && (tmp != SOCK_IPRAW)) return SOCKERR_SOCKSTATUS;
|
||||
//#else
|
||||
// if(tmp != SOCK_MACRAW && tmp != SOCK_UDP) return SOCKERR_SOCKSTATUS;
|
||||
//#endif
|
||||
|
||||
setSn_DIPR(sn,addr);
|
||||
setSn_DPORT(sn,port);
|
||||
freesize = getSn_TxMAX(sn);
|
||||
if (len > freesize) len = freesize; // check size not to exceed MAX size.
|
||||
while(1)
|
||||
{
|
||||
freesize = getSn_TX_FSR(sn);
|
||||
if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED;
|
||||
if( (sock_io_mode & (1<<sn)) && (len > freesize) ) return SOCK_BUSY;
|
||||
if(len <= freesize) break;
|
||||
};
|
||||
wiz_send_data(sn, buf, len);
|
||||
|
||||
#if _WIZCHIP_ < 5500 //M20150401 : for WIZCHIP Errata #4, #5 (ARP errata)
|
||||
getSIPR((uint8_t*)&taddr);
|
||||
if(taddr == 0)
|
||||
{
|
||||
getSUBR((uint8_t*)&taddr);
|
||||
setSUBR((uint8_t*)"\x00\x00\x00\x00");
|
||||
}
|
||||
else taddr = 0;
|
||||
#endif
|
||||
|
||||
//A20150601 : For W5300
|
||||
#if _WIZCHIP_ == 5300
|
||||
setSn_TX_WRSR(sn, len);
|
||||
#endif
|
||||
//
|
||||
setSn_CR(sn,Sn_CR_SEND);
|
||||
/* wait to process the command... */
|
||||
while(getSn_CR(sn));
|
||||
while(1)
|
||||
{
|
||||
tmp = getSn_IR(sn);
|
||||
if(tmp & Sn_IR_SENDOK)
|
||||
{
|
||||
setSn_IR(sn, Sn_IR_SENDOK);
|
||||
break;
|
||||
}
|
||||
//M:20131104
|
||||
//else if(tmp & Sn_IR_TIMEOUT) return SOCKERR_TIMEOUT;
|
||||
else if(tmp & Sn_IR_TIMEOUT)
|
||||
{
|
||||
setSn_IR(sn, Sn_IR_TIMEOUT);
|
||||
//M20150409 : Fixed the lost of sign bits by type casting.
|
||||
//len = (uint16_t)SOCKERR_TIMEOUT;
|
||||
//break;
|
||||
#if _WIZCHIP_ < 5500 //M20150401 : for WIZCHIP Errata #4, #5 (ARP errata)
|
||||
if(taddr) setSUBR((uint8_t*)&taddr);
|
||||
#endif
|
||||
return SOCKERR_TIMEOUT;
|
||||
}
|
||||
////////////
|
||||
}
|
||||
#if _WIZCHIP_ < 5500 //M20150401 : for WIZCHIP Errata #4, #5 (ARP errata)
|
||||
if(taddr) setSUBR((uint8_t*)&taddr);
|
||||
#endif
|
||||
//M20150409 : Explicit Type Casting
|
||||
//return len;
|
||||
return (int32_t)len;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int32_t recvfrom(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port)
|
||||
{
|
||||
//M20150601 : For W5300
|
||||
#if _WIZCHIP_ == 5300
|
||||
uint16_t mr;
|
||||
uint16_t mr1;
|
||||
#else
|
||||
uint8_t mr;
|
||||
#endif
|
||||
//
|
||||
uint8_t head[8];
|
||||
uint16_t pack_len=0;
|
||||
|
||||
CHECK_SOCKNUM();
|
||||
//CHECK_SOCKMODE(Sn_MR_UDP);
|
||||
//A20150601
|
||||
#if _WIZCHIP_ == 5300
|
||||
mr1 = getMR();
|
||||
#endif
|
||||
|
||||
switch((mr=getSn_MR(sn)) & 0x0F)
|
||||
{
|
||||
case Sn_MR_UDP:
|
||||
case Sn_MR_IPRAW:
|
||||
case Sn_MR_MACRAW:
|
||||
break;
|
||||
#if ( _WIZCHIP_ < 5200 )
|
||||
case Sn_MR_PPPoE:
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return SOCKERR_SOCKMODE;
|
||||
}
|
||||
CHECK_SOCKDATA();
|
||||
if(sock_remained_size[sn] == 0)
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
pack_len = getSn_RX_RSR(sn);
|
||||
if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED;
|
||||
if( (sock_io_mode & (1<<sn)) && (pack_len == 0) ) return SOCK_BUSY;
|
||||
if(pack_len != 0) break;
|
||||
};
|
||||
}
|
||||
//D20150601 : Move it to bottom
|
||||
// sock_pack_info[sn] = PACK_COMPLETED;
|
||||
switch (mr & 0x07)
|
||||
{
|
||||
case Sn_MR_UDP :
|
||||
if(sock_remained_size[sn] == 0)
|
||||
{
|
||||
wiz_recv_data(sn, head, 8);
|
||||
setSn_CR(sn,Sn_CR_RECV);
|
||||
while(getSn_CR(sn));
|
||||
// read peer's IP address, port number & packet length
|
||||
//A20150601 : For W5300
|
||||
#if _WIZCHIP_ == 5300
|
||||
if(mr1 & MR_FS)
|
||||
{
|
||||
addr[0] = head[1];
|
||||
addr[1] = head[0];
|
||||
addr[2] = head[3];
|
||||
addr[3] = head[2];
|
||||
*port = head[5];
|
||||
*port = (*port << 8) + head[4];
|
||||
sock_remained_size[sn] = head[7];
|
||||
sock_remained_size[sn] = (sock_remained_size[sn] << 8) + head[6];
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
addr[0] = head[0];
|
||||
addr[1] = head[1];
|
||||
addr[2] = head[2];
|
||||
addr[3] = head[3];
|
||||
*port = head[4];
|
||||
*port = (*port << 8) + head[5];
|
||||
sock_remained_size[sn] = head[6];
|
||||
sock_remained_size[sn] = (sock_remained_size[sn] << 8) + head[7];
|
||||
#if _WIZCHIP_ == 5300
|
||||
}
|
||||
#endif
|
||||
sock_pack_info[sn] = PACK_FIRST;
|
||||
}
|
||||
if(len < sock_remained_size[sn]) pack_len = len;
|
||||
else pack_len = sock_remained_size[sn];
|
||||
//A20150601 : For W5300
|
||||
len = pack_len;
|
||||
#if _WIZCHIP_ == 5300
|
||||
if(sock_pack_info[sn] & PACK_FIFOBYTE)
|
||||
{
|
||||
*buf++ = sock_remained_byte[sn];
|
||||
pack_len -= 1;
|
||||
sock_remained_size[sn] -= 1;
|
||||
sock_pack_info[sn] &= ~PACK_FIFOBYTE;
|
||||
}
|
||||
#endif
|
||||
//
|
||||
// Need to packet length check (default 1472)
|
||||
//
|
||||
wiz_recv_data(sn, buf, pack_len); // data copy.
|
||||
break;
|
||||
case Sn_MR_MACRAW :
|
||||
if(sock_remained_size[sn] == 0)
|
||||
{
|
||||
wiz_recv_data(sn, head, 2);
|
||||
setSn_CR(sn,Sn_CR_RECV);
|
||||
while(getSn_CR(sn));
|
||||
// read peer's IP address, port number & packet length
|
||||
sock_remained_size[sn] = head[0];
|
||||
sock_remained_size[sn] = (sock_remained_size[sn] <<8) + head[1] -2;
|
||||
#if _WIZCHIP_ == W5300
|
||||
if(sock_remained_size[sn] & 0x01)
|
||||
sock_remained_size[sn] = sock_remained_size[sn] + 1 - 4;
|
||||
else
|
||||
sock_remained_size[sn] -= 4;
|
||||
#endif
|
||||
if(sock_remained_size[sn] > 1514)
|
||||
{
|
||||
close(sn);
|
||||
return SOCKFATAL_PACKLEN;
|
||||
}
|
||||
sock_pack_info[sn] = PACK_FIRST;
|
||||
}
|
||||
if(len < sock_remained_size[sn]) pack_len = len;
|
||||
else pack_len = sock_remained_size[sn];
|
||||
wiz_recv_data(sn,buf,pack_len);
|
||||
break;
|
||||
//#if ( _WIZCHIP_ < 5200 )
|
||||
case Sn_MR_IPRAW:
|
||||
if(sock_remained_size[sn] == 0)
|
||||
{
|
||||
wiz_recv_data(sn, head, 6);
|
||||
setSn_CR(sn,Sn_CR_RECV);
|
||||
while(getSn_CR(sn));
|
||||
addr[0] = head[0];
|
||||
addr[1] = head[1];
|
||||
addr[2] = head[2];
|
||||
addr[3] = head[3];
|
||||
sock_remained_size[sn] = head[4];
|
||||
//M20150401 : For Typing Error
|
||||
//sock_remaiend_size[sn] = (sock_remained_size[sn] << 8) + head[5];
|
||||
sock_remained_size[sn] = (sock_remained_size[sn] << 8) + head[5];
|
||||
sock_pack_info[sn] = PACK_FIRST;
|
||||
}
|
||||
//
|
||||
// Need to packet length check
|
||||
//
|
||||
if(len < sock_remained_size[sn]) pack_len = len;
|
||||
else pack_len = sock_remained_size[sn];
|
||||
wiz_recv_data(sn, buf, pack_len); // data copy.
|
||||
break;
|
||||
//#endif
|
||||
default:
|
||||
wiz_recv_ignore(sn, pack_len); // data copy.
|
||||
sock_remained_size[sn] = pack_len;
|
||||
break;
|
||||
}
|
||||
setSn_CR(sn,Sn_CR_RECV);
|
||||
/* wait to process the command... */
|
||||
while(getSn_CR(sn)) ;
|
||||
sock_remained_size[sn] -= pack_len;
|
||||
//M20150601 :
|
||||
//if(sock_remained_size[sn] != 0) sock_pack_info[sn] |= 0x01;
|
||||
if(sock_remained_size[sn] != 0)
|
||||
{
|
||||
sock_pack_info[sn] |= PACK_REMAINED;
|
||||
#if _WIZCHIP_ == 5300
|
||||
if(pack_len & 0x01) sock_pack_info[sn] |= PACK_FIFOBYTE;
|
||||
#endif
|
||||
}
|
||||
else sock_pack_info[sn] = PACK_COMPLETED;
|
||||
#if _WIZCHIP_ == 5300
|
||||
pack_len = len;
|
||||
#endif
|
||||
//
|
||||
//M20150409 : Explicit Type Casting
|
||||
//return pack_len;
|
||||
return (int32_t)pack_len;
|
||||
}
|
||||
|
||||
|
||||
int8_t ctlsocket(uint8_t sn, ctlsock_type cstype, void* arg)
|
||||
{
|
||||
uint8_t tmp = 0;
|
||||
CHECK_SOCKNUM();
|
||||
switch(cstype)
|
||||
{
|
||||
case CS_SET_IOMODE:
|
||||
tmp = *((uint8_t*)arg);
|
||||
if(tmp == SOCK_IO_NONBLOCK) sock_io_mode |= (1<<sn);
|
||||
else if(tmp == SOCK_IO_BLOCK) sock_io_mode &= ~(1<<sn);
|
||||
else return SOCKERR_ARG;
|
||||
break;
|
||||
case CS_GET_IOMODE:
|
||||
//M20140501 : implict type casting -> explict type casting
|
||||
//*((uint8_t*)arg) = (sock_io_mode >> sn) & 0x0001;
|
||||
*((uint8_t*)arg) = (uint8_t)((sock_io_mode >> sn) & 0x0001);
|
||||
//
|
||||
break;
|
||||
case CS_GET_MAXTXBUF:
|
||||
*((uint16_t*)arg) = getSn_TxMAX(sn);
|
||||
break;
|
||||
case CS_GET_MAXRXBUF:
|
||||
*((uint16_t*)arg) = getSn_RxMAX(sn);
|
||||
break;
|
||||
case CS_CLR_INTERRUPT:
|
||||
if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG;
|
||||
setSn_IR(sn,*(uint8_t*)arg);
|
||||
break;
|
||||
case CS_GET_INTERRUPT:
|
||||
*((uint8_t*)arg) = getSn_IR(sn);
|
||||
break;
|
||||
#if _WIZCHIP_ != 5100
|
||||
case CS_SET_INTMASK:
|
||||
if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG;
|
||||
setSn_IMR(sn,*(uint8_t*)arg);
|
||||
break;
|
||||
case CS_GET_INTMASK:
|
||||
*((uint8_t*)arg) = getSn_IMR(sn);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return SOCKERR_ARG;
|
||||
}
|
||||
return SOCK_OK;
|
||||
}
|
||||
|
||||
int8_t setsockopt(uint8_t sn, sockopt_type sotype, void* arg)
|
||||
{
|
||||
// M20131220 : Remove warning
|
||||
//uint8_t tmp;
|
||||
CHECK_SOCKNUM();
|
||||
switch(sotype)
|
||||
{
|
||||
case SO_TTL:
|
||||
setSn_TTL(sn,*(uint8_t*)arg);
|
||||
break;
|
||||
case SO_TOS:
|
||||
setSn_TOS(sn,*(uint8_t*)arg);
|
||||
break;
|
||||
case SO_MSS:
|
||||
setSn_MSSR(sn,*(uint16_t*)arg);
|
||||
break;
|
||||
case SO_DESTIP:
|
||||
setSn_DIPR(sn, (uint8_t*)arg);
|
||||
break;
|
||||
case SO_DESTPORT:
|
||||
setSn_DPORT(sn, *(uint16_t*)arg);
|
||||
break;
|
||||
#if _WIZCHIP_ != 5100
|
||||
case SO_KEEPALIVESEND:
|
||||
CHECK_SOCKMODE(Sn_MR_TCP);
|
||||
#if _WIZCHIP_ > 5200
|
||||
if(getSn_KPALVTR(sn) != 0) return SOCKERR_SOCKOPT;
|
||||
#endif
|
||||
setSn_CR(sn,Sn_CR_SEND_KEEP);
|
||||
while(getSn_CR(sn) != 0)
|
||||
{
|
||||
// M20131220
|
||||
//if ((tmp = getSn_IR(sn)) & Sn_IR_TIMEOUT)
|
||||
if (getSn_IR(sn) & Sn_IR_TIMEOUT)
|
||||
{
|
||||
setSn_IR(sn, Sn_IR_TIMEOUT);
|
||||
return SOCKERR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#if !( (_WIZCHIP_ == 5100) || (_WIZCHIP_ == 5200) )
|
||||
case SO_KEEPALIVEAUTO:
|
||||
CHECK_SOCKMODE(Sn_MR_TCP);
|
||||
setSn_KPALVTR(sn,*(uint8_t*)arg);
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
default:
|
||||
return SOCKERR_ARG;
|
||||
}
|
||||
return SOCK_OK;
|
||||
}
|
||||
|
||||
int8_t getsockopt(uint8_t sn, sockopt_type sotype, void* arg)
|
||||
{
|
||||
CHECK_SOCKNUM();
|
||||
switch(sotype)
|
||||
{
|
||||
case SO_FLAG:
|
||||
*(uint8_t*)arg = getSn_MR(sn) & 0xF0;
|
||||
break;
|
||||
case SO_TTL:
|
||||
*(uint8_t*) arg = getSn_TTL(sn);
|
||||
break;
|
||||
case SO_TOS:
|
||||
*(uint8_t*) arg = getSn_TOS(sn);
|
||||
break;
|
||||
case SO_MSS:
|
||||
*(uint16_t*) arg = getSn_MSSR(sn);
|
||||
break;
|
||||
case SO_DESTIP:
|
||||
getSn_DIPR(sn, (uint8_t*)arg);
|
||||
break;
|
||||
case SO_DESTPORT:
|
||||
*(uint16_t*) arg = getSn_DPORT(sn);
|
||||
break;
|
||||
#if _WIZCHIP_ > 5200
|
||||
case SO_KEEPALIVEAUTO:
|
||||
CHECK_SOCKMODE(Sn_MR_TCP);
|
||||
*(uint16_t*) arg = getSn_KPALVTR(sn);
|
||||
break;
|
||||
#endif
|
||||
case SO_SENDBUF:
|
||||
*(uint16_t*) arg = getSn_TX_FSR(sn);
|
||||
break;
|
||||
case SO_RECVBUF:
|
||||
*(uint16_t*) arg = getSn_RX_RSR(sn);
|
||||
break;
|
||||
case SO_STATUS:
|
||||
*(uint8_t*) arg = getSn_SR(sn);
|
||||
break;
|
||||
case SO_REMAINSIZE:
|
||||
if(getSn_MR(sn) & Sn_MR_TCP)
|
||||
*(uint16_t*)arg = getSn_RX_RSR(sn);
|
||||
else
|
||||
*(uint16_t*)arg = sock_remained_size[sn];
|
||||
break;
|
||||
case SO_PACKINFO:
|
||||
//CHECK_SOCKMODE(Sn_MR_TCP);
|
||||
#if _WIZCHIP_ != 5300
|
||||
if((getSn_MR(sn) == Sn_MR_TCP))
|
||||
return SOCKERR_SOCKMODE;
|
||||
#endif
|
||||
*(uint8_t*)arg = sock_pack_info[sn];
|
||||
break;
|
||||
default:
|
||||
return SOCKERR_SOCKOPT;
|
||||
}
|
||||
return SOCK_OK;
|
||||
}
|
||||
@ -0,0 +1,489 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! \file socket.h
|
||||
//! \brief SOCKET APIs Header file.
|
||||
//! \details SOCKET APIs like as berkeley socket api.
|
||||
//! \version 1.0.2
|
||||
//! \date 2013/10/21
|
||||
//! \par Revision history
|
||||
//! <2015/02/05> Notice
|
||||
//! The version history is not updated after this point.
|
||||
//! Download the latest version directly from GitHub. Please visit the our GitHub repository for ioLibrary.
|
||||
//! >> https://github.com/Wiznet/ioLibrary_Driver
|
||||
//! <2014/05/01> V1.0.2. Refer to M20140501
|
||||
//! 1. Modify the comment : SO_REMAINED -> PACK_REMAINED
|
||||
//! 2. Add the comment as zero byte udp data reception in getsockopt().
|
||||
//! <2013/10/21> 1st Release
|
||||
//! \author MidnightCow
|
||||
//! \copyright
|
||||
//!
|
||||
//! Copyright (c) 2013, WIZnet Co., LTD.
|
||||
//! All rights reserved.
|
||||
//!
|
||||
//! Redistribution and use in source and binary forms, with or without
|
||||
//! modification, are permitted provided that the following conditions
|
||||
//! are met:
|
||||
//!
|
||||
//! * Redistributions of source code must retain the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer.
|
||||
//! * Redistributions in binary form must reproduce the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer in the
|
||||
//! documentation and/or other materials provided with the distribution.
|
||||
//! * Neither the name of the <ORGANIZATION> nor the names of its
|
||||
//! contributors may be used to endorse or promote products derived
|
||||
//! from this software without specific prior written permission.
|
||||
//!
|
||||
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
//! THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//*****************************************************************************
|
||||
/**
|
||||
* @defgroup WIZnet_socket_APIs 1. WIZnet socket APIs
|
||||
* @brief WIZnet socket APIs are based on Berkeley socket APIs, thus it has much similar name and interface.
|
||||
* But there is a little bit of difference.
|
||||
* @details
|
||||
* <b> Comparison between WIZnet and Berkeley SOCKET APIs </b>
|
||||
* <table>
|
||||
* <tr> <td><b>API</b></td> <td><b>WIZnet</b></td> <td><b>Berkeley</b></td> </tr>
|
||||
* <tr> <td>socket()</td> <td>O</td> <td>O</td> </tr>
|
||||
* <tr> <td><b>bind()</b></td> <td>X</td> <td>O</td> </tr>
|
||||
* <tr> <td><b>listen()</b></td> <td>O</td> <td>O</td> </tr>
|
||||
* <tr> <td><b>connect()</b></td> <td>O</td> <td>O</td> </tr>
|
||||
* <tr> <td><b>accept()</b></td> <td>X</td> <td>O</td> </tr>
|
||||
* <tr> <td><b>recv()</b></td> <td>O</td> <td>O</td> </tr>
|
||||
* <tr> <td><b>send()</b></td> <td>O</td> <td>O</td> </tr>
|
||||
* <tr> <td><b>recvfrom()</b></td> <td>O</td> <td>O</td> </tr>
|
||||
* <tr> <td><b>sendto()</b></td> <td>O</td> <td>O</td> </tr>
|
||||
* <tr> <td><b>closesocket()</b></td> <td>O<br>close() & disconnect()</td> <td>O</td> </tr>
|
||||
* </table>
|
||||
* There are @b bind() and @b accept() functions in @b Berkeley SOCKET API but,
|
||||
* not in @b WIZnet SOCKET API. Because socket() of WIZnet is not only creating a SOCKET but also binding a local port number,
|
||||
* and listen() of WIZnet is not only listening to connection request from client but also accepting the connection request. \n
|
||||
* When you program "TCP SERVER" with Berkeley SOCKET API, you can use only one listen port.
|
||||
* When the listen SOCKET accepts a connection request from a client, it keeps listening.
|
||||
* After accepting the connection request, a new SOCKET is created and the new SOCKET is used in communication with the client. \n
|
||||
* Following figure shows network flow diagram by Berkeley SOCKET API.
|
||||
* @image html Berkeley_SOCKET.jpg "<Berkeley SOCKET API>"
|
||||
* But, When you program "TCP SERVER" with WIZnet SOCKET API, you can use as many as 8 listen SOCKET with same port number. \n
|
||||
* Because there's no accept() in WIZnet SOCKET APIs, when the listen SOCKET accepts a connection request from a client,
|
||||
* it is changed in order to communicate with the client.
|
||||
* And the changed SOCKET is not listening any more and is dedicated for communicating with the client. \n
|
||||
* If there're many listen SOCKET with same listen port number and a client requests a connection,
|
||||
* the SOCKET which has the smallest SOCKET number accepts the request and is changed as communication SOCKET. \n
|
||||
* Following figure shows network flow diagram by WIZnet SOCKET API.
|
||||
* @image html WIZnet_SOCKET.jpg "<WIZnet SOCKET API>"
|
||||
*/
|
||||
#ifndef _SOCKET_H_
|
||||
#define _SOCKET_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "wizchip_conf.h"
|
||||
|
||||
#define SOCKET uint8_t ///< SOCKET type define for legacy driver
|
||||
|
||||
#define SOCK_OK 1 ///< Result is OK about socket process.
|
||||
#define SOCK_BUSY 0 ///< Socket is busy on processing the operation. Valid only Non-block IO Mode.
|
||||
#define SOCK_FATAL -1000 ///< Result is fatal error about socket process.
|
||||
|
||||
#define SOCK_ERROR 0
|
||||
#define SOCKERR_SOCKNUM (SOCK_ERROR - 1) ///< Invalid socket number
|
||||
#define SOCKERR_SOCKOPT (SOCK_ERROR - 2) ///< Invalid socket option
|
||||
#define SOCKERR_SOCKINIT (SOCK_ERROR - 3) ///< Socket is not initialized or SIPR is Zero IP address when Sn_MR_TCP
|
||||
#define SOCKERR_SOCKCLOSED (SOCK_ERROR - 4) ///< Socket unexpectedly closed.
|
||||
#define SOCKERR_SOCKMODE (SOCK_ERROR - 5) ///< Invalid socket mode for socket operation.
|
||||
#define SOCKERR_SOCKFLAG (SOCK_ERROR - 6) ///< Invalid socket flag
|
||||
#define SOCKERR_SOCKSTATUS (SOCK_ERROR - 7) ///< Invalid socket status for socket operation.
|
||||
#define SOCKERR_ARG (SOCK_ERROR - 10) ///< Invalid argument.
|
||||
#define SOCKERR_PORTZERO (SOCK_ERROR - 11) ///< Port number is zero
|
||||
#define SOCKERR_IPINVALID (SOCK_ERROR - 12) ///< Invalid IP address
|
||||
#define SOCKERR_TIMEOUT (SOCK_ERROR - 13) ///< Timeout occurred
|
||||
#define SOCKERR_DATALEN (SOCK_ERROR - 14) ///< Data length is zero or greater than buffer max size.
|
||||
#define SOCKERR_BUFFER (SOCK_ERROR - 15) ///< Socket buffer is not enough for data communication.
|
||||
|
||||
#define SOCKFATAL_PACKLEN (SOCK_FATAL - 1) ///< Invalid packet length. Fatal Error.
|
||||
|
||||
/*
|
||||
* SOCKET FLAG
|
||||
*/
|
||||
#define SF_ETHER_OWN (Sn_MR_MFEN) ///< In @ref Sn_MR_MACRAW, Receive only the packet as broadcast, multicast and own packet
|
||||
#define SF_IGMP_VER2 (Sn_MR_MC) ///< In @ref Sn_MR_UDP with \ref SF_MULTI_ENABLE, Select IGMP version 2.
|
||||
#define SF_TCP_NODELAY (Sn_MR_ND) ///< In @ref Sn_MR_TCP, Use to nodelayed ack.
|
||||
#define SF_MULTI_ENABLE (Sn_MR_MULTI) ///< In @ref Sn_MR_UDP, Enable multicast mode.
|
||||
|
||||
#if _WIZCHIP_ == 5500
|
||||
#define SF_BROAD_BLOCK (Sn_MR_BCASTB) ///< In @ref Sn_MR_UDP or @ref Sn_MR_MACRAW, Block broadcast packet. Valid only in W5500
|
||||
#define SF_MULTI_BLOCK (Sn_MR_MMB) ///< In @ref Sn_MR_MACRAW, Block multicast packet. Valid only in W5500
|
||||
#define SF_IPv6_BLOCK (Sn_MR_MIP6B) ///< In @ref Sn_MR_MACRAW, Block IPv6 packet. Valid only in W5500
|
||||
#define SF_UNI_BLOCK (Sn_MR_UCASTB) ///< In @ref Sn_MR_UDP with \ref SF_MULTI_ENABLE. Valid only in W5500
|
||||
#endif
|
||||
|
||||
//A201505 : For W5300
|
||||
#if _WIZCHIP_ == 5300
|
||||
#define SF_TCP_ALIGN 0x02 ///< Valid only \ref Sn_MR_TCP and W5300, refer to \ref Sn_MR_ALIGN
|
||||
#endif
|
||||
|
||||
#define SF_IO_NONBLOCK 0x01 ///< Socket nonblock io mode. It used parameter in \ref socket().
|
||||
|
||||
/*
|
||||
* UDP & MACRAW Packet Infomation
|
||||
*/
|
||||
#define PACK_FIRST 0x80 ///< In Non-TCP packet, It indicates to start receiving a packet. (When W5300, This flag can be applied)
|
||||
#define PACK_REMAINED 0x01 ///< In Non-TCP packet, It indicates to remain a packet to be received. (When W5300, This flag can be applied)
|
||||
#define PACK_COMPLETED 0x00 ///< In Non-TCP packet, It indicates to complete to receive a packet. (When W5300, This flag can be applied)
|
||||
//A20150601 : For Integrating with W5300
|
||||
#define PACK_FIFOBYTE 0x02 ///< Valid only W5300, It indicate to have read already the Sn_RX_FIFOR.
|
||||
//
|
||||
|
||||
/**
|
||||
* @ingroup WIZnet_socket_APIs
|
||||
* @brief Open a socket.
|
||||
* @details Initializes the socket with 'sn' passed as parameter and open.
|
||||
*
|
||||
* @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
|
||||
* @param protocol Protocol type to operate such as TCP, UDP and MACRAW.
|
||||
* @param port Port number to be bined.
|
||||
* @param flag Socket flags as \ref SF_ETHER_OWN, \ref SF_IGMP_VER2, \ref SF_TCP_NODELAY, \ref SF_MULTI_ENABLE, \ref SF_IO_NONBLOCK and so on.\n
|
||||
* Valid flags only in W5500 : @ref SF_BROAD_BLOCK, @ref SF_MULTI_BLOCK, @ref SF_IPv6_BLOCK, and @ref SF_UNI_BLOCK.
|
||||
* @sa Sn_MR
|
||||
*
|
||||
* @return @b Success : The socket number @b 'sn' passed as parameter\n
|
||||
* @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number\n
|
||||
* @ref SOCKERR_SOCKMODE - Not support socket mode as TCP, UDP, and so on. \n
|
||||
* @ref SOCKERR_SOCKFLAG - Invaild socket flag.
|
||||
*/
|
||||
int8_t socket(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag);
|
||||
|
||||
/**
|
||||
* @ingroup WIZnet_socket_APIs
|
||||
* @brief Close a socket.
|
||||
* @details It closes the socket with @b'sn' passed as parameter.
|
||||
*
|
||||
* @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
|
||||
*
|
||||
* @return @b Success : @ref SOCK_OK \n
|
||||
* @b Fail : @ref SOCKERR_SOCKNUM - Invalid socket number
|
||||
*/
|
||||
int8_t close(uint8_t sn);
|
||||
|
||||
/**
|
||||
* @ingroup WIZnet_socket_APIs
|
||||
* @brief Listen to a connection request from a client.
|
||||
* @details It is listening to a connection request from a client.
|
||||
* If connection request is accepted successfully, the connection is established. Socket sn is used in passive(server) mode.
|
||||
*
|
||||
* @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
|
||||
* @return @b Success : @ref SOCK_OK \n
|
||||
* @b Fail :\n @ref SOCKERR_SOCKINIT - Socket is not initialized \n
|
||||
* @ref SOCKERR_SOCKCLOSED - Socket closed unexpectedly.
|
||||
*/
|
||||
int8_t listen(uint8_t sn);
|
||||
|
||||
/**
|
||||
* @ingroup WIZnet_socket_APIs
|
||||
* @brief Try to connect a server.
|
||||
* @details It requests connection to the server with destination IP address and port number passed as parameter.\n
|
||||
* @note It is valid only in TCP client mode.
|
||||
* In block io mode, it does not return until connection is completed.
|
||||
* In Non-block io mode, it return @ref SOCK_BUSY immediately.
|
||||
*
|
||||
* @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
|
||||
* @param addr Pointer variable of destination IP address. It should be allocated 4 bytes.
|
||||
* @param port Destination port number.
|
||||
*
|
||||
* @return @b Success : @ref SOCK_OK \n
|
||||
* @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number\n
|
||||
* @ref SOCKERR_SOCKMODE - Invalid socket mode\n
|
||||
* @ref SOCKERR_SOCKINIT - Socket is not initialized\n
|
||||
* @ref SOCKERR_IPINVALID - Wrong server IP address\n
|
||||
* @ref SOCKERR_PORTZERO - Server port zero\n
|
||||
* @ref SOCKERR_TIMEOUT - Timeout occurred during request connection\n
|
||||
* @ref SOCK_BUSY - In non-block io mode, it returned immediately\n
|
||||
*/
|
||||
int8_t connect(uint8_t sn, uint8_t * addr, uint16_t port);
|
||||
|
||||
/**
|
||||
* @ingroup WIZnet_socket_APIs
|
||||
* @brief Try to disconnect a connection socket.
|
||||
* @details It sends request message to disconnect the TCP socket 'sn' passed as parameter to the server or client.
|
||||
* @note It is valid only in TCP server or client mode. \n
|
||||
* In block io mode, it does not return until disconnection is completed. \n
|
||||
* In Non-block io mode, it return @ref SOCK_BUSY immediately. \n
|
||||
|
||||
* @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
|
||||
* @return @b Success : @ref SOCK_OK \n
|
||||
* @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number \n
|
||||
* @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n
|
||||
* @ref SOCKERR_TIMEOUT - Timeout occurred \n
|
||||
* @ref SOCK_BUSY - Socket is busy.
|
||||
*/
|
||||
int8_t disconnect(uint8_t sn);
|
||||
|
||||
/**
|
||||
* @ingroup WIZnet_socket_APIs
|
||||
* @brief Send data to the connected peer in TCP socket.
|
||||
* @details It is used to send outgoing data to the connected socket.
|
||||
* @note It is valid only in TCP server or client mode. It can't send data greater than socket buffer size. \n
|
||||
* In block io mode, It doesn't return until data send is completed - socket buffer size is greater than data. \n
|
||||
* In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough. \n
|
||||
* @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
|
||||
* @param buf Pointer buffer containing data to be sent.
|
||||
* @param len The byte length of data in buf.
|
||||
* @return @b Success : The sent data size \n
|
||||
* @b Fail : \n @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n
|
||||
* @ref SOCKERR_TIMEOUT - Timeout occurred \n
|
||||
* @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n
|
||||
* @ref SOCKERR_SOCKNUM - Invalid socket number \n
|
||||
* @ref SOCKERR_DATALEN - zero data length \n
|
||||
* @ref SOCK_BUSY - Socket is busy.
|
||||
*/
|
||||
int32_t send(uint8_t sn, uint8_t * buf, uint16_t len);
|
||||
|
||||
/**
|
||||
* @ingroup WIZnet_socket_APIs
|
||||
* @brief Receive data from the connected peer.
|
||||
* @details It is used to read incoming data from the connected socket.\n
|
||||
* It waits for data as much as the application wants to receive.
|
||||
* @note It is valid only in TCP server or client mode. It can't receive data greater than socket buffer size. \n
|
||||
* In block io mode, it doesn't return until data reception is completed - data is filled as <I>len</I> in socket buffer. \n
|
||||
* In non-block io mode, it return @ref SOCK_BUSY immediately when <I>len</I> is greater than data size in socket buffer. \n
|
||||
*
|
||||
* @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
|
||||
* @param buf Pointer buffer to read incoming data.
|
||||
* @param len The max data length of data in buf.
|
||||
* @return @b Success : The real received data size \n
|
||||
* @b Fail :\n
|
||||
* @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n
|
||||
* @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n
|
||||
* @ref SOCKERR_SOCKNUM - Invalid socket number \n
|
||||
* @ref SOCKERR_DATALEN - zero data length \n
|
||||
* @ref SOCK_BUSY - Socket is busy.
|
||||
*/
|
||||
int32_t recv(uint8_t sn, uint8_t * buf, uint16_t len);
|
||||
|
||||
/**
|
||||
* @ingroup WIZnet_socket_APIs
|
||||
* @brief Sends datagram to the peer with destination IP address and port number passed as parameter.
|
||||
* @details It sends datagram of UDP or MACRAW to the peer with destination IP address and port number passed as parameter.\n
|
||||
* Even if the connectionless socket has been previously connected to a specific address,
|
||||
* the address and port number parameters override the destination address for that particular datagram only.
|
||||
* @note In block io mode, It doesn't return until data send is completed - socket buffer size is greater than <I>len</I>.
|
||||
* In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough.
|
||||
*
|
||||
* @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
|
||||
* @param buf Pointer buffer to send outgoing data.
|
||||
* @param len The byte length of data in buf.
|
||||
* @param addr Pointer variable of destination IP address. It should be allocated 4 bytes.
|
||||
* @param port Destination port number.
|
||||
*
|
||||
* @return @b Success : The sent data size \n
|
||||
* @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number \n
|
||||
* @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n
|
||||
* @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n
|
||||
* @ref SOCKERR_DATALEN - zero data length \n
|
||||
* @ref SOCKERR_IPINVALID - Wrong server IP address\n
|
||||
* @ref SOCKERR_PORTZERO - Server port zero\n
|
||||
* @ref SOCKERR_SOCKCLOSED - Socket unexpectedly closed \n
|
||||
* @ref SOCKERR_TIMEOUT - Timeout occurred \n
|
||||
* @ref SOCK_BUSY - Socket is busy.
|
||||
*/
|
||||
int32_t sendto(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port);
|
||||
|
||||
/**
|
||||
* @ingroup WIZnet_socket_APIs
|
||||
* @brief Receive datagram of UDP or MACRAW
|
||||
* @details This function is an application I/F function which is used to receive the data in other then TCP mode. \n
|
||||
* This function is used to receive UDP and MAC_RAW mode, and handle the header as well.
|
||||
* This function can divide to received the packet data.
|
||||
* On the MACRAW SOCKET, the addr and port parameters are ignored.
|
||||
* @note In block io mode, it doesn't return until data reception is completed - data is filled as <I>len</I> in socket buffer
|
||||
* In non-block io mode, it return @ref SOCK_BUSY immediately when <I>len</I> is greater than data size in socket buffer.
|
||||
*
|
||||
* @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
|
||||
* @param buf Pointer buffer to read incoming data.
|
||||
* @param len The max data length of data in buf.
|
||||
* When the received packet size <= len, receives data as packet sized.
|
||||
* When others, receives data as len.
|
||||
* @param addr Pointer variable of destination IP address. It should be allocated 4 bytes.
|
||||
* It is valid only when the first call recvfrom for receiving the packet.
|
||||
* When it is valid, @ref packinfo[7] should be set as '1' after call @ref getsockopt(sn, SO_PACKINFO, &packinfo).
|
||||
* @param port Pointer variable of destination port number.
|
||||
* It is valid only when the first call recvform for receiving the packet.
|
||||
* When it is valid, @ref packinfo[7] should be set as '1' after call @ref getsockopt(sn, SO_PACKINFO, &packinfo).
|
||||
*
|
||||
* @return @b Success : This function return real received data size for success.\n
|
||||
* @b Fail : @ref SOCKERR_DATALEN - zero data length \n
|
||||
* @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n
|
||||
* @ref SOCKERR_SOCKNUM - Invalid socket number \n
|
||||
* @ref SOCKBUSY - Socket is busy.
|
||||
*/
|
||||
int32_t recvfrom(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port);
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// SOCKET CONTROL & OPTION //
|
||||
/////////////////////////////
|
||||
#define SOCK_IO_BLOCK 0 ///< Socket Block IO Mode in @ref setsockopt().
|
||||
#define SOCK_IO_NONBLOCK 1 ///< Socket Non-block IO Mode in @ref setsockopt().
|
||||
|
||||
/**
|
||||
* @defgroup DATA_TYPE DATA TYPE
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup DATA_TYPE
|
||||
* @brief The kind of Socket Interrupt.
|
||||
* @sa Sn_IR, Sn_IMR, setSn_IR(), getSn_IR(), setSn_IMR(), getSn_IMR()
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
SIK_CONNECTED = (1 << 0), ///< connected
|
||||
SIK_DISCONNECTED = (1 << 1), ///< disconnected
|
||||
SIK_RECEIVED = (1 << 2), ///< data received
|
||||
SIK_TIMEOUT = (1 << 3), ///< timeout occurred
|
||||
SIK_SENT = (1 << 4), ///< send ok
|
||||
//M20150410 : Remove the comma of last member
|
||||
//SIK_ALL = 0x1F, ///< all interrupt
|
||||
SIK_ALL = 0x1F ///< all interrupt
|
||||
}sockint_kind;
|
||||
|
||||
/**
|
||||
* @ingroup DATA_TYPE
|
||||
* @brief The type of @ref ctlsocket().
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
CS_SET_IOMODE, ///< set socket IO mode with @ref SOCK_IO_BLOCK or @ref SOCK_IO_NONBLOCK
|
||||
CS_GET_IOMODE, ///< get socket IO mode
|
||||
CS_GET_MAXTXBUF, ///< get the size of socket buffer allocated in TX memory
|
||||
CS_GET_MAXRXBUF, ///< get the size of socket buffer allocated in RX memory
|
||||
CS_CLR_INTERRUPT, ///< clear the interrupt of socket with @ref sockint_kind
|
||||
CS_GET_INTERRUPT, ///< get the socket interrupt. refer to @ref sockint_kind
|
||||
#if _WIZCHIP_ > 5100
|
||||
CS_SET_INTMASK, ///< set the interrupt mask of socket with @ref sockint_kind, Not supported in W5100
|
||||
CS_GET_INTMASK ///< get the masked interrupt of socket. refer to @ref sockint_kind, Not supported in W5100
|
||||
#endif
|
||||
}ctlsock_type;
|
||||
|
||||
|
||||
/**
|
||||
* @ingroup DATA_TYPE
|
||||
* @brief The type of socket option in @ref setsockopt() or @ref getsockopt()
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
SO_FLAG, ///< Valid only in getsockopt(), For set flag of socket refer to <I>flag</I> in @ref socket().
|
||||
SO_TTL, ///< Set TTL. @ref Sn_TTL ( @ref setSn_TTL(), @ref getSn_TTL() )
|
||||
SO_TOS, ///< Set TOS. @ref Sn_TOS ( @ref setSn_TOS(), @ref getSn_TOS() )
|
||||
SO_MSS, ///< Set MSS. @ref Sn_MSSR ( @ref setSn_MSSR(), @ref getSn_MSSR() )
|
||||
SO_DESTIP, ///< Set the destination IP address. @ref Sn_DIPR ( @ref setSn_DIPR(), @ref getSn_DIPR() )
|
||||
SO_DESTPORT, ///< Set the destination Port number. @ref Sn_DPORT ( @ref setSn_DPORT(), @ref getSn_DPORT() )
|
||||
#if _WIZCHIP_ != 5100
|
||||
SO_KEEPALIVESEND, ///< Valid only in setsockopt. Manually send keep-alive packet in TCP mode, Not supported in W5100
|
||||
#if !( (_WIZCHIP_ == 5100) || (_WIZCHIP_ == 5200) )
|
||||
SO_KEEPALIVEAUTO, ///< Set/Get keep-alive auto transmission timer in TCP mode, Not supported in W5100, W5200
|
||||
#endif
|
||||
#endif
|
||||
SO_SENDBUF, ///< Valid only in getsockopt. Get the free data size of Socekt TX buffer. @ref Sn_TX_FSR, @ref getSn_TX_FSR()
|
||||
SO_RECVBUF, ///< Valid only in getsockopt. Get the received data size in socket RX buffer. @ref Sn_RX_RSR, @ref getSn_RX_RSR()
|
||||
SO_STATUS, ///< Valid only in getsockopt. Get the socket status. @ref Sn_SR, @ref getSn_SR()
|
||||
SO_REMAINSIZE, ///< Valid only in getsockopt. Get the remained packet size in other then TCP mode.
|
||||
SO_PACKINFO ///< Valid only in getsockopt. Get the packet information as @ref PACK_FIRST, @ref PACK_REMAINED, and @ref PACK_COMPLETED in other then TCP mode.
|
||||
}sockopt_type;
|
||||
|
||||
/**
|
||||
* @ingroup WIZnet_socket_APIs
|
||||
* @brief Control socket.
|
||||
* @details Control IO mode, Interrupt & Mask of socket and get the socket buffer information.
|
||||
* Refer to @ref ctlsock_type.
|
||||
* @param sn socket number
|
||||
* @param cstype type of control socket. refer to @ref ctlsock_type.
|
||||
* @param arg Data type and value is determined according to @ref ctlsock_type. \n
|
||||
* <table>
|
||||
* <tr> <td> @b cstype </td> <td> @b data type</td><td>@b value</td></tr>
|
||||
* <tr> <td> @ref CS_SET_IOMODE \n @ref CS_GET_IOMODE </td> <td> uint8_t </td><td>@ref SOCK_IO_BLOCK @ref SOCK_IO_NONBLOCK</td></tr>
|
||||
* <tr> <td> @ref CS_GET_MAXTXBUF \n @ref CS_GET_MAXRXBUF </td> <td> uint16_t </td><td> 0 ~ 16K </td></tr>
|
||||
* <tr> <td> @ref CS_CLR_INTERRUPT \n @ref CS_GET_INTERRUPT \n @ref CS_SET_INTMASK \n @ref CS_GET_INTMASK </td> <td> @ref sockint_kind </td><td> @ref SIK_CONNECTED, etc. </td></tr>
|
||||
* </table>
|
||||
* @return @b Success @ref SOCK_OK \n
|
||||
* @b fail @ref SOCKERR_ARG - Invalid argument\n
|
||||
*/
|
||||
int8_t ctlsocket(uint8_t sn, ctlsock_type cstype, void* arg);
|
||||
|
||||
/**
|
||||
* @ingroup WIZnet_socket_APIs
|
||||
* @brief set socket options
|
||||
* @details Set socket option like as TTL, MSS, TOS, and so on. Refer to @ref sockopt_type.
|
||||
*
|
||||
* @param sn socket number
|
||||
* @param sotype socket option type. refer to @ref sockopt_type
|
||||
* @param arg Data type and value is determined according to <I>sotype</I>. \n
|
||||
* <table>
|
||||
* <tr> <td> @b sotype </td> <td> @b data type</td><td>@b value</td></tr>
|
||||
* <tr> <td> @ref SO_TTL </td> <td> uint8_t </td><td> 0 ~ 255 </td> </tr>
|
||||
* <tr> <td> @ref SO_TOS </td> <td> uint8_t </td><td> 0 ~ 255 </td> </tr>
|
||||
* <tr> <td> @ref SO_MSS </td> <td> uint16_t </td><td> 0 ~ 65535 </td> </tr>
|
||||
* <tr> <td> @ref SO_DESTIP </td> <td> uint8_t[4] </td><td> </td></tr>
|
||||
* <tr> <td> @ref SO_DESTPORT </td> <td> uint16_t </td><td> 0 ~ 65535 </td></tr>
|
||||
* <tr> <td> @ref SO_KEEPALIVESEND </td> <td> null </td><td> null </td></tr>
|
||||
* <tr> <td> @ref SO_KEEPALIVEAUTO </td> <td> uint8_t </td><td> 0 ~ 255 </td></tr>
|
||||
* </table>
|
||||
* @return
|
||||
* - @b Success : @ref SOCK_OK \n
|
||||
* - @b Fail
|
||||
* - @ref SOCKERR_SOCKNUM - Invalid Socket number \n
|
||||
* - @ref SOCKERR_SOCKMODE - Invalid socket mode \n
|
||||
* - @ref SOCKERR_SOCKOPT - Invalid socket option or its value \n
|
||||
* - @ref SOCKERR_TIMEOUT - Timeout occurred when sending keep-alive packet \n
|
||||
*/
|
||||
int8_t setsockopt(uint8_t sn, sockopt_type sotype, void* arg);
|
||||
|
||||
/**
|
||||
* @ingroup WIZnet_socket_APIs
|
||||
* @brief get socket options
|
||||
* @details Get socket option like as FLAG, TTL, MSS, and so on. Refer to @ref sockopt_type
|
||||
* @param sn socket number
|
||||
* @param sotype socket option type. refer to @ref sockopt_type
|
||||
* @param arg Data type and value is determined according to <I>sotype</I>. \n
|
||||
* <table>
|
||||
* <tr> <td> @b sotype </td> <td>@b data type</td><td>@b value</td></tr>
|
||||
* <tr> <td> @ref SO_FLAG </td> <td> uint8_t </td><td> @ref SF_ETHER_OWN, etc... </td> </tr>
|
||||
* <tr> <td> @ref SO_TOS </td> <td> uint8_t </td><td> 0 ~ 255 </td> </tr>
|
||||
* <tr> <td> @ref SO_MSS </td> <td> uint16_t </td><td> 0 ~ 65535 </td> </tr>
|
||||
* <tr> <td> @ref SO_DESTIP </td> <td> uint8_t[4] </td><td> </td></tr>
|
||||
* <tr> <td> @ref SO_DESTPORT </td> <td> uint16_t </td><td> </td></tr>
|
||||
* <tr> <td> @ref SO_KEEPALIVEAUTO </td> <td> uint8_t </td><td> 0 ~ 255 </td></tr>
|
||||
* <tr> <td> @ref SO_SENDBUF </td> <td> uint16_t </td><td> 0 ~ 65535 </td></tr>
|
||||
* <tr> <td> @ref SO_RECVBUF </td> <td> uint16_t </td><td> 0 ~ 65535 </td></tr>
|
||||
* <tr> <td> @ref SO_STATUS </td> <td> uint8_t </td><td> @ref SOCK_ESTABLISHED, etc.. </td></tr>
|
||||
* <tr> <td> @ref SO_REMAINSIZE </td> <td> uint16_t </td><td> 0~ 65535 </td></tr>
|
||||
* <tr> <td> @ref SO_PACKINFO </td> <td> uint8_t </td><td> @ref PACK_FIRST, etc... </td></tr>
|
||||
* </table>
|
||||
* @return
|
||||
* - @b Success : @ref SOCK_OK \n
|
||||
* - @b Fail
|
||||
* - @ref SOCKERR_SOCKNUM - Invalid Socket number \n
|
||||
* - @ref SOCKERR_SOCKOPT - Invalid socket option or its value \n
|
||||
* - @ref SOCKERR_SOCKMODE - Invalid socket mode \n
|
||||
* @note
|
||||
* The option as PACK_REMAINED and SO_PACKINFO is valid only in NON-TCP mode and after call @ref recvfrom(). \n
|
||||
* When SO_PACKINFO value is PACK_FIRST and the return value of recvfrom() is zero,
|
||||
* This means the zero byte UDP data(UDP Header only) received.
|
||||
*/
|
||||
int8_t getsockopt(uint8_t sn, sockopt_type sotype, void* arg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _SOCKET_H_
|
||||
@ -0,0 +1,908 @@
|
||||
//****************************************************************************/
|
||||
//!
|
||||
//! \file wizchip_conf.c
|
||||
//! \brief WIZCHIP Config Header File.
|
||||
//! \version 1.0.1
|
||||
//! \date 2013/10/21
|
||||
//! \par Revision history
|
||||
//! <2015/02/05> Notice
|
||||
//! The version history is not updated after this point.
|
||||
//! Download the latest version directly from GitHub. Please visit the our GitHub repository for ioLibrary.
|
||||
//! >> https://github.com/Wiznet/ioLibrary_Driver
|
||||
//! <2014/05/01> V1.0.1 Refer to M20140501
|
||||
//! 1. Explicit type casting in wizchip_bus_readdata() & wizchip_bus_writedata()
|
||||
// Issued by Mathias ClauBen.
|
||||
//! uint32_t type converts into ptrdiff_t first. And then recoverting it into uint8_t*
|
||||
//! For remove the warning when pointer type size is not 32bit.
|
||||
//! If ptrdiff_t doesn't support in your complier, You should must replace ptrdiff_t into your suitable pointer type.
|
||||
//! <2013/10/21> 1st Release
|
||||
//! \author MidnightCow
|
||||
//! \copyright
|
||||
//!
|
||||
//! Copyright (c) 2013, WIZnet Co., LTD.
|
||||
//! All rights reserved.
|
||||
//!
|
||||
//! Redistribution and use in source and binary forms, with or without
|
||||
//! modification, are permitted provided that the following conditions
|
||||
//! are met:
|
||||
//!
|
||||
//! * Redistributions of source code must retain the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer.
|
||||
//! * Redistributions in binary form must reproduce the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer in the
|
||||
//! documentation and/or other materials provided with the distribution.
|
||||
//! * Neither the name of the <ORGANIZATION> nor the names of its
|
||||
//! contributors may be used to endorse or promote products derived
|
||||
//! from this software without specific prior written permission.
|
||||
//!
|
||||
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
//! THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//*****************************************************************************/
|
||||
//A20140501 : for use the type - ptrdiff_t
|
||||
#include <stddef.h>
|
||||
//
|
||||
|
||||
#include "wizchip_conf.h"
|
||||
|
||||
/////////////
|
||||
//M20150401 : Remove ; in the default callback function such as wizchip_cris_enter(), wizchip_cs_select() and etc.
|
||||
/////////////
|
||||
|
||||
/**
|
||||
* @brief Default function to enable interrupt.
|
||||
* @note This function help not to access wrong address. If you do not describe this function or register any functions,
|
||||
* null function is called.
|
||||
*/
|
||||
//void wizchip_cris_enter(void) {};
|
||||
void wizchip_cris_enter(void) {}
|
||||
|
||||
/**
|
||||
* @brief Default function to disable interrupt.
|
||||
* @note This function help not to access wrong address. If you do not describe this function or register any functions,
|
||||
* null function is called.
|
||||
*/
|
||||
//void wizchip_cris_exit(void) {};
|
||||
void wizchip_cris_exit(void) {}
|
||||
|
||||
/**
|
||||
* @brief Default function to select chip.
|
||||
* @note This function help not to access wrong address. If you do not describe this function or register any functions,
|
||||
* null function is called.
|
||||
*/
|
||||
//void wizchip_cs_select(void) {};
|
||||
void wizchip_cs_select(void) {}
|
||||
|
||||
/**
|
||||
* @brief Default function to deselect chip.
|
||||
* @note This function help not to access wrong address. If you do not describe this function or register any functions,
|
||||
* null function is called.
|
||||
*/
|
||||
//void wizchip_cs_deselect(void) {};
|
||||
void wizchip_cs_deselect(void) {}
|
||||
|
||||
/**
|
||||
* @brief Default function to read in direct or indirect interface.
|
||||
* @note This function help not to access wrong address. If you do not describe this function or register any functions,
|
||||
* null function is called.
|
||||
*/
|
||||
//M20150601 : Rename the function for integrating with W5300
|
||||
//uint8_t wizchip_bus_readbyte(uint32_t AddrSel) { return * ((volatile uint8_t *)((ptrdiff_t) AddrSel)); }
|
||||
iodata_t wizchip_bus_readdata(uint32_t AddrSel) { return * ((volatile iodata_t *)((ptrdiff_t) AddrSel)); }
|
||||
|
||||
/**
|
||||
* @brief Default function to write in direct or indirect interface.
|
||||
* @note This function help not to access wrong address. If you do not describe this function or register any functions,
|
||||
* null function is called.
|
||||
*/
|
||||
//M20150601 : Rename the function for integrating with W5300
|
||||
//void wizchip_bus_writebyte(uint32_t AddrSel, uint8_t wb) { *((volatile uint8_t*)((ptrdiff_t)AddrSel)) = wb; }
|
||||
void wizchip_bus_writedata(uint32_t AddrSel, iodata_t wb) { *((volatile iodata_t*)((ptrdiff_t)AddrSel)) = wb; }
|
||||
|
||||
/**
|
||||
* @brief Default function to read in SPI interface.
|
||||
* @note This function help not to access wrong address. If you do not describe this function or register any functions,
|
||||
* null function is called.
|
||||
*/
|
||||
//uint8_t wizchip_spi_readbyte(void) {return 0;};
|
||||
uint8_t wizchip_spi_readbyte(void) {return 0;}
|
||||
|
||||
/**
|
||||
* @brief Default function to write in SPI interface.
|
||||
* @note This function help not to access wrong address. If you do not describe this function or register any functions,
|
||||
* null function is called.
|
||||
*/
|
||||
//void wizchip_spi_writebyte(uint8_t wb) {};
|
||||
void wizchip_spi_writebyte(uint8_t wb) {}
|
||||
|
||||
/**
|
||||
* @brief Default function to burst read in SPI interface.
|
||||
* @note This function help not to access wrong address. If you do not describe this function or register any functions,
|
||||
* null function is called.
|
||||
*/
|
||||
//void wizchip_spi_readburst(uint8_t* pBuf, uint16_t len) {};
|
||||
void wizchip_spi_readburst(uint8_t* pBuf, uint16_t len) {}
|
||||
|
||||
/**
|
||||
* @brief Default function to burst write in SPI interface.
|
||||
* @note This function help not to access wrong address. If you do not describe this function or register any functions,
|
||||
* null function is called.
|
||||
*/
|
||||
//void wizchip_spi_writeburst(uint8_t* pBuf, uint16_t len) {};
|
||||
void wizchip_spi_writeburst(uint8_t* pBuf, uint16_t len) {}
|
||||
|
||||
/**
|
||||
* @\ref _WIZCHIP instance
|
||||
*/
|
||||
//
|
||||
//M20150401 : For a compiler didnot support a member of structure
|
||||
// Replace the assignment of struct members with the assingment of array
|
||||
//
|
||||
/*
|
||||
_WIZCHIP WIZCHIP =
|
||||
{
|
||||
.id = _WIZCHIP_ID_,
|
||||
.if_mode = _WIZCHIP_IO_MODE_,
|
||||
.CRIS._enter = wizchip_cris_enter,
|
||||
.CRIS._exit = wizchip_cris_exit,
|
||||
.CS._select = wizchip_cs_select,
|
||||
.CS._deselect = wizchip_cs_deselect,
|
||||
.IF.BUS._read_byte = wizchip_bus_readbyte,
|
||||
.IF.BUS._write_byte = wizchip_bus_writebyte
|
||||
// .IF.SPI._read_byte = wizchip_spi_readbyte,
|
||||
// .IF.SPI._write_byte = wizchip_spi_writebyte
|
||||
};
|
||||
*/
|
||||
_WIZCHIP WIZCHIP =
|
||||
{
|
||||
_WIZCHIP_IO_MODE_,
|
||||
_WIZCHIP_ID_ ,
|
||||
{
|
||||
wizchip_cris_enter,
|
||||
wizchip_cris_exit
|
||||
},
|
||||
{
|
||||
wizchip_cs_select,
|
||||
wizchip_cs_deselect
|
||||
},
|
||||
{
|
||||
{
|
||||
//M20150601 : Rename the function
|
||||
//wizchip_bus_readbyte,
|
||||
//wizchip_bus_writebyte
|
||||
wizchip_bus_readdata,
|
||||
wizchip_bus_writedata
|
||||
},
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static uint8_t _DNS_[4]; // DNS server ip address
|
||||
static dhcp_mode _DHCP_; // DHCP mode
|
||||
|
||||
void reg_wizchip_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void))
|
||||
{
|
||||
if(!cris_en || !cris_ex)
|
||||
{
|
||||
WIZCHIP.CRIS._enter = wizchip_cris_enter;
|
||||
WIZCHIP.CRIS._exit = wizchip_cris_exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
WIZCHIP.CRIS._enter = cris_en;
|
||||
WIZCHIP.CRIS._exit = cris_ex;
|
||||
}
|
||||
}
|
||||
|
||||
void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void))
|
||||
{
|
||||
if(!cs_sel || !cs_desel)
|
||||
{
|
||||
WIZCHIP.CS._select = wizchip_cs_select;
|
||||
WIZCHIP.CS._deselect = wizchip_cs_deselect;
|
||||
}
|
||||
else
|
||||
{
|
||||
WIZCHIP.CS._select = cs_sel;
|
||||
WIZCHIP.CS._deselect = cs_desel;
|
||||
}
|
||||
}
|
||||
|
||||
//M20150515 : For integrating with W5300
|
||||
//void reg_wizchip_bus_cbfunc(uint8_t(*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, uint8_t wb))
|
||||
void reg_wizchip_bus_cbfunc(iodata_t(*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, iodata_t wb))
|
||||
{
|
||||
while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_BUS_));
|
||||
//M20150601 : Rename call back function for integrating with W5300
|
||||
/*
|
||||
if(!bus_rb || !bus_wb)
|
||||
{
|
||||
WIZCHIP.IF.BUS._read_byte = wizchip_bus_readbyte;
|
||||
WIZCHIP.IF.BUS._write_byte = wizchip_bus_writebyte;
|
||||
}
|
||||
else
|
||||
{
|
||||
WIZCHIP.IF.BUS._read_byte = bus_rb;
|
||||
WIZCHIP.IF.BUS._write_byte = bus_wb;
|
||||
}
|
||||
*/
|
||||
if(!bus_rb || !bus_wb)
|
||||
{
|
||||
WIZCHIP.IF.BUS._read_data = wizchip_bus_readdata;
|
||||
WIZCHIP.IF.BUS._write_data = wizchip_bus_writedata;
|
||||
}
|
||||
else
|
||||
{
|
||||
WIZCHIP.IF.BUS._read_data = bus_rb;
|
||||
WIZCHIP.IF.BUS._write_data = bus_wb;
|
||||
}
|
||||
}
|
||||
|
||||
void reg_wizchip_spi_cbfunc(uint8_t (*spi_rb)(void), void (*spi_wb)(uint8_t wb))
|
||||
{
|
||||
while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_SPI_));
|
||||
|
||||
if(!spi_rb || !spi_wb)
|
||||
{
|
||||
WIZCHIP.IF.SPI._read_byte = wizchip_spi_readbyte;
|
||||
WIZCHIP.IF.SPI._write_byte = wizchip_spi_writebyte;
|
||||
}
|
||||
else
|
||||
{
|
||||
WIZCHIP.IF.SPI._read_byte = spi_rb;
|
||||
WIZCHIP.IF.SPI._write_byte = spi_wb;
|
||||
}
|
||||
}
|
||||
|
||||
// 20140626 Eric Added for SPI burst operations
|
||||
void reg_wizchip_spiburst_cbfunc(void (*spi_rb)(uint8_t* pBuf, uint16_t len), void (*spi_wb)(uint8_t* pBuf, uint16_t len))
|
||||
{
|
||||
while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_SPI_));
|
||||
|
||||
if(!spi_rb || !spi_wb)
|
||||
{
|
||||
WIZCHIP.IF.SPI._read_burst = wizchip_spi_readburst;
|
||||
WIZCHIP.IF.SPI._write_burst = wizchip_spi_writeburst;
|
||||
}
|
||||
else
|
||||
{
|
||||
WIZCHIP.IF.SPI._read_burst = spi_rb;
|
||||
WIZCHIP.IF.SPI._write_burst = spi_wb;
|
||||
}
|
||||
}
|
||||
|
||||
int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg)
|
||||
{
|
||||
#if _WIZCHIP_ == W5100S || _WIZCHIP_ == W5200 || _WIZCHIP_ == W5500
|
||||
uint8_t tmp = 0;
|
||||
#endif
|
||||
uint8_t* ptmp[2] = {0,0};
|
||||
switch(cwtype)
|
||||
{
|
||||
case CW_RESET_WIZCHIP:
|
||||
wizchip_sw_reset();
|
||||
break;
|
||||
case CW_INIT_WIZCHIP:
|
||||
if(arg != 0)
|
||||
{
|
||||
ptmp[0] = (uint8_t*)arg;
|
||||
ptmp[1] = ptmp[0] + _WIZCHIP_SOCK_NUM_;
|
||||
}
|
||||
return wizchip_init(ptmp[0], ptmp[1]);
|
||||
case CW_CLR_INTERRUPT:
|
||||
wizchip_clrinterrupt(*((intr_kind*)arg));
|
||||
break;
|
||||
case CW_GET_INTERRUPT:
|
||||
*((intr_kind*)arg) = wizchip_getinterrupt();
|
||||
break;
|
||||
case CW_SET_INTRMASK:
|
||||
wizchip_setinterruptmask(*((intr_kind*)arg));
|
||||
break;
|
||||
case CW_GET_INTRMASK:
|
||||
*((intr_kind*)arg) = wizchip_getinterruptmask();
|
||||
break;
|
||||
//M20150601 : This can be supported by W5200, W5500
|
||||
//#if _WIZCHIP_ > W5100
|
||||
#if (_WIZCHIP_ == W5200 || _WIZCHIP_ == W5500)
|
||||
case CW_SET_INTRTIME:
|
||||
setINTLEVEL(*(uint16_t*)arg);
|
||||
break;
|
||||
case CW_GET_INTRTIME:
|
||||
*(uint16_t*)arg = getINTLEVEL();
|
||||
break;
|
||||
#endif
|
||||
case CW_GET_ID:
|
||||
((uint8_t*)arg)[0] = WIZCHIP.id[0];
|
||||
((uint8_t*)arg)[1] = WIZCHIP.id[1];
|
||||
((uint8_t*)arg)[2] = WIZCHIP.id[2];
|
||||
((uint8_t*)arg)[3] = WIZCHIP.id[3];
|
||||
((uint8_t*)arg)[4] = WIZCHIP.id[4];
|
||||
((uint8_t*)arg)[5] = 0;
|
||||
break;
|
||||
#if _WIZCHIP_ == W5100S || _WIZCHIP_ == W5500
|
||||
case CW_RESET_PHY:
|
||||
wizphy_reset();
|
||||
break;
|
||||
case CW_SET_PHYCONF:
|
||||
wizphy_setphyconf((wiz_PhyConf*)arg);
|
||||
break;
|
||||
case CW_GET_PHYCONF:
|
||||
wizphy_getphyconf((wiz_PhyConf*)arg);
|
||||
break;
|
||||
case CW_GET_PHYSTATUS:
|
||||
break;
|
||||
case CW_SET_PHYPOWMODE:
|
||||
return wizphy_setphypmode(*(uint8_t*)arg);
|
||||
#endif
|
||||
#if _WIZCHIP_ == W5100S || _WIZCHIP_ == W5200 || _WIZCHIP_ == W5500
|
||||
case CW_GET_PHYPOWMODE:
|
||||
tmp = wizphy_getphypmode();
|
||||
if((int8_t)tmp == -1) return -1;
|
||||
*(uint8_t*)arg = tmp;
|
||||
break;
|
||||
case CW_GET_PHYLINK:
|
||||
tmp = wizphy_getphylink();
|
||||
if((int8_t)tmp == -1) return -1;
|
||||
*(uint8_t*)arg = tmp;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int8_t ctlnetwork(ctlnetwork_type cntype, void* arg)
|
||||
{
|
||||
|
||||
switch(cntype)
|
||||
{
|
||||
case CN_SET_NETINFO:
|
||||
wizchip_setnetinfo((wiz_NetInfo*)arg);
|
||||
break;
|
||||
case CN_GET_NETINFO:
|
||||
wizchip_getnetinfo((wiz_NetInfo*)arg);
|
||||
break;
|
||||
case CN_SET_NETMODE:
|
||||
return wizchip_setnetmode(*(netmode_type*)arg);
|
||||
case CN_GET_NETMODE:
|
||||
*(netmode_type*)arg = wizchip_getnetmode();
|
||||
break;
|
||||
case CN_SET_TIMEOUT:
|
||||
wizchip_settimeout((wiz_NetTimeout*)arg);
|
||||
break;
|
||||
case CN_GET_TIMEOUT:
|
||||
wizchip_gettimeout((wiz_NetTimeout*)arg);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wizchip_sw_reset(void)
|
||||
{
|
||||
uint8_t gw[4], sn[4], sip[4];
|
||||
uint8_t mac[6];
|
||||
//A20150601
|
||||
#if _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_
|
||||
uint16_t mr = (uint16_t)getMR();
|
||||
setMR(mr | MR_IND);
|
||||
#endif
|
||||
//
|
||||
getSHAR(mac);
|
||||
getGAR(gw); getSUBR(sn); getSIPR(sip);
|
||||
setMR(MR_RST);
|
||||
getMR(); // for delay
|
||||
//A2015051 : For indirect bus mode
|
||||
#if _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_
|
||||
setMR(mr | MR_IND);
|
||||
#endif
|
||||
//
|
||||
setSHAR(mac);
|
||||
setGAR(gw);
|
||||
setSUBR(sn);
|
||||
setSIPR(sip);
|
||||
}
|
||||
|
||||
int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize)
|
||||
{
|
||||
int8_t i;
|
||||
#if _WIZCHIP_ < W5200
|
||||
int8_t j;
|
||||
#endif
|
||||
int8_t tmp = 0;
|
||||
wizchip_sw_reset();
|
||||
if(txsize)
|
||||
{
|
||||
tmp = 0;
|
||||
//M20150601 : For integrating with W5300
|
||||
#if _WIZCHIP_ == W5300
|
||||
for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
|
||||
{
|
||||
if(txsize[i] >= 64) return -1; //No use 64KB even if W5300 support max 64KB memory allocation
|
||||
tmp += txsize[i];
|
||||
if(tmp > 128) return -1;
|
||||
}
|
||||
if(tmp % 8) return -1;
|
||||
#else
|
||||
for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
|
||||
{
|
||||
tmp += txsize[i];
|
||||
|
||||
#if _WIZCHIP_ < W5200 //2016.10.28 peter add condition for w5100 and w5100s
|
||||
if(tmp > 8) return -1;
|
||||
#else
|
||||
if(tmp > 16) return -1;
|
||||
#endif
|
||||
}
|
||||
for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
|
||||
{
|
||||
#if _WIZCHIP_ < W5200 //2016.10.28 peter add condition for w5100
|
||||
j = 0;
|
||||
while((txsize[i] >> j != 1)&&(txsize[i] !=0)){j++;}
|
||||
setSn_TXBUF_SIZE(i, j);
|
||||
#else
|
||||
setSn_TXBUF_SIZE(i, txsize[i]);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
if(rxsize)
|
||||
{
|
||||
tmp = 0;
|
||||
#if _WIZCHIP_ == W5300
|
||||
for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
|
||||
{
|
||||
if(rxsize[i] >= 64) return -1; //No use 64KB even if W5300 support max 64KB memory allocation
|
||||
tmp += rxsize[i];
|
||||
if(tmp > 128) return -1;
|
||||
}
|
||||
if(tmp % 8) return -1;
|
||||
#else
|
||||
for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
|
||||
{
|
||||
tmp += rxsize[i];
|
||||
#if _WIZCHIP_ < W5200 //2016.10.28 peter add condition for w5100 and w5100s
|
||||
if(tmp > 8) return -1;
|
||||
#else
|
||||
if(tmp > 16) return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
|
||||
{
|
||||
#if _WIZCHIP_ < W5200 // add condition for w5100
|
||||
j = 0;
|
||||
while((rxsize[i] >> j != 1)&&(txsize[i] !=0)){j++;}
|
||||
setSn_RXBUF_SIZE(i, j);
|
||||
#else
|
||||
setSn_RXBUF_SIZE(i, rxsize[i]);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wizchip_clrinterrupt(intr_kind intr)
|
||||
{
|
||||
uint8_t ir = (uint8_t)intr;
|
||||
uint8_t sir = (uint8_t)((uint16_t)intr >> 8);
|
||||
#if _WIZCHIP_ < W5500
|
||||
ir |= (1<<4); // IK_WOL
|
||||
#endif
|
||||
#if _WIZCHIP_ == W5200
|
||||
ir |= (1 << 6);
|
||||
#endif
|
||||
|
||||
#if _WIZCHIP_ < W5200
|
||||
sir &= 0x0F;
|
||||
#endif
|
||||
|
||||
#if _WIZCHIP_ <= W5100S
|
||||
ir |= sir;
|
||||
setIR(ir);
|
||||
//A20150601 : For integrating with W5300
|
||||
#elif _WIZCHIP_ == W5300
|
||||
setIR( ((((uint16_t)ir) << 8) | (((uint16_t)sir) & 0x00FF)) );
|
||||
#else
|
||||
setIR(ir);
|
||||
//M20200227 : For clear
|
||||
//setSIR(sir);
|
||||
for(ir=0; ir<8; ir++){
|
||||
if(sir & (0x01 <<ir) ) setSn_IR(ir, 0xff);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
intr_kind wizchip_getinterrupt(void)
|
||||
{
|
||||
uint8_t ir = 0;
|
||||
uint8_t sir = 0;
|
||||
uint16_t ret = 0;
|
||||
#if _WIZCHIP_ <= W5100S
|
||||
ir = getIR();
|
||||
sir = ir & 0x0F;
|
||||
//A20150601 : For integrating with W5300
|
||||
#elif _WIZCHIP_ == W5300
|
||||
ret = getIR();
|
||||
ir = (uint8_t)(ret >> 8);
|
||||
sir = (uint8_t)ret;
|
||||
#else
|
||||
ir = getIR();
|
||||
sir = getSIR();
|
||||
#endif
|
||||
|
||||
//M20150601 : For Integrating with W5300
|
||||
//#if _WIZCHIP_ < W5500
|
||||
#if _WIZCHIP_ < W5200
|
||||
ir &= ~(1<<4); // IK_WOL
|
||||
#endif
|
||||
#if _WIZCHIP_ == W5200
|
||||
ir &= ~(1 << 6);
|
||||
#endif
|
||||
ret = sir;
|
||||
ret = (ret << 8) + ir;
|
||||
return (intr_kind)ret;
|
||||
}
|
||||
|
||||
void wizchip_setinterruptmask(intr_kind intr)
|
||||
{
|
||||
uint8_t imr = (uint8_t)intr;
|
||||
uint8_t simr = (uint8_t)((uint16_t)intr >> 8);
|
||||
#if _WIZCHIP_ < W5500
|
||||
imr &= ~(1<<4); // IK_WOL
|
||||
#endif
|
||||
#if _WIZCHIP_ == W5200
|
||||
imr &= ~(1 << 6);
|
||||
#endif
|
||||
|
||||
#if _WIZCHIP_ < W5200
|
||||
simr &= 0x0F;
|
||||
imr |= simr;
|
||||
setIMR(imr);
|
||||
//A20150601 : For integrating with W5300
|
||||
#elif _WIZCHIP_ == W5300
|
||||
setIMR( ((((uint16_t)imr) << 8) | (((uint16_t)simr) & 0x00FF)) );
|
||||
#else
|
||||
setIMR(imr);
|
||||
setSIMR(simr);
|
||||
#endif
|
||||
}
|
||||
|
||||
intr_kind wizchip_getinterruptmask(void)
|
||||
{
|
||||
uint8_t imr = 0;
|
||||
uint8_t simr = 0;
|
||||
uint16_t ret = 0;
|
||||
#if _WIZCHIP_ < W5200
|
||||
imr = getIMR();
|
||||
simr = imr & 0x0F;
|
||||
//A20150601 : For integrating with W5300
|
||||
#elif _WIZCHIP_ == W5300
|
||||
ret = getIMR();
|
||||
imr = (uint8_t)(ret >> 8);
|
||||
simr = (uint8_t)ret;
|
||||
#else
|
||||
imr = getIMR();
|
||||
simr = getSIMR();
|
||||
#endif
|
||||
|
||||
#if _WIZCHIP_ < W5500
|
||||
imr &= ~(1<<4); // IK_WOL
|
||||
#endif
|
||||
#if _WIZCHIP_ == W5200
|
||||
imr &= ~(1 << 6); // IK_DEST_UNREACH
|
||||
#endif
|
||||
ret = simr;
|
||||
ret = (ret << 8) + imr;
|
||||
return (intr_kind)ret;
|
||||
}
|
||||
|
||||
int8_t wizphy_getphylink(void)
|
||||
{
|
||||
int8_t tmp = PHY_LINK_OFF;
|
||||
#if _WIZCHIP_ == W5100S
|
||||
if(getPHYSR() & PHYSR_LNK)
|
||||
tmp = PHY_LINK_ON;
|
||||
#elif _WIZCHIP_ == W5200
|
||||
if(getPHYSTATUS() & PHYSTATUS_LINK)
|
||||
tmp = PHY_LINK_ON;
|
||||
#elif _WIZCHIP_ == W5500
|
||||
if(getPHYCFGR() & PHYCFGR_LNK_ON)
|
||||
tmp = PHY_LINK_ON;
|
||||
|
||||
#else
|
||||
tmp = -1;
|
||||
#endif
|
||||
return tmp;
|
||||
}
|
||||
|
||||
#if _WIZCHIP_ > W5100
|
||||
|
||||
int8_t wizphy_getphypmode(void)
|
||||
{
|
||||
int8_t tmp = 0;
|
||||
#if _WIZCHIP_ == W5200
|
||||
if(getPHYSTATUS() & PHYSTATUS_POWERDOWN)
|
||||
tmp = PHY_POWER_DOWN;
|
||||
else
|
||||
tmp = PHY_POWER_NORM;
|
||||
#elif _WIZCHIP_ == 5500
|
||||
if((getPHYCFGR() & PHYCFGR_OPMDC_ALLA) == PHYCFGR_OPMDC_PDOWN)
|
||||
tmp = PHY_POWER_DOWN;
|
||||
else
|
||||
tmp = PHY_POWER_NORM;
|
||||
#else
|
||||
tmp = -1;
|
||||
#endif
|
||||
return tmp;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if _WIZCHIP_ == W5100S
|
||||
void wizphy_reset(void)
|
||||
{
|
||||
uint16_t tmp = wiz_mdio_read(PHYMDIO_BMCR);
|
||||
tmp |= BMCR_RESET;
|
||||
wiz_mdio_write(PHYMDIO_BMCR, tmp);
|
||||
while(wiz_mdio_read(PHYMDIO_BMCR)&BMCR_RESET){}
|
||||
}
|
||||
|
||||
void wizphy_setphyconf(wiz_PhyConf* phyconf)
|
||||
{
|
||||
uint16_t tmp = wiz_mdio_read(PHYMDIO_BMCR);
|
||||
if(phyconf->mode == PHY_MODE_AUTONEGO)
|
||||
tmp |= BMCR_AUTONEGO;
|
||||
else
|
||||
{
|
||||
tmp &= ~BMCR_AUTONEGO;
|
||||
if(phyconf->duplex == PHY_DUPLEX_FULL)
|
||||
{
|
||||
tmp |= BMCR_DUP;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp &= ~BMCR_DUP;
|
||||
}
|
||||
if(phyconf->speed == PHY_SPEED_100)
|
||||
{
|
||||
tmp |= BMCR_SPEED;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp &= ~BMCR_SPEED;
|
||||
}
|
||||
}
|
||||
wiz_mdio_write(PHYMDIO_BMCR, tmp);
|
||||
}
|
||||
|
||||
void wizphy_getphyconf(wiz_PhyConf* phyconf)
|
||||
{
|
||||
uint16_t tmp = 0;
|
||||
tmp = wiz_mdio_read(PHYMDIO_BMCR);
|
||||
phyconf->by = PHY_CONFBY_SW;
|
||||
if(tmp & BMCR_AUTONEGO)
|
||||
{
|
||||
phyconf->mode = PHY_MODE_AUTONEGO;
|
||||
}
|
||||
else
|
||||
{
|
||||
phyconf->mode = PHY_MODE_MANUAL;
|
||||
if(tmp&BMCR_DUP) phyconf->duplex = PHY_DUPLEX_FULL;
|
||||
else phyconf->duplex = PHY_DUPLEX_HALF;
|
||||
if(tmp&BMCR_SPEED) phyconf->speed = PHY_SPEED_100;
|
||||
else phyconf->speed = PHY_SPEED_10;
|
||||
}
|
||||
}
|
||||
|
||||
int8_t wizphy_setphypmode(uint8_t pmode)
|
||||
{
|
||||
uint16_t tmp = 0;
|
||||
tmp = wiz_mdio_read(PHYMDIO_BMCR);
|
||||
if( pmode == PHY_POWER_DOWN)
|
||||
{
|
||||
tmp |= BMCR_PWDN;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp &= ~BMCR_PWDN;
|
||||
}
|
||||
wiz_mdio_write(PHYMDIO_BMCR, tmp);
|
||||
tmp = wiz_mdio_read(PHYMDIO_BMCR);
|
||||
if( pmode == PHY_POWER_DOWN)
|
||||
{
|
||||
if(tmp & BMCR_PWDN) return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if((tmp & BMCR_PWDN) != BMCR_PWDN) return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
#if _WIZCHIP_ == W5500
|
||||
void wizphy_reset(void)
|
||||
{
|
||||
uint8_t tmp = getPHYCFGR();
|
||||
tmp &= PHYCFGR_RST;
|
||||
setPHYCFGR(tmp);
|
||||
tmp = getPHYCFGR();
|
||||
tmp |= ~PHYCFGR_RST;
|
||||
setPHYCFGR(tmp);
|
||||
}
|
||||
|
||||
void wizphy_setphyconf(wiz_PhyConf* phyconf)
|
||||
{
|
||||
uint8_t tmp = 0;
|
||||
if(phyconf->by == PHY_CONFBY_SW)
|
||||
tmp |= PHYCFGR_OPMD;
|
||||
else
|
||||
tmp &= ~PHYCFGR_OPMD;
|
||||
if(phyconf->mode == PHY_MODE_AUTONEGO)
|
||||
tmp |= PHYCFGR_OPMDC_ALLA;
|
||||
else
|
||||
{
|
||||
if(phyconf->duplex == PHY_DUPLEX_FULL)
|
||||
{
|
||||
if(phyconf->speed == PHY_SPEED_100)
|
||||
tmp |= PHYCFGR_OPMDC_100F;
|
||||
else
|
||||
tmp |= PHYCFGR_OPMDC_10F;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(phyconf->speed == PHY_SPEED_100)
|
||||
tmp |= PHYCFGR_OPMDC_100H;
|
||||
else
|
||||
tmp |= PHYCFGR_OPMDC_10H;
|
||||
}
|
||||
}
|
||||
setPHYCFGR(tmp);
|
||||
wizphy_reset();
|
||||
}
|
||||
|
||||
void wizphy_getphyconf(wiz_PhyConf* phyconf)
|
||||
{
|
||||
uint8_t tmp = 0;
|
||||
tmp = getPHYCFGR();
|
||||
phyconf->by = (tmp & PHYCFGR_OPMD) ? PHY_CONFBY_SW : PHY_CONFBY_HW;
|
||||
switch(tmp & PHYCFGR_OPMDC_ALLA)
|
||||
{
|
||||
case PHYCFGR_OPMDC_ALLA:
|
||||
case PHYCFGR_OPMDC_100FA:
|
||||
phyconf->mode = PHY_MODE_AUTONEGO;
|
||||
break;
|
||||
default:
|
||||
phyconf->mode = PHY_MODE_MANUAL;
|
||||
break;
|
||||
}
|
||||
switch(tmp & PHYCFGR_OPMDC_ALLA)
|
||||
{
|
||||
case PHYCFGR_OPMDC_100FA:
|
||||
case PHYCFGR_OPMDC_100F:
|
||||
case PHYCFGR_OPMDC_100H:
|
||||
phyconf->speed = PHY_SPEED_100;
|
||||
break;
|
||||
default:
|
||||
phyconf->speed = PHY_SPEED_10;
|
||||
break;
|
||||
}
|
||||
switch(tmp & PHYCFGR_OPMDC_ALLA)
|
||||
{
|
||||
case PHYCFGR_OPMDC_100FA:
|
||||
case PHYCFGR_OPMDC_100F:
|
||||
case PHYCFGR_OPMDC_10F:
|
||||
phyconf->duplex = PHY_DUPLEX_FULL;
|
||||
break;
|
||||
default:
|
||||
phyconf->duplex = PHY_DUPLEX_HALF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void wizphy_getphystat(wiz_PhyConf* phyconf)
|
||||
{
|
||||
uint8_t tmp = getPHYCFGR();
|
||||
phyconf->duplex = (tmp & PHYCFGR_DPX_FULL) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF;
|
||||
phyconf->speed = (tmp & PHYCFGR_SPD_100) ? PHY_SPEED_100 : PHY_SPEED_10;
|
||||
}
|
||||
|
||||
int8_t wizphy_setphypmode(uint8_t pmode)
|
||||
{
|
||||
uint8_t tmp = 0;
|
||||
tmp = getPHYCFGR();
|
||||
if((tmp & PHYCFGR_OPMD)== 0) return -1;
|
||||
tmp &= ~PHYCFGR_OPMDC_ALLA;
|
||||
if( pmode == PHY_POWER_DOWN)
|
||||
tmp |= PHYCFGR_OPMDC_PDOWN;
|
||||
else
|
||||
tmp |= PHYCFGR_OPMDC_ALLA;
|
||||
setPHYCFGR(tmp);
|
||||
wizphy_reset();
|
||||
tmp = getPHYCFGR();
|
||||
if( pmode == PHY_POWER_DOWN)
|
||||
{
|
||||
if(tmp & PHYCFGR_OPMDC_PDOWN) return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(tmp & PHYCFGR_OPMDC_ALLA) return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void wizchip_setnetinfo(wiz_NetInfo* pnetinfo)
|
||||
{
|
||||
setSHAR(pnetinfo->mac);
|
||||
setGAR(pnetinfo->gw);
|
||||
setSUBR(pnetinfo->sn);
|
||||
setSIPR(pnetinfo->ip);
|
||||
_DNS_[0] = pnetinfo->dns[0];
|
||||
_DNS_[1] = pnetinfo->dns[1];
|
||||
_DNS_[2] = pnetinfo->dns[2];
|
||||
_DNS_[3] = pnetinfo->dns[3];
|
||||
_DHCP_ = pnetinfo->dhcp;
|
||||
}
|
||||
|
||||
void wizchip_getnetinfo(wiz_NetInfo* pnetinfo)
|
||||
{
|
||||
getSHAR(pnetinfo->mac);
|
||||
getGAR(pnetinfo->gw);
|
||||
getSUBR(pnetinfo->sn);
|
||||
getSIPR(pnetinfo->ip);
|
||||
pnetinfo->dns[0]= _DNS_[0];
|
||||
pnetinfo->dns[1]= _DNS_[1];
|
||||
pnetinfo->dns[2]= _DNS_[2];
|
||||
pnetinfo->dns[3]= _DNS_[3];
|
||||
pnetinfo->dhcp = _DHCP_;
|
||||
}
|
||||
|
||||
int8_t wizchip_setnetmode(netmode_type netmode)
|
||||
{
|
||||
uint8_t tmp = 0;
|
||||
#if _WIZCHIP_ != W5500
|
||||
if(netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK)) return -1;
|
||||
#else
|
||||
if(netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK | NM_FORCEARP)) return -1;
|
||||
#endif
|
||||
tmp = getMR();
|
||||
tmp |= (uint8_t)netmode;
|
||||
setMR(tmp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
netmode_type wizchip_getnetmode(void)
|
||||
{
|
||||
return (netmode_type) getMR();
|
||||
}
|
||||
|
||||
void wizchip_settimeout(wiz_NetTimeout* nettime)
|
||||
{
|
||||
setRCR(nettime->retry_cnt);
|
||||
setRTR(nettime->time_100us);
|
||||
}
|
||||
|
||||
void wizchip_gettimeout(wiz_NetTimeout* nettime)
|
||||
{
|
||||
nettime->retry_cnt = getRCR();
|
||||
nettime->time_100us = getRTR();
|
||||
}
|
||||
@ -0,0 +1,661 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! \file wizchip_conf.h
|
||||
//! \brief WIZCHIP Config Header File.
|
||||
//! \version 1.0.0
|
||||
//! \date 2013/10/21
|
||||
//! \par Revision history
|
||||
//! <2015/02/05> Notice
|
||||
//! The version history is not updated after this point.
|
||||
//! Download the latest version directly from GitHub. Please visit the our GitHub repository for ioLibrary.
|
||||
//! >> https://github.com/Wiznet/ioLibrary_Driver
|
||||
//! <2013/10/21> 1st Release
|
||||
//! \author MidnightCow
|
||||
//! \copyright
|
||||
//!
|
||||
//! Copyright (c) 2013, WIZnet Co., LTD.
|
||||
//! All rights reserved.
|
||||
//!
|
||||
//! Redistribution and use in source and binary forms, with or without
|
||||
//! modification, are permitted provided that the following conditions
|
||||
//! are met:
|
||||
//!
|
||||
//! * Redistributions of source code must retain the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer.
|
||||
//! * Redistributions in binary form must reproduce the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer in the
|
||||
//! documentation and/or other materials provided with the distribution.
|
||||
//! * Neither the name of the <ORGANIZATION> nor the names of its
|
||||
//! contributors may be used to endorse or promote products derived
|
||||
//! from this software without specific prior written permission.
|
||||
//!
|
||||
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
//! THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
/**
|
||||
* @defgroup extra_functions 2. WIZnet Extra Functions
|
||||
*
|
||||
* @brief These functions is optional function. It could be replaced at WIZCHIP I/O function because they were made by WIZCHIP I/O functions.
|
||||
* @details There are functions of configuring WIZCHIP, network, interrupt, phy, network information and timer. \n
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _WIZCHIP_CONF_H_
|
||||
#define _WIZCHIP_CONF_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
/**
|
||||
* @brief Select WIZCHIP.
|
||||
* @todo You should select one, \b W5100, \b W5100S, \b W5200, \b W5300, \b W5500 or etc. \n\n
|
||||
* ex> <code> #define \_WIZCHIP_ W5500 </code>
|
||||
*/
|
||||
|
||||
#define W5100 5100
|
||||
#define W5100S 5100+5
|
||||
#define W5200 5200
|
||||
#define W5300 5300
|
||||
#define W5500 5500
|
||||
|
||||
#ifndef _WIZCHIP_
|
||||
#define _WIZCHIP_ W5100 // W5100, W5100S, W5200, W5300, W5500
|
||||
#endif
|
||||
|
||||
#define _WIZCHIP_IO_MODE_NONE_ 0x0000
|
||||
#define _WIZCHIP_IO_MODE_BUS_ 0x0100 /**< Bus interface mode */
|
||||
#define _WIZCHIP_IO_MODE_SPI_ 0x0200 /**< SPI interface mode */
|
||||
//#define _WIZCHIP_IO_MODE_IIC_ 0x0400
|
||||
//#define _WIZCHIP_IO_MODE_SDIO_ 0x0800
|
||||
// Add to
|
||||
//
|
||||
|
||||
#define _WIZCHIP_IO_MODE_BUS_DIR_ (_WIZCHIP_IO_MODE_BUS_ + 1) /**< BUS interface mode for direct */
|
||||
#define _WIZCHIP_IO_MODE_BUS_INDIR_ (_WIZCHIP_IO_MODE_BUS_ + 2) /**< BUS interface mode for indirect */
|
||||
|
||||
#define _WIZCHIP_IO_MODE_SPI_VDM_ (_WIZCHIP_IO_MODE_SPI_ + 1) /**< SPI interface mode for variable length data*/
|
||||
#define _WIZCHIP_IO_MODE_SPI_FDM_ (_WIZCHIP_IO_MODE_SPI_ + 2) /**< SPI interface mode for fixed length data mode*/
|
||||
#define _WIZCHIP_IO_MODE_SPI_5500_ (_WIZCHIP_IO_MODE_SPI_ + 3) /**< SPI interface mode for fixed length data mode*/
|
||||
|
||||
#if (_WIZCHIP_ == W5100)
|
||||
#define _WIZCHIP_ID_ "W5100\0"
|
||||
/**
|
||||
* @brief Define interface mode.
|
||||
* @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ , @ref \_WIZCHIP_IO_MODE_BUS_DIR_ or @ref \_WIZCHIP_IO_MODE_BUS_INDIR_
|
||||
*/
|
||||
// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_DIR_
|
||||
// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_INDIR_
|
||||
#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_
|
||||
|
||||
//A20150601 : Define the unit of IO DATA.
|
||||
typedef uint8_t iodata_t;
|
||||
//A20150401 : Indclude W5100.h file
|
||||
#include "W5100/w5100.h"
|
||||
|
||||
#elif (_WIZCHIP_ == W5100S)
|
||||
#define _WIZCHIP_ID_ "W5100S\0"
|
||||
/**
|
||||
* @brief Define interface mode.
|
||||
* @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ , @ref \_WIZCHIP_IO_MODE_BUS_DIR_ or @ref \_WIZCHIP_IO_MODE_BUS_INDIR_
|
||||
*/
|
||||
// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_INDIR_
|
||||
//#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_5500_
|
||||
#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_
|
||||
|
||||
//A20150601 : Define the unit of IO DATA.
|
||||
typedef uint8_t iodata_t;
|
||||
//A20150401 : Indclude W5100.h file
|
||||
#include "W5100S/w5100s.h"
|
||||
#elif (_WIZCHIP_ == W5200)
|
||||
#define _WIZCHIP_ID_ "W5200\0"
|
||||
/**
|
||||
* @brief Define interface mode.
|
||||
* @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ or @ref \ _WIZCHIP_IO_MODE_BUS_INDIR_
|
||||
*/
|
||||
#ifndef _WIZCHIP_IO_MODE_
|
||||
// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_INDIR_
|
||||
#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_
|
||||
#endif
|
||||
//A20150601 : Define the unit of IO DATA.
|
||||
typedef uint8_t iodata_t;
|
||||
#include "W5200/w5200.h"
|
||||
#elif (_WIZCHIP_ == W5500)
|
||||
#define _WIZCHIP_ID_ "W5500\0"
|
||||
|
||||
/**
|
||||
* @brief Define interface mode. \n
|
||||
* @todo Should select interface mode as chip.
|
||||
* - @ref \_WIZCHIP_IO_MODE_SPI_ \n
|
||||
* -@ref \_WIZCHIP_IO_MODE_SPI_VDM_ : Valid only in @ref \_WIZCHIP_ == W5500 \n
|
||||
* -@ref \_WIZCHIP_IO_MODE_SPI_FDM_ : Valid only in @ref \_WIZCHIP_ == W5500 \n
|
||||
* - @ref \_WIZCHIP_IO_MODE_BUS_ \n
|
||||
* - @ref \_WIZCHIP_IO_MODE_BUS_DIR_ \n
|
||||
* - @ref \_WIZCHIP_IO_MODE_BUS_INDIR_ \n
|
||||
* - Others will be defined in future. \n\n
|
||||
* ex> <code> #define \_WIZCHIP_IO_MODE_ \_WIZCHIP_IO_MODE_SPI_VDM_ </code>
|
||||
*
|
||||
*/
|
||||
#ifndef _WIZCHIP_IO_MODE_
|
||||
//#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_FDM_
|
||||
#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_VDM_
|
||||
#endif
|
||||
//A20150601 : Define the unit of IO DATA.
|
||||
typedef uint8_t iodata_t;
|
||||
#include "W5500/w5500.h"
|
||||
#elif ( _WIZCHIP_ == W5300)
|
||||
#define _WIZCHIP_ID_ "W5300\0"
|
||||
/**
|
||||
* @brief Define interface mode.
|
||||
* @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ , @ref \_WIZCHIP_IO_MODE_BUS_DIR_ or @ref \_WIZCHIP_IO_MODE_BUS_INDIR_
|
||||
*/
|
||||
#ifndef _WIZCHIP_IO_MODE_
|
||||
#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_DIR_
|
||||
// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_INDIR_
|
||||
#endif
|
||||
|
||||
//A20150601 : Define the unit and bus width of IO DATA.
|
||||
/**
|
||||
* @brief Select the data width 8 or 16 bits.
|
||||
* @todo you should select the bus width. Select one of 8 or 16.
|
||||
*/
|
||||
#ifndef _WIZCHIP_IO_BUS_WIDTH_
|
||||
#define _WIZCHIP_IO_BUS_WIDTH_ 16 // 8
|
||||
#endif
|
||||
#if _WIZCHIP_IO_BUS_WIDTH_ == 8
|
||||
typedef uint8_t iodata_t;
|
||||
#elif _WIZCHIP_IO_BUS_WIDTH_ == 16
|
||||
typedef uint16_t iodata_t;
|
||||
#else
|
||||
#error "Unknown _WIZCHIP_IO_BUS_WIDTH_. It should be 8 or 16."
|
||||
#endif
|
||||
//
|
||||
#include "W5300/w5300.h"
|
||||
#else
|
||||
#error "Unknown defined _WIZCHIP_. You should define one of 5100, 5200, and 5500 !!!"
|
||||
#endif
|
||||
|
||||
#ifndef _WIZCHIP_IO_MODE_
|
||||
#error "Undefined _WIZCHIP_IO_MODE_. You should define it !!!"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Define I/O base address when BUS IF mode.
|
||||
* @todo Should re-define it to fit your system when BUS IF Mode (@ref \_WIZCHIP_IO_MODE_BUS_,
|
||||
* @ref \_WIZCHIP_IO_MODE_BUS_DIR_, @ref \_WIZCHIP_IO_MODE_BUS_INDIR_). \n\n
|
||||
* ex> <code> #define \_WIZCHIP_IO_BASE_ 0x00008000 </code>
|
||||
*/
|
||||
#if _WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_
|
||||
// #define _WIZCHIP_IO_BASE_ 0x60000000 // for 5100S IND
|
||||
#define _WIZCHIP_IO_BASE_ 0x68000000 // for W5300
|
||||
#elif _WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_
|
||||
#define _WIZCHIP_IO_BASE_ 0x00000000 // for 5100S SPI
|
||||
#endif
|
||||
|
||||
#ifndef _WIZCHIP_IO_BASE_
|
||||
#define _WIZCHIP_IO_BASE_ 0x00000000 // 0x8000
|
||||
#endif
|
||||
|
||||
//M20150401 : Typing Error
|
||||
//#if _WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS
|
||||
#if _WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_
|
||||
#ifndef _WIZCHIP_IO_BASE_
|
||||
#error "You should be define _WIZCHIP_IO_BASE to fit your system memory map."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if _WIZCHIP_ >= W5200
|
||||
#define _WIZCHIP_SOCK_NUM_ 8 ///< The count of independant socket of @b WIZCHIP
|
||||
#else
|
||||
#define _WIZCHIP_SOCK_NUM_ 4 ///< The count of independant socket of @b WIZCHIP
|
||||
#endif
|
||||
|
||||
|
||||
/********************************************************
|
||||
* WIZCHIP BASIC IF functions for SPI, SDIO, I2C , ETC.
|
||||
*********************************************************/
|
||||
/**
|
||||
* @ingroup DATA_TYPE
|
||||
* @brief The set of callback functions for W5500:@ref WIZCHIP_IO_Functions W5200:@ref WIZCHIP_IO_Functions_W5200
|
||||
*/
|
||||
typedef struct __WIZCHIP
|
||||
{
|
||||
uint16_t if_mode; ///< host interface mode
|
||||
uint8_t id[7]; ///< @b WIZCHIP ID such as @b 5100, @b 5200, @b 5500, and so on.
|
||||
/**
|
||||
* The set of critical section callback func.
|
||||
*/
|
||||
struct _CRIS
|
||||
{
|
||||
void (*_enter) (void); ///< crtical section enter
|
||||
void (*_exit) (void); ///< critial section exit
|
||||
}CRIS;
|
||||
/**
|
||||
* The set of @ref \_WIZCHIP_ select control callback func.
|
||||
*/
|
||||
struct _CS
|
||||
{
|
||||
void (*_select) (void); ///< @ref \_WIZCHIP_ selected
|
||||
void (*_deselect)(void); ///< @ref \_WIZCHIP_ deselected
|
||||
}CS;
|
||||
/**
|
||||
* The set of interface IO callback func.
|
||||
*/
|
||||
union _IF
|
||||
{
|
||||
/**
|
||||
* For BUS interface IO
|
||||
*/
|
||||
//M20156501 : Modify the function name for integrating with W5300
|
||||
//struct
|
||||
//{
|
||||
// uint8_t (*_read_byte) (uint32_t AddrSel);
|
||||
// void (*_write_byte) (uint32_t AddrSel, uint8_t wb);
|
||||
//}BUS;
|
||||
struct
|
||||
{
|
||||
iodata_t (*_read_data) (uint32_t AddrSel);
|
||||
void (*_write_data) (uint32_t AddrSel, iodata_t wb);
|
||||
}BUS;
|
||||
|
||||
/**
|
||||
* For SPI interface IO
|
||||
*/
|
||||
struct
|
||||
{
|
||||
uint8_t (*_read_byte) (void);
|
||||
void (*_write_byte) (uint8_t wb);
|
||||
void (*_read_burst) (uint8_t* pBuf, uint16_t len);
|
||||
void (*_write_burst) (uint8_t* pBuf, uint16_t len);
|
||||
}SPI;
|
||||
// To be added
|
||||
//
|
||||
}IF;
|
||||
}_WIZCHIP;
|
||||
|
||||
extern _WIZCHIP WIZCHIP;
|
||||
|
||||
/**
|
||||
* @ingroup DATA_TYPE
|
||||
* WIZCHIP control type enumration used in @ref ctlwizchip().
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
CW_RESET_WIZCHIP, ///< Resets WIZCHIP by softly
|
||||
CW_INIT_WIZCHIP, ///< Initializes to WIZCHIP with SOCKET buffer size 2 or 1 dimension array typed uint8_t.
|
||||
CW_GET_INTERRUPT, ///< Get Interrupt status of WIZCHIP
|
||||
CW_CLR_INTERRUPT, ///< Clears interrupt
|
||||
CW_SET_INTRMASK, ///< Masks interrupt
|
||||
CW_GET_INTRMASK, ///< Get interrupt mask
|
||||
CW_SET_INTRTIME, ///< Set interval time between the current and next interrupt.
|
||||
CW_GET_INTRTIME, ///< Set interval time between the current and next interrupt.
|
||||
CW_GET_ID, ///< Gets WIZCHIP name.
|
||||
|
||||
//D20150601 : For no modification your application code
|
||||
//#if _WIZCHIP_ == W5500
|
||||
CW_RESET_PHY, ///< Resets internal PHY. Valid Only W5500
|
||||
CW_SET_PHYCONF, ///< When PHY configured by internal register, PHY operation mode (Manual/Auto, 10/100, Half/Full). Valid Only W5000
|
||||
CW_GET_PHYCONF, ///< Get PHY operation mode in internal register. Valid Only W5500
|
||||
CW_GET_PHYSTATUS, ///< Get real PHY status on operating. Valid Only W5500
|
||||
CW_SET_PHYPOWMODE, ///< Set PHY power mode as normal and down when PHYSTATUS.OPMD == 1. Valid Only W5500
|
||||
//#endif
|
||||
//D20150601 : For no modification your application code
|
||||
//#if _WIZCHIP_ == W5200 || _WIZCHIP_ == W5500
|
||||
CW_GET_PHYPOWMODE, ///< Get PHY Power mode as down or normal, Valid Only W5100, W5200
|
||||
CW_GET_PHYLINK ///< Get PHY Link status, Valid Only W5100, W5200
|
||||
//#endif
|
||||
}ctlwizchip_type;
|
||||
|
||||
/**
|
||||
* @ingroup DATA_TYPE
|
||||
* Network control type enumration used in @ref ctlnetwork().
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
CN_SET_NETINFO, ///< Set Network with @ref wiz_NetInfo
|
||||
CN_GET_NETINFO, ///< Get Network with @ref wiz_NetInfo
|
||||
CN_SET_NETMODE, ///< Set network mode as WOL, PPPoE, Ping Block, and Force ARP mode
|
||||
CN_GET_NETMODE, ///< Get network mode as WOL, PPPoE, Ping Block, and Force ARP mode
|
||||
CN_SET_TIMEOUT, ///< Set network timeout as retry count and time.
|
||||
CN_GET_TIMEOUT, ///< Get network timeout as retry count and time.
|
||||
}ctlnetwork_type;
|
||||
|
||||
/**
|
||||
* @ingroup DATA_TYPE
|
||||
* Interrupt kind when CW_SET_INTRRUPT, CW_GET_INTERRUPT, CW_SET_INTRMASK
|
||||
* and CW_GET_INTRMASK is used in @ref ctlnetwork().
|
||||
* It can be used with OR operation.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
#if _WIZCHIP_ == W5500
|
||||
IK_WOL = (1 << 4), ///< Wake On Lan by receiving the magic packet. Valid in W500.
|
||||
#elif _WIZCHIP_ == W5300
|
||||
IK_FMTU = (1 << 4), ///< Received a ICMP message (Fragment MTU)
|
||||
#endif
|
||||
|
||||
IK_PPPOE_TERMINATED = (1 << 5), ///< PPPoE Disconnected
|
||||
|
||||
#if _WIZCHIP_ != W5200
|
||||
IK_DEST_UNREACH = (1 << 6), ///< Destination IP & Port Unreachable, No use in W5200
|
||||
#endif
|
||||
|
||||
IK_IP_CONFLICT = (1 << 7), ///< IP conflict occurred
|
||||
|
||||
IK_SOCK_0 = (1 << 8), ///< Socket 0 interrupt
|
||||
IK_SOCK_1 = (1 << 9), ///< Socket 1 interrupt
|
||||
IK_SOCK_2 = (1 << 10), ///< Socket 2 interrupt
|
||||
IK_SOCK_3 = (1 << 11), ///< Socket 3 interrupt
|
||||
#if _WIZCHIP_ > W5100S
|
||||
IK_SOCK_4 = (1 << 12), ///< Socket 4 interrupt, No use in 5100
|
||||
IK_SOCK_5 = (1 << 13), ///< Socket 5 interrupt, No use in 5100
|
||||
IK_SOCK_6 = (1 << 14), ///< Socket 6 interrupt, No use in 5100
|
||||
IK_SOCK_7 = (1 << 15), ///< Socket 7 interrupt, No use in 5100
|
||||
#endif
|
||||
|
||||
#if _WIZCHIP_ > W5100S
|
||||
IK_SOCK_ALL = (0xFF << 8) ///< All Socket interrupt
|
||||
#else
|
||||
IK_SOCK_ALL = (0x0F << 8) ///< All Socket interrupt
|
||||
#endif
|
||||
}intr_kind;
|
||||
|
||||
#define PHY_CONFBY_HW 0 ///< Configured PHY operation mode by HW pin
|
||||
#define PHY_CONFBY_SW 1 ///< Configured PHY operation mode by SW register
|
||||
#define PHY_MODE_MANUAL 0 ///< Configured PHY operation mode with user setting.
|
||||
#define PHY_MODE_AUTONEGO 1 ///< Configured PHY operation mode with auto-negotiation
|
||||
#define PHY_SPEED_10 0 ///< Link Speed 10
|
||||
#define PHY_SPEED_100 1 ///< Link Speed 100
|
||||
#define PHY_DUPLEX_HALF 0 ///< Link Half-Duplex
|
||||
#define PHY_DUPLEX_FULL 1 ///< Link Full-Duplex
|
||||
#define PHY_LINK_OFF 0 ///< Link Off
|
||||
#define PHY_LINK_ON 1 ///< Link On
|
||||
#define PHY_POWER_NORM 0 ///< PHY power normal mode
|
||||
#define PHY_POWER_DOWN 1 ///< PHY power down mode
|
||||
|
||||
|
||||
#if _WIZCHIP_ == W5100S || _WIZCHIP_ == W5500
|
||||
/**
|
||||
* @ingroup DATA_TYPE
|
||||
* It configures PHY configuration when CW_SET PHYCONF or CW_GET_PHYCONF in W5500,
|
||||
* and it indicates the real PHY status configured by HW or SW in all WIZCHIP. \n
|
||||
* Valid only in W5500.
|
||||
*/
|
||||
typedef struct wiz_PhyConf_t
|
||||
{
|
||||
uint8_t by; ///< set by @ref PHY_CONFBY_HW or @ref PHY_CONFBY_SW
|
||||
uint8_t mode; ///< set by @ref PHY_MODE_MANUAL or @ref PHY_MODE_AUTONEGO
|
||||
uint8_t speed; ///< set by @ref PHY_SPEED_10 or @ref PHY_SPEED_100
|
||||
uint8_t duplex; ///< set by @ref PHY_DUPLEX_HALF @ref PHY_DUPLEX_FULL
|
||||
//uint8_t power; ///< set by @ref PHY_POWER_NORM or @ref PHY_POWER_DOWN
|
||||
//uint8_t link; ///< Valid only in CW_GET_PHYSTATUS. set by @ref PHY_LINK_ON or PHY_DUPLEX_OFF
|
||||
}wiz_PhyConf;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @ingroup DATA_TYPE
|
||||
* It used in setting dhcp_mode of @ref wiz_NetInfo.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
NETINFO_STATIC = 1, ///< Static IP configuration by manually.
|
||||
NETINFO_DHCP ///< Dynamic IP configruation from a DHCP sever
|
||||
}dhcp_mode;
|
||||
|
||||
/**
|
||||
* @ingroup DATA_TYPE
|
||||
* Network Information for WIZCHIP
|
||||
*/
|
||||
typedef struct wiz_NetInfo_t
|
||||
{
|
||||
uint8_t mac[6]; ///< Source Mac Address
|
||||
uint8_t ip[4]; ///< Source IP Address
|
||||
uint8_t sn[4]; ///< Subnet Mask
|
||||
uint8_t gw[4]; ///< Gateway IP Address
|
||||
uint8_t dns[4]; ///< DNS server IP Address
|
||||
dhcp_mode dhcp; ///< 1 - Static, 2 - DHCP
|
||||
}wiz_NetInfo;
|
||||
|
||||
/**
|
||||
* @ingroup DATA_TYPE
|
||||
* Network mode
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
#if _WIZCHIP_ == W5500
|
||||
NM_FORCEARP = (1<<1), ///< Force to APP send whenever udp data is sent. Valid only in W5500
|
||||
#endif
|
||||
NM_WAKEONLAN = (1<<5), ///< Wake On Lan
|
||||
NM_PINGBLOCK = (1<<4), ///< Block ping-request
|
||||
NM_PPPOE = (1<<3), ///< PPPoE mode
|
||||
}netmode_type;
|
||||
|
||||
/**
|
||||
* @ingroup DATA_TYPE
|
||||
* Used in CN_SET_TIMEOUT or CN_GET_TIMEOUT of @ref ctlwizchip() for timeout configruation.
|
||||
*/
|
||||
typedef struct wiz_NetTimeout_t
|
||||
{
|
||||
uint8_t retry_cnt; ///< retry count
|
||||
uint16_t time_100us; ///< time unit 100us
|
||||
}wiz_NetTimeout;
|
||||
|
||||
/**
|
||||
*@brief Registers call back function for critical section of I/O functions such as
|
||||
*\ref WIZCHIP_READ, @ref WIZCHIP_WRITE, @ref WIZCHIP_READ_BUF and @ref WIZCHIP_WRITE_BUF.
|
||||
*@param cris_en : callback function for critical section enter.
|
||||
*@param cris_ex : callback function for critical section exit.
|
||||
*@todo Describe @ref WIZCHIP_CRITICAL_ENTER and @ref WIZCHIP_CRITICAL_EXIT marco or register your functions.
|
||||
*@note If you do not describe or register, default functions(@ref wizchip_cris_enter & @ref wizchip_cris_exit) is called.
|
||||
*/
|
||||
void reg_wizchip_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void));
|
||||
|
||||
|
||||
/**
|
||||
*@brief Registers call back function for WIZCHIP select & deselect.
|
||||
*@param cs_sel : callback function for WIZCHIP select
|
||||
*@param cs_desel : callback fucntion for WIZCHIP deselect
|
||||
*@todo Describe @ref wizchip_cs_select and @ref wizchip_cs_deselect function or register your functions.
|
||||
*@note If you do not describe or register, null function is called.
|
||||
*/
|
||||
void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void));
|
||||
|
||||
/**
|
||||
*@brief Registers call back function for bus interface.
|
||||
*@param bus_rb : callback function to read byte data using system bus
|
||||
*@param bus_wb : callback function to write byte data using system bus
|
||||
*@todo Describe @ref wizchip_bus_readbyte and @ref wizchip_bus_writebyte function
|
||||
*or register your functions.
|
||||
*@note If you do not describe or register, null function is called.
|
||||
*/
|
||||
//M20150601 : For integrating with W5300
|
||||
//void reg_wizchip_bus_cbfunc(uint8_t (*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, uint8_t wb));
|
||||
void reg_wizchip_bus_cbfunc(iodata_t (*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, iodata_t wb));
|
||||
|
||||
/**
|
||||
*@brief Registers call back function for SPI interface.
|
||||
*@param spi_rb : callback function to read byte using SPI
|
||||
*@param spi_wb : callback function to write byte using SPI
|
||||
*@todo Describe \ref wizchip_spi_readbyte and \ref wizchip_spi_writebyte function
|
||||
*or register your functions.
|
||||
*@note If you do not describe or register, null function is called.
|
||||
*/
|
||||
void reg_wizchip_spi_cbfunc(uint8_t (*spi_rb)(void), void (*spi_wb)(uint8_t wb));
|
||||
|
||||
/**
|
||||
*@brief Registers call back function for SPI interface.
|
||||
*@param spi_rb : callback function to burst read using SPI
|
||||
*@param spi_wb : callback function to burst write using SPI
|
||||
*@todo Describe \ref wizchip_spi_readbyte and \ref wizchip_spi_writebyte function
|
||||
*or register your functions.
|
||||
*@note If you do not describe or register, null function is called.
|
||||
*/
|
||||
void reg_wizchip_spiburst_cbfunc(void (*spi_rb)(uint8_t* pBuf, uint16_t len), void (*spi_wb)(uint8_t* pBuf, uint16_t len));
|
||||
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Controls to the WIZCHIP.
|
||||
* @details Resets WIZCHIP & internal PHY, Configures PHY mode, Monitor PHY(Link,Speed,Half/Full/Auto),
|
||||
* controls interrupt & mask and so on.
|
||||
* @param cwtype : Decides to the control type
|
||||
* @param arg : arg type is dependent on cwtype.
|
||||
* @return 0 : Success \n
|
||||
* -1 : Fail because of invalid \ref ctlwizchip_type or unsupported \ref ctlwizchip_type in WIZCHIP
|
||||
*/
|
||||
int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg);
|
||||
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Controls to network.
|
||||
* @details Controls to network environment, mode, timeout and so on.
|
||||
* @param cntype : Input. Decides to the control type
|
||||
* @param arg : Inout. arg type is dependent on cntype.
|
||||
* @return -1 : Fail because of invalid \ref ctlnetwork_type or unsupported \ref ctlnetwork_type in WIZCHIP \n
|
||||
* 0 : Success
|
||||
*/
|
||||
int8_t ctlnetwork(ctlnetwork_type cntype, void* arg);
|
||||
|
||||
|
||||
/*
|
||||
* The following functions are implemented for internal use.
|
||||
* but You can call these functions for code size reduction instead of ctlwizchip() and ctlnetwork().
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Reset WIZCHIP by softly.
|
||||
*/
|
||||
void wizchip_sw_reset(void);
|
||||
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Initializes WIZCHIP with socket buffer size
|
||||
* @param txsize Socket tx buffer sizes. If null, initialized the default size 2KB.
|
||||
* @param rxsize Socket rx buffer sizes. If null, initialized the default size 2KB.
|
||||
* @return 0 : succcess \n
|
||||
* -1 : fail. Invalid buffer size
|
||||
*/
|
||||
int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize);
|
||||
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Clear Interrupt of WIZCHIP.
|
||||
* @param intr : @ref intr_kind value operated OR. It can type-cast to uint16_t.
|
||||
*/
|
||||
void wizchip_clrinterrupt(intr_kind intr);
|
||||
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Get Interrupt of WIZCHIP.
|
||||
* @return @ref intr_kind value operated OR. It can type-cast to uint16_t.
|
||||
*/
|
||||
intr_kind wizchip_getinterrupt(void);
|
||||
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Mask or Unmask Interrupt of WIZCHIP.
|
||||
* @param intr : @ref intr_kind value operated OR. It can type-cast to uint16_t.
|
||||
*/
|
||||
void wizchip_setinterruptmask(intr_kind intr);
|
||||
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Get Interrupt mask of WIZCHIP.
|
||||
* @return : The operated OR vaule of @ref intr_kind. It can type-cast to uint16_t.
|
||||
*/
|
||||
intr_kind wizchip_getinterruptmask(void);
|
||||
|
||||
//todo
|
||||
#if _WIZCHIP_ > W5100
|
||||
int8_t wizphy_getphylink(void); ///< get the link status of phy in WIZCHIP. No use in W5100
|
||||
int8_t wizphy_getphypmode(void); ///< get the power mode of PHY in WIZCHIP. No use in W5100
|
||||
#endif
|
||||
|
||||
#if _WIZCHIP_ == W5100S || _WIZCHIP_ == W5500
|
||||
void wizphy_reset(void); ///< Reset phy. Vailid only in W5500
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Set the phy information for WIZCHIP without power mode
|
||||
* @param phyconf : @ref wiz_PhyConf
|
||||
*/
|
||||
void wizphy_setphyconf(wiz_PhyConf* phyconf);
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Get phy configuration information.
|
||||
* @param phyconf : @ref wiz_PhyConf
|
||||
*/
|
||||
void wizphy_getphyconf(wiz_PhyConf* phyconf);
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Get phy status.
|
||||
* @param phyconf : @ref wiz_PhyConf
|
||||
*/
|
||||
void wizphy_getphystat(wiz_PhyConf* phyconf);
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief set the power mode of phy inside WIZCHIP. Refer to @ref PHYCFGR in W5500, @ref PHYSTATUS in W5200
|
||||
* @param pmode Settig value of power down mode.
|
||||
*/
|
||||
int8_t wizphy_setphypmode(uint8_t pmode);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Set the network information for WIZCHIP
|
||||
* @param pnetinfo : @ref wizNetInfo
|
||||
*/
|
||||
void wizchip_setnetinfo(wiz_NetInfo* pnetinfo);
|
||||
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Get the network information for WIZCHIP
|
||||
* @param pnetinfo : @ref wizNetInfo
|
||||
*/
|
||||
void wizchip_getnetinfo(wiz_NetInfo* pnetinfo);
|
||||
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Set the network mode such WOL, PPPoE, Ping Block, and etc.
|
||||
* @param pnetinfo Value of network mode. Refer to @ref netmode_type.
|
||||
*/
|
||||
int8_t wizchip_setnetmode(netmode_type netmode);
|
||||
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Get the network mode such WOL, PPPoE, Ping Block, and etc.
|
||||
* @return Value of network mode. Refer to @ref netmode_type.
|
||||
*/
|
||||
netmode_type wizchip_getnetmode(void);
|
||||
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Set retry time value(@ref _RTR_) and retry count(@ref _RCR_).
|
||||
* @details @ref _RTR_ configures the retransmission timeout period and @ref _RCR_ configures the number of time of retransmission.
|
||||
* @param nettime @ref _RTR_ value and @ref _RCR_ value. Refer to @ref wiz_NetTimeout.
|
||||
*/
|
||||
void wizchip_settimeout(wiz_NetTimeout* nettime);
|
||||
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Get retry time value(@ref _RTR_) and retry count(@ref _RCR_).
|
||||
* @details @ref _RTR_ configures the retransmission timeout period and @ref _RCR_ configures the number of time of retransmission.
|
||||
* @param nettime @ref _RTR_ value and @ref _RCR_ value. Refer to @ref wiz_NetTimeout.
|
||||
*/
|
||||
void wizchip_gettimeout(wiz_NetTimeout* nettime);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _WIZCHIP_CONF_H_
|
||||
@ -0,0 +1,538 @@
|
||||
/*
|
||||
* Copyright (c) 2014 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Allan Stockdill-Mander/Ian Craggs - initial API and implementation and/or initial documentation
|
||||
*******************************************************************************/
|
||||
#include "MQTTClient.h"
|
||||
//#include <terminal_io.h>
|
||||
|
||||
|
||||
void NewMessageData(MessageData* md, MQTTString* aTopicName, MQTTMessage* aMessgage)
|
||||
{
|
||||
md->topicName = aTopicName;
|
||||
md->message = aMessgage;
|
||||
}
|
||||
|
||||
int32_t getNextPacketId(Client *c)
|
||||
{
|
||||
return c->next_packetid = (c->next_packetid == MAX_PACKET_ID) ? 1 : c->next_packetid + 1;
|
||||
}
|
||||
|
||||
int32_t sendPacket(Client* c, int32_t length, Timer* timer)
|
||||
{
|
||||
int32_t rc = FAILURE, sent = 0;
|
||||
|
||||
while (sent < length && !expired(timer))
|
||||
{
|
||||
rc = c->ipstack->mqttwrite(c->ipstack, &c->buf[sent], length, left_ms(timer));
|
||||
|
||||
if (rc < 0) // there was an error writing the data
|
||||
break;
|
||||
|
||||
sent += rc;
|
||||
}
|
||||
|
||||
if (sent == length)
|
||||
{
|
||||
countdown(&c->ping_timer, c->keepAliveInterval); // record the fact that we have SUCCESSSfully sent the packet
|
||||
rc = SUCCESSS;
|
||||
}
|
||||
else
|
||||
rc = FAILURE;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
void MQTTClient(Client* c, Network* network, uint32_t command_timeout_ms, uint8_t* buf, size_t buf_size, uint8_t* readbuf, size_t readbuf_size)
|
||||
{
|
||||
c->ipstack = network;
|
||||
|
||||
for (int32_t i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
|
||||
c->messageHandlers[i].topicFilter = 0;
|
||||
|
||||
c->command_timeout_ms = command_timeout_ms;
|
||||
c->buf = buf;
|
||||
c->buf_size = buf_size;
|
||||
c->readbuf = readbuf;
|
||||
c->readbuf_size = readbuf_size;
|
||||
c->isconnected = 0;
|
||||
c->ping_outstanding = 0;
|
||||
c->defaultMessageHandler = NULL;
|
||||
|
||||
InitTimer(&c->ping_timer);
|
||||
}
|
||||
|
||||
|
||||
int32_t decodePacket(Client* c, int32_t* value, int32_t timeout)
|
||||
{
|
||||
uint8_t i;
|
||||
int32_t multiplier = 1;
|
||||
int32_t len = 0;
|
||||
const int MAX_NO_OF_REMAINING_LENGTH_BYTES = 4;
|
||||
|
||||
*value = 0;
|
||||
do
|
||||
{
|
||||
int32_t rc = MQTTPACKET_READ_ERROR;
|
||||
|
||||
if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES)
|
||||
{
|
||||
rc = MQTTPACKET_READ_ERROR; /* bad data */
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = c->ipstack->mqttread(c->ipstack, &i, 1, timeout);
|
||||
|
||||
if (rc != 1)
|
||||
goto exit;
|
||||
|
||||
*value += (i & 127) * multiplier;
|
||||
multiplier *= 128;
|
||||
} while ((i & 128) != 0);
|
||||
exit:
|
||||
return len;
|
||||
}
|
||||
|
||||
int32_t readPacket(Client* c, Timer* timer)
|
||||
{
|
||||
int32_t rc = FAILURE;
|
||||
MQTTHeader header = {0};
|
||||
int32_t len = 0;
|
||||
int32_t rem_len = 0;
|
||||
|
||||
/* 1. read the header byte. This has the packet type in it */
|
||||
if (c->ipstack->mqttread(c->ipstack, c->readbuf, 1, left_ms(timer)) != 1)
|
||||
goto exit;
|
||||
|
||||
len = 1;
|
||||
/* 2. read the remaining length. This is variable in itself */
|
||||
decodePacket(c, &rem_len, left_ms(timer));
|
||||
len += MQTTPacket_encode(c->readbuf + 1, rem_len); /* put the original remaining length back into the buffer */
|
||||
|
||||
/* 3. read the rest of the buffer using a callback to supply the rest of the data */
|
||||
if (rem_len > 0 && (c->ipstack->mqttread(c->ipstack, c->readbuf + len, rem_len, left_ms(timer)) != rem_len))
|
||||
goto exit;
|
||||
|
||||
header.byte = c->readbuf[0];
|
||||
rc = header.bits.type;
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
// assume topic filter and name is in correct format
|
||||
// # can only be at end
|
||||
// + and # can only be next to separator
|
||||
char isTopicMatched(char* topicFilter, MQTTString* topicName)
|
||||
{
|
||||
char* curf = topicFilter;
|
||||
char* curn = topicName->lenstring.data;
|
||||
char* curn_end = curn + topicName->lenstring.len;
|
||||
|
||||
while (*curf && curn < curn_end)
|
||||
{
|
||||
if (*curn == '/' && *curf != '/')
|
||||
break;
|
||||
|
||||
if (*curf != '+' && *curf != '#' && *curf != *curn)
|
||||
break;
|
||||
|
||||
if (*curf == '+')
|
||||
{ // skip until we meet the next separator, or end of string
|
||||
char* nextpos = curn + 1;
|
||||
|
||||
while (nextpos < curn_end && *nextpos != '/')
|
||||
nextpos = ++curn + 1;
|
||||
}
|
||||
else if (*curf == '#')
|
||||
curn = curn_end - 1; // skip until end of string
|
||||
|
||||
curf++;
|
||||
curn++;
|
||||
}
|
||||
|
||||
return (curn == curn_end) && (*curf == '\0');
|
||||
}
|
||||
|
||||
int32_t deliverMessage(Client* c, MQTTString* topicName, MQTTMessage* message)
|
||||
{
|
||||
int32_t rc = FAILURE;
|
||||
|
||||
// we have to find the right message handler - indexed by topic
|
||||
for (int32_t i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
|
||||
{
|
||||
if (c->messageHandlers[i].topicFilter != 0 && (MQTTPacket_equals(topicName, (char*)c->messageHandlers[i].topicFilter) ||
|
||||
isTopicMatched((char*)c->messageHandlers[i].topicFilter, topicName)))
|
||||
{
|
||||
if (c->messageHandlers[i].fp != NULL)
|
||||
{
|
||||
MessageData md;
|
||||
NewMessageData(&md, topicName, message);
|
||||
c->messageHandlers[i].fp(&md);
|
||||
rc = SUCCESSS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rc == FAILURE && c->defaultMessageHandler != NULL)
|
||||
{
|
||||
MessageData md;
|
||||
NewMessageData(&md, topicName, message);
|
||||
c->defaultMessageHandler(&md);
|
||||
rc = SUCCESSS;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int32_t keepalive(Client* c)
|
||||
{
|
||||
int32_t rc = FAILURE;
|
||||
|
||||
if (c->keepAliveInterval == 0)
|
||||
{
|
||||
rc = SUCCESSS;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (expired(&c->ping_timer))
|
||||
{
|
||||
if (!c->ping_outstanding)
|
||||
{
|
||||
Timer timer;
|
||||
InitTimer(&timer);
|
||||
countdown_ms(&timer, 1000);
|
||||
int32_t len = MQTTSerialize_pingreq(c->buf, c->buf_size);
|
||||
|
||||
if (len > 0 && (rc = sendPacket(c, len, &timer)) == SUCCESSS) // send the ping packet
|
||||
c->ping_outstanding = 1;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int32_t cycle(Client* c, Timer* timer)
|
||||
{
|
||||
// read the socket, see what work is due
|
||||
uint16_t packet_type = readPacket(c, timer);
|
||||
|
||||
int32_t len = 0, rc = SUCCESSS;
|
||||
|
||||
switch (packet_type)
|
||||
{
|
||||
case CONNACK:
|
||||
case PUBACK:
|
||||
case SUBACK:
|
||||
break;
|
||||
case PUBLISH:
|
||||
{
|
||||
MQTTString topicName;
|
||||
MQTTMessage msg;
|
||||
|
||||
if (MQTTDeserialize_publish((uint8_t*)&msg.dup, (uint8_t*)&msg.qos, (uint8_t*)&msg.retained, (uint16_t*)&msg.id, &topicName,
|
||||
(uint8_t**)&msg.payload, (int32_t*)&msg.payloadlen, c->readbuf, c->readbuf_size) != 1)
|
||||
goto exit;
|
||||
|
||||
deliverMessage(c, &topicName, &msg);
|
||||
|
||||
if (msg.qos != QOS0)
|
||||
{
|
||||
if (msg.qos == QOS1)
|
||||
len = MQTTSerialize_ack(c->buf, c->buf_size, PUBACK, 0, msg.id);
|
||||
else if (msg.qos == QOS2)
|
||||
len = MQTTSerialize_ack(c->buf, c->buf_size, PUBREC, 0, msg.id);
|
||||
|
||||
if (len <= 0)
|
||||
rc = FAILURE;
|
||||
else
|
||||
rc = sendPacket(c, len, timer);
|
||||
|
||||
if (rc == FAILURE)
|
||||
goto exit; // there was a problem
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PUBREC:
|
||||
{
|
||||
uint16_t mypacketid;
|
||||
uint8_t dup, type;
|
||||
|
||||
if (MQTTDeserialize_ack(&type, &dup, &mypacketid, c->readbuf, c->readbuf_size) != 1)
|
||||
rc = FAILURE;
|
||||
else if ((len = MQTTSerialize_ack(c->buf, c->buf_size, PUBREL, 0, mypacketid)) <= 0)
|
||||
rc = FAILURE;
|
||||
else if ((rc = sendPacket(c, len, timer)) != SUCCESSS) // send the PUBREL packet
|
||||
rc = FAILURE; // there was a problem
|
||||
|
||||
if (rc == FAILURE)
|
||||
goto exit; // there was a problem
|
||||
|
||||
break;
|
||||
}
|
||||
case PUBCOMP:
|
||||
break;
|
||||
case PINGRESP:
|
||||
c->ping_outstanding = 0;
|
||||
break;
|
||||
}
|
||||
keepalive(c);
|
||||
exit:
|
||||
if (rc == SUCCESSS)
|
||||
rc = packet_type;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int32_t MQTTYield(Client* c, int32_t timeout_ms)
|
||||
{
|
||||
int32_t rc = SUCCESSS;
|
||||
Timer timer;
|
||||
|
||||
InitTimer(&timer);
|
||||
countdown_ms(&timer, timeout_ms);
|
||||
|
||||
while (!expired(&timer))
|
||||
{
|
||||
if (cycle(c, &timer) == FAILURE)
|
||||
{
|
||||
rc = FAILURE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
// only used in single-threaded mode where one command at a time is in process
|
||||
int32_t waitfor(Client* c, int32_t packet_type, Timer* timer)
|
||||
{
|
||||
int32_t rc = FAILURE;
|
||||
|
||||
do
|
||||
{
|
||||
if (expired(timer))
|
||||
break; // we timed out
|
||||
}
|
||||
while ((rc = cycle(c, timer)) != packet_type);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int32_t MQTTConnect(Client* c, MQTTPacket_connectData* options)
|
||||
{
|
||||
Timer connect_timer;
|
||||
int32_t rc = FAILURE;
|
||||
MQTTPacket_connectData default_options = MQTTPacket_connectData_initializer;
|
||||
int32_t len = 0;
|
||||
|
||||
InitTimer(&connect_timer);
|
||||
countdown_ms(&connect_timer, c->command_timeout_ms);
|
||||
|
||||
if (c->isconnected) // don't send connect packet again if we are already connected
|
||||
goto exit;
|
||||
|
||||
if (options == 0)
|
||||
options = &default_options; // set default options if none were supplied
|
||||
|
||||
c->keepAliveInterval = options->keepAliveInterval;
|
||||
countdown(&c->ping_timer, c->keepAliveInterval);
|
||||
|
||||
if ((len = MQTTSerialize_connect(c->buf, c->buf_size, options)) <= 0)
|
||||
goto exit;
|
||||
|
||||
if ((rc = sendPacket(c, len, &connect_timer)) != SUCCESSS) // send the connect packet
|
||||
goto exit; // there was a problem
|
||||
|
||||
// this will be a blocking call, wait for the connack
|
||||
if (waitfor(c, CONNACK, &connect_timer) == CONNACK)
|
||||
{
|
||||
uint8_t connack_rc = 255;
|
||||
int8_t sessionPresent = 0;
|
||||
|
||||
if (MQTTDeserialize_connack((uint8_t*)&sessionPresent, &connack_rc, c->readbuf, c->readbuf_size) == 1)
|
||||
rc = connack_rc;
|
||||
else
|
||||
rc = FAILURE;
|
||||
}
|
||||
else
|
||||
rc = FAILURE;
|
||||
|
||||
exit:
|
||||
if (rc == SUCCESSS)
|
||||
c->isconnected = 1;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int32_t MQTTSubscribe(Client* c, const char* topicFilter, enum QoS qos, messageHandler messageHandler)
|
||||
{
|
||||
int32_t rc = FAILURE;
|
||||
Timer timer;
|
||||
int32_t len = 0;
|
||||
MQTTString topic = MQTTString_initializer;
|
||||
topic.cstring = (char *)topicFilter;
|
||||
|
||||
InitTimer(&timer);
|
||||
countdown_ms(&timer, c->command_timeout_ms);
|
||||
|
||||
if (!c->isconnected)
|
||||
goto exit;
|
||||
|
||||
len = MQTTSerialize_subscribe(c->buf, c->buf_size, 0, getNextPacketId(c), 1, &topic, (int32_t*)&qos);
|
||||
|
||||
if (len <= 0)
|
||||
goto exit;
|
||||
|
||||
if ((rc = sendPacket(c, len, &timer)) != SUCCESSS) // send the subscribe packet
|
||||
goto exit; // there was a problem
|
||||
|
||||
if (waitfor(c, SUBACK, &timer) == SUBACK) // wait for suback
|
||||
{
|
||||
int32_t count = 0, grantedQoS = -1;
|
||||
uint16_t mypacketid;
|
||||
|
||||
if (MQTTDeserialize_suback(&mypacketid, 1, &count, &grantedQoS, c->readbuf, c->readbuf_size) == 1)
|
||||
rc = grantedQoS; // 0, 1, 2 or 0x80
|
||||
|
||||
if (rc != 0x80)
|
||||
{
|
||||
for (int32_t i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
|
||||
{
|
||||
if (c->messageHandlers[i].topicFilter == 0)
|
||||
{
|
||||
c->messageHandlers[i].topicFilter = topicFilter;
|
||||
c->messageHandlers[i].fp = messageHandler;
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
rc = FAILURE;
|
||||
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int32_t MQTTUnsubscribe(Client* c, const char* topicFilter)
|
||||
{
|
||||
int32_t rc = FAILURE;
|
||||
Timer timer;
|
||||
MQTTString topic = MQTTString_initializer;
|
||||
topic.cstring = (char *)topicFilter;
|
||||
int32_t len = 0;
|
||||
|
||||
InitTimer(&timer);
|
||||
countdown_ms(&timer, c->command_timeout_ms);
|
||||
|
||||
if (!c->isconnected)
|
||||
goto exit;
|
||||
|
||||
if ((len = MQTTSerialize_unsubscribe(c->buf, c->buf_size, 0, getNextPacketId(c), 1, &topic)) <= 0)
|
||||
goto exit;
|
||||
|
||||
if ((rc = sendPacket(c, len, &timer)) != SUCCESSS) // send the subscribe packet
|
||||
goto exit; // there was a problem
|
||||
|
||||
if (waitfor(c, UNSUBACK, &timer) == UNSUBACK)
|
||||
{
|
||||
uint16_t mypacketid; // should be the same as the packetid above
|
||||
|
||||
if (MQTTDeserialize_unsuback(&mypacketid, c->readbuf, c->readbuf_size) == 1)
|
||||
rc = 0;
|
||||
}
|
||||
else
|
||||
rc = FAILURE;
|
||||
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int32_t MQTTPublish(Client* c, const char* topicName, MQTTMessage* message)
|
||||
{
|
||||
int32_t rc = FAILURE;
|
||||
Timer timer;
|
||||
MQTTString topic = MQTTString_initializer;
|
||||
topic.cstring = (char *)topicName;
|
||||
int32_t len = 0;
|
||||
|
||||
InitTimer(&timer);
|
||||
countdown_ms(&timer, c->command_timeout_ms);
|
||||
|
||||
if (!c->isconnected)
|
||||
goto exit;
|
||||
|
||||
if (message->qos == QOS1 || message->qos == QOS2)
|
||||
message->id = getNextPacketId(c);
|
||||
|
||||
len = MQTTSerialize_publish(c->buf, c->buf_size, 0, message->qos, message->retained, message->id,
|
||||
topic, (uint8_t*)message->payload, message->payloadlen);
|
||||
|
||||
if (len <= 0)
|
||||
goto exit;
|
||||
|
||||
if ((rc = sendPacket(c, len, &timer)) != SUCCESSS) // send the subscribe packet
|
||||
goto exit; // there was a problem
|
||||
|
||||
if (message->qos == QOS1)
|
||||
{
|
||||
if (waitfor(c, PUBACK, &timer) == PUBACK)
|
||||
{
|
||||
uint16_t mypacketid;
|
||||
uint8_t dup, type;
|
||||
|
||||
if (MQTTDeserialize_ack(&type, &dup, &mypacketid, c->readbuf, c->readbuf_size) != 1)
|
||||
rc = FAILURE;
|
||||
}
|
||||
else
|
||||
rc = FAILURE;
|
||||
}
|
||||
else if (message->qos == QOS2)
|
||||
{
|
||||
if (waitfor(c, PUBCOMP, &timer) == PUBCOMP)
|
||||
{
|
||||
uint16_t mypacketid;
|
||||
uint8_t dup, type;
|
||||
|
||||
if (MQTTDeserialize_ack(&type, &dup, &mypacketid, c->readbuf, c->readbuf_size) != 1)
|
||||
rc = FAILURE;
|
||||
}
|
||||
else
|
||||
rc = FAILURE;
|
||||
}
|
||||
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int32_t MQTTDisconnect(Client* c)
|
||||
{
|
||||
int32_t rc = FAILURE;
|
||||
Timer timer; // we might wait for incomplete incoming publishes to complete
|
||||
int32_t len = MQTTSerialize_disconnect(c->buf, c->buf_size);
|
||||
|
||||
InitTimer(&timer);
|
||||
countdown_ms(&timer, c->command_timeout_ms);
|
||||
|
||||
if (len > 0)
|
||||
rc = sendPacket(c, len, &timer); // send the disconnect packet
|
||||
|
||||
c->isconnected = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) 2014 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Allan Stockdill-Mander/Ian Craggs - initial API and implementation and/or initial documentation
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __MQTT_CLIENT_C_
|
||||
#define __MQTT_CLIENT_C_
|
||||
|
||||
#include "MQTTPacket.h"
|
||||
#include "mqtt_interface.h" //Platform specific implementation header file
|
||||
#include "stdio.h"
|
||||
|
||||
#define MAX_PACKET_ID 65535
|
||||
#define MAX_MESSAGE_HANDLERS 5
|
||||
|
||||
enum QoS
|
||||
{
|
||||
QOS0,
|
||||
QOS1,
|
||||
QOS2
|
||||
};
|
||||
|
||||
// all failure return codes must be negative
|
||||
enum returnCode
|
||||
{
|
||||
BUFFER_OVERFLOW = -2,
|
||||
FAILURE = -1,
|
||||
SUCCESSS = 0
|
||||
};
|
||||
|
||||
void NewTimer(Timer*);
|
||||
|
||||
typedef struct MQTTMessage MQTTMessage;
|
||||
|
||||
typedef struct MessageData MessageData;
|
||||
|
||||
struct MQTTMessage
|
||||
{
|
||||
enum QoS qos;
|
||||
char retained;
|
||||
char dup;
|
||||
uint16_t id;
|
||||
void *payload;
|
||||
size_t payloadlen;
|
||||
};
|
||||
|
||||
struct MessageData
|
||||
{
|
||||
MQTTMessage* message;
|
||||
MQTTString* topicName;
|
||||
};
|
||||
|
||||
typedef void (*messageHandler)(MessageData*);
|
||||
|
||||
typedef struct Client Client;
|
||||
|
||||
int32_t MQTTConnect (Client*, MQTTPacket_connectData*);
|
||||
int32_t MQTTPublish (Client*, const char*, MQTTMessage*);
|
||||
int32_t MQTTSubscribe (Client*, const char*, enum QoS, messageHandler);
|
||||
int32_t MQTTUnsubscribe (Client*, const char*);
|
||||
int32_t MQTTDisconnect (Client*);
|
||||
int32_t MQTTYield (Client*, int32_t);
|
||||
|
||||
void setDefaultMessageHandler(Client*, messageHandler);
|
||||
|
||||
void MQTTClient(Client*, Network*, uint32_t, unsigned char*, size_t, unsigned char*, size_t);
|
||||
|
||||
struct Client
|
||||
{
|
||||
uint32_t next_packetid;
|
||||
uint32_t command_timeout_ms;
|
||||
size_t buf_size, readbuf_size;
|
||||
uint8_t *buf;
|
||||
uint8_t *readbuf;
|
||||
uint32_t keepAliveInterval;
|
||||
int8_t ping_outstanding;
|
||||
int32_t isconnected;
|
||||
|
||||
struct MessageHandlers
|
||||
{
|
||||
const char* topicFilter;
|
||||
void (*fp) (MessageData*);
|
||||
} messageHandlers[MAX_MESSAGE_HANDLERS]; // Message handlers are indexed by subscription topic
|
||||
|
||||
void (*defaultMessageHandler) (MessageData*);
|
||||
|
||||
Network* ipstack;
|
||||
Timer ping_timer;
|
||||
};
|
||||
|
||||
#define DefaultClient {0, 0, 0, 0, NULL, NULL, 0, 0, 0}
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (c) 2014 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||
* Xiang Rong - 442039 Add makefile to Embedded C client
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef MQTTCONNECT_H_
|
||||
#define MQTTCONNECT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#if !defined(DLLImport)
|
||||
#define DLLImport
|
||||
#endif
|
||||
#if !defined(DLLExport)
|
||||
#define DLLExport
|
||||
#endif
|
||||
|
||||
|
||||
typedef union
|
||||
{
|
||||
uint8_t all; /**< all connect flags */
|
||||
#if defined(REVERSED)
|
||||
struct
|
||||
{
|
||||
uint8_t username : 1; /**< 3.1 user name */
|
||||
uint8_t password : 1; /**< 3.1 password */
|
||||
uint8_t willRetain : 1; /**< will retain setting */
|
||||
uint8_t willQoS : 2; /**< will QoS value */
|
||||
uint8_t will : 1; /**< will flag */
|
||||
uint8_t cleansession: 1; /**< clean session flag */
|
||||
uint8_t : 1; /**< unused */
|
||||
} bits;
|
||||
#else
|
||||
struct
|
||||
{
|
||||
uint8_t : 1; /**< unused */
|
||||
uint8_t cleansession: 1; /**< cleansession flag */
|
||||
uint8_t will : 1; /**< will flag */
|
||||
uint8_t willQoS : 2; /**< will QoS value */
|
||||
uint8_t willRetain : 1; /**< will retain setting */
|
||||
uint8_t password : 1; /**< 3.1 password */
|
||||
uint8_t username : 1; /**< 3.1 user name */
|
||||
} bits;
|
||||
#endif
|
||||
} MQTTConnectFlags; /**< connect flags byte */
|
||||
|
||||
|
||||
|
||||
/** Defines the MQTT "Last Will and Testament" (LWT) settings for the connect packet. */
|
||||
typedef struct
|
||||
{
|
||||
/** The eyecatcher for this structure. must be MQTW. */
|
||||
int8_t struct_id[4];
|
||||
/** The version number of this structure. Must be 0 */
|
||||
int16_t struct_version;
|
||||
/** The LWT topic to which the LWT message will be published. */
|
||||
MQTTString topicName;
|
||||
/** The LWT payload. */
|
||||
MQTTString message;
|
||||
/** The retained flag for the LWT message (see MQTTAsync_message.retained). */
|
||||
uint8_t retained;
|
||||
/** The quality of service setting for the LWT message (see MQTTAsync_message.qos and @ref qos). */
|
||||
int8_t qos;
|
||||
} MQTTPacket_willOptions;
|
||||
|
||||
|
||||
#define MQTTPacket_willOptions_initializer { {'M', 'Q', 'T', 'W'}, 0, {NULL, {0, NULL}}, {NULL, {0, NULL}}, 0, 0 }
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/** The eyecatcher for this structure. must be MQTC. */
|
||||
int8_t struct_id[4];
|
||||
/** The version number of this structure. Must be 0 */
|
||||
uint16_t struct_version;
|
||||
/** Version of MQTT to be used. 3 = 3.1 4 = 3.1.1 */
|
||||
uint8_t MQTTVersion;
|
||||
MQTTString clientID;
|
||||
uint16_t keepAliveInterval;
|
||||
uint8_t cleansession;
|
||||
uint8_t willFlag;
|
||||
MQTTPacket_willOptions will;
|
||||
MQTTString username;
|
||||
MQTTString password;
|
||||
} MQTTPacket_connectData;
|
||||
|
||||
typedef union
|
||||
{
|
||||
unsigned char all; /**< all connack flags */
|
||||
#if defined(REVERSED)
|
||||
struct
|
||||
{
|
||||
uint8_t sessionpresent : 1; /**< session present flag */
|
||||
uint8_t : 7; /**< unused */
|
||||
} bits;
|
||||
#else
|
||||
struct
|
||||
{
|
||||
uint8_t : 7; /**< unused */
|
||||
uint8_t sessionpresent : 1; /**< session present flag */
|
||||
} bits;
|
||||
#endif
|
||||
} MQTTConnackFlags; /**< connack flags byte */
|
||||
|
||||
#define MQTTPacket_connectData_initializer { {'M', 'Q', 'T', 'C'}, 0, 4, {NULL, {0, NULL}}, 60, 1, 0, \
|
||||
MQTTPacket_willOptions_initializer, {NULL, {0, NULL}}, {NULL, {0, NULL}} }
|
||||
|
||||
DLLExport int32_t MQTTSerialize_connect(uint8_t* buf, int32_t buflen, MQTTPacket_connectData* options);
|
||||
DLLExport int32_t MQTTDeserialize_connect(MQTTPacket_connectData* data, uint8_t* buf, int32_t len);
|
||||
|
||||
DLLExport int32_t MQTTSerialize_connack(uint8_t* buf, int32_t buflen, uint8_t connack_rc, uint8_t sessionPresent);
|
||||
DLLExport int32_t MQTTDeserialize_connack(uint8_t* sessionPresent, uint8_t* connack_rc, uint8_t* buf, int32_t buflen);
|
||||
|
||||
DLLExport int32_t MQTTSerialize_disconnect(uint8_t* buf, int32_t buflen);
|
||||
DLLExport int32_t MQTTSerialize_pingreq(uint8_t* buf, int32_t buflen);
|
||||
|
||||
#endif /* MQTTCONNECT_H_ */
|
||||
@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright (c) 2014 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||
*******************************************************************************/
|
||||
|
||||
#include "MQTTPacket.h"
|
||||
#include "StackTrace.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* Determines the length of the MQTT connect packet that would be produced using the supplied connect options.
|
||||
* @param options the options to be used to build the connect packet
|
||||
* @return the length of buffer needed to contain the serialized version of the packet
|
||||
*/
|
||||
int32_t MQTTSerialize_connectLength(MQTTPacket_connectData* options)
|
||||
{
|
||||
int32_t len = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
|
||||
if (options->MQTTVersion == 3)
|
||||
len = 12; /* variable depending on MQTT or MQIsdp */
|
||||
else if (options->MQTTVersion == 4)
|
||||
len = 10;
|
||||
|
||||
len += MQTTstrlen(options->clientID) + 2;
|
||||
if (options->willFlag)
|
||||
len += MQTTstrlen(options->will.topicName) + 2 + MQTTstrlen(options->will.message) + 2;
|
||||
if (options->username.cstring || options->username.lenstring.data)
|
||||
len += MQTTstrlen(options->username)+2;
|
||||
if (options->password.cstring || options->password.lenstring.data)
|
||||
len += MQTTstrlen(options->password)+2;
|
||||
|
||||
FUNC_EXIT_RC(len);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes the connect options into the buffer.
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param len the length in bytes of the supplied buffer
|
||||
* @param options the options to be used to build the connect packet
|
||||
* @return serialized length, or error if 0
|
||||
*/
|
||||
int32_t MQTTSerialize_connect(uint8_t* buf, int32_t buflen, MQTTPacket_connectData* options)
|
||||
{
|
||||
uint8_t *ptr = buf;
|
||||
MQTTHeader header = {0};
|
||||
MQTTConnectFlags flags = {0};
|
||||
int32_t len = 0;
|
||||
int32_t rc = -1;
|
||||
|
||||
FUNC_ENTRY;
|
||||
if (MQTTPacket_len(len = MQTTSerialize_connectLength(options)) > buflen)
|
||||
{
|
||||
rc = MQTTPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
header.byte = 0;
|
||||
header.bits.type = CONNECT;
|
||||
writeChar(&ptr, header.byte); /* write header */
|
||||
|
||||
ptr += MQTTPacket_encode(ptr, len); /* write remaining length */
|
||||
|
||||
if (options->MQTTVersion == 4)
|
||||
{
|
||||
writeCString(&ptr, "MQTT");
|
||||
writeChar(&ptr, (char) 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
writeCString(&ptr, "MQIsdp");
|
||||
writeChar(&ptr, (char) 3);
|
||||
}
|
||||
|
||||
flags.all = 0;
|
||||
flags.bits.cleansession = options->cleansession;
|
||||
flags.bits.will = (options->willFlag) ? 1 : 0;
|
||||
|
||||
if (flags.bits.will)
|
||||
{
|
||||
flags.bits.willQoS = options->will.qos;
|
||||
flags.bits.willRetain = options->will.retained;
|
||||
}
|
||||
|
||||
if (options->username.cstring || options->username.lenstring.data)
|
||||
flags.bits.username = 1;
|
||||
if (options->password.cstring || options->password.lenstring.data)
|
||||
flags.bits.password = 1;
|
||||
|
||||
writeChar(&ptr, flags.all);
|
||||
writeInt(&ptr, options->keepAliveInterval);
|
||||
writeMQTTString(&ptr, options->clientID);
|
||||
|
||||
if (options->willFlag)
|
||||
{
|
||||
writeMQTTString(&ptr, options->will.topicName);
|
||||
writeMQTTString(&ptr, options->will.message);
|
||||
}
|
||||
|
||||
if (flags.bits.username)
|
||||
writeMQTTString(&ptr, options->username);
|
||||
if (flags.bits.password)
|
||||
writeMQTTString(&ptr, options->password);
|
||||
|
||||
rc = ptr - buf;
|
||||
|
||||
exit: FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into connack data - return code
|
||||
* @param sessionPresent the session present flag returned (only for MQTT 3.1.1)
|
||||
* @param connack_rc returned integer value of the connack return code
|
||||
* @param buf the raw buffer data, of the correct length determined by the remaining length field
|
||||
* @param len the length in bytes of the data in the supplied buffer
|
||||
* @return error code. 1 is success, 0 is failure
|
||||
*/
|
||||
int32_t MQTTDeserialize_connack(uint8_t* sessionPresent, uint8_t* connack_rc, uint8_t* buf, int32_t buflen)
|
||||
{
|
||||
MQTTHeader header = {0};
|
||||
uint8_t* curdata = buf;
|
||||
uint8_t* enddata = NULL;
|
||||
int32_t rc = 0;
|
||||
int32_t mylen;
|
||||
MQTTConnackFlags flags = {0};
|
||||
|
||||
FUNC_ENTRY;
|
||||
header.byte = readChar(&curdata);
|
||||
if (header.bits.type != CONNACK)
|
||||
goto exit;
|
||||
|
||||
curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
|
||||
enddata = curdata + mylen;
|
||||
if (enddata - curdata < 2)
|
||||
goto exit;
|
||||
|
||||
flags.all = readChar(&curdata);
|
||||
*sessionPresent = flags.bits.sessionpresent;
|
||||
*connack_rc = readChar(&curdata);
|
||||
|
||||
rc = 1;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes a 0-length packet into the supplied buffer, ready for writing to a socket
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param buflen the length in bytes of the supplied buffer, to avoid overruns
|
||||
* @param packettype the message type
|
||||
* @return serialized length, or error if 0
|
||||
*/
|
||||
int32_t MQTTSerialize_zero(uint8_t* buf, int32_t buflen, uint8_t packettype)
|
||||
{
|
||||
MQTTHeader header = {0};
|
||||
int32_t rc = -1;
|
||||
uint8_t *ptr = buf;
|
||||
|
||||
FUNC_ENTRY;
|
||||
if (buflen < 2)
|
||||
{
|
||||
rc = MQTTPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
header.byte = 0;
|
||||
header.bits.type = packettype;
|
||||
writeChar(&ptr, header.byte); /* write header */
|
||||
|
||||
ptr += MQTTPacket_encode(ptr, 0); /* write remaining length */
|
||||
rc = ptr - buf;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes a disconnect packet into the supplied buffer, ready for writing to a socket
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param buflen the length in bytes of the supplied buffer, to avoid overruns
|
||||
* @return serialized length, or error if 0
|
||||
*/
|
||||
int32_t MQTTSerialize_disconnect(uint8_t* buf, int32_t buflen)
|
||||
{
|
||||
return MQTTSerialize_zero(buf, buflen, DISCONNECT);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes a disconnect packet into the supplied buffer, ready for writing to a socket
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param buflen the length in bytes of the supplied buffer, to avoid overruns
|
||||
* @return serialized length, or error if 0
|
||||
*/
|
||||
int32_t MQTTSerialize_pingreq(uint8_t* buf, int32_t buflen)
|
||||
{
|
||||
return MQTTSerialize_zero(buf, buflen, PINGREQ);
|
||||
}
|
||||
@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright (c) 2014 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||
*******************************************************************************/
|
||||
|
||||
#include "StackTrace.h"
|
||||
#include "MQTTPacket.h"
|
||||
#include <string.h>
|
||||
|
||||
#define min(a, b) ((a < b) ? a : b)
|
||||
|
||||
|
||||
/**
|
||||
* Validates MQTT protocol name and version combinations
|
||||
* @param protocol the MQTT protocol name as an MQTTString
|
||||
* @param version the MQTT protocol version number, as in the connect packet
|
||||
* @return correct MQTT combination? 1 is true, 0 is false
|
||||
*/
|
||||
int32_t MQTTPacket_checkVersion(MQTTString* protocol, int32_t version)
|
||||
{
|
||||
int32_t rc = 0;
|
||||
|
||||
if (version == 3 && memcmp(protocol->lenstring.data, "MQIsdp", min(6, protocol->lenstring.len)) == 0)
|
||||
rc = 1;
|
||||
else if (version == 4 && memcmp(protocol->lenstring.data, "MQTT", min(4, protocol->lenstring.len)) == 0)
|
||||
rc = 1;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into connect data structure
|
||||
* @param data the connect data structure to be filled out
|
||||
* @param buf the raw buffer data, of the correct length determined by the remaining length field
|
||||
* @param len the length in bytes of the data in the supplied buffer
|
||||
* @return error code. 1 is success, 0 is failure
|
||||
*/
|
||||
int32_t MQTTDeserialize_connect(MQTTPacket_connectData* data, uint8_t* buf, int32_t len)
|
||||
{
|
||||
MQTTHeader header = {0};
|
||||
MQTTConnectFlags flags = {0};
|
||||
uint8_t* curdata = buf;
|
||||
uint8_t* enddata = &buf[len];
|
||||
int32_t rc = 0;
|
||||
MQTTString Protocol;
|
||||
int32_t version;
|
||||
int32_t mylen = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
header.byte = readChar(&curdata);
|
||||
if (header.bits.type != CONNECT)
|
||||
goto exit;
|
||||
|
||||
curdata += MQTTPacket_decodeBuf(curdata, &mylen); /* read remaining length */
|
||||
|
||||
/* do we have enough data to read the protocol version byte? */
|
||||
if (!readMQTTLenString(&Protocol, &curdata, enddata) || enddata - curdata < 0)
|
||||
goto exit;
|
||||
|
||||
version = (int)readChar(&curdata); /* Protocol version */
|
||||
|
||||
/* If we don't recognize the protocol version, we don't parse the connect packet on the
|
||||
* basis that we don't know what the format will be. */
|
||||
if (MQTTPacket_checkVersion(&Protocol, version))
|
||||
{
|
||||
flags.all = readChar(&curdata);
|
||||
data->cleansession = flags.bits.cleansession;
|
||||
data->keepAliveInterval = readInt(&curdata);
|
||||
|
||||
if (!readMQTTLenString(&data->clientID, &curdata, enddata))
|
||||
goto exit;
|
||||
|
||||
data->willFlag = flags.bits.will;
|
||||
if (flags.bits.will)
|
||||
{
|
||||
data->will.qos = flags.bits.willQoS;
|
||||
data->will.retained = flags.bits.willRetain;
|
||||
|
||||
if (!readMQTTLenString(&data->will.topicName, &curdata, enddata) ||
|
||||
!readMQTTLenString(&data->will.message, &curdata, enddata))
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (flags.bits.username)
|
||||
{
|
||||
if (enddata - curdata < 3 || !readMQTTLenString(&data->username, &curdata, enddata))
|
||||
goto exit; /* username flag set, but no username supplied - invalid */
|
||||
if (flags.bits.password &&
|
||||
(enddata - curdata < 3 || !readMQTTLenString(&data->password, &curdata, enddata)))
|
||||
goto exit; /* password flag set, but no password supplied - invalid */
|
||||
}
|
||||
else if (flags.bits.password)
|
||||
goto exit; /* password flag set without username - invalid */
|
||||
|
||||
rc = 1;
|
||||
}
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes the connack packet into the supplied buffer.
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param buflen the length in bytes of the supplied buffer
|
||||
* @param connack_rc the integer connack return code to be used
|
||||
* @param sessionPresent the MQTT 3.1.1 sessionPresent flag
|
||||
* @return serialized length, or error if 0
|
||||
*/
|
||||
int32_t MQTTSerialize_connack(uint8_t* buf, int32_t buflen, uint8_t connack_rc, uint8_t sessionPresent)
|
||||
{
|
||||
MQTTHeader header = {0};
|
||||
int32_t rc = 0;
|
||||
uint8_t *ptr = buf;
|
||||
MQTTConnackFlags flags = {0};
|
||||
|
||||
FUNC_ENTRY;
|
||||
if (buflen < 2)
|
||||
{
|
||||
rc = MQTTPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
header.byte = 0;
|
||||
header.bits.type = CONNACK;
|
||||
writeChar(&ptr, header.byte); /* write header */
|
||||
|
||||
ptr += MQTTPacket_encode(ptr, 2); /* write remaining length */
|
||||
|
||||
flags.all = 0;
|
||||
flags.bits.sessionpresent = sessionPresent;
|
||||
writeChar(&ptr, flags.all);
|
||||
writeChar(&ptr, connack_rc);
|
||||
|
||||
rc = ptr - buf;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -0,0 +1,109 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2014 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||
*******************************************************************************/
|
||||
|
||||
#include "StackTrace.h"
|
||||
#include "MQTTPacket.h"
|
||||
#include <string.h>
|
||||
|
||||
#define min(a, b) ((a < b) ? 1 : 0)
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into publish data
|
||||
* @param dup returned integer - the MQTT dup flag
|
||||
* @param qos returned integer - the MQTT QoS value
|
||||
* @param retained returned integer - the MQTT retained flag
|
||||
* @param packetid returned integer - the MQTT packet identifier
|
||||
* @param topicName returned MQTTString - the MQTT topic in the publish
|
||||
* @param payload returned byte buffer - the MQTT publish payload
|
||||
* @param payloadlen returned integer - the length of the MQTT payload
|
||||
* @param buf the raw buffer data, of the correct length determined by the remaining length field
|
||||
* @param buflen the length in bytes of the data in the supplied buffer
|
||||
* @return error code. 1 is success
|
||||
*/
|
||||
int32_t MQTTDeserialize_publish(uint8_t* dup, uint8_t* qos, uint8_t* retained, uint16_t* packetid, MQTTString* topicName,
|
||||
uint8_t** payload, int32_t* payloadlen, uint8_t* buf, int32_t buflen)
|
||||
{
|
||||
MQTTHeader header = {0};
|
||||
uint8_t* curdata = buf;
|
||||
uint8_t* enddata = NULL;
|
||||
int32_t rc = 0;
|
||||
int32_t mylen = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
header.byte = readChar(&curdata);
|
||||
|
||||
if (header.bits.type != PUBLISH)
|
||||
goto exit;
|
||||
|
||||
*dup = header.bits.dup;
|
||||
*qos = header.bits.qos;
|
||||
*retained = header.bits.retain;
|
||||
|
||||
curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
|
||||
enddata = curdata + mylen;
|
||||
|
||||
/* do we have enough data to read the protocol version byte? */
|
||||
if (!readMQTTLenString(topicName, &curdata, enddata) || enddata - curdata < 0)
|
||||
goto exit;
|
||||
|
||||
if (*qos > 0)
|
||||
*packetid = readInt(&curdata);
|
||||
|
||||
*payloadlen = enddata - curdata;
|
||||
*payload = curdata;
|
||||
rc = 1;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into an ack
|
||||
* @param packettype returned integer - the MQTT packet type
|
||||
* @param dup returned integer - the MQTT dup flag
|
||||
* @param packetid returned integer - the MQTT packet identifier
|
||||
* @param buf the raw buffer data, of the correct length determined by the remaining length field
|
||||
* @param buflen the length in bytes of the data in the supplied buffer
|
||||
* @return error code. 1 is success, 0 is failure
|
||||
*/
|
||||
int32_t MQTTDeserialize_ack(uint8_t* packettype, uint8_t* dup, uint16_t* packetid, uint8_t* buf, int32_t buflen)
|
||||
{
|
||||
MQTTHeader header = {0};
|
||||
uint8_t* curdata = buf;
|
||||
uint8_t* enddata = NULL;
|
||||
int32_t rc = 0;
|
||||
int32_t mylen;
|
||||
|
||||
FUNC_ENTRY;
|
||||
header.byte = readChar(&curdata);
|
||||
*dup = header.bits.dup;
|
||||
*packettype = header.bits.type;
|
||||
|
||||
curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
|
||||
enddata = curdata + mylen;
|
||||
|
||||
if (enddata - curdata < 2)
|
||||
goto exit;
|
||||
|
||||
*packetid = readInt(&curdata);
|
||||
|
||||
rc = 1;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -0,0 +1,268 @@
|
||||
/*
|
||||
* Copyright (c) 2014 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||
*******************************************************************************/
|
||||
|
||||
#include "StackTrace.h"
|
||||
#include "MQTTPacket.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
const char* MQTTPacket_names[] =
|
||||
{
|
||||
"RESERVED", "CONNECT", "CONNACK", "PUBLISH", "PUBACK", "PUBREC", "PUBREL",
|
||||
"PUBCOMP", "SUBSCRIBE", "SUBACK", "UNSUBSCRIBE", "UNSUBACK", "PINGREQ",
|
||||
"PINGRESP", "DISCONNECT"
|
||||
};
|
||||
|
||||
|
||||
const char* MQTTPacket_getName(uint16_t packetid)
|
||||
{
|
||||
return MQTTPacket_names[packetid];
|
||||
}
|
||||
|
||||
|
||||
int32_t MQTTStringFormat_connect(char* strbuf, int32_t strbuflen, MQTTPacket_connectData* data)
|
||||
{
|
||||
int32_t strindex = 0;
|
||||
|
||||
strindex = snprintf(strbuf, strbuflen,
|
||||
"CONNECT MQTT version %ld, client id %.*s, clean session %ld, keep alive %d",
|
||||
(int32_t)data->MQTTVersion, (int)data->clientID.lenstring.len, data->clientID.lenstring.data,
|
||||
(int32_t)data->cleansession, data->keepAliveInterval);
|
||||
if (data->willFlag)
|
||||
strindex += snprintf(&strbuf[strindex], strbuflen - strindex,
|
||||
", will QoS %d, will retain %d, will topic %.*s, will message %.*s",
|
||||
data->will.qos, data->will.retained,
|
||||
(int)data->will.topicName.lenstring.len, data->will.topicName.lenstring.data,
|
||||
(int)data->will.message.lenstring.len, data->will.message.lenstring.data);
|
||||
if (data->username.lenstring.data && data->username.lenstring.len > 0)
|
||||
strindex += snprintf(&strbuf[strindex], strbuflen - strindex,
|
||||
", user name %.*s", (int)data->username.lenstring.len, data->username.lenstring.data);
|
||||
if (data->password.lenstring.data && data->password.lenstring.len > 0)
|
||||
strindex += snprintf(&strbuf[strindex], strbuflen - strindex,
|
||||
", password %.*s", (int)data->password.lenstring.len, data->password.lenstring.data);
|
||||
return strindex;
|
||||
}
|
||||
|
||||
|
||||
int32_t MQTTStringFormat_connack(char* strbuf, int32_t strbuflen, uint8_t connack_rc, uint8_t sessionPresent)
|
||||
{
|
||||
int32_t strindex = snprintf(strbuf, strbuflen, "CONNACK session present %d, rc %d", sessionPresent, connack_rc);
|
||||
return strindex;
|
||||
}
|
||||
|
||||
|
||||
int32_t MQTTStringFormat_publish(char* strbuf, int32_t strbuflen, uint8_t dup, uint8_t qos, uint8_t retained,
|
||||
uint16_t packetid, MQTTString topicName, uint8_t* payload, int32_t payloadlen)
|
||||
{
|
||||
int32_t strindex = snprintf(strbuf, strbuflen,
|
||||
"PUBLISH dup %d, QoS %d, retained %d, packet id %d, topic %.*s, payload length %ld, payload %.*s",
|
||||
dup, qos, retained, packetid,
|
||||
(topicName.lenstring.len < 20) ? (int)topicName.lenstring.len : 20, topicName.lenstring.data,
|
||||
payloadlen, (payloadlen < 20) ? (int)payloadlen : 20, payload);
|
||||
return strindex;
|
||||
}
|
||||
|
||||
|
||||
int32_t MQTTStringFormat_ack(char* strbuf, int32_t strbuflen, uint8_t packettype, uint8_t dup, uint16_t packetid)
|
||||
{
|
||||
int32_t strindex = snprintf(strbuf, strbuflen, "%s, packet id %d", MQTTPacket_names[packettype], packetid);
|
||||
|
||||
if (dup)
|
||||
strindex += snprintf(strbuf + strindex, strbuflen - strindex, ", dup %d", dup);
|
||||
|
||||
return strindex;
|
||||
}
|
||||
|
||||
|
||||
int32_t MQTTStringFormat_subscribe(char* strbuf, int32_t strbuflen, uint8_t dup, uint16_t packetid, int32_t count,
|
||||
MQTTString topicFilters[], int32_t requestedQoSs[])
|
||||
{
|
||||
return snprintf(strbuf, strbuflen, "SUBSCRIBE dup %d, packet id %d count %ld topic %.*s qos %ld",
|
||||
dup, packetid, count, (int)topicFilters[0].lenstring.len, topicFilters[0].lenstring.data,
|
||||
requestedQoSs[0]);
|
||||
}
|
||||
|
||||
|
||||
int32_t MQTTStringFormat_suback(char* strbuf, int32_t strbuflen, uint16_t packetid, int32_t count, int32_t* grantedQoSs)
|
||||
{
|
||||
return snprintf(strbuf, strbuflen,
|
||||
"SUBACK packet id %d count %ld granted qos %ld", packetid, count, grantedQoSs[0]);
|
||||
}
|
||||
|
||||
|
||||
int32_t MQTTStringFormat_unsubscribe(char* strbuf, int32_t strbuflen, uint8_t dup, uint16_t packetid,
|
||||
int32_t count, MQTTString topicFilters[])
|
||||
{
|
||||
return snprintf(strbuf, strbuflen, "UNSUBSCRIBE dup %d, packet id %d count %ld topic %.*s",
|
||||
dup, packetid, count, (int)topicFilters[0].lenstring.len, topicFilters[0].lenstring.data);
|
||||
}
|
||||
|
||||
|
||||
char* MQTTFormat_toClientString(char* strbuf, int32_t strbuflen, uint8_t* buf, int32_t buflen)
|
||||
{
|
||||
int32_t index = 0;
|
||||
int32_t rem_length = 0;
|
||||
MQTTHeader header = {0};
|
||||
int32_t strindex = 0;
|
||||
|
||||
header.byte = buf[index++];
|
||||
index += MQTTPacket_decodeBuf(&buf[index], &rem_length);
|
||||
|
||||
switch (header.bits.type)
|
||||
{
|
||||
case CONNACK:
|
||||
{
|
||||
uint8_t sessionPresent, connack_rc;
|
||||
if (MQTTDeserialize_connack(&sessionPresent, &connack_rc, buf, buflen) == 1)
|
||||
strindex = MQTTStringFormat_connack(strbuf, strbuflen, connack_rc, sessionPresent);
|
||||
}
|
||||
break;
|
||||
case PUBLISH:
|
||||
{
|
||||
uint8_t dup, retained, *payload;
|
||||
uint16_t packetid;
|
||||
uint8_t qos;
|
||||
int32_t payloadlen;
|
||||
MQTTString topicName = MQTTString_initializer;
|
||||
|
||||
if (MQTTDeserialize_publish(&dup, &qos, &retained, &packetid, &topicName,
|
||||
&payload, &payloadlen, buf, buflen) == 1)
|
||||
strindex = MQTTStringFormat_publish(strbuf, strbuflen, dup, qos, retained,
|
||||
packetid, topicName, payload, payloadlen);
|
||||
}
|
||||
break;
|
||||
case PUBACK:
|
||||
case PUBREC:
|
||||
case PUBREL:
|
||||
case PUBCOMP:
|
||||
{
|
||||
uint8_t packettype, dup;
|
||||
uint16_t packetid;
|
||||
if (MQTTDeserialize_ack(&packettype, &dup, &packetid, buf, buflen) == 1)
|
||||
strindex = MQTTStringFormat_ack(strbuf, strbuflen, packettype, dup, packetid);
|
||||
}
|
||||
break;
|
||||
case SUBACK:
|
||||
{
|
||||
uint16_t packetid;
|
||||
int32_t maxcount = 1, count = 0;
|
||||
int32_t grantedQoSs[1];
|
||||
if (MQTTDeserialize_suback(&packetid, maxcount, &count, grantedQoSs, buf, buflen) == 1)
|
||||
strindex = MQTTStringFormat_suback(strbuf, strbuflen, packetid, count, grantedQoSs);
|
||||
}
|
||||
break;
|
||||
case UNSUBACK:
|
||||
{
|
||||
uint16_t packetid;
|
||||
if (MQTTDeserialize_unsuback(&packetid, buf, buflen) == 1)
|
||||
strindex = MQTTStringFormat_ack(strbuf, strbuflen, UNSUBACK, 0, packetid);
|
||||
}
|
||||
break;
|
||||
case PINGREQ:
|
||||
case PINGRESP:
|
||||
case DISCONNECT:
|
||||
strindex = snprintf(strbuf, strbuflen, "%s", MQTTPacket_names[header.bits.type]);
|
||||
break;
|
||||
}
|
||||
|
||||
(void) strindex;
|
||||
|
||||
return strbuf;
|
||||
}
|
||||
|
||||
|
||||
char* MQTTFormat_toServerString(char* strbuf, int32_t strbuflen, uint8_t* buf, int32_t buflen)
|
||||
{
|
||||
int32_t index = 0;
|
||||
int32_t rem_length = 0;
|
||||
MQTTHeader header = {0};
|
||||
int32_t strindex = 0;
|
||||
|
||||
header.byte = buf[index++];
|
||||
index += MQTTPacket_decodeBuf(&buf[index], &rem_length);
|
||||
|
||||
switch (header.bits.type)
|
||||
{
|
||||
case CONNECT:
|
||||
{
|
||||
MQTTPacket_connectData data;
|
||||
int32_t rc;
|
||||
|
||||
if ((rc = MQTTDeserialize_connect(&data, buf, buflen)) == 1)
|
||||
strindex = MQTTStringFormat_connect(strbuf, strbuflen, &data);
|
||||
}
|
||||
break;
|
||||
case PUBLISH:
|
||||
{
|
||||
uint8_t dup, retained, *payload;
|
||||
uint16_t packetid;
|
||||
uint8_t qos;
|
||||
int32_t payloadlen;
|
||||
MQTTString topicName = MQTTString_initializer;
|
||||
|
||||
if (MQTTDeserialize_publish(&dup, &qos, &retained, &packetid, &topicName,
|
||||
&payload, &payloadlen, buf, buflen) == 1)
|
||||
strindex = MQTTStringFormat_publish(strbuf, strbuflen, dup, qos, retained,
|
||||
packetid, topicName, payload, payloadlen);
|
||||
}
|
||||
break;
|
||||
case PUBACK:
|
||||
case PUBREC:
|
||||
case PUBREL:
|
||||
case PUBCOMP:
|
||||
{
|
||||
uint8_t packettype, dup;
|
||||
uint16_t packetid;
|
||||
|
||||
if (MQTTDeserialize_ack(&packettype, &dup, &packetid, buf, buflen) == 1)
|
||||
strindex = MQTTStringFormat_ack(strbuf, strbuflen, packettype, dup, packetid);
|
||||
}
|
||||
break;
|
||||
case SUBSCRIBE:
|
||||
{
|
||||
uint8_t dup;
|
||||
uint16_t packetid;
|
||||
int32_t maxcount = 1, count = 0;
|
||||
MQTTString topicFilters[1];
|
||||
int32_t requestedQoSs[1];
|
||||
|
||||
if (MQTTDeserialize_subscribe(&dup, &packetid, maxcount, &count,
|
||||
topicFilters, requestedQoSs, buf, buflen) == 1)
|
||||
strindex = MQTTStringFormat_subscribe(strbuf, strbuflen, dup, packetid, count, topicFilters, requestedQoSs);;
|
||||
}
|
||||
break;
|
||||
case UNSUBSCRIBE:
|
||||
{
|
||||
uint8_t dup;
|
||||
uint16_t packetid;
|
||||
int32_t maxcount = 1, count = 0;
|
||||
MQTTString topicFilters[1];
|
||||
if (MQTTDeserialize_unsubscribe(&dup, &packetid, maxcount, &count, topicFilters, buf, buflen) == 1)
|
||||
strindex = MQTTStringFormat_unsubscribe(strbuf, strbuflen, dup, packetid, count, topicFilters);
|
||||
}
|
||||
break;
|
||||
case PINGREQ:
|
||||
case PINGRESP:
|
||||
case DISCONNECT:
|
||||
strindex = snprintf(strbuf, strbuflen, "%s", MQTTPacket_names[header.bits.type]);
|
||||
break;
|
||||
}
|
||||
|
||||
(void) strindex;
|
||||
strbuf[strbuflen] = '\0';
|
||||
return strbuf;
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2014 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||
*******************************************************************************/
|
||||
|
||||
#if !defined(MQTTFORMAT_H)
|
||||
#define MQTTFORMAT_H
|
||||
|
||||
#include "StackTrace.h"
|
||||
#include "MQTTPacket.h"
|
||||
|
||||
const char* MQTTPacket_getName(uint16_t packetid);
|
||||
int32_t MQTTStringFormat_connect(char* strbuf, int32_t strbuflen, MQTTPacket_connectData* data);
|
||||
int32_t MQTTStringFormat_connack(char* strbuf, int32_t strbuflen, uint8_t connack_rc, uint8_t sessionPresent);
|
||||
int32_t MQTTStringFormat_publish(char* strbuf, int32_t strbuflen, uint8_t dup, uint8_t qos, uint8_t retained,
|
||||
uint16_t packetid, MQTTString topicName, uint8_t* payload, int32_t payloadlen);
|
||||
int32_t MQTTStringFormat_ack(char* strbuf, int32_t strbuflen, uint8_t packettype, uint8_t dup, uint16_t packetid);
|
||||
int32_t MQTTStringFormat_subscribe(char* strbuf, int32_t strbuflen, uint8_t dup, uint16_t packetid, int32_t count,
|
||||
MQTTString topicFilters[], int32_t requestedQoSs[]);
|
||||
int32_t MQTTStringFormat_suback(char* strbuf, int32_t strbuflen, uint16_t packetid, int32_t count, int32_t* grantedQoSs);
|
||||
int32_t MQTTStringFormat_unsubscribe(char* strbuf, int32_t strbuflen, uint8_t dup, uint16_t packetid,
|
||||
int32_t count, MQTTString topicFilters[]);
|
||||
char* MQTTFormat_toClientString(char* strbuf, int32_t strbuflen, uint8_t* buf, int32_t buflen);
|
||||
char* MQTTFormat_toServerString(char* strbuf, int32_t strbuflen, uint8_t* buf, int32_t buflen);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,443 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2014 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||
* Sergio R. Caprile - non-blocking packet read functions for stream transport
|
||||
*******************************************************************************/
|
||||
|
||||
#include "StackTrace.h"
|
||||
#include "MQTTPacket.h"
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* Encodes the message length according to the MQTT algorithm
|
||||
* @param buf the buffer into which the encoded data is written
|
||||
* @param length the length to be encoded
|
||||
* @return the number of bytes written to buffer
|
||||
*/
|
||||
int32_t MQTTPacket_encode(uint8_t* buf, int32_t length)
|
||||
{
|
||||
int32_t rc = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
do
|
||||
{
|
||||
uint8_t d = length % 128;
|
||||
length /= 128;
|
||||
|
||||
/* if there are more digits to encode, set the top bit of this digit */
|
||||
if (length > 0)
|
||||
d |= 0x80;
|
||||
|
||||
buf[rc++] = d;
|
||||
} while (length > 0);
|
||||
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decodes the message length according to the MQTT algorithm
|
||||
* @param getcharfn pointer to function to read the next character from the data source
|
||||
* @param value the decoded length returned
|
||||
* @return the number of bytes read from the socket
|
||||
*/
|
||||
int32_t MQTTPacket_decode(int32_t (*getcharfn)(uint8_t*, int32_t), int32_t* value)
|
||||
{
|
||||
uint8_t c;
|
||||
int32_t multiplier = 1;
|
||||
int32_t len = 0;
|
||||
|
||||
#define MAX_NO_OF_REMAINING_LENGTH_BYTES 4
|
||||
|
||||
FUNC_ENTRY;
|
||||
*value = 0;
|
||||
|
||||
do
|
||||
{
|
||||
int32_t rc = MQTTPACKET_READ_ERROR;
|
||||
|
||||
if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES)
|
||||
{
|
||||
rc = MQTTPACKET_READ_ERROR; /* bad data */
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = (*getcharfn)(&c, 1);
|
||||
|
||||
if (rc != 1)
|
||||
goto exit;
|
||||
|
||||
*value += (c & 127) * multiplier;
|
||||
multiplier *= 128;
|
||||
} while ((c & 128) != 0);
|
||||
|
||||
exit:
|
||||
FUNC_EXIT_RC(len);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
int32_t MQTTPacket_len(int32_t rem_len)
|
||||
{
|
||||
rem_len += 1; /* header byte */
|
||||
|
||||
/* now remaining_length field */
|
||||
if (rem_len < 128)
|
||||
rem_len += 1;
|
||||
else if (rem_len < 16384)
|
||||
rem_len += 2;
|
||||
else if (rem_len < 2097151)
|
||||
rem_len += 3;
|
||||
else
|
||||
rem_len += 4;
|
||||
|
||||
return rem_len;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t* bufptr;
|
||||
|
||||
int32_t bufchar(uint8_t* c, int32_t count)
|
||||
{
|
||||
for (int32_t i = 0; i < count; ++i)
|
||||
*c = *bufptr++;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
int32_t MQTTPacket_decodeBuf(uint8_t* buf, int32_t* value)
|
||||
{
|
||||
bufptr = buf;
|
||||
return MQTTPacket_decode(bufchar, value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculates an integer from two bytes read from the input buffer
|
||||
* @param pptr pointer to the input buffer - incremented by the number of bytes used & returned
|
||||
* @return the integer value calculated
|
||||
*/
|
||||
int32_t readInt(uint8_t** pptr)
|
||||
{
|
||||
uint8_t* ptr = *pptr;
|
||||
int32_t len = 256*(*ptr) + (*(ptr+1));
|
||||
*pptr += 2;
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads one character from the input buffer.
|
||||
* @param pptr pointer to the input buffer - incremented by the number of bytes used & returned
|
||||
* @return the character read
|
||||
*/
|
||||
char readChar(uint8_t** pptr)
|
||||
{
|
||||
char c = **pptr;
|
||||
(*pptr)++;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Writes one character to an output buffer.
|
||||
* @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
|
||||
* @param c the character to write
|
||||
*/
|
||||
void writeChar(uint8_t** pptr, char c)
|
||||
{
|
||||
**pptr = c;
|
||||
(*pptr)++;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Writes an integer as 2 bytes to an output buffer.
|
||||
* @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
|
||||
* @param anInt the integer to write
|
||||
*/
|
||||
void writeInt(uint8_t** pptr, int32_t anInt)
|
||||
{
|
||||
**pptr = (uint8_t)(anInt / 256);
|
||||
(*pptr)++;
|
||||
**pptr = (uint8_t)(anInt % 256);
|
||||
(*pptr)++;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Writes a "UTF" string to an output buffer. Converts C string to length-delimited.
|
||||
* @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
|
||||
* @param string the C string to write
|
||||
*/
|
||||
void writeCString(uint8_t** pptr, const char* string)
|
||||
{
|
||||
int32_t len = strlen(string);
|
||||
writeInt(pptr, len);
|
||||
memcpy(*pptr, string, len);
|
||||
*pptr += len;
|
||||
}
|
||||
|
||||
|
||||
int32_t getLenStringLen(char* ptr)
|
||||
{
|
||||
int32_t len = 256*((uint8_t)(*ptr)) + (uint8_t)(*(ptr+1));
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
void writeMQTTString(uint8_t** pptr, MQTTString mqttstring)
|
||||
{
|
||||
if (mqttstring.lenstring.len > 0)
|
||||
{
|
||||
writeInt(pptr, mqttstring.lenstring.len);
|
||||
memcpy(*pptr, mqttstring.lenstring.data, mqttstring.lenstring.len);
|
||||
*pptr += mqttstring.lenstring.len;
|
||||
}
|
||||
else if (mqttstring.cstring)
|
||||
writeCString(pptr, mqttstring.cstring);
|
||||
else
|
||||
writeInt(pptr, 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param mqttstring the MQTTString structure into which the data is to be read
|
||||
* @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
|
||||
* @param enddata pointer to the end of the data: do not read beyond
|
||||
* @return 1 if successful, 0 if not
|
||||
*/
|
||||
int32_t readMQTTLenString(MQTTString* mqttstring, uint8_t** pptr, uint8_t* enddata)
|
||||
{
|
||||
int32_t rc = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
|
||||
/* the first two bytes are the length of the string */
|
||||
if (enddata - (*pptr) > 1) /* enough length to read the integer? */
|
||||
{
|
||||
mqttstring->lenstring.len = readInt(pptr); /* increments pptr to point past length */
|
||||
|
||||
if (&(*pptr)[mqttstring->lenstring.len] <= enddata)
|
||||
{
|
||||
mqttstring->lenstring.data = (char*)*pptr;
|
||||
*pptr += mqttstring->lenstring.len;
|
||||
rc = 1;
|
||||
}
|
||||
}
|
||||
|
||||
mqttstring->cstring = NULL;
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the length of the MQTTstring - C string if there is one, otherwise the length delimited string
|
||||
* @param mqttstring the string to return the length of
|
||||
* @return the length of the string
|
||||
*/
|
||||
int32_t MQTTstrlen(MQTTString mqttstring)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (mqttstring.cstring)
|
||||
rc = strlen(mqttstring.cstring);
|
||||
else
|
||||
rc = mqttstring.lenstring.len;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compares an MQTTString to a C string
|
||||
* @param a the MQTTString to compare
|
||||
* @param bptr the C string to compare
|
||||
* @return boolean - equal or not
|
||||
*/
|
||||
int32_t MQTTPacket_equals(MQTTString* a, char* bptr)
|
||||
{
|
||||
int32_t alen = 0, blen = 0;
|
||||
char *aptr;
|
||||
|
||||
if (a->cstring)
|
||||
{
|
||||
aptr = a->cstring;
|
||||
alen = strlen(a->cstring);
|
||||
}
|
||||
else
|
||||
{
|
||||
aptr = a->lenstring.data;
|
||||
alen = a->lenstring.len;
|
||||
}
|
||||
|
||||
blen = strlen(bptr);
|
||||
|
||||
return (alen == blen) && (strncmp(aptr, bptr, alen) == 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper function to read packet data from some source into a buffer
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param buflen the length in bytes of the supplied buffer
|
||||
* @param getfn pointer to a function which will read any number of bytes from the needed source
|
||||
* @return integer MQTT packet type, or -1 on error
|
||||
* @note the whole message must fit into the caller's buffer
|
||||
*/
|
||||
int32_t MQTTPacket_read(uint8_t* buf, int32_t buflen, int32_t (*getfn)(uint8_t*, int32_t))
|
||||
{
|
||||
int32_t rc = -1;
|
||||
MQTTHeader header = {0};
|
||||
int32_t len = 0;
|
||||
int32_t rem_len = 0;
|
||||
|
||||
/* 1. read the header byte. This has the packet type in it */
|
||||
if ((*getfn)(buf, 1) != 1)
|
||||
goto exit;
|
||||
|
||||
len = 1;
|
||||
/* 2. read the remaining length. This is variable in itself */
|
||||
MQTTPacket_decode(getfn, &rem_len);
|
||||
len += MQTTPacket_encode(buf + 1, rem_len); /* put the original remaining length back into the buffer */
|
||||
|
||||
/* 3. read the rest of the buffer using a callback to supply the rest of the data */
|
||||
if((rem_len + len) > buflen)
|
||||
goto exit;
|
||||
if ((*getfn)(buf + len, rem_len) != rem_len)
|
||||
goto exit;
|
||||
|
||||
header.byte = buf[0];
|
||||
rc = header.bits.type;
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes the message length according to the MQTT algorithm, non-blocking
|
||||
* @param trp pointer to a transport structure holding what is needed to solve getting data from it
|
||||
* @param value the decoded length returned
|
||||
* @return integer the number of bytes read from the socket, 0 for call again, or -1 on error
|
||||
*/
|
||||
static int32_t MQTTPacket_decodenb(MQTTTransport *trp)
|
||||
{
|
||||
uint8_t c;
|
||||
int32_t rc = MQTTPACKET_READ_ERROR;
|
||||
|
||||
FUNC_ENTRY;
|
||||
|
||||
if (trp->len == 0)
|
||||
{ /* initialize on first call */
|
||||
trp->multiplier = 1;
|
||||
trp->rem_len = 0;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
int32_t frc;
|
||||
|
||||
if (trp->len >= MAX_NO_OF_REMAINING_LENGTH_BYTES)
|
||||
goto exit;
|
||||
|
||||
if ((frc=(*trp->getfn)(trp->sck, &c, 1)) == -1)
|
||||
goto exit;
|
||||
|
||||
if (frc == 0)
|
||||
{
|
||||
rc = 0;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
++(trp->len);
|
||||
trp->rem_len += (c & 127) * trp->multiplier;
|
||||
trp->multiplier *= 128;
|
||||
} while ((c & 128) != 0);
|
||||
|
||||
rc = trp->len;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to read packet data from some source into a buffer, non-blocking
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param buflen the length in bytes of the supplied buffer
|
||||
* @param trp pointer to a transport structure holding what is needed to solve getting data from it
|
||||
* @return integer MQTT packet type, 0 for call again, or -1 on error
|
||||
* @note the whole message must fit into the caller's buffer
|
||||
*/
|
||||
int32_t MQTTPacket_readnb(uint8_t* buf, int32_t buflen, MQTTTransport *trp)
|
||||
{
|
||||
int32_t rc = -1, frc;
|
||||
MQTTHeader header = {0};
|
||||
|
||||
switch (trp->state)
|
||||
{
|
||||
default:
|
||||
trp->state = 0;
|
||||
/*FALLTHROUGH*/
|
||||
case 0:
|
||||
/* read the header byte. This has the packet type in it */
|
||||
if ((frc=(*trp->getfn)(trp->sck, buf, 1)) == -1)
|
||||
goto exit;
|
||||
|
||||
if (frc == 0)
|
||||
return 0;
|
||||
|
||||
trp->len = 0;
|
||||
++trp->state;
|
||||
|
||||
/*FALLTHROUGH*/
|
||||
/* read the remaining length. This is variable in itself */
|
||||
case 1:
|
||||
if ((frc=MQTTPacket_decodenb(trp)) == MQTTPACKET_READ_ERROR)
|
||||
goto exit;
|
||||
|
||||
if (frc == 0)
|
||||
return 0;
|
||||
|
||||
trp->len = 1 + MQTTPacket_encode(buf + 1, trp->rem_len); /* put the original remaining length back into the buffer */
|
||||
|
||||
if ((trp->rem_len + trp->len) > buflen)
|
||||
goto exit;
|
||||
|
||||
++trp->state;
|
||||
/*FALLTHROUGH*/
|
||||
case 2:
|
||||
/* read the rest of the buffer using a callback to supply the rest of the data */
|
||||
if ((frc=(*trp->getfn)(trp->sck, buf + trp->len, trp->rem_len)) == -1)
|
||||
goto exit;
|
||||
|
||||
if (frc == 0)
|
||||
return 0;
|
||||
|
||||
trp->rem_len -= frc;
|
||||
trp->len += frc;
|
||||
|
||||
if (trp->rem_len)
|
||||
return 0;
|
||||
|
||||
header.byte = buf[0];
|
||||
rc = header.bits.type;
|
||||
break;
|
||||
}
|
||||
exit:
|
||||
trp->state = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (c) 2014 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||
* Xiang Rong - 442039 Add makefile to Embedded C client
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef MQTTPACKET_H_
|
||||
#define MQTTPACKET_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(WIN32_DLL) || defined(WIN64_DLL)
|
||||
#define DLLImport __declspec(dllimport)
|
||||
#define DLLExport __declspec(dllexport)
|
||||
#elif defined(LINUX_SO)
|
||||
#define DLLImport extern
|
||||
#define DLLExport __attribute__ ((visibility ("default")))
|
||||
#else
|
||||
#define DLLImport
|
||||
#define DLLExport
|
||||
#endif
|
||||
|
||||
enum errors
|
||||
{
|
||||
MQTTPACKET_BUFFER_TOO_SHORT = -2,
|
||||
MQTTPACKET_READ_ERROR = -1,
|
||||
MQTTPACKET_READ_COMPLETE
|
||||
};
|
||||
|
||||
enum msgTypes
|
||||
{
|
||||
CONNECT = 1, CONNACK, PUBLISH, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBSCRIBE,
|
||||
SUBACK, UNSUBSCRIBE, UNSUBACK, PINGREQ, PINGRESP, DISCONNECT
|
||||
};
|
||||
|
||||
/**
|
||||
* Bitfields for the MQTT header byte.
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
uint8_t byte; /**< the whole byte */
|
||||
#if defined(REVERSED)
|
||||
struct
|
||||
{
|
||||
uint8_t type : 4; /**< message type nibble */
|
||||
uint8_t dup : 1; /**< DUP flag bit */
|
||||
uint8_t qos : 2; /**< QoS value, 0, 1 or 2 */
|
||||
uint8_t retain : 1; /**< retained flag bit */
|
||||
} bits;
|
||||
#else
|
||||
struct
|
||||
{
|
||||
uint8_t retain : 1; /**< retained flag bit */
|
||||
uint8_t qos : 2; /**< QoS value, 0, 1 or 2 */
|
||||
uint8_t dup : 1; /**< DUP flag bit */
|
||||
uint8_t type : 4; /**< message type nibble */
|
||||
} bits;
|
||||
#endif
|
||||
} MQTTHeader;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int32_t len;
|
||||
char* data;
|
||||
} MQTTLenString;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char* cstring;
|
||||
MQTTLenString lenstring;
|
||||
} MQTTString;
|
||||
|
||||
#define MQTTString_initializer {NULL, {0, NULL}}
|
||||
|
||||
int32_t MQTTstrlen(MQTTString mqttstring);
|
||||
|
||||
#include "MQTTConnect.h"
|
||||
#include "MQTTPublish.h"
|
||||
#include "MQTTSubscribe.h"
|
||||
#include "MQTTUnsubscribe.h"
|
||||
#include "MQTTFormat.h"
|
||||
|
||||
int32_t MQTTSerialize_ack(uint8_t* buf, int32_t buflen, uint8_t type, uint8_t dup, uint16_t packetid);
|
||||
int32_t MQTTDeserialize_ack(uint8_t* packettype, uint8_t* dup, uint16_t* packetid, uint8_t* buf, int32_t buflen);
|
||||
|
||||
int32_t MQTTPacket_len(int32_t rem_len);
|
||||
int32_t MQTTPacket_equals(MQTTString* a, char* b);
|
||||
|
||||
int32_t MQTTPacket_encode(uint8_t* buf, int32_t length);
|
||||
int32_t MQTTPacket_decode(int32_t (*getcharfn)(uint8_t*, int32_t), int32_t* value);
|
||||
int32_t MQTTPacket_decodeBuf(uint8_t* buf, int32_t* value);
|
||||
|
||||
int32_t readInt(uint8_t** pptr);
|
||||
char readChar(uint8_t** pptr);
|
||||
void writeChar(uint8_t** pptr, char c);
|
||||
void writeInt(uint8_t** pptr, int32_t anInt);
|
||||
int32_t readMQTTLenString(MQTTString* mqttstring, uint8_t** pptr, uint8_t* enddata);
|
||||
void writeCString(uint8_t** pptr, const char* string);
|
||||
void writeMQTTString(uint8_t** pptr, MQTTString mqttstring);
|
||||
|
||||
DLLExport int32_t MQTTPacket_read(uint8_t* buf, int32_t buflen, int32_t (*getfn)(uint8_t*, int32_t));
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int32_t (*getfn)(void *, uint8_t*, int32_t); /* must return -1 for error, 0 for call again, or the number of bytes read */
|
||||
void *sck; /* pointer to whatever the system may use to identify the transport */
|
||||
int32_t multiplier;
|
||||
int32_t rem_len;
|
||||
int32_t len;
|
||||
char state;
|
||||
}MQTTTransport;
|
||||
|
||||
int32_t MQTTPacket_readnb(uint8_t* buf, int32_t buflen, MQTTTransport *trp);
|
||||
|
||||
#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* MQTTPACKET_H_ */
|
||||
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2014 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||
* Xiang Rong - 442039 Add makefile to Embedded C client
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef MQTTPUBLISH_H_
|
||||
#define MQTTPUBLISH_H_
|
||||
|
||||
#if !defined(DLLImport)
|
||||
#define DLLImport
|
||||
#endif
|
||||
#if !defined(DLLExport)
|
||||
#define DLLExport
|
||||
#endif
|
||||
|
||||
DLLExport int32_t MQTTSerialize_publish(uint8_t* buf, int32_t buflen, uint8_t dup, uint8_t qos, uint8_t retained, uint16_t packetid,
|
||||
MQTTString topicName, uint8_t* payload, int32_t payloadlen);
|
||||
|
||||
DLLExport int32_t MQTTDeserialize_publish(uint8_t* dup, uint8_t* qos, uint8_t* retained, uint16_t* packetid, MQTTString* topicName,
|
||||
uint8_t** payload, int32_t* payloadlen, uint8_t* buf, int32_t len);
|
||||
|
||||
DLLExport int32_t MQTTSerialize_puback(uint8_t* buf, int32_t buflen, uint16_t packetid);
|
||||
DLLExport int32_t MQTTSerialize_pubrel(uint8_t* buf, int32_t buflen, uint8_t dup, uint16_t packetid);
|
||||
DLLExport int32_t MQTTSerialize_pubcomp(uint8_t* buf, int32_t buflen, uint16_t packetid);
|
||||
|
||||
#endif /* MQTTPUBLISH_H_ */
|
||||
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (c) 2014 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||
* Ian Craggs - fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=453144
|
||||
*******************************************************************************/
|
||||
|
||||
#include "MQTTPacket.h"
|
||||
#include "StackTrace.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/**
|
||||
* Determines the length of the MQTT publish packet that would be produced using the supplied parameters
|
||||
* @param qos the MQTT QoS of the publish (packetid is omitted for QoS 0)
|
||||
* @param topicName the topic name to be used in the publish
|
||||
* @param payloadlen the length of the payload to be sent
|
||||
* @return the length of buffer needed to contain the serialized version of the packet
|
||||
*/
|
||||
int32_t MQTTSerialize_publishLength(uint8_t qos, MQTTString topicName, int32_t payloadlen)
|
||||
{
|
||||
int32_t len = 2 + MQTTstrlen(topicName) + payloadlen;
|
||||
|
||||
if (qos > 0)
|
||||
len += 2; /* packetid */
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes the supplied publish data into the supplied buffer, ready for sending
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param buflen the length in bytes of the supplied buffer
|
||||
* @param dup integer - the MQTT dup flag
|
||||
* @param qos integer - the MQTT QoS value
|
||||
* @param retained integer - the MQTT retained flag
|
||||
* @param packetid integer - the MQTT packet identifier
|
||||
* @param topicName MQTTString - the MQTT topic in the publish
|
||||
* @param payload byte buffer - the MQTT publish payload
|
||||
* @param payloadlen integer - the length of the MQTT payload
|
||||
* @return the length of the serialized data. <= 0 indicates error
|
||||
*/
|
||||
int32_t MQTTSerialize_publish(uint8_t* buf, int32_t buflen, uint8_t dup, uint8_t qos, uint8_t retained, uint16_t packetid,
|
||||
MQTTString topicName, uint8_t* payload, int32_t payloadlen)
|
||||
{
|
||||
uint8_t *ptr = buf;
|
||||
MQTTHeader header = {0};
|
||||
int32_t rem_len = 0;
|
||||
int32_t rc = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
|
||||
if (MQTTPacket_len(rem_len = MQTTSerialize_publishLength(qos, topicName, payloadlen)) > buflen)
|
||||
{
|
||||
rc = MQTTPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
header.bits.type = PUBLISH;
|
||||
header.bits.dup = dup;
|
||||
header.bits.qos = qos;
|
||||
header.bits.retain = retained;
|
||||
writeChar(&ptr, header.byte); /* write header */
|
||||
|
||||
ptr += MQTTPacket_encode(ptr, rem_len); /* write remaining length */;
|
||||
|
||||
writeMQTTString(&ptr, topicName);
|
||||
|
||||
if (qos > 0)
|
||||
writeInt(&ptr, packetid);
|
||||
|
||||
memcpy(ptr, payload, payloadlen);
|
||||
ptr += payloadlen;
|
||||
|
||||
rc = ptr - buf;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Serializes the ack packet into the supplied buffer.
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param buflen the length in bytes of the supplied buffer
|
||||
* @param type the MQTT packet type
|
||||
* @param dup the MQTT dup flag
|
||||
* @param packetid the MQTT packet identifier
|
||||
* @return serialized length, or error if 0
|
||||
*/
|
||||
int32_t MQTTSerialize_ack(uint8_t* buf, int32_t buflen, uint8_t packettype, uint8_t dup, uint16_t packetid)
|
||||
{
|
||||
MQTTHeader header = {0};
|
||||
int32_t rc = 0;
|
||||
uint8_t *ptr = buf;
|
||||
|
||||
FUNC_ENTRY;
|
||||
|
||||
if (buflen < 4)
|
||||
{
|
||||
rc = MQTTPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
header.bits.type = packettype;
|
||||
header.bits.dup = dup;
|
||||
header.bits.qos = (packettype == PUBREL) ? 1 : 0;
|
||||
writeChar(&ptr, header.byte); /* write header */
|
||||
|
||||
ptr += MQTTPacket_encode(ptr, 2); /* write remaining length */
|
||||
writeInt(&ptr, packetid);
|
||||
rc = ptr - buf;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes a puback packet into the supplied buffer.
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param buflen the length in bytes of the supplied buffer
|
||||
* @param packetid integer - the MQTT packet identifier
|
||||
* @return serialized length, or error if 0
|
||||
*/
|
||||
int32_t MQTTSerialize_puback(uint8_t* buf, int32_t buflen, uint16_t packetid)
|
||||
{
|
||||
return MQTTSerialize_ack(buf, buflen, PUBACK, 0, packetid);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes a pubrel packet into the supplied buffer.
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param buflen the length in bytes of the supplied buffer
|
||||
* @param dup integer - the MQTT dup flag
|
||||
* @param packetid integer - the MQTT packet identifier
|
||||
* @return serialized length, or error if 0
|
||||
*/
|
||||
int32_t MQTTSerialize_pubrel(uint8_t* buf, int32_t buflen, uint8_t dup, uint16_t packetid)
|
||||
{
|
||||
return MQTTSerialize_ack(buf, buflen, PUBREL, dup, packetid);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes a pubrel packet into the supplied buffer.
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param buflen the length in bytes of the supplied buffer
|
||||
* @param packetid integer - the MQTT packet identifier
|
||||
* @return serialized length, or error if 0
|
||||
*/
|
||||
int32_t MQTTSerialize_pubcomp(uint8_t* buf, int32_t buflen, uint16_t packetid)
|
||||
{
|
||||
return MQTTSerialize_ack(buf, buflen, PUBCOMP, 0, packetid);
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2014 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||
* Xiang Rong - 442039 Add makefile to Embedded C client
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef MQTTSUBSCRIBE_H_
|
||||
#define MQTTSUBSCRIBE_H_
|
||||
|
||||
#if !defined(DLLImport)
|
||||
#define DLLImport
|
||||
#endif
|
||||
#if !defined(DLLExport)
|
||||
#define DLLExport
|
||||
#endif
|
||||
|
||||
DLLExport int32_t MQTTSerialize_subscribe(uint8_t* buf, int32_t buflen, uint8_t dup, uint16_t packetid,
|
||||
int32_t count, MQTTString topicFilters[], int32_t requestedQoSs[]);
|
||||
|
||||
DLLExport int32_t MQTTDeserialize_subscribe(uint8_t* dup, uint16_t* packetid,
|
||||
int32_t maxcount, int32_t* count, MQTTString topicFilters[], int32_t requestedQoSs[], uint8_t* buf, int32_t len);
|
||||
|
||||
DLLExport int32_t MQTTSerialize_suback(uint8_t* buf, int32_t buflen, uint16_t packetid, int32_t count, int32_t* grantedQoSs);
|
||||
DLLExport int32_t MQTTDeserialize_suback(uint16_t* packetid, int32_t maxcount, int32_t* count, int32_t grantedQoSs[], uint8_t* buf, int32_t len);
|
||||
|
||||
|
||||
#endif /* MQTTSUBSCRIBE_H_ */
|
||||
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (c) 2014 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||
*******************************************************************************/
|
||||
|
||||
#include "MQTTPacket.h"
|
||||
#include "StackTrace.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* Determines the length of the MQTT subscribe packet that would be produced using the supplied parameters
|
||||
* @param count the number of topic filter strings in topicFilters
|
||||
* @param topicFilters the array of topic filter strings to be used in the publish
|
||||
* @return the length of buffer needed to contain the serialized version of the packet
|
||||
*/
|
||||
int32_t MQTTSerialize_subscribeLength(int32_t count, MQTTString topicFilters[])
|
||||
{
|
||||
int32_t len = 2; /* packetid */
|
||||
|
||||
for (int32_t i = 0; i < count; ++i)
|
||||
len += 2 + MQTTstrlen(topicFilters[i]) + 1; /* length + topic + req_qos */
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes the supplied subscribe data into the supplied buffer, ready for sending
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param buflen the length in bytes of the supplied bufferr
|
||||
* @param dup integer - the MQTT dup flag
|
||||
* @param packetid integer - the MQTT packet identifier
|
||||
* @param count - number of members in the topicFilters and reqQos arrays
|
||||
* @param topicFilters - array of topic filter names
|
||||
* @param requestedQoSs - array of requested QoS
|
||||
* @return the length of the serialized data. <= 0 indicates error
|
||||
*/
|
||||
int32_t MQTTSerialize_subscribe(uint8_t* buf, int32_t buflen, uint8_t dup, uint16_t packetid, int32_t count,
|
||||
MQTTString topicFilters[], int32_t requestedQoSs[])
|
||||
{
|
||||
uint8_t *ptr = buf;
|
||||
MQTTHeader header = {0};
|
||||
int32_t rem_len = 0;
|
||||
int32_t rc = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
|
||||
if (MQTTPacket_len(rem_len = MQTTSerialize_subscribeLength(count, topicFilters)) > buflen)
|
||||
{
|
||||
rc = MQTTPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
header.byte = 0;
|
||||
header.bits.type = SUBSCRIBE;
|
||||
header.bits.dup = dup;
|
||||
header.bits.qos = 1;
|
||||
writeChar(&ptr, header.byte); /* write header */
|
||||
|
||||
ptr += MQTTPacket_encode(ptr, rem_len); /* write remaining length */;
|
||||
|
||||
writeInt(&ptr, packetid);
|
||||
|
||||
for (int32_t i = 0; i < count; ++i)
|
||||
{
|
||||
writeMQTTString(&ptr, topicFilters[i]);
|
||||
writeChar(&ptr, requestedQoSs[i]);
|
||||
}
|
||||
|
||||
rc = ptr - buf;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into suback data
|
||||
* @param packetid returned integer - the MQTT packet identifier
|
||||
* @param maxcount - the maximum number of members allowed in the grantedQoSs array
|
||||
* @param count returned integer - number of members in the grantedQoSs array
|
||||
* @param grantedQoSs returned array of integers - the granted qualities of service
|
||||
* @param buf the raw buffer data, of the correct length determined by the remaining length field
|
||||
* @param buflen the length in bytes of the data in the supplied buffer
|
||||
* @return error code. 1 is success, 0 is failure
|
||||
*/
|
||||
int32_t MQTTDeserialize_suback(uint16_t* packetid, int32_t maxcount, int32_t* count, int32_t grantedQoSs[], uint8_t* buf, int32_t buflen)
|
||||
{
|
||||
MQTTHeader header = {0};
|
||||
uint8_t* curdata = buf;
|
||||
uint8_t* enddata = NULL;
|
||||
int32_t rc = 0;
|
||||
int32_t mylen;
|
||||
|
||||
FUNC_ENTRY;
|
||||
|
||||
header.byte = readChar(&curdata);
|
||||
if (header.bits.type != SUBACK)
|
||||
goto exit;
|
||||
|
||||
curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
|
||||
enddata = curdata + mylen;
|
||||
|
||||
if (enddata - curdata < 2)
|
||||
goto exit;
|
||||
|
||||
*packetid = readInt(&curdata);
|
||||
|
||||
*count = 0;
|
||||
|
||||
while (curdata < enddata)
|
||||
{
|
||||
if (*count > maxcount)
|
||||
{
|
||||
rc = -1;
|
||||
goto exit;
|
||||
}
|
||||
grantedQoSs[(*count)++] = readChar(&curdata);
|
||||
}
|
||||
|
||||
rc = 1;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2014 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||
*******************************************************************************/
|
||||
|
||||
#include "MQTTPacket.h"
|
||||
#include "StackTrace.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into subscribe data
|
||||
* @param dup integer returned - the MQTT dup flag
|
||||
* @param packetid integer returned - the MQTT packet identifier
|
||||
* @param maxcount - the maximum number of members allowed in the topicFilters and requestedQoSs arrays
|
||||
* @param count - number of members in the topicFilters and requestedQoSs arrays
|
||||
* @param topicFilters - array of topic filter names
|
||||
* @param requestedQoSs - array of requested QoS
|
||||
* @param buf the raw buffer data, of the correct length determined by the remaining length field
|
||||
* @param buflen the length in bytes of the data in the supplied buffer
|
||||
* @return the length of the serialized data. <= 0 indicates error
|
||||
*/
|
||||
int32_t MQTTDeserialize_subscribe(uint8_t* dup, uint16_t* packetid, int32_t maxcount, int32_t* count, MQTTString topicFilters[],
|
||||
int32_t requestedQoSs[], uint8_t* buf, int32_t buflen)
|
||||
{
|
||||
MQTTHeader header = {0};
|
||||
uint8_t* curdata = buf;
|
||||
uint8_t* enddata = NULL;
|
||||
int32_t rc = -1;
|
||||
int32_t mylen = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
|
||||
header.byte = readChar(&curdata);
|
||||
|
||||
if (header.bits.type != SUBSCRIBE)
|
||||
goto exit;
|
||||
|
||||
*dup = header.bits.dup;
|
||||
curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
|
||||
enddata = curdata + mylen;
|
||||
*packetid = readInt(&curdata);
|
||||
*count = 0;
|
||||
|
||||
while (curdata < enddata)
|
||||
{
|
||||
if (!readMQTTLenString(&topicFilters[*count], &curdata, enddata))
|
||||
goto exit;
|
||||
|
||||
if (curdata >= enddata) /* do we have enough data to read the req_qos version byte? */
|
||||
goto exit;
|
||||
|
||||
requestedQoSs[*count] = readChar(&curdata);
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
rc = 1;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes the supplied suback data into the supplied buffer, ready for sending
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param buflen the length in bytes of the supplied buffer
|
||||
* @param packetid integer - the MQTT packet identifier
|
||||
* @param count - number of members in the grantedQoSs array
|
||||
* @param grantedQoSs - array of granted QoS
|
||||
* @return the length of the serialized data. <= 0 indicates error
|
||||
*/
|
||||
int32_t MQTTSerialize_suback(uint8_t* buf, int32_t buflen, uint16_t packetid, int32_t count, int32_t* grantedQoSs)
|
||||
{
|
||||
MQTTHeader header = {0};
|
||||
int32_t rc = -1;
|
||||
uint8_t *ptr = buf;
|
||||
|
||||
FUNC_ENTRY;
|
||||
|
||||
if (buflen < 2 + count)
|
||||
{
|
||||
rc = MQTTPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
header.byte = 0;
|
||||
header.bits.type = SUBACK;
|
||||
writeChar(&ptr, header.byte); /* write header */
|
||||
ptr += MQTTPacket_encode(ptr, 2 + count); /* write remaining length */
|
||||
writeInt(&ptr, packetid);
|
||||
|
||||
for (int32_t i = 0; i < count; ++i)
|
||||
writeChar(&ptr, grantedQoSs[i]);
|
||||
|
||||
rc = ptr - buf;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2014 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||
* Xiang Rong - 442039 Add makefile to Embedded C client
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef MQTTUNSUBSCRIBE_H_
|
||||
#define MQTTUNSUBSCRIBE_H_
|
||||
|
||||
#if !defined(DLLImport)
|
||||
#define DLLImport
|
||||
#endif
|
||||
#if !defined(DLLExport)
|
||||
#define DLLExport
|
||||
#endif
|
||||
|
||||
DLLExport int32_t MQTTSerialize_unsubscribe(uint8_t* buf, int32_t buflen, uint8_t dup, uint16_t packetid,
|
||||
int32_t count, MQTTString topicFilters[]);
|
||||
|
||||
DLLExport int32_t MQTTDeserialize_unsubscribe(uint8_t* dup, uint16_t* packetid, int32_t max_count, int32_t* count, MQTTString topicFilters[],
|
||||
uint8_t* buf, int32_t len);
|
||||
|
||||
DLLExport int32_t MQTTSerialize_unsuback(uint8_t* buf, int32_t buflen, uint16_t packetid);
|
||||
DLLExport int32_t MQTTDeserialize_unsuback(uint16_t* packetid, uint8_t* buf, int32_t len);
|
||||
|
||||
#endif /* MQTTUNSUBSCRIBE_H_ */
|
||||
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2014 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||
*******************************************************************************/
|
||||
|
||||
#include "MQTTPacket.h"
|
||||
#include "StackTrace.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* Determines the length of the MQTT unsubscribe packet that would be produced using the supplied parameters
|
||||
* @param count the number of topic filter strings in topicFilters
|
||||
* @param topicFilters the array of topic filter strings to be used in the publish
|
||||
* @return the length of buffer needed to contain the serialized version of the packet
|
||||
*/
|
||||
int32_t MQTTSerialize_unsubscribeLength(int32_t count, MQTTString topicFilters[])
|
||||
{
|
||||
int32_t len = 2; /* packetid */
|
||||
|
||||
for (int32_t i = 0; i < count; ++i)
|
||||
len += 2 + MQTTstrlen(topicFilters[i]); /* length + topic*/
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes the supplied unsubscribe data into the supplied buffer, ready for sending
|
||||
* @param buf the raw buffer data, of the correct length determined by the remaining length field
|
||||
* @param buflen the length in bytes of the data in the supplied buffer
|
||||
* @param dup integer - the MQTT dup flag
|
||||
* @param packetid integer - the MQTT packet identifier
|
||||
* @param count - number of members in the topicFilters array
|
||||
* @param topicFilters - array of topic filter names
|
||||
* @return the length of the serialized data. <= 0 indicates error
|
||||
*/
|
||||
int32_t MQTTSerialize_unsubscribe(uint8_t* buf, int32_t buflen, uint8_t dup, uint16_t packetid,
|
||||
int32_t count, MQTTString topicFilters[])
|
||||
{
|
||||
uint8_t *ptr = buf;
|
||||
MQTTHeader header = {0};
|
||||
int32_t rem_len = 0;
|
||||
int32_t rc = -1;
|
||||
|
||||
FUNC_ENTRY;
|
||||
|
||||
if (MQTTPacket_len(rem_len = MQTTSerialize_unsubscribeLength(count, topicFilters)) > buflen)
|
||||
{
|
||||
rc = MQTTPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
header.byte = 0;
|
||||
header.bits.type = UNSUBSCRIBE;
|
||||
header.bits.dup = dup;
|
||||
header.bits.qos = 1;
|
||||
writeChar(&ptr, header.byte); /* write header */
|
||||
ptr += MQTTPacket_encode(ptr, rem_len); /* write remaining length */;
|
||||
writeInt(&ptr, packetid);
|
||||
|
||||
for (int32_t i = 0; i < count; ++i)
|
||||
writeMQTTString(&ptr, topicFilters[i]);
|
||||
|
||||
rc = ptr - buf;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into unsuback data
|
||||
* @param packetid returned integer - the MQTT packet identifier
|
||||
* @param buf the raw buffer data, of the correct length determined by the remaining length field
|
||||
* @param buflen the length in bytes of the data in the supplied buffer
|
||||
* @return error code. 1 is success, 0 is failure
|
||||
*/
|
||||
int32_t MQTTDeserialize_unsuback(uint16_t* packetid, uint8_t* buf, int32_t buflen)
|
||||
{
|
||||
uint8_t type = 0;
|
||||
uint8_t dup = 0;
|
||||
int32_t rc = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
|
||||
rc = MQTTDeserialize_ack(&type, &dup, packetid, buf, buflen);
|
||||
|
||||
if (type == UNSUBACK)
|
||||
rc = 1;
|
||||
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2014 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||
*******************************************************************************/
|
||||
#include "MQTTPacket.h"
|
||||
#include "StackTrace.h"
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into unsubscribe data
|
||||
* @param dup integer returned - the MQTT dup flag
|
||||
* @param packetid integer returned - the MQTT packet identifier
|
||||
* @param maxcount - the maximum number of members allowed in the topicFilters and requestedQoSs arrays
|
||||
* @param count - number of members in the topicFilters and requestedQoSs arrays
|
||||
* @param topicFilters - array of topic filter names
|
||||
* @param buf the raw buffer data, of the correct length determined by the remaining length field
|
||||
* @param buflen the length in bytes of the data in the supplied buffer
|
||||
* @return the length of the serialized data. <= 0 indicates error
|
||||
*/
|
||||
int32_t MQTTDeserialize_unsubscribe(uint8_t* dup, uint16_t* packetid, int32_t maxcount, int32_t* count, MQTTString topicFilters[],
|
||||
uint8_t* buf, int32_t len)
|
||||
{
|
||||
MQTTHeader header = {0};
|
||||
uint8_t* curdata = buf;
|
||||
uint8_t* enddata = NULL;
|
||||
int32_t rc = 0;
|
||||
int32_t mylen = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
|
||||
header.byte = readChar(&curdata);
|
||||
if (header.bits.type != UNSUBSCRIBE)
|
||||
goto exit;
|
||||
*dup = header.bits.dup;
|
||||
|
||||
curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
|
||||
enddata = curdata + mylen;
|
||||
|
||||
*packetid = readInt(&curdata);
|
||||
*count = 0;
|
||||
|
||||
while (curdata < enddata)
|
||||
{
|
||||
if (!readMQTTLenString(&topicFilters[*count], &curdata, enddata))
|
||||
goto exit;
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
rc = 1;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes the supplied unsuback data into the supplied buffer, ready for sending
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param buflen the length in bytes of the supplied buffer
|
||||
* @param packetid integer - the MQTT packet identifier
|
||||
* @return the length of the serialized data. <= 0 indicates error
|
||||
*/
|
||||
int32_t MQTTSerialize_unsuback(uint8_t* buf, int32_t buflen, uint16_t packetid)
|
||||
{
|
||||
MQTTHeader header = {0};
|
||||
int32_t rc = 0;
|
||||
uint8_t *ptr = buf;
|
||||
|
||||
FUNC_ENTRY;
|
||||
|
||||
if (buflen < 2)
|
||||
{
|
||||
rc = MQTTPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
header.byte = 0;
|
||||
header.bits.type = UNSUBACK;
|
||||
writeChar(&ptr, header.byte); /* write header */
|
||||
ptr += MQTTPacket_encode(ptr, 2); /* write remaining length */
|
||||
writeInt(&ptr, packetid);
|
||||
|
||||
rc = ptr - buf;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2014 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||
* Ian Craggs - fix for bug #434081
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef STACKTRACE_H_
|
||||
#define STACKTRACE_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#define NOSTACKTRACE 1
|
||||
|
||||
#if defined(NOSTACKTRACE)
|
||||
#define FUNC_ENTRY
|
||||
#define FUNC_ENTRY_NOLOG
|
||||
#define FUNC_ENTRY_MED
|
||||
#define FUNC_ENTRY_MAX
|
||||
#define FUNC_EXIT
|
||||
#define FUNC_EXIT_NOLOG
|
||||
#define FUNC_EXIT_MED
|
||||
#define FUNC_EXIT_MAX
|
||||
#define FUNC_EXIT_RC(x)
|
||||
#define FUNC_EXIT_MED_RC(x)
|
||||
#define FUNC_EXIT_MAX_RC(x)
|
||||
|
||||
#else
|
||||
|
||||
#if defined(WIN32)
|
||||
#define inline __inline
|
||||
#define FUNC_ENTRY StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MINIMUM)
|
||||
#define FUNC_ENTRY_NOLOG StackTrace_entry(__FUNCTION__, __LINE__, -1)
|
||||
#define FUNC_ENTRY_MED StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MEDIUM)
|
||||
#define FUNC_ENTRY_MAX StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MAXIMUM)
|
||||
#define FUNC_EXIT StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MINIMUM)
|
||||
#define FUNC_EXIT_NOLOG StackTrace_exit(__FUNCTION__, __LINE__, -1)
|
||||
#define FUNC_EXIT_MED StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MEDIUM)
|
||||
#define FUNC_EXIT_MAX StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MAXIMUM)
|
||||
#define FUNC_EXIT_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MINIMUM)
|
||||
#define FUNC_EXIT_MED_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MEDIUM)
|
||||
#define FUNC_EXIT_MAX_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MAXIMUM)
|
||||
#else
|
||||
#define FUNC_ENTRY StackTrace_entry(__func__, __LINE__, TRACE_MINIMUM)
|
||||
#define FUNC_ENTRY_NOLOG StackTrace_entry(__func__, __LINE__, -1)
|
||||
#define FUNC_ENTRY_MED StackTrace_entry(__func__, __LINE__, TRACE_MEDIUM)
|
||||
#define FUNC_ENTRY_MAX StackTrace_entry(__func__, __LINE__, TRACE_MAXIMUM)
|
||||
#define FUNC_EXIT StackTrace_exit(__func__, __LINE__, NULL, TRACE_MINIMUM)
|
||||
#define FUNC_EXIT_NOLOG StackTrace_exit(__func__, __LINE__, NULL, -1)
|
||||
#define FUNC_EXIT_MED StackTrace_exit(__func__, __LINE__, NULL, TRACE_MEDIUM)
|
||||
#define FUNC_EXIT_MAX StackTrace_exit(__func__, __LINE__, NULL, TRACE_MAXIMUM)
|
||||
#define FUNC_EXIT_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MINIMUM)
|
||||
#define FUNC_EXIT_MED_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MEDIUM)
|
||||
#define FUNC_EXIT_MAX_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MAXIMUM)
|
||||
|
||||
void StackTrace_entry(const char* name, int32_t line, int32_t trace);
|
||||
void StackTrace_exit(const char* name, int32_t line, void* return_value, int32_t trace);
|
||||
|
||||
void StackTrace_printStack(FILE* dest);
|
||||
char* StackTrace_get(unsigned long);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* STACKTRACE_H_ */
|
||||
@ -0,0 +1,80 @@
|
||||
#include "mqtt_interface.h"
|
||||
#include "wizchip_conf.h"
|
||||
#include "socket.h"
|
||||
//#include <terminal_io.h>
|
||||
#include <stdint.h>
|
||||
#include "millis.h"
|
||||
|
||||
/*
|
||||
uint32_t MilliTimer;
|
||||
|
||||
void MilliTimer_Handler(void)
|
||||
{
|
||||
MilliTimer++;
|
||||
}
|
||||
*/
|
||||
|
||||
int8_t expired(Timer* timer)
|
||||
{
|
||||
int32_t left = (timer->end_time) - millis();
|
||||
return (left < 0);
|
||||
}
|
||||
|
||||
void countdown_ms(Timer* timer, uint32_t timeout)
|
||||
{
|
||||
timer->end_time = millis() + timeout;
|
||||
}
|
||||
|
||||
void countdown(Timer* timer, uint32_t timeout)
|
||||
{
|
||||
timer->end_time = millis() + (timeout * 1000UL);
|
||||
}
|
||||
|
||||
int32_t left_ms(Timer* timer)
|
||||
{
|
||||
int32_t left = timer->end_time - millis();
|
||||
return (left < 0) ? 0 : left;
|
||||
}
|
||||
|
||||
void InitTimer(Timer* timer)
|
||||
{
|
||||
timer->end_time = 0;
|
||||
}
|
||||
|
||||
|
||||
void NewNetwork(Network* n)
|
||||
{
|
||||
//n->my_socket = 0; //initialized outside actually..
|
||||
n->mqttread = w5500_read;
|
||||
n->mqttwrite = w5500_write;
|
||||
n->disconnect = w5500_disconnect;
|
||||
}
|
||||
|
||||
int32_t w5500_read(Network* n, uint8_t* buffer, int32_t len, int32_t timeout_ms)
|
||||
{
|
||||
if ((getSn_SR(n->my_socket) == SOCK_ESTABLISHED) && (getSn_RX_RSR(n->my_socket) > 0))
|
||||
return recv(n->my_socket, buffer, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t w5500_write(Network* n, uint8_t* buffer, int32_t len, int32_t timeout_ms)
|
||||
{
|
||||
if (getSn_SR(n->my_socket) == SOCK_ESTABLISHED)
|
||||
return send(n->my_socket, buffer, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void w5500_disconnect(Network* n)
|
||||
{
|
||||
disconnect(n->my_socket);
|
||||
}
|
||||
|
||||
int32_t ConnectNetwork(Network* n, uint8_t* ip, uint16_t port)
|
||||
{
|
||||
socket(n->my_socket, Sn_MR_TCP, 12345, 0);
|
||||
connect(n->my_socket, ip, port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
#ifndef __MQTT_INTERFACE_H_
|
||||
#define __MQTT_INTERFACE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct Timer Timer;
|
||||
|
||||
struct Timer
|
||||
{
|
||||
uint32_t systick_period;
|
||||
uint32_t end_time;
|
||||
};
|
||||
|
||||
typedef struct Network Network;
|
||||
|
||||
struct Network
|
||||
{
|
||||
int32_t my_socket;
|
||||
int32_t (*mqttread) (Network*, uint8_t*, int32_t, int32_t);
|
||||
int32_t (*mqttwrite) (Network*, uint8_t*, int32_t, int32_t);
|
||||
void (*disconnect) (Network*);
|
||||
};
|
||||
|
||||
void InitTimer(Timer*);
|
||||
/*
|
||||
void MilliTimer_Handler(void);
|
||||
*/
|
||||
|
||||
int8_t expired(Timer*);
|
||||
void countdown_ms(Timer*, uint32_t);
|
||||
void countdown(Timer*, uint32_t);
|
||||
int32_t left_ms(Timer*);
|
||||
|
||||
int32_t w5500_read(Network*, uint8_t*, int32_t, int32_t);
|
||||
int32_t w5500_write(Network*, uint8_t*, int32_t, int32_t);
|
||||
void w5500_disconnect(Network*);
|
||||
void NewNetwork(Network*);
|
||||
|
||||
int32_t ConnectNetwork(Network*, uint8_t*, uint16_t);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,58 @@
|
||||
TARGET = main
|
||||
SRCS := $(shell find -name '*.c')
|
||||
FILES = $(SRCS:%.c=%) #main uart avrIOhelper/io-helper #uart#hier alle c-Datein reinschreiben, trennung durch " " und ohne .c-Endung
|
||||
MCU = atmega2560
|
||||
PROGC = m2560
|
||||
CC = avr-gcc
|
||||
TOOL = atmelice_isp
|
||||
#TOOL = avrispmkii
|
||||
#TOOL = usbasp-clone
|
||||
|
||||
BUILDDIR = Builds
|
||||
|
||||
DEFINES = -I . -IInternet/MQTT -I Internet/MQTT/MQTTPacket/src -I Ethernet/W5500 -I Ethernet -DF_CPU=16000000UL -D_WIZCHIP_=W5100
|
||||
|
||||
CFLAGS =-mmcu=$(MCU) -O2 -Wall -Wpedantic $(DEFINES) -std=c99 -ffunction-sections -fdata-sections
|
||||
LDFLAGS =-mmcu=$(MCU) -Wl,--gc-sections
|
||||
|
||||
LDFILES = $(foreach FILE,$(FILES),$(BUILDDIR)/$(FILE).o)
|
||||
|
||||
all: clean $(BUILDDIR)/$(TARGET).elf
|
||||
|
||||
$(BUILDDIR)/%.o: %.c
|
||||
mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c $< -o $(BUILDDIR)/$*.o
|
||||
|
||||
$(BUILDDIR)/$(TARGET).elf: $(LDFILES)
|
||||
mkdir -p $(dir $@)
|
||||
$(CC) $(LDFLAGS) $(LDFILES) -o $(BUILDDIR)/$(TARGET).elf
|
||||
|
||||
$(BUILDDIR)/$(TARGET).hex : $(BUILDDIR)/$(TARGET).elf
|
||||
avr-objcopy -j .data -j .text -O ihex $< $@
|
||||
|
||||
fuse:
|
||||
avrdude -p $(PROGC) -c $(TOOL) -U lfuse:w:0xE8:m -U hfuse:w:0xD1:m
|
||||
|
||||
load: $(BUILDDIR)/$(TARGET).hex
|
||||
avrdude -p $(PROGC) -c $(TOOL) -U flash:w:$(BUILDDIR)/$(TARGET).hex -v -B 4MHz
|
||||
|
||||
program: clean load
|
||||
|
||||
reset:
|
||||
avrdude -p $(PROGC) -c $(TOOL)
|
||||
|
||||
size: $(BUILDDIR)/$(TARGET).elf
|
||||
avr-size -C --mcu=$(MCU) $(BUILDDIR)/$(TARGET).elf
|
||||
|
||||
.PHONY=clean
|
||||
clean:
|
||||
rm -rf $(BUILDDIR)
|
||||
|
||||
|
||||
#Fuse m1284p external Osz. Long startuptime
|
||||
# avrdude -c usbasp-clone -p m1284p -U lfuse:w:0xff:m -U hfuse:w:0xd9:m -U efuse:w:0xff:m
|
||||
|
||||
#Fuse m1284p internal Osz. Long startuptime
|
||||
# avrdude -c usbasp-clone -p m1284p -U lfuse:w:0xe2:m -U hfuse:w:0xd9:m -U efuse:w:0xff:m
|
||||
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
## Network Config
|
||||
|
||||
|Parameter| Value
|
||||
|---------|-------------
|
||||
| IP Adr. | 192.168.2.1
|
||||
| Subnet | 255.255.0.0
|
||||
| MAC | 00-08-dc-ab-cd-f1
|
||||
|
||||
### MQTT
|
||||
|
||||
#### Connect to MQTT Host 192.168.5.2
|
||||
|
||||
##### Publish
|
||||
|Topic |Values | Unit
|
||||
|--------------------------------------------------------|------------|-------
|
||||
| TODO | |
|
||||
|
||||
|
||||
##### Subscribe
|
||||
|
||||
|Topic |Values | Unit
|
||||
|--------------------------------------------------------|------------|-------
|
||||
| TODO | |
|
||||
|
||||
## Hardware usage
|
||||
|
||||
### Timers
|
||||
|
||||
|Timer| Type | Usage | Mode | used ISRs | Output connected
|
||||
|-----|--------|-------------------------------|------------------------|----------------|------------------
|
||||
| 0 | 8 bit | Millis Tick Timer (1kHz) | 2 (CTC) | COMPA | -
|
||||
|
||||
### UART
|
||||
|
||||
|UART| Usage
|
||||
|----|----------------------------------
|
||||
| 0 | Debug Prints (connected to USB)
|
||||
| 1 |
|
||||
| 2 |
|
||||
| 3 |
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,100 @@
|
||||
#ifndef _IO_HELPER_
|
||||
#define _IO_HELPER_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define LEVEL 0
|
||||
#define EDGE 1
|
||||
#define RISING 2
|
||||
#define FALLING 3
|
||||
|
||||
#define OFF 0
|
||||
#define ON 1
|
||||
#define BLINK 2
|
||||
#define TOGGLE 3
|
||||
|
||||
|
||||
#define NUMBER_OF_INPUT_BYTES 4
|
||||
|
||||
extern volatile uint8_t outStates[NUMBER_OF_INPUT_BYTES];
|
||||
extern volatile uint8_t outStatesBlinking[NUMBER_OF_INPUT_BYTES];
|
||||
extern volatile uint8_t inStates[NUMBER_OF_INPUT_BYTES];
|
||||
extern volatile uint8_t inStatesRaw[NUMBER_OF_INPUT_BYTES];
|
||||
extern volatile uint8_t ioHelperDebounceTable[NUMBER_OF_INPUT_BYTES*8];
|
||||
extern volatile uint8_t oldInstates[NUMBER_OF_INPUT_BYTES];
|
||||
extern volatile uint8_t inStatesBothEdges[NUMBER_OF_INPUT_BYTES];
|
||||
extern volatile uint8_t inStatesRisingEdge[NUMBER_OF_INPUT_BYTES];
|
||||
extern volatile uint8_t inStatesFallingEdge[NUMBER_OF_INPUT_BYTES];
|
||||
|
||||
|
||||
uint8_t read_Input(uint8_t nr, uint8_t type);
|
||||
void set_Output(uint8_t nr, uint8_t state);
|
||||
|
||||
void ioHelperInitBuffer(void);
|
||||
void ioHelperSetOuts(void);
|
||||
void ioHelperReadPins(void);
|
||||
void ioHelperIoConf(void);
|
||||
void ioHelperSetBit(volatile uint8_t *list, uint8_t nr, uint8_t state);
|
||||
unsigned char ioHelperReadBit(volatile uint8_t *list, uint8_t nr);
|
||||
void ioHelperDebounce(void);
|
||||
void ioHelperEdgeDetector(void);
|
||||
|
||||
//Outputs
|
||||
//Verknüpfen von Pin | Bit mit Bitposition (0...n) outStates[0...n/8].
|
||||
#define BitPE4 0 //D0
|
||||
#define BitPE5 1 //D1
|
||||
#define BitPG5 2 //D2
|
||||
#define BitPE3 3 //D3
|
||||
#define BitPH3 4 //D4
|
||||
#define BitPH4 5 //D5
|
||||
#define BitPH5 6 //D6
|
||||
#define BitPH6 7 //D7
|
||||
|
||||
#define BitPB4 8 //D8
|
||||
#define BitPB5 9 //D9
|
||||
#define BitPB6 10 //D10
|
||||
#define BitPB7 11 //D11
|
||||
#define BitPL7 12 //D12
|
||||
#define BitPL6 13 //D13
|
||||
#define BitPL5 14 //D14
|
||||
#define BitPL4 15 //D15
|
||||
|
||||
#define BitPL3 16 //D16
|
||||
#define BitPL2 17 //D17
|
||||
#define BitPL1 18 //D18
|
||||
#define BitPL0 19 //D19
|
||||
#define BitPD4 20 //D20
|
||||
#define BitPD5 21 //D21
|
||||
#define BitPD6 22 //D22
|
||||
#define BitPJ4 23 //D23
|
||||
|
||||
|
||||
#define LED_GRN_NOTAUS_ANLAGE BitPE4
|
||||
#define LED_ROT_NOTAUS_ANLAGE BitPE5
|
||||
#define LED_GRN_NOTAUS_SCHRANK BitPG5
|
||||
#define LED_ROT_NOTAUS_SCHRANK BitPE3
|
||||
#define LED_PLC_OK BitPH5
|
||||
#define LED_BUS_OK BitPD4
|
||||
|
||||
|
||||
//Inputs
|
||||
//Verknüpfen von Pin | Bit mit Bitposition (0...n) inStates[0...n/8].
|
||||
#define BitPinF0 0 //A0
|
||||
#define BitPinF1 1 //A1
|
||||
#define BitPinF2 2 //A2
|
||||
#define BitPinF3 3 //A3
|
||||
#define BitPinF4 4 //A4
|
||||
#define BitPinF5 5 //A5
|
||||
#define BitPinF6 6 //A6
|
||||
#define BitPinF7 7 //A7
|
||||
|
||||
#define BitPinK0 8 //A8
|
||||
#define BitPinK1 9 //A9
|
||||
#define BitPinD3 10 //INO
|
||||
#define BitPinD2 11 //IN1
|
||||
|
||||
#define IN_ANLAGE_EIN_INV BitPinF5
|
||||
#define IN_NOTAUS_ANLAGE BitPinF7
|
||||
#define IN_NOTAUS_SCHRANK BitPinK0
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,155 @@
|
||||
import string
|
||||
|
||||
ddr="""#ifdef DDRA
|
||||
DDRA|=0
|
||||
#ifdef BitPA0
|
||||
|(1<<0)
|
||||
#endif
|
||||
#ifdef BitPA1
|
||||
|(1<<1)
|
||||
#endif
|
||||
#ifdef BitPA2
|
||||
|(1<<2)
|
||||
#endif
|
||||
#ifdef BitPA3
|
||||
|(1<<3)
|
||||
#endif
|
||||
#ifdef BitPA4
|
||||
|(1<<4)
|
||||
#endif
|
||||
#ifdef BitPA5
|
||||
|(1<<5)
|
||||
#endif
|
||||
#ifdef BitPA6
|
||||
|(1<<6)
|
||||
#endif
|
||||
#ifdef BitPA7
|
||||
|(1<<7)
|
||||
#endif
|
||||
|0;
|
||||
|
||||
#endif
|
||||
|
||||
"""
|
||||
|
||||
port="""
|
||||
#ifdef PORTA
|
||||
PORTA|=0
|
||||
#ifdef BitPA0
|
||||
|(getBit1(BitPA0)<<0)
|
||||
#endif
|
||||
#ifdef BitPA1
|
||||
|(getBit1(BitPA1)<<1)
|
||||
#endif
|
||||
#ifdef BitPA2
|
||||
|(getBit1(BitPA2)<<2)
|
||||
#endif
|
||||
#ifdef BitPA3
|
||||
|(getBit1(BitPA3)<<3)
|
||||
#endif
|
||||
#ifdef BitPA4
|
||||
|(getBit1(BitPA4)<<4)
|
||||
#endif
|
||||
#ifdef BitPA5
|
||||
|(getBit1(BitPA5)<<5)
|
||||
#endif
|
||||
#ifdef BitPA6
|
||||
|(getBit1(BitPA6)<<6)
|
||||
#endif
|
||||
#ifdef BitPA7
|
||||
|(getBit1(BitPA7)<<7)
|
||||
#endif
|
||||
|0;
|
||||
|
||||
PORTA&=~(0
|
||||
#ifdef BitPA0
|
||||
|(getBit0(BitPA0)<<0)
|
||||
#endif
|
||||
#ifdef BitPA1
|
||||
|(getBit0(BitPA1)<<1)
|
||||
#endif
|
||||
#ifdef BitPA2
|
||||
|(getBit0(BitPA2)<<2)
|
||||
#endif
|
||||
#ifdef BitPA3
|
||||
|(getBit0(BitPA3)<<3)
|
||||
#endif
|
||||
#ifdef BitPA4
|
||||
|(getBit0(BitPA4)<<4)
|
||||
#endif
|
||||
#ifdef BitPA5
|
||||
|(getBit0(BitPA5)<<5)
|
||||
#endif
|
||||
#ifdef BitPA6
|
||||
|(getBit0(BitPA6)<<6)
|
||||
#endif
|
||||
#ifdef BitPA7
|
||||
|(getBit0(BitPA7)<<7)
|
||||
#endif
|
||||
|0);
|
||||
#endif
|
||||
|
||||
"""
|
||||
|
||||
pin="""
|
||||
#ifdef PINA
|
||||
#ifdef BitPinA0
|
||||
ioHelperCpBit(PINA,0,BitPinA0);
|
||||
#endif
|
||||
#ifdef BitPinA1
|
||||
ioHelperCpBit(PINA,1,BitPinA1);
|
||||
#endif
|
||||
#ifdef BitPinA2
|
||||
ioHelperCpBit(PINA,2,BitPinA2);
|
||||
#endif
|
||||
#ifdef BitPinA3
|
||||
ioHelperCpBit(PINA,3,BitPinA3);
|
||||
#endif
|
||||
#ifdef BitPinA4
|
||||
ioHelperCpBit(PINA,4,BitPinA4);
|
||||
#endif
|
||||
#ifdef BitPinA5
|
||||
ioHelperCpBit(PINA,5,BitPinA5);
|
||||
#endif
|
||||
#ifdef BitPinA6
|
||||
ioHelperCpBit(PINA,6,BitPinA6);
|
||||
#endif
|
||||
#ifdef BitPinA7
|
||||
ioHelperCpBit(PINA,7,BitPinA7);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
"""
|
||||
|
||||
port_letters=list(string.ascii_uppercase);
|
||||
|
||||
allddr=[]
|
||||
for x in range(0,len(port_letters)):
|
||||
allddr.append(ddr)
|
||||
allddr[x]=allddr[x].replace("DDRA","DDR"+port_letters[x])
|
||||
allddr[x]=allddr[x].replace("BitPA","BitP"+port_letters[x])
|
||||
|
||||
allport=[]
|
||||
for x in range(0,len(port_letters)):
|
||||
allport.append(port)
|
||||
allport[x]=allport[x].replace("PORTA","PORT"+port_letters[x])
|
||||
allport[x]=allport[x].replace("BitPA","BitP"+port_letters[x])
|
||||
|
||||
allpin=[]
|
||||
for x in range(0,len(port_letters)):
|
||||
allpin.append(pin)
|
||||
allpin[x]=allpin[x].replace("PINA","PIN"+port_letters[x])
|
||||
allpin[x]=allpin[x].replace("BitPinA","BitPin"+port_letters[x])
|
||||
|
||||
|
||||
for x in allddr:
|
||||
#print(x)
|
||||
pass
|
||||
|
||||
for x in allport:
|
||||
#print(x)
|
||||
pass
|
||||
|
||||
for x in allpin:
|
||||
print(x)
|
||||
pass
|
||||
@ -0,0 +1,18 @@
|
||||
-D
|
||||
__AVR_ATmega2560__
|
||||
-D
|
||||
F_CPU=16000000UL
|
||||
-D
|
||||
_WIZCHIP_=W5100
|
||||
-I
|
||||
/usr/lib/avr/include
|
||||
-I
|
||||
Internet
|
||||
-I
|
||||
Internet/MQTT
|
||||
-I
|
||||
Internet/MQTT/MQTTPacket/src
|
||||
-I
|
||||
Ethernet
|
||||
-I
|
||||
Ethernet/W5500
|
||||
@ -0,0 +1,247 @@
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/wdt.h> // WatchDog
|
||||
#include <string.h>
|
||||
|
||||
#include "Ethernet/socket.h"
|
||||
#include "Ethernet/wizchip_conf.h"
|
||||
|
||||
#include "Internet/MQTT/mqtt_interface.h"
|
||||
#include "Internet/MQTT/MQTTClient.h"
|
||||
|
||||
#include "avrIOhelper/io-helper.h"
|
||||
#include "millis.h"
|
||||
#include "uart.h"
|
||||
#include "spi.h"
|
||||
#include "mqtt.h"
|
||||
|
||||
#include "util/delay.h"
|
||||
|
||||
#define PLC_MQTT_ENABLED 0
|
||||
|
||||
Client mqtt_client;
|
||||
|
||||
//***********Prologue for fast WDT disable & and save reason of reset/power-up: BEGIN
|
||||
uint8_t mcucsr_mirror __attribute__ ((section (".noinit")));
|
||||
|
||||
// This is for fast WDT disable & and save reason of reset/power-up
|
||||
void get_mcusr(void) \
|
||||
__attribute__((naked)) \
|
||||
__attribute__((section(".init3")));
|
||||
void get_mcusr(void)
|
||||
{
|
||||
mcucsr_mirror = MCUSR;
|
||||
MCUSR = 0;
|
||||
wdt_disable();
|
||||
}
|
||||
//***********Prologue for fast WDT disable & and save reason of reset/power-up: END
|
||||
|
||||
|
||||
//FUNC headers
|
||||
static void avr_init(void);
|
||||
void timer0_init(void);
|
||||
void print_network_information(void);
|
||||
|
||||
void IO_LIBRARY_Init(void) {
|
||||
uint8_t bufSize[] = {2, 2, 2, 2, 2, 2, 2, 2};
|
||||
|
||||
reg_wizchip_cs_cbfunc(spi_select, spi_deselect);
|
||||
reg_wizchip_spi_cbfunc(spi_read, spi_write);
|
||||
//reg_wizchip_spiburst_cbfunc(spi_rb_burst, spi_wb_burst);
|
||||
|
||||
wizchip_init(bufSize, bufSize);
|
||||
wizchip_setnetinfo(&netInfo);
|
||||
//wizchip_setinterruptmask(IK_SOCK_0);
|
||||
}
|
||||
|
||||
void do_notaus(){
|
||||
if(read_Input(IN_NOTAUS_ANLAGE, LEVEL) || read_Input(IN_NOTAUS_SCHRANK, LEVEL)){ // NOTAUS
|
||||
set_Output(LED_GRN_NOTAUS_SCHRANK, OFF); // disable green lamps
|
||||
set_Output(LED_GRN_NOTAUS_ANLAGE, OFF);
|
||||
}
|
||||
|
||||
if(read_Input(IN_NOTAUS_ANLAGE, LEVEL) && read_Input(IN_NOTAUS_SCHRANK, LEVEL)){ // both activated
|
||||
set_Output(LED_ROT_NOTAUS_ANLAGE, BLINK);
|
||||
set_Output(LED_ROT_NOTAUS_SCHRANK, BLINK);
|
||||
}
|
||||
else if(read_Input(IN_NOTAUS_ANLAGE, LEVEL)){ // top one activated
|
||||
set_Output(LED_ROT_NOTAUS_ANLAGE, BLINK);
|
||||
set_Output(LED_ROT_NOTAUS_SCHRANK, ON);
|
||||
}
|
||||
else if(read_Input(IN_NOTAUS_SCHRANK, LEVEL)){ // bottom one activated
|
||||
set_Output(LED_ROT_NOTAUS_SCHRANK, BLINK);
|
||||
set_Output(LED_ROT_NOTAUS_ANLAGE, ON);
|
||||
}
|
||||
else{ // none activated
|
||||
set_Output(LED_ROT_NOTAUS_SCHRANK, OFF);
|
||||
set_Output(LED_ROT_NOTAUS_ANLAGE, OFF);
|
||||
if(!read_Input(IN_ANLAGE_EIN_INV, LEVEL)){
|
||||
set_Output(LED_GRN_NOTAUS_ANLAGE, ON);
|
||||
set_Output(LED_GRN_NOTAUS_SCHRANK, ON);
|
||||
}
|
||||
else{
|
||||
set_Output(LED_GRN_NOTAUS_ANLAGE, ON);
|
||||
set_Output(LED_GRN_NOTAUS_SCHRANK, ON);
|
||||
set_Output(LED_ROT_NOTAUS_ANLAGE, ON);
|
||||
set_Output(LED_ROT_NOTAUS_SCHRANK, ON);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// INIT MCU
|
||||
avr_init();
|
||||
spi_init(); //SPI Master, MODE0, 4Mhz(DIV4), CS_PB.3=HIGH - suitable for WIZNET 5x00(1/2/5)
|
||||
//spi_speed_tst(); / Here on SPI pins: MOSI 400Khz freq out, on SCLK 3.2MhzOUT (Witk SPI CLK 4Mhz)
|
||||
|
||||
ioHelperInitBuffer();
|
||||
ioHelperIoConf();
|
||||
|
||||
//Wizchip WIZ5500 Ethernet initialize
|
||||
IO_LIBRARY_Init(); //After that ping must working
|
||||
print_network_information();
|
||||
|
||||
#if PLC_MQTT_ENABLED
|
||||
//****************MQTT client initialize
|
||||
//Find MQTT broker and connect with it
|
||||
uint8_t mqtt_buf[100];
|
||||
int32_t mqtt_rc = 0;
|
||||
Network mqtt_network;
|
||||
mqtt_network.my_socket = SOCK_MQTT;
|
||||
|
||||
printf(">>Trying connect to MQTT broker: %d.%d.%d.%d ..\r\n", MQTT_targetIP[0], MQTT_targetIP[1], MQTT_targetIP[2], MQTT_targetIP[3]);
|
||||
NewNetwork(&mqtt_network);
|
||||
ConnectNetwork(&mqtt_network, MQTT_targetIP, 1883);
|
||||
MQTTClient(&mqtt_client, &mqtt_network, 1000, mqtt_buf, 100, mqtt_readBuffer, MQTT_BUFFER_SIZE);
|
||||
|
||||
//Connection to MQTT broker
|
||||
MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
|
||||
data.willFlag = 0;
|
||||
data.MQTTVersion = 4;//3;
|
||||
data.clientID.cstring = (char*)"controllino_wasserbecken";
|
||||
data.username.cstring = (char*)"Wasserbecken";
|
||||
data.password.cstring = (char*)"\0";
|
||||
data.keepAliveInterval = 10;
|
||||
data.cleansession = 1;
|
||||
mqtt_rc = MQTTConnect(&mqtt_client, &data);
|
||||
if (mqtt_rc == SUCCESSS)
|
||||
{
|
||||
printf("++MQTT Connected SUCCESS: %ld\r\n", mqtt_rc);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("--MQTT Connected ERROR: %ld\r\n", mqtt_rc);
|
||||
while(1); //Reboot the board
|
||||
}
|
||||
|
||||
// Subscribe to all topics
|
||||
char SubString[] = "/Filamentanlage/02_Wasserbecken/#";
|
||||
//char SubString[] = "/Filamentanlage/03_Wasserbecken/#";
|
||||
mqtt_rc = MQTTSubscribe(&mqtt_client, SubString, QOS0, messageArrived);
|
||||
printf("Subscribed (%s) %ld\r\n", SubString, mqtt_rc);
|
||||
#endif
|
||||
|
||||
|
||||
ioHelperSetBit(outStatesBlinking, LED_PLC_OK, 1);
|
||||
|
||||
uint32_t timer_blink_outs = millis();
|
||||
uint32_t timer_send_uptime = millis();
|
||||
|
||||
printf("anlage: %x\n\r", read_Input(IN_ANLAGE_EIN_INV, LEVEL));
|
||||
|
||||
while(1)
|
||||
{
|
||||
wdt_reset(); // WDT reset at least every sec
|
||||
|
||||
ioHelperReadPins();
|
||||
ioHelperDebounce();
|
||||
ioHelperEdgeDetector();
|
||||
|
||||
// Toggle all outs which are set to blinking
|
||||
if(millis() - timer_blink_outs > 500){
|
||||
outStates[0] ^= outStatesBlinking[0];
|
||||
outStates[1] ^= outStatesBlinking[1];
|
||||
timer_blink_outs = millis();
|
||||
}
|
||||
|
||||
#if PLC_MQTT_ENABLED
|
||||
// send misc info
|
||||
if(millis() - timer_send_uptime > 5000){
|
||||
timer_send_uptime += 5000;
|
||||
char msg[64];
|
||||
sprintf(msg, "%ld", millis()/1000);
|
||||
mqtt_pub(&mqtt_client, "/Filamentanlage/02_Wasserbecken/uptime", msg, strlen(msg));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if(read_Input(IN_ANLAGE_EIN_INV, FALLING)){
|
||||
printf("anlage ein\n\r");
|
||||
}
|
||||
// ioHelperSetBit(outStates, LED_GRN_NOTAUS_SCHRANK, 1);
|
||||
//}
|
||||
//else{
|
||||
// ioHelperSetBit(outStates, LED_GRN_NOTAUS_SCHRANK, 0);
|
||||
//}
|
||||
do_notaus();
|
||||
|
||||
#if PLC_MQTT_ENABLED
|
||||
ioHelperSetBit(outStates, LED_BUS_OK, 1);
|
||||
ioHelperSetOuts();
|
||||
MQTTYield(&mqtt_client, 10); //blocking call
|
||||
ioHelperSetBit(outStates, LED_BUS_OK, 0);
|
||||
#endif
|
||||
ioHelperSetOuts();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Timer0
|
||||
// 1ms IRQ
|
||||
// Used for millis() timing
|
||||
void timer0_init(void)
|
||||
{
|
||||
TCCR0A = (1<<WGM01); //TIMER0 SET-UP: CTC MODE
|
||||
TCCR0B = (1<<CS01)|(1<<CS00); // PS 1:64
|
||||
OCR0A = 249; // 1ms reach for clear (16mz:64=>250kHz:250-=>1kHz)
|
||||
TIMSK0 |= 1<<OCIE0A; //IRQ on TIMER0 output compareA
|
||||
}
|
||||
|
||||
static void avr_init(void)
|
||||
{
|
||||
// Initialize device here.
|
||||
// WatchDog INIT
|
||||
wdt_enable(WDTO_8S); // set up wdt reset interval 2 second
|
||||
wdt_reset(); // wdt reset ~ every <2000ms
|
||||
|
||||
timer0_init();// Timer0 millis engine init
|
||||
uart_init();
|
||||
|
||||
sei(); //re-enable global interrupts
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void print_network_information(void)
|
||||
{
|
||||
|
||||
uint8_t tmpstr[6] = {0,};
|
||||
ctlwizchip(CW_GET_ID,(void*)tmpstr); // Get WIZCHIP name
|
||||
printf("\r\n=======================================\r\n");
|
||||
printf(" WIZnet chip: %s \r\n", tmpstr);
|
||||
printf("=======================================\r\n");
|
||||
|
||||
wiz_NetInfo gWIZNETINFO;
|
||||
wizchip_getnetinfo(&gWIZNETINFO);
|
||||
if (gWIZNETINFO.dhcp == NETINFO_STATIC)
|
||||
printf("STATIC IP\r\n");
|
||||
else
|
||||
printf("DHCP IP\r\n");
|
||||
printf("Mac address: %02x:%02x:%02x:%02x:%02x:%02x\n\r",gWIZNETINFO.mac[0],gWIZNETINFO.mac[1],gWIZNETINFO.mac[2],gWIZNETINFO.mac[3],gWIZNETINFO.mac[4],gWIZNETINFO.mac[5]);
|
||||
printf("IP address : %d.%d.%d.%d\n\r",gWIZNETINFO.ip[0],gWIZNETINFO.ip[1],gWIZNETINFO.ip[2],gWIZNETINFO.ip[3]);
|
||||
printf("SM Mask : %d.%d.%d.%d\n\r",gWIZNETINFO.sn[0],gWIZNETINFO.sn[1],gWIZNETINFO.sn[2],gWIZNETINFO.sn[3]);
|
||||
printf("Gate way : %d.%d.%d.%d\n\r",gWIZNETINFO.gw[0],gWIZNETINFO.gw[1],gWIZNETINFO.gw[2],gWIZNETINFO.gw[3]);
|
||||
printf("DNS Server : %d.%d.%d.%d\n\r",gWIZNETINFO.dns[0],gWIZNETINFO.dns[1],gWIZNETINFO.dns[2],gWIZNETINFO.dns[3]);
|
||||
}
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include "millis.h"
|
||||
|
||||
volatile unsigned long _millis; // for millis tick !! Overflow every ~49.7 days
|
||||
|
||||
ISR (TIMER0_COMPA_vect)
|
||||
{
|
||||
_millis++; // INC millis tick
|
||||
}
|
||||
|
||||
unsigned long millis(void)
|
||||
{
|
||||
unsigned long i;
|
||||
cli();
|
||||
// Atomic tick reading
|
||||
i = _millis;
|
||||
sei();
|
||||
return i;
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
#ifndef _MILLIS_H_
|
||||
#define _MILLIS_H_
|
||||
|
||||
#define TICK_PER_SEC 1000UL
|
||||
unsigned long millis(void);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,66 @@
|
||||
#include <string.h>
|
||||
#include "mqtt.h"
|
||||
|
||||
uint8_t mqtt_readBuffer[MQTT_BUFFER_SIZE];
|
||||
volatile uint16_t mes_id;
|
||||
|
||||
wiz_NetInfo netInfo = { .mac = {0x00, 0x08, 0xdc, 0xab, 0xcd, 0xf1}, // Mac address
|
||||
.ip = {192, 168, 2, 1}, // IP address
|
||||
.sn = {255, 255, 0, 0}, // Subnet mask
|
||||
.dns = {0,0,0,0}, // DNS address (google dns)
|
||||
.gw = {192, 168, 0, 1}, // Gateway address
|
||||
.dhcp = NETINFO_STATIC}; //Static IP configuration
|
||||
uint8_t MQTT_targetIP[4] = {192, 168, 5, 2};
|
||||
|
||||
//MQTT subscribe call-back is here
|
||||
void messageArrived(MessageData* md)
|
||||
{
|
||||
char _topic_name[64] = "\0";
|
||||
char _message[128] = "\0";
|
||||
|
||||
MQTTMessage* message = md->message;
|
||||
MQTTString* topic = md->topicName;
|
||||
strncpy(_topic_name, topic->lenstring.data, topic->lenstring.len);
|
||||
strncpy(_message, message->payload, message->payloadlen);
|
||||
printf("<<MQTT Sub: [%s] %s", _topic_name , _message);
|
||||
|
||||
//md->topicName->
|
||||
/*
|
||||
for (uint8_t i = 0; i < md->topicName->lenstring.len; i++)
|
||||
putchar(*(md->topicName->lenstring.data + i));
|
||||
|
||||
printf(" (%.*s)\r\n", (int32_t)message->payloadlen, (char*)message->payload);
|
||||
*/
|
||||
}
|
||||
|
||||
void mqtt_pub(Client* mqtt_client, char * mqtt_topic, char * mqtt_msg, int mqtt_msg_len)
|
||||
{
|
||||
static uint32_t mqtt_pub_count = 0;
|
||||
static uint8_t mqtt_err_cnt = 0;
|
||||
int32_t mqtt_rc;
|
||||
|
||||
printf(">>MQTT pub msg nr%lu ", ++mqtt_pub_count);
|
||||
MQTTMessage pubMessage;
|
||||
pubMessage.qos = QOS0;
|
||||
pubMessage.id = mes_id++;
|
||||
pubMessage.payloadlen = (size_t)mqtt_msg_len;
|
||||
pubMessage.payload = mqtt_msg;
|
||||
mqtt_rc = MQTTPublish(mqtt_client, mqtt_topic , &pubMessage);
|
||||
//Analize MQTT publish result (for MQTT failover mode)
|
||||
if (mqtt_rc == SUCCESSS)
|
||||
{
|
||||
mqtt_err_cnt = 0;
|
||||
printf(" - OK\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(" - ERROR\r\n");
|
||||
//Reboot device after 20 continuous errors (~ 20sec)
|
||||
//while(1);
|
||||
if(mqtt_err_cnt++ > 20)
|
||||
{
|
||||
printf("Connection with MQTT Broker was lost!!\r\nReboot the board..\r\n");
|
||||
while(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
#ifndef _MQTT_H_
|
||||
#define _MQTT_H_
|
||||
|
||||
#include "Ethernet/socket.h"
|
||||
#include "Internet/MQTT/mqtt_interface.h"
|
||||
#include "Internet/MQTT/MQTTClient.h"
|
||||
|
||||
#define SOCK_MQTT 2
|
||||
#define MQTT_BUFFER_SIZE 512 // 2048
|
||||
|
||||
extern uint8_t mqtt_readBuffer[MQTT_BUFFER_SIZE];
|
||||
extern wiz_NetInfo netInfo;
|
||||
extern uint8_t MQTT_targetIP[4];
|
||||
|
||||
void messageArrived(MessageData* md);
|
||||
void mqtt_pub(Client* mqtt_client, char * mqtt_topic, char * mqtt_msg, int mqtt_msg_len);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,37 @@
|
||||
#include "spi.h"
|
||||
|
||||
void spi_select(void)
|
||||
{
|
||||
CS_PORT&=~(1<<CS_BIT);
|
||||
}
|
||||
|
||||
void spi_deselect(void)
|
||||
{
|
||||
CS_PORT|=(1<<CS_BIT);
|
||||
}
|
||||
|
||||
unsigned char spi_xchg(unsigned char val)
|
||||
{
|
||||
SPDR = val;
|
||||
while (!(SPSR & (1 << SPIF))) ;
|
||||
return SPDR;
|
||||
}
|
||||
|
||||
uint8_t spi_read(){
|
||||
return spi_xchg(0x00);
|
||||
}
|
||||
|
||||
void spi_write(uint8_t d){
|
||||
spi_xchg(d);
|
||||
}
|
||||
|
||||
void spi_init(){
|
||||
CS_PORT |= (1 << CS_BIT); // pull CS pin high
|
||||
CS_DDR |= (1 << CS_BIT); // now make it an output
|
||||
|
||||
SPI_PORT |= (1 << 0); // make sure SS is high
|
||||
SPI_DDR = (1 << PORTB2) | (1 << PORTB1) | (1 << PORTB0); // set MOSI, SCK and SS as output, others as input
|
||||
SPCR = (1 << SPE) | (1 << MSTR); // enable SPI, master mode 0
|
||||
SPCR |= (1 << SPR0) | (0<<SPR1); // div 128
|
||||
SPSR |= (0 << SPI2X); // set the clock rate fck/2
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
#ifndef _SPI_H_
|
||||
#define _SPI_H_
|
||||
|
||||
#include <avr/io.h>
|
||||
|
||||
#define SPI_PORT PORTB /* target-specific port containing the SPI lines */
|
||||
#define SPI_DDR DDRB /* target-specific DDR for the SPI port lines */
|
||||
|
||||
#define CS_DDR DDRJ /* target-specific DDR for chip-select */
|
||||
#define CS_PORT PORTJ /* target-specific port used as chip-select */
|
||||
#define CS_BIT 3 /* target-specific port line used as chip-select */
|
||||
|
||||
uint8_t spi_read();
|
||||
void spi_write(uint8_t d);
|
||||
void spi_select(void);
|
||||
void spi_deselect(void);
|
||||
unsigned char spi_xchg(unsigned char val);
|
||||
void spi_init(void);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,53 @@
|
||||
#include <avr/io.h>
|
||||
#include "uart.h"
|
||||
|
||||
static int uart_putchar(char c, FILE *stream);
|
||||
|
||||
FILE uart_output = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
|
||||
|
||||
void uart_init()
|
||||
{
|
||||
DDRD |= 1 << 1; // TX
|
||||
UART_BAUD_REGH = (BAUDRATE>>8);
|
||||
UART_BAUD_REGL = BAUDRATE; // set baud rate
|
||||
|
||||
UART_CTRL_REGB |= (1<<UART_TXEN_BM)
|
||||
//|(1<<UART_RXEN_BM)
|
||||
|(1<<UART_RXCIE_BM); // enable receiver and transmitter
|
||||
|
||||
UART_CTRL_REGC |= (1<<UART_URSEL_BM)
|
||||
|(1<<UART_UCSZ0_BM)
|
||||
|(1<<UART_UCSZ1_BM); // 8bit data format
|
||||
|
||||
stdout = &uart_output;
|
||||
}
|
||||
|
||||
static int uart_putchar(char c, FILE *stream) {
|
||||
if (c == '\n') {
|
||||
uart_putchar('\r', stream);
|
||||
}
|
||||
loop_until_bit_is_set(UART_CTRL_REGA, UART_UDRE_BM);
|
||||
UART_DATA_REG = c;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void read_sync(char buffer[], uint8_t buffersize, uint8_t * bufferindex){
|
||||
for(int i=0; i < buffersize; i++){
|
||||
buffer[i]=0;
|
||||
}
|
||||
*bufferindex=0;
|
||||
|
||||
char input;
|
||||
do{
|
||||
while ((UART_CTRL_REGA & (1 << UART_RXC_BM)) == 0);
|
||||
input = UART_DATA_REG;
|
||||
|
||||
putchar(input); //echo
|
||||
buffer[*bufferindex]=input;
|
||||
*bufferindex=*bufferindex+1;
|
||||
}while(!(input == '\n' || input == '\r'));
|
||||
buffer[*bufferindex]=0;
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
#ifndef _UART_H_
|
||||
#define _UART_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define BAUD 9600
|
||||
#define BAUDRATE ((F_CPU)/(BAUD*16UL)-1)
|
||||
|
||||
#define UART_BAUD_REGH UBRR0H
|
||||
#define UART_BAUD_REGL UBRR0L
|
||||
|
||||
#define UART_CTRL_REGA UCSR0A
|
||||
#define UART_CTRL_REGB UCSR0B
|
||||
#define UART_CTRL_REGC UCSR0C
|
||||
|
||||
// UCSRA
|
||||
#define UART_UDRE_BM UDRE0
|
||||
#define UART_RXC_BM RXC0
|
||||
|
||||
// UCSRB
|
||||
#define UART_TXEN_BM TXEN0
|
||||
#define UART_RXEN_BM RXEN0
|
||||
#define UART_RXCIE_BM RXCIE0
|
||||
|
||||
// UCSRC
|
||||
#define UART_URSEL_BM 0 /* only for old atmega */
|
||||
#define UART_UCSZ0_BM UCSZ00
|
||||
#define UART_UCSZ1_BM UCSZ01
|
||||
|
||||
#define UART_DATA_REG UDR0
|
||||
|
||||
void uart_init (void);
|
||||
void read_sync(char buffer[], uint8_t buffersize, uint8_t * bufferindex);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue