Compare commits
5 Commits
master
...
8b632ee3d6
| Author | SHA1 | Date | |
|---|---|---|---|
| 8b632ee3d6 | |||
| b814cad16f | |||
| a3a7810658 | |||
| becc43adf8 | |||
| 1639b7eda6 |
Binary file not shown.
@@ -1,386 +0,0 @@
|
|||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
//! \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
@@ -1,425 +0,0 @@
|
|||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
//! \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
@@ -1,353 +0,0 @@
|
|||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
//! \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
@@ -1,225 +0,0 @@
|
|||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
//! \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
@@ -1,267 +0,0 @@
|
|||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
//! \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
@@ -1,931 +0,0 @@
|
|||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
//! \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;
|
|
||||||
}
|
|
||||||
@@ -1,489 +0,0 @@
|
|||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
//! \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_
|
|
||||||
@@ -1,908 +0,0 @@
|
|||||||
//****************************************************************************/
|
|
||||||
//!
|
|
||||||
//! \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();
|
|
||||||
}
|
|
||||||
@@ -1,661 +0,0 @@
|
|||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
//! \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_
|
|
||||||
@@ -1,538 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
||||||
@@ -1,129 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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_ */
|
|
||||||
@@ -1,217 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
@@ -1,153 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,268 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
||||||
@@ -1,443 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,136 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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_ */
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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_ */
|
|
||||||
@@ -1,171 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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_ */
|
|
||||||
@@ -1,140 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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_ */
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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_ */
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
#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;
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
#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
|
|
||||||
5
Makefile
5
Makefile
@@ -4,13 +4,16 @@ FILES = $(SRCS:%.c=%) #main uart avrIOhelper/io-helper #uart#hier alle c-Datei
|
|||||||
MCU = atmega2560
|
MCU = atmega2560
|
||||||
PROGC = m2560
|
PROGC = m2560
|
||||||
CC = avr-gcc
|
CC = avr-gcc
|
||||||
|
#TOOL = stk500 -P /dev/ttyUSB0
|
||||||
|
#TOOL = dragon_isp
|
||||||
|
#TOOL = atmelice
|
||||||
TOOL = atmelice_isp
|
TOOL = atmelice_isp
|
||||||
#TOOL = avrispmkii
|
#TOOL = avrispmkii
|
||||||
#TOOL = usbasp-clone
|
#TOOL = usbasp-clone
|
||||||
|
|
||||||
BUILDDIR = Builds
|
BUILDDIR = Builds
|
||||||
|
|
||||||
DEFINES = -I . -IInternet/MQTT -I Internet/MQTT/MQTTPacket/src -I Ethernet/W5500 -I Ethernet -DF_CPU=16000000UL -D_WIZCHIP_=W5100
|
DEFINES = -I . -DF_CPU=16000000UL -D_WIZCHIP_=W5100
|
||||||
|
|
||||||
CFLAGS =-mmcu=$(MCU) -O2 -Wall -Wpedantic $(DEFINES) -std=c99 -ffunction-sections -fdata-sections
|
CFLAGS =-mmcu=$(MCU) -O2 -Wall -Wpedantic $(DEFINES) -std=c99 -ffunction-sections -fdata-sections
|
||||||
LDFLAGS =-mmcu=$(MCU) -Wl,--gc-sections
|
LDFLAGS =-mmcu=$(MCU) -Wl,--gc-sections
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
|||||||
#ifndef _IO_HELPER_
|
#ifndef _IO_HELPER_
|
||||||
#define _IO_HELPER_
|
#define _IO_HELPER_
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <avr/io.h>
|
||||||
|
|
||||||
#define LEVEL 0
|
#define LEVEL 0
|
||||||
#define EDGE 1
|
#define EDGE 1
|
||||||
@@ -13,24 +13,20 @@
|
|||||||
#define BLINK 2
|
#define BLINK 2
|
||||||
#define TOGGLE 3
|
#define TOGGLE 3
|
||||||
|
|
||||||
|
#define nrOfOutputs 32 //must be multiple of 8
|
||||||
|
#define nrOfInputs 32 //must be multiple of 8
|
||||||
|
|
||||||
#define NUMBER_OF_INPUT_BYTES 4
|
extern volatile uint8_t outStates[nrOfOutputs/8];
|
||||||
|
extern volatile uint8_t inStates[nrOfInputs/8];
|
||||||
|
extern volatile uint8_t ioHelperDebounceTable[nrOfInputs];
|
||||||
|
|
||||||
extern volatile uint8_t outStates[NUMBER_OF_INPUT_BYTES];
|
extern volatile uint8_t outStatesBlinking[nrOfOutputs/8];
|
||||||
extern volatile uint8_t outStatesBlinking[NUMBER_OF_INPUT_BYTES];
|
|
||||||
extern volatile uint8_t inStates[NUMBER_OF_INPUT_BYTES];
|
extern volatile uint8_t inStatesBothEdges[nrOfInputs/8];
|
||||||
extern volatile uint8_t inStatesRaw[NUMBER_OF_INPUT_BYTES];
|
extern volatile uint8_t inStatesRisingEdge[nrOfInputs/8];
|
||||||
extern volatile uint8_t ioHelperDebounceTable[NUMBER_OF_INPUT_BYTES*8];
|
extern volatile uint8_t inStatesFallingEdge[nrOfInputs/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 ioHelperSetOuts(void);
|
||||||
void ioHelperReadPins(void);
|
void ioHelperReadPins(void);
|
||||||
void ioHelperIoConf(void);
|
void ioHelperIoConf(void);
|
||||||
@@ -38,6 +34,10 @@ void ioHelperSetBit(volatile uint8_t *list, uint8_t nr, uint8_t state);
|
|||||||
unsigned char ioHelperReadBit(volatile uint8_t *list, uint8_t nr);
|
unsigned char ioHelperReadBit(volatile uint8_t *list, uint8_t nr);
|
||||||
void ioHelperDebounce(void);
|
void ioHelperDebounce(void);
|
||||||
void ioHelperEdgeDetector(void);
|
void ioHelperEdgeDetector(void);
|
||||||
|
void ioHelperBlinkOuts(void);
|
||||||
|
|
||||||
|
uint8_t read_Input(uint8_t nr, uint8_t type);
|
||||||
|
void set_Output(uint8_t nr, uint8_t state);
|
||||||
|
|
||||||
//Outputs
|
//Outputs
|
||||||
//Verknüpfen von Pin | Bit mit Bitposition (0...n) outStates[0...n/8].
|
//Verknüpfen von Pin | Bit mit Bitposition (0...n) outStates[0...n/8].
|
||||||
@@ -68,14 +68,7 @@ void ioHelperEdgeDetector(void);
|
|||||||
#define BitPD6 22 //D22
|
#define BitPD6 22 //D22
|
||||||
#define BitPJ4 23 //D23
|
#define BitPJ4 23 //D23
|
||||||
|
|
||||||
|
#define LED_EXTR_FEHLER BitPB6
|
||||||
#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
|
//Inputs
|
||||||
//Verknüpfen von Pin | Bit mit Bitposition (0...n) inStates[0...n/8].
|
//Verknüpfen von Pin | Bit mit Bitposition (0...n) inStates[0...n/8].
|
||||||
@@ -90,11 +83,23 @@ void ioHelperEdgeDetector(void);
|
|||||||
|
|
||||||
#define BitPinK0 8 //A8
|
#define BitPinK0 8 //A8
|
||||||
#define BitPinK1 9 //A9
|
#define BitPinK1 9 //A9
|
||||||
|
#define BitPinK2 10 //A10
|
||||||
|
#define BitPinK3 11 //A11
|
||||||
|
#define BitPinK4 12 //A12
|
||||||
|
#define BitPinK5 13 //A13
|
||||||
|
#define BitPinK6 14 //A14
|
||||||
|
#define BitPinK7 15 //A15
|
||||||
|
|
||||||
|
#define BitPinD7 16 //I16
|
||||||
|
#define BitPinG2 17 //I17
|
||||||
|
#define BitPinG1 18 //I18
|
||||||
#define BitPinD3 10 //INO
|
#define BitPinD3 10 //INO
|
||||||
#define BitPinD2 11 //IN1
|
#define BitPinD2 11 //IN1
|
||||||
|
|
||||||
#define IN_ANLAGE_EIN_INV BitPinF5
|
|
||||||
#define IN_NOTAUS_ANLAGE BitPinF7
|
#define BTN_DREHZAHL_GROB_PLUS BitPinF4 // modbus
|
||||||
#define IN_NOTAUS_SCHRANK BitPinK0
|
#define BTN_DREHZAHL_GROB_MINUS BitPinF5 // modbus
|
||||||
|
|
||||||
|
#define IN_ANLAGE_EIN_INV BitPinK3 // modbus
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,92 +1,97 @@
|
|||||||
import string
|
import string
|
||||||
|
|
||||||
ddr="""#ifdef DDRA
|
ddr="""#ifdef DDRA
|
||||||
DDRA|=0
|
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
||||||
|
DDRA|=0
|
||||||
#ifdef BitPA0
|
#ifdef BitPA0
|
||||||
|(1<<0)
|
|(1<<0)
|
||||||
#endif
|
#endif
|
||||||
#ifdef BitPA1
|
#ifdef BitPA1
|
||||||
|(1<<1)
|
|(1<<1)
|
||||||
#endif
|
#endif
|
||||||
#ifdef BitPA2
|
#ifdef BitPA2
|
||||||
|(1<<2)
|
|(1<<2)
|
||||||
#endif
|
#endif
|
||||||
#ifdef BitPA3
|
#ifdef BitPA3
|
||||||
|(1<<3)
|
|(1<<3)
|
||||||
#endif
|
#endif
|
||||||
#ifdef BitPA4
|
#ifdef BitPA4
|
||||||
|(1<<4)
|
|(1<<4)
|
||||||
#endif
|
#endif
|
||||||
#ifdef BitPA5
|
#ifdef BitPA5
|
||||||
|(1<<5)
|
|(1<<5)
|
||||||
#endif
|
#endif
|
||||||
#ifdef BitPA6
|
#ifdef BitPA6
|
||||||
|(1<<6)
|
|(1<<6)
|
||||||
#endif
|
#endif
|
||||||
#ifdef BitPA7
|
#ifdef BitPA7
|
||||||
|(1<<7)
|
|(1<<7)
|
||||||
#endif
|
#endif
|
||||||
|0;
|
|0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
port="""
|
port="""
|
||||||
#ifdef PORTA
|
#ifdef PORTA
|
||||||
PORTA|=0
|
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
||||||
|
PORTA|=0
|
||||||
#ifdef BitPA0
|
#ifdef BitPA0
|
||||||
|(getBit1(BitPA0)<<0)
|
|(getBit1(BitPA0)<<0)
|
||||||
#endif
|
#endif
|
||||||
#ifdef BitPA1
|
#ifdef BitPA1
|
||||||
|(getBit1(BitPA1)<<1)
|
|(getBit1(BitPA1)<<1)
|
||||||
#endif
|
#endif
|
||||||
#ifdef BitPA2
|
#ifdef BitPA2
|
||||||
|(getBit1(BitPA2)<<2)
|
|(getBit1(BitPA2)<<2)
|
||||||
#endif
|
#endif
|
||||||
#ifdef BitPA3
|
#ifdef BitPA3
|
||||||
|(getBit1(BitPA3)<<3)
|
|(getBit1(BitPA3)<<3)
|
||||||
#endif
|
#endif
|
||||||
#ifdef BitPA4
|
#ifdef BitPA4
|
||||||
|(getBit1(BitPA4)<<4)
|
|(getBit1(BitPA4)<<4)
|
||||||
#endif
|
#endif
|
||||||
#ifdef BitPA5
|
#ifdef BitPA5
|
||||||
|(getBit1(BitPA5)<<5)
|
|(getBit1(BitPA5)<<5)
|
||||||
#endif
|
#endif
|
||||||
#ifdef BitPA6
|
#ifdef BitPA6
|
||||||
|(getBit1(BitPA6)<<6)
|
|(getBit1(BitPA6)<<6)
|
||||||
#endif
|
#endif
|
||||||
#ifdef BitPA7
|
#ifdef BitPA7
|
||||||
|(getBit1(BitPA7)<<7)
|
|(getBit1(BitPA7)<<7)
|
||||||
#endif
|
#endif
|
||||||
|0;
|
|0;
|
||||||
|
}
|
||||||
|
|
||||||
PORTA&=~(0
|
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
||||||
|
PORTA&=~(0
|
||||||
#ifdef BitPA0
|
#ifdef BitPA0
|
||||||
|(getBit0(BitPA0)<<0)
|
|(getBit0(BitPA0)<<0)
|
||||||
#endif
|
#endif
|
||||||
#ifdef BitPA1
|
#ifdef BitPA1
|
||||||
|(getBit0(BitPA1)<<1)
|
|(getBit0(BitPA1)<<1)
|
||||||
#endif
|
#endif
|
||||||
#ifdef BitPA2
|
#ifdef BitPA2
|
||||||
|(getBit0(BitPA2)<<2)
|
|(getBit0(BitPA2)<<2)
|
||||||
#endif
|
#endif
|
||||||
#ifdef BitPA3
|
#ifdef BitPA3
|
||||||
|(getBit0(BitPA3)<<3)
|
|(getBit0(BitPA3)<<3)
|
||||||
#endif
|
#endif
|
||||||
#ifdef BitPA4
|
#ifdef BitPA4
|
||||||
|(getBit0(BitPA4)<<4)
|
|(getBit0(BitPA4)<<4)
|
||||||
#endif
|
#endif
|
||||||
#ifdef BitPA5
|
#ifdef BitPA5
|
||||||
|(getBit0(BitPA5)<<5)
|
|(getBit0(BitPA5)<<5)
|
||||||
#endif
|
#endif
|
||||||
#ifdef BitPA6
|
#ifdef BitPA6
|
||||||
|(getBit0(BitPA6)<<6)
|
|(getBit0(BitPA6)<<6)
|
||||||
#endif
|
#endif
|
||||||
#ifdef BitPA7
|
#ifdef BitPA7
|
||||||
|(getBit0(BitPA7)<<7)
|
|(getBit0(BitPA7)<<7)
|
||||||
#endif
|
#endif
|
||||||
|0);
|
|0);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|||||||
314
main.c
314
main.c
@@ -1,206 +1,18 @@
|
|||||||
#include <avr/io.h>
|
#include <avr/io.h>
|
||||||
#include <avr/interrupt.h>
|
#include <avr/interrupt.h>
|
||||||
#include <avr/wdt.h> // WatchDog
|
#include <avr/wdt.h> // WatchDog
|
||||||
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#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 "avrIOhelper/io-helper.h"
|
||||||
#include "millis.h"
|
#include "millis.h"
|
||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
#include "spi.h"
|
#include "modbus.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
|
// Timer0
|
||||||
// 1ms IRQ
|
// 1ms IRQ
|
||||||
// Used for millis() timing
|
// Used for millis() timing
|
||||||
void timer0_init(void)
|
void timer0_init()
|
||||||
{
|
{
|
||||||
TCCR0A = (1<<WGM01); //TIMER0 SET-UP: CTC MODE
|
TCCR0A = (1<<WGM01); //TIMER0 SET-UP: CTC MODE
|
||||||
TCCR0B = (1<<CS01)|(1<<CS00); // PS 1:64
|
TCCR0B = (1<<CS01)|(1<<CS00); // PS 1:64
|
||||||
@@ -208,40 +20,104 @@ void timer0_init(void)
|
|||||||
TIMSK0 |= 1<<OCIE0A; //IRQ on TIMER0 output compareA
|
TIMSK0 |= 1<<OCIE0A; //IRQ on TIMER0 output compareA
|
||||||
}
|
}
|
||||||
|
|
||||||
static void avr_init(void)
|
void timer2_init()
|
||||||
{
|
{
|
||||||
// Initialize device here.
|
TCCR2A = (1<<WGM21); //TIMER0 SET-UP: CTC MODE
|
||||||
// WatchDog INIT
|
TCCR2B|=(1<<CS21); //prescaler 8
|
||||||
wdt_enable(WDTO_8S); // set up wdt reset interval 2 second
|
OCR2A = 200;
|
||||||
wdt_reset(); // wdt reset ~ every <2000ms
|
TIMSK2|=(1<<OCIE2A);
|
||||||
|
}
|
||||||
|
|
||||||
|
void modbusGet(void) {
|
||||||
|
if (modbusGetBusState() & (1<<ReceiveCompleted))
|
||||||
|
{
|
||||||
|
switch(rxbuffer[1]) {
|
||||||
|
case fcPresetSingleRegister:
|
||||||
|
case fcPresetMultipleRegisters:
|
||||||
|
case fcReadHoldingRegisters:
|
||||||
|
//;
|
||||||
|
//uint16_t test;
|
||||||
|
//modbusExchangeRegisters(&test,0,1);
|
||||||
|
modbusExchangeRegisters((void *)outStates,0,1);
|
||||||
|
break;
|
||||||
|
case fcReadInputRegisters:
|
||||||
|
if(modbusRequestedAddress() < 100)
|
||||||
|
modbusExchangeRegisters((void *)inStates,0,nrOfInputs/16);
|
||||||
|
else if(modbusRequestedAddress() < 200)
|
||||||
|
modbusExchangeRegisters((void *)inStatesBothEdges,100,nrOfInputs/16);
|
||||||
|
else if(modbusRequestedAddress() < 300)
|
||||||
|
modbusExchangeRegisters((void *)inStatesFallingEdge,200,nrOfInputs/16);
|
||||||
|
else if(modbusRequestedAddress() < 400)
|
||||||
|
modbusExchangeRegisters((void *)inStatesRisingEdge,300,nrOfInputs/16);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case fcReadInputStatus:
|
||||||
|
if(modbusRequestedAddress() < 100)
|
||||||
|
modbusExchangeBits(inStates,0,nrOfInputs);
|
||||||
|
else if(modbusRequestedAddress() < 200)
|
||||||
|
modbusExchangeBits(inStatesBothEdges,100,nrOfInputs);
|
||||||
|
else if(modbusRequestedAddress() < 300)
|
||||||
|
modbusExchangeBits(inStatesFallingEdge,200,nrOfInputs);
|
||||||
|
else if(modbusRequestedAddress() < 400)
|
||||||
|
modbusExchangeBits(inStatesRisingEdge,300,nrOfInputs);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case fcForceMultipleCoils:
|
||||||
|
case fcForceSingleCoil:
|
||||||
|
case fcReadCoilStatus:
|
||||||
|
if(modbusRequestedAddress() < 100)
|
||||||
|
modbusExchangeBits(outStates,0,nrOfOutputs);
|
||||||
|
else if(modbusRequestedAddress() < 200)
|
||||||
|
modbusExchangeBits(outStatesBlinking,100,nrOfOutputs);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
modbusSendException(ecIllegalFunction);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
wdt_enable(WDTO_2S); // set up wdt reset interval 2 second
|
||||||
|
|
||||||
timer0_init();// Timer0 millis engine init
|
|
||||||
uart_init();
|
uart_init();
|
||||||
|
|
||||||
sei(); //re-enable global interrupts
|
ioHelperIoConf();
|
||||||
|
timer0_init();// Timer0 millis engine init
|
||||||
|
|
||||||
return;
|
modbusSetAddress(4);
|
||||||
|
modbusInit();
|
||||||
|
timer2_init();
|
||||||
|
|
||||||
|
sei();
|
||||||
|
|
||||||
|
set_Output(LED_EXTR_FEHLER, BLINK);
|
||||||
|
uint32_t timer_blink_outs = millis();
|
||||||
|
|
||||||
|
printf("moin\n");
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
wdt_reset(); // wdt reset ~ every <2000ms
|
||||||
|
ioHelperReadPins();
|
||||||
|
ioHelperDebounce();
|
||||||
|
ioHelperEdgeDetector();
|
||||||
|
|
||||||
|
modbusGet();
|
||||||
|
|
||||||
|
// Toggle all outs which are set to blinking
|
||||||
|
if(millis() - timer_blink_outs > 500){
|
||||||
|
ioHelperBlinkOuts();
|
||||||
|
timer_blink_outs = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
ioHelperSetOuts();
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_network_information(void)
|
ISR(TIMER2_COMPA_vect) { //this ISR is called 9765.625 times per second
|
||||||
{
|
modbusTickTimer();
|
||||||
|
|
||||||
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]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
13
millis.c
13
millis.c
@@ -11,10 +11,11 @@ ISR (TIMER0_COMPA_vect)
|
|||||||
|
|
||||||
unsigned long millis(void)
|
unsigned long millis(void)
|
||||||
{
|
{
|
||||||
unsigned long i;
|
//unsigned long i;
|
||||||
cli();
|
//cli();
|
||||||
// Atomic tick reading
|
//// Atomic tick reading
|
||||||
i = _millis;
|
//i = _millis;
|
||||||
sei();
|
//sei();
|
||||||
return i;
|
//return i;
|
||||||
|
return _millis;
|
||||||
}
|
}
|
||||||
|
|||||||
436
modbus.c
Normal file
436
modbus.c
Normal file
@@ -0,0 +1,436 @@
|
|||||||
|
/*************************************************************************
|
||||||
|
Title: Yet another (small) modbus (server) implementation for the avr.
|
||||||
|
Author: Max Brueggemann
|
||||||
|
Hardware: any AVR with hardware UART, tested on Atmega 88/168 at 20Mhz
|
||||||
|
License: BSD-3-Clause
|
||||||
|
|
||||||
|
DESCRIPTION:
|
||||||
|
Refer to the header file yaMBSiavr.h.
|
||||||
|
|
||||||
|
USAGE:
|
||||||
|
Refer to the header file yaMBSiavr.h.
|
||||||
|
|
||||||
|
LICENSE:
|
||||||
|
|
||||||
|
Copyright 2017 Max Brueggemann, www.maxbrueggemann.de
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. 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.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder 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 HOLDER 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 <avr/io.h>
|
||||||
|
#include "modbus.h"
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
|
||||||
|
volatile unsigned char BusState = 0;
|
||||||
|
volatile uint16_t modbusTimer = 0;
|
||||||
|
volatile unsigned char rxbuffer[MaxFrameIndex+1];
|
||||||
|
volatile uint16_t DataPos = 0;
|
||||||
|
volatile unsigned char PacketTopIndex = 7;
|
||||||
|
volatile unsigned char modBusStaMaStates = 0;
|
||||||
|
volatile uint16_t modbusDataAmount = 0;
|
||||||
|
volatile uint16_t modbusDataLocation = 0;
|
||||||
|
|
||||||
|
/* @brief: save address and amount
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void modbusSaveLocation(void)
|
||||||
|
{
|
||||||
|
modbusDataLocation=(rxbuffer[3]|(rxbuffer[2]<<8));
|
||||||
|
if (rxbuffer[1]==fcPresetSingleRegister || rxbuffer[1]==fcForceSingleCoil) modbusDataAmount=1;
|
||||||
|
else modbusDataAmount=(rxbuffer[5]|(rxbuffer[4]<<8));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* @brief: returns 1 if data location adr is touched by current command
|
||||||
|
*
|
||||||
|
* Arguments: - adr: address of the data object
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t modbusIsInRange(uint16_t adr)
|
||||||
|
{
|
||||||
|
if((modbusDataLocation <= adr) && (adr<(modbusDataLocation+modbusDataAmount)))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* @brief: returns 1 if range of data locations is touched by current command
|
||||||
|
*
|
||||||
|
* Arguments: - startAdr: address of first data object in range
|
||||||
|
* - lastAdr: address of last data object in range
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t modbusIsRangeInRange(uint16_t startAdr, uint16_t lastAdr)
|
||||||
|
{
|
||||||
|
if(modbusIsInRange(startAdr) && modbusIsInRange(lastAdr))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t modbusGetBusState(void)
|
||||||
|
{
|
||||||
|
return BusState;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ADDRESS_MODE == SINGLE_ADR
|
||||||
|
volatile unsigned char Address = 0x00;
|
||||||
|
uint8_t modbusGetAddress(void)
|
||||||
|
{
|
||||||
|
return Address;
|
||||||
|
}
|
||||||
|
|
||||||
|
void modbusSetAddress(unsigned char newadr)
|
||||||
|
{
|
||||||
|
Address = newadr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PHYSICAL_TYPE == 485
|
||||||
|
void transceiver_txen(void)
|
||||||
|
{
|
||||||
|
TRANSCEIVER_ENABLE_PORT|=(1<<TRANSCEIVER_ENABLE_PIN);
|
||||||
|
TRANSCEIVER_ENABLE_PORT|=(1<<TRANSCEIVER_ENABLE_PIN_2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void transceiver_rxen(void)
|
||||||
|
{
|
||||||
|
TRANSCEIVER_ENABLE_PORT&=~(1<<TRANSCEIVER_ENABLE_PIN);
|
||||||
|
TRANSCEIVER_ENABLE_PORT&=~(1<<TRANSCEIVER_ENABLE_PIN_2);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* @brief: A fairly simple Modbus compliant 16 Bit CRC algorithm.
|
||||||
|
*
|
||||||
|
* Returns 1 if the crc check is positive, returns 0 and saves the calculated CRC bytes
|
||||||
|
* at the end of the data array if it fails.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t crc16(volatile uint8_t *ptrToArray,uint8_t inputSize) //A standard CRC algorithm
|
||||||
|
{
|
||||||
|
uint16_t out=0xffff;
|
||||||
|
uint16_t carry;
|
||||||
|
unsigned char n;
|
||||||
|
inputSize++;
|
||||||
|
for (int l=0; l<inputSize; l++) {
|
||||||
|
out ^= ptrToArray[l];
|
||||||
|
for (n = 0; n < 8; n++) {
|
||||||
|
carry = out & 1;
|
||||||
|
out >>= 1;
|
||||||
|
if (carry) out ^= 0xA001;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//out=0x1234;
|
||||||
|
if ((ptrToArray[inputSize]==out%256) && (ptrToArray[inputSize+1]==out/256)) //check
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
ptrToArray[inputSize]=out%256; //append Lo
|
||||||
|
ptrToArray[inputSize+1]=out/256; //append Hi
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* @brief: copies a single bit from one char to another char (or arrays thereof)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void listBitCopy(volatile uint8_t *source, uint16_t sourceNr,volatile uint8_t *target, uint16_t targetNr)
|
||||||
|
{
|
||||||
|
if(*(source+(sourceNr/8))&(1<<(sourceNr-((sourceNr/8)*8))))
|
||||||
|
{
|
||||||
|
*(target+(targetNr/8))|=(1<<(targetNr-((targetNr/8)*8)));
|
||||||
|
} else *(target+(targetNr/8))&=~(1<<(targetNr-((targetNr/8)*8)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* @brief: Back to receiving state.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void modbusReset(void)
|
||||||
|
{
|
||||||
|
BusState=(1<<TimerActive); //stop receiving (error)
|
||||||
|
modbusTimer=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void modbusTickTimer(void)
|
||||||
|
{
|
||||||
|
if (BusState&(1<<TimerActive))
|
||||||
|
{
|
||||||
|
modbusTimer++;
|
||||||
|
if (BusState&(1<<Receiving)) //we are in receiving mode
|
||||||
|
{
|
||||||
|
if ((modbusTimer==modbusInterCharTimeout)) {
|
||||||
|
BusState|=(1<<GapDetected);
|
||||||
|
} else if ((modbusTimer==modbusInterFrameDelayReceiveEnd)) { //end of message
|
||||||
|
#if ADDRESS_MODE == MULTIPLE_ADR
|
||||||
|
if (crc16(rxbuffer,DataPos-3)) { //perform crc check only. This is for multiple/all address mode.
|
||||||
|
modbusSaveLocation();
|
||||||
|
BusState=(1<<ReceiveCompleted);
|
||||||
|
} else modbusReset();
|
||||||
|
#endif
|
||||||
|
#if ADDRESS_MODE == SINGLE_ADR
|
||||||
|
if (rxbuffer[0]==Address && crc16(rxbuffer,DataPos-3)) { //is the message for us? => perform crc check
|
||||||
|
modbusSaveLocation();
|
||||||
|
BusState=(1<<ReceiveCompleted);
|
||||||
|
} else modbusReset();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
} else if (modbusTimer==modbusInterFrameDelayReceiveStart){
|
||||||
|
BusState|=(1<<BusTimedOut);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ISR(UART_RECEIVE_INTERRUPT)
|
||||||
|
{
|
||||||
|
unsigned char data;
|
||||||
|
data = UART_DATA;
|
||||||
|
//printf("%x ", data);
|
||||||
|
modbusTimer=0; //reset timer
|
||||||
|
if (!(BusState & (1<<ReceiveCompleted)) && !(BusState & (1<<TransmitRequested)) && !(BusState & (1<<Transmitting)) && (BusState & (1<<Receiving)) && !(BusState & (1<<BusTimedOut)))
|
||||||
|
{
|
||||||
|
if (DataPos>MaxFrameIndex) modbusReset();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rxbuffer[DataPos]=data;
|
||||||
|
DataPos++; //TODO: maybe prevent this from exceeding 255?
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
// Bus state is Timed out..
|
||||||
|
if (!(BusState & (1<<ReceiveCompleted)) && !(BusState & (1<<TransmitRequested)) && !(BusState & (1<<Transmitting)) && !(BusState & (1<<Receiving)) && (BusState & (1<<BusTimedOut)))
|
||||||
|
{
|
||||||
|
rxbuffer[0]=data;
|
||||||
|
BusState=((1<<Receiving)|(1<<TimerActive));
|
||||||
|
DataPos=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ISR(UART_TRANSMIT_INTERRUPT)
|
||||||
|
{
|
||||||
|
BusState&=~(1<<TransmitRequested);
|
||||||
|
BusState|=(1<<Transmitting);
|
||||||
|
UART_DATA=rxbuffer[DataPos];
|
||||||
|
DataPos++;
|
||||||
|
if (DataPos==(PacketTopIndex+1)) {
|
||||||
|
UART_CONTROL&=~(1<<UART_UDRIE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ISR(UART_TRANSMIT_COMPLETE_INTERRUPT)
|
||||||
|
{
|
||||||
|
#if PHYSICAL_TYPE == 485
|
||||||
|
transceiver_rxen();
|
||||||
|
#endif
|
||||||
|
modbusReset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void modbusInit(void)
|
||||||
|
{
|
||||||
|
UBRRH = (unsigned char)((_UBRR) >> 8);
|
||||||
|
UBRRL = (unsigned char) _UBRR;
|
||||||
|
UART_STATUS = (1<<U2X); //double speed mode.
|
||||||
|
#ifdef URSEL // if UBRRH and UCSRC share the same I/O location , e.g. ATmega8
|
||||||
|
UCSRC = (1<<URSEL)|(3<<UCSZ0); //Frame Size
|
||||||
|
#else
|
||||||
|
UCSRC = (3<<UCSZ0); //Frame Size
|
||||||
|
#endif
|
||||||
|
UART_CONTROL = (1<<TXCIE)|(1<<RXCIE)|(1<<RXEN)|(1<<TXEN); // USART receiver and transmitter and receive complete interrupt
|
||||||
|
#if PHYSICAL_TYPE == 485
|
||||||
|
TRANSCEIVER_ENABLE_PORT_DDR|=(1<<TRANSCEIVER_ENABLE_PIN);
|
||||||
|
TRANSCEIVER_ENABLE_PORT_DDR|=(1<<TRANSCEIVER_ENABLE_PIN_2);
|
||||||
|
transceiver_rxen();
|
||||||
|
#endif
|
||||||
|
BusState=(1<<TimerActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* @brief: Sends a response.
|
||||||
|
*
|
||||||
|
* Arguments: - packtop: Position of the last byte containing data.
|
||||||
|
* modbusSendException is a good usage example.
|
||||||
|
*/
|
||||||
|
void modbusSendMessage(unsigned char packtop)
|
||||||
|
{
|
||||||
|
PacketTopIndex=packtop+2;
|
||||||
|
crc16(rxbuffer,packtop);
|
||||||
|
BusState|=(1<<TransmitRequested);
|
||||||
|
DataPos=0;
|
||||||
|
#if PHYSICAL_TYPE == 485
|
||||||
|
transceiver_txen();
|
||||||
|
#endif
|
||||||
|
UART_CONTROL|=(1<<UART_UDRIE);
|
||||||
|
BusState&=~(1<<ReceiveCompleted);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* @brief: Sends an exception response.
|
||||||
|
*
|
||||||
|
* Arguments: - exceptionCode
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void modbusSendException(unsigned char exceptionCode)
|
||||||
|
{
|
||||||
|
rxbuffer[1]|=(1<<7); //setting MSB of the function code (the exception flag)
|
||||||
|
rxbuffer[2]=exceptionCode; //Exceptioncode. Also the last byte containing data
|
||||||
|
modbusSendMessage(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* @brief: Returns the amount of requested data objects (coils, discretes, registers)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint16_t modbusRequestedAmount(void)
|
||||||
|
{
|
||||||
|
return modbusDataAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* @brief: Returns the address of the first requested data object (coils, discretes, registers)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint16_t modbusRequestedAddress(void)
|
||||||
|
{
|
||||||
|
return modbusDataLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* @brief: copies a single or multiple bytes from one array of bytes to an array of 16-bit-words
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void intToModbusRegister(volatile uint16_t *inreg, volatile uint8_t *outreg, uint8_t amount)
|
||||||
|
{
|
||||||
|
for (uint8_t c=0; c<amount; c++)
|
||||||
|
{
|
||||||
|
*(outreg+c*2) = (uint8_t)(*(inreg+c) >> 8);
|
||||||
|
*(outreg+1+c*2) = (uint8_t)(*(inreg+c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* @brief: copies a single or multiple 16-bit-words from one array of integers to an array of bytes
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void modbusRegisterToInt(volatile uint8_t *inreg, volatile uint16_t *outreg, uint8_t amount)
|
||||||
|
{
|
||||||
|
for (uint8_t c=0; c<amount; c++)
|
||||||
|
{
|
||||||
|
*(outreg+c) = (*(inreg+c*2) << 8) + *(inreg+1+c*2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* @brief: Handles single/multiple register reading and single/multiple register writing.
|
||||||
|
*
|
||||||
|
* Arguments: - ptrToInArray: pointer to the user's data array containing registers
|
||||||
|
* - startAddress: address of the first register in the supplied array
|
||||||
|
* - size: input array size in the requested format (16bit-registers)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t modbusExchangeRegisters(volatile uint16_t *ptrToInArray, uint16_t startAddress, uint16_t size)
|
||||||
|
{
|
||||||
|
if ((modbusDataLocation>=startAddress) && ((startAddress+size)>=(modbusDataAmount+modbusDataLocation))) {
|
||||||
|
|
||||||
|
if ((rxbuffer[1]==fcReadHoldingRegisters) || (rxbuffer[1]==fcReadInputRegisters) )
|
||||||
|
{
|
||||||
|
if ((modbusDataAmount*2)<=(MaxFrameIndex-4)) //message buffer big enough?
|
||||||
|
{
|
||||||
|
rxbuffer[2]=(unsigned char)(modbusDataAmount*2);
|
||||||
|
intToModbusRegister(ptrToInArray+(modbusDataLocation-startAddress),rxbuffer+3,modbusDataAmount);
|
||||||
|
modbusSendMessage(2+rxbuffer[2]);
|
||||||
|
return 1;
|
||||||
|
} else modbusSendException(ecIllegalDataValue);
|
||||||
|
}
|
||||||
|
else if (rxbuffer[1]==fcPresetMultipleRegisters)
|
||||||
|
{
|
||||||
|
if (((rxbuffer[6])>=modbusDataAmount*2) && ((DataPos-9)>=rxbuffer[6])) //enough data received?
|
||||||
|
{
|
||||||
|
modbusRegisterToInt(rxbuffer+7,ptrToInArray+(modbusDataLocation-startAddress),(unsigned char)(modbusDataAmount));
|
||||||
|
modbusSendMessage(5);
|
||||||
|
return 1;
|
||||||
|
} else modbusSendException(ecIllegalDataValue);//too few data bytes received
|
||||||
|
}
|
||||||
|
else if (rxbuffer[1]==fcPresetSingleRegister)
|
||||||
|
{
|
||||||
|
modbusRegisterToInt(rxbuffer+4,ptrToInArray+(modbusDataLocation-startAddress),1);
|
||||||
|
modbusSendMessage(5);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
//modbusSendException(ecSlaveDeviceFailure); //inapropriate call of modbusExchangeRegisters
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
modbusSendException(ecIllegalDataValue);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* @brief: Handles single/multiple input/coil reading and single/multiple coil writing.
|
||||||
|
*
|
||||||
|
* Arguments: - ptrToInArray: pointer to the user's data array containing bits
|
||||||
|
* - startAddress: address of the first bit in the supplied array
|
||||||
|
* - size: input array size in the requested format (bits)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t modbusExchangeBits(volatile uint8_t *ptrToInArray, uint16_t startAddress, uint16_t size)
|
||||||
|
{
|
||||||
|
if ((modbusDataLocation>=startAddress) && ((startAddress+size)>=(modbusDataAmount+modbusDataLocation)))
|
||||||
|
{
|
||||||
|
if ((rxbuffer[1]==fcReadInputStatus) || (rxbuffer[1]==fcReadCoilStatus))
|
||||||
|
{
|
||||||
|
if (modbusDataAmount<=((MaxFrameIndex-4)*8)) //message buffer big enough?
|
||||||
|
{
|
||||||
|
rxbuffer[2]=(modbusDataAmount/8);
|
||||||
|
if (modbusDataAmount%8>0)
|
||||||
|
{
|
||||||
|
rxbuffer[(uint8_t)(modbusDataAmount/8)+3]=0x00; //fill last data byte with zeros
|
||||||
|
rxbuffer[2]++;
|
||||||
|
}
|
||||||
|
for (uint16_t c = 0; c<modbusDataAmount; c++)
|
||||||
|
{
|
||||||
|
listBitCopy(ptrToInArray,modbusDataLocation-startAddress+c,rxbuffer+3,c);
|
||||||
|
}
|
||||||
|
modbusSendMessage(rxbuffer[2]+2);
|
||||||
|
return 1;
|
||||||
|
} else modbusSendException(ecIllegalDataValue); //too many bits requested within single request
|
||||||
|
}
|
||||||
|
else if (rxbuffer[1]==fcForceMultipleCoils)
|
||||||
|
{
|
||||||
|
if (((rxbuffer[6]*8)>=modbusDataAmount) && ((DataPos-9)>=rxbuffer[6])) //enough data received?
|
||||||
|
{
|
||||||
|
for (uint16_t c = 0; c<modbusDataAmount; c++)
|
||||||
|
{
|
||||||
|
listBitCopy(rxbuffer+7,c,ptrToInArray,modbusDataLocation-startAddress+c);
|
||||||
|
}
|
||||||
|
modbusSendMessage(5);
|
||||||
|
return 1;
|
||||||
|
} else modbusSendException(ecIllegalDataValue);//exception too few data bytes received
|
||||||
|
}
|
||||||
|
else if (rxbuffer[1]==fcForceSingleCoil) {
|
||||||
|
listBitCopy(rxbuffer+4,0,ptrToInArray,modbusDataLocation-startAddress);
|
||||||
|
modbusSendMessage(5);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
//modbusSendException(ecSlaveDeviceFailure); //inanpropriate call of modbusExchangeBits
|
||||||
|
return 0;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
modbusSendException(ecIllegalDataValue);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
421
modbus.h
Normal file
421
modbus.h
Normal file
@@ -0,0 +1,421 @@
|
|||||||
|
#ifndef yaMBIavr_H
|
||||||
|
#define yaMBIavr_H
|
||||||
|
/************************************************************************
|
||||||
|
Title: Yet another (small) Modbus (server) implementation for the avr.
|
||||||
|
Author: Max Brueggemann
|
||||||
|
Hardware: any AVR with hardware UART, tested on Atmega 88/168 at 20Mhz
|
||||||
|
License: BSD-3-Clause
|
||||||
|
|
||||||
|
LICENSE:
|
||||||
|
|
||||||
|
Copyright 2017 Max Brueggemann, www.maxbrueggemann.de
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. 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.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder 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 HOLDER 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 <avr/io.h>
|
||||||
|
/**
|
||||||
|
* @code #include <yaMBSIavr.h> @endcode
|
||||||
|
*
|
||||||
|
* @brief Interrupt-based Modbus implementation for small avr microcontrollers.
|
||||||
|
* The Modbus implementation guidelines at modbus.org call for response
|
||||||
|
* timeouts in the range of several seconds , hence only timing critical
|
||||||
|
* parts have been implemented within ISRs. The actual handling of the Modbus
|
||||||
|
* frame can easily be done in the main while loop.
|
||||||
|
*
|
||||||
|
* @author Max Brueggemann www.maxbrueggemann.de
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* define baudrate of modbus */
|
||||||
|
#ifndef BAUD
|
||||||
|
#define BAUD 38400L
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definitions for transceiver enable pin.
|
||||||
|
*/
|
||||||
|
#ifndef TRANSCEIVER_ENABLE_PORT
|
||||||
|
#define TRANSCEIVER_ENABLE_PORT PORTJ
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TRANSCEIVER_ENABLE_PIN
|
||||||
|
#define TRANSCEIVER_ENABLE_PIN 6
|
||||||
|
#define TRANSCEIVER_ENABLE_PIN_2 5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TRANSCEIVER_ENABLE_PORT_DDR
|
||||||
|
#define TRANSCEIVER_ENABLE_PORT_DDR DDRJ
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
* At the moment the user has to set the value for Baudrate and
|
||||||
|
* speed mode manually. The values depend on the operating frequency
|
||||||
|
* of your AVR and can be found in its datasheet.
|
||||||
|
*/
|
||||||
|
#if defined(__AVR_ATtiny2313__)
|
||||||
|
#define UART_TRANSMIT_COMPLETE_INTERRUPT USART_TX_vect
|
||||||
|
#define UART_RECEIVE_INTERRUPT USART_RX_vect
|
||||||
|
#define UART_TRANSMIT_INTERRUPT USART_UDRE_vect
|
||||||
|
#define UART_STATUS UCSRA
|
||||||
|
#define UART_CONTROL UCSRB
|
||||||
|
#define UART_DATA UDR
|
||||||
|
#define UART_UDRIE UDRIE
|
||||||
|
|
||||||
|
#elif defined(__AVR_ATmega164P__)
|
||||||
|
#define UART_TRANSMIT_COMPLETE_INTERRUPT USART1_TX_vect
|
||||||
|
#define UART_RECEIVE_INTERRUPT USART1_RX_vect
|
||||||
|
#define UART_TRANSMIT_INTERRUPT USART1_UDRE_vect
|
||||||
|
#define UART_STATUS UCSR1A
|
||||||
|
#define UART_CONTROL UCSR1B
|
||||||
|
#define UART_DATA UDR1
|
||||||
|
#define UART_UDRIE UDRIE1
|
||||||
|
#define UCSRC UCSR1C
|
||||||
|
#define RXCIE RXCIE1
|
||||||
|
#define TXCIE TXCIE1
|
||||||
|
#define RXEN RXEN1
|
||||||
|
#define TXEN TXEN1
|
||||||
|
#define UCSZ0 UCSZ10
|
||||||
|
#define U2X U2X1
|
||||||
|
#define UBRRH UBRR1H
|
||||||
|
#define UBRRL UBRR1L
|
||||||
|
|
||||||
|
#elif defined(__AVR_ATmega168PA__)|(__AVR_ATmega88PA__)|(__AVR_ATmega328P__)|(__AVR_ATmega168P__)|(__AVR_ATmega88P__)
|
||||||
|
#define UART_TRANSMIT_COMPLETE_INTERRUPT USART_TX_vect
|
||||||
|
#define UART_RECEIVE_INTERRUPT USART_RX_vect
|
||||||
|
#define UART_TRANSMIT_INTERRUPT USART_UDRE_vect
|
||||||
|
#define UART_STATUS UCSR0A
|
||||||
|
#define UART_CONTROL UCSR0B
|
||||||
|
#define UART_DATA UDR0
|
||||||
|
#define UART_UDRIE UDRIE0
|
||||||
|
#define UCSRC UCSR0C
|
||||||
|
#define RXCIE RXCIE0
|
||||||
|
#define TXCIE TXCIE0
|
||||||
|
#define RXEN RXEN0
|
||||||
|
#define TXEN TXEN0
|
||||||
|
#define UCSZ0 UCSZ00
|
||||||
|
#define U2X U2X0
|
||||||
|
#define UBRRH UBRR0H
|
||||||
|
#define UBRRL UBRR0L
|
||||||
|
|
||||||
|
#elif defined(__AVR_ATmega328PB__)
|
||||||
|
#define UART_TRANSMIT_COMPLETE_INTERRUPT USART0_TX_vect
|
||||||
|
#define UART_RECEIVE_INTERRUPT USART0_RX_vect
|
||||||
|
#define UART_TRANSMIT_INTERRUPT USART0_UDRE_vect
|
||||||
|
#define UART_STATUS UCSR0A
|
||||||
|
#define UART_CONTROL UCSR0B
|
||||||
|
#define UART_DATA UDR0
|
||||||
|
#define UART_UDRIE UDRIE0
|
||||||
|
#define UCSRC UCSR0C
|
||||||
|
#define RXCIE RXCIE0
|
||||||
|
#define TXCIE TXCIE0
|
||||||
|
#define RXEN RXEN0
|
||||||
|
#define TXEN TXEN0
|
||||||
|
#define UCSZ0 UCSZ00
|
||||||
|
#define U2X U2X0
|
||||||
|
#define UBRRH UBRR0H
|
||||||
|
#define UBRRL UBRR0L
|
||||||
|
|
||||||
|
#elif defined(__AVR_ATtiny441__)
|
||||||
|
#define UART_TRANSMIT_COMPLETE_INTERRUPT USART0_TX_vect
|
||||||
|
#define UART_RECEIVE_INTERRUPT USART0_RX_vect
|
||||||
|
#define UART_TRANSMIT_INTERRUPT USART0_UDRE_vect
|
||||||
|
#define UART_STATUS UCSR0A
|
||||||
|
#define UART_CONTROL UCSR0B
|
||||||
|
#define UART_DATA UDR0
|
||||||
|
#define UART_UDRIE UDRIE0
|
||||||
|
#define UCSRC UCSR0C
|
||||||
|
#define RXCIE RXCIE0
|
||||||
|
#define TXCIE TXCIE0
|
||||||
|
#define RXEN RXEN0
|
||||||
|
#define TXEN TXEN0
|
||||||
|
#define UCSZ0 UCSZ00
|
||||||
|
#define U2X U2X0
|
||||||
|
#define UBRRH UBRR0H
|
||||||
|
#define UBRRL UBRR0L
|
||||||
|
|
||||||
|
#elif defined(__AVR_ATmega8__)|| defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) || defined(__AVR_ATmega323__)
|
||||||
|
#define UART_TRANSMIT_COMPLETE_INTERRUPT USART_TXC_vect
|
||||||
|
#define UART_RECEIVE_INTERRUPT USART_RXC_vect
|
||||||
|
#define UART_TRANSMIT_INTERRUPT USART_UDRE_vect
|
||||||
|
#define UART_STATUS UCSRA
|
||||||
|
#define UART_CONTROL UCSRB
|
||||||
|
#define UART_DATA UDR
|
||||||
|
#define UART_UDRIE UDRIE
|
||||||
|
|
||||||
|
#elif defined(__AVR_AT90PWM3B__)
|
||||||
|
#define UART_TRANSMIT_COMPLETE_INTERRUPT USART_TX_vect
|
||||||
|
#define UART_RECEIVE_INTERRUPT USART_RX_vect
|
||||||
|
#define UART_TRANSMIT_INTERRUPT USART_UDRE_vect
|
||||||
|
#define UART_STATUS UCSRA
|
||||||
|
#define UART_CONTROL UCSRB
|
||||||
|
#define UART_DATA UDR
|
||||||
|
#define UART_UDRIE UDRIE
|
||||||
|
|
||||||
|
#elif defined(__AVR_ATmega1284P__)
|
||||||
|
#define UART_TRANSMIT_COMPLETE_INTERRUPT USART0_TX_vect
|
||||||
|
#define UART_RECEIVE_INTERRUPT USART0_RX_vect
|
||||||
|
#define UART_TRANSMIT_INTERRUPT USART0_UDRE_vect
|
||||||
|
#define UART_STATUS UCSR0A
|
||||||
|
#define UART_CONTROL UCSR0B
|
||||||
|
#define UART_DATA UDR0
|
||||||
|
#define UART_UDRIE UDRIE0
|
||||||
|
#define UCSRC UCSR0C
|
||||||
|
#define RXCIE RXCIE0
|
||||||
|
#define TXCIE TXCIE0
|
||||||
|
#define RXEN RXEN0
|
||||||
|
#define TXEN TXEN0
|
||||||
|
#define UCSZ0 UCSZ00
|
||||||
|
#define U2X U2X0
|
||||||
|
#define UBRRH UBRR0H
|
||||||
|
#define UBRRL UBRR0L
|
||||||
|
|
||||||
|
#elif defined(__AVR_ATmega2560__)
|
||||||
|
#define UART_TRANSMIT_COMPLETE_INTERRUPT USART3_TX_vect
|
||||||
|
#define UART_RECEIVE_INTERRUPT USART3_RX_vect
|
||||||
|
#define UART_TRANSMIT_INTERRUPT USART3_UDRE_vect
|
||||||
|
#define UART_STATUS UCSR3A
|
||||||
|
#define UART_CONTROL UCSR3B
|
||||||
|
#define UART_DATA UDR3
|
||||||
|
#define UART_UDRIE UDRIE3
|
||||||
|
#define UCSRC UCSR3C
|
||||||
|
#define RXCIE RXCIE3
|
||||||
|
#define TXCIE TXCIE3
|
||||||
|
#define RXEN RXEN3
|
||||||
|
#define TXEN TXEN3
|
||||||
|
#define UCSZ0 UCSZ30
|
||||||
|
#define U2X U2X0
|
||||||
|
#define UBRRH UBRR3H
|
||||||
|
#define UBRRL UBRR3L
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error "no definition available"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef F_CPU
|
||||||
|
#error " F_CPU not defined "
|
||||||
|
#else
|
||||||
|
#define _UBRR (F_CPU / 8 / BAUD ) -1
|
||||||
|
#endif /* F_CPU */
|
||||||
|
/*
|
||||||
|
* Available address modes.
|
||||||
|
*/
|
||||||
|
#define MULTIPLE_ADR 2
|
||||||
|
#define SINGLE_ADR 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use SINGLE_ADR or MULTIPLE_ADR, default: SINGLE_ADR
|
||||||
|
* This is useful for building gateways, routers or clients that for whatever reason need multiple addresses.
|
||||||
|
*/
|
||||||
|
#define ADDRESS_MODE SINGLE_ADR
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use 485 or 232, default: 485
|
||||||
|
* Use 232 for testing purposes or very simple applications that do not require RS485 and bus topology.
|
||||||
|
*/
|
||||||
|
#define PHYSICAL_TYPE 485 //possible values: 485, 232
|
||||||
|
|
||||||
|
#if BAUD>=19200
|
||||||
|
#define modbusInterFrameDelayReceiveStart 16
|
||||||
|
#define modbusInterFrameDelayReceiveEnd 18
|
||||||
|
#define modbusInterCharTimeout 7
|
||||||
|
#else
|
||||||
|
#define modbusBlocksize 10
|
||||||
|
#define modbusBlockTime ((float)modbusBlocksize*1000000)/((float) BAUD) //is 260 for 38400
|
||||||
|
#define timerISROccurenceTime 100 //time in microseconds between two calls of modbusTickTimer
|
||||||
|
#define modbusInterFrameDelayReceiveStart (uint16_t)(modbusBlockTime*3.5/(float)timerISROccurenceTime)
|
||||||
|
#define modbusInterFrameDelayReceiveEnd (uint16_t)(modbusBlockTime*4/(float)timerISROccurenceTime)
|
||||||
|
#define modbusInterCharTimeout (uint16_t)(modbusBlockTime*1.5/(float)timerISROccurenceTime)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Defines the maximum Modbus frame size accepted by the device. 255 is the default
|
||||||
|
* and also the maximum value. However, it might be useful to set this to lower
|
||||||
|
* values, with 8 being the lowest possible value, in order to save on ram space.
|
||||||
|
*/
|
||||||
|
#define MaxFrameIndex 255
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Modbus Function Codes
|
||||||
|
* Refer to modbus.org for further information.
|
||||||
|
* It's good practice to return exception code 01 in case you receive a function code
|
||||||
|
* that you haven't implemented in your application.
|
||||||
|
*/
|
||||||
|
#define fcReadCoilStatus 1 //read single/multiple coils
|
||||||
|
#define fcReadInputStatus 2 //read single/multiple inputs
|
||||||
|
#define fcReadHoldingRegisters 3 //read analog output registers
|
||||||
|
#define fcReadInputRegisters 4 //read analog input registers (2 Bytes per register)
|
||||||
|
#define fcForceSingleCoil 5 //write single bit
|
||||||
|
#define fcPresetSingleRegister 6 //write analog output register (2 Bytes)
|
||||||
|
#define fcForceMultipleCoils 15 //write multiple bits
|
||||||
|
#define fcPresetMultipleRegisters 16 //write multiple analog output registers (2 Bytes each)
|
||||||
|
#define fcReportSlaveID 17 //read device description, run status and other device specific information
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Modbus Exception Codes
|
||||||
|
* Refer to modbus.org for further information.
|
||||||
|
* It's good practice to return exception code 01 in case you receive a function code
|
||||||
|
* that you haven't implemented in your application.
|
||||||
|
*/
|
||||||
|
#define ecIllegalFunction 1
|
||||||
|
#define ecIllegalDataAddress 2
|
||||||
|
#define ecIllegalDataValue 3
|
||||||
|
#define ecSlaveDeviceFailure 4
|
||||||
|
#define ecAcknowledge 5
|
||||||
|
#define ecSlaveDeviceBusy 6
|
||||||
|
#define ecNegativeAcknowledge 7
|
||||||
|
#define ecMemoryParityError 8
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Internal bit definitions
|
||||||
|
*/
|
||||||
|
#define BusTimedOut 0
|
||||||
|
#define Receiving 1
|
||||||
|
#define Transmitting 2
|
||||||
|
#define ReceiveCompleted 3
|
||||||
|
#define TransmitRequested 4
|
||||||
|
#define TimerActive 5
|
||||||
|
#define GapDetected 6
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Configures the UART. Call this function only once.
|
||||||
|
*/
|
||||||
|
extern void modbusInit(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief receive/transmit data array
|
||||||
|
*/
|
||||||
|
extern volatile unsigned char rxbuffer[MaxFrameIndex+1];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Current receive/transmit position
|
||||||
|
*/
|
||||||
|
extern volatile uint16_t DataPos;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This only applies to single address mode.
|
||||||
|
*/
|
||||||
|
#if ADDRESS_MODE == SINGLE_ADR
|
||||||
|
/**
|
||||||
|
* @brief: Read the device address
|
||||||
|
*/
|
||||||
|
extern uint8_t modbusGetAddress(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief: Set the device address
|
||||||
|
* Arguments: - newadr: the new device address
|
||||||
|
*/
|
||||||
|
extern void modbusSetAddress(unsigned char newadr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* @brief: Sends a response.
|
||||||
|
*
|
||||||
|
* Arguments: - packtop, index of the last byte in rxbuffer
|
||||||
|
* that contains payload. Maximum value is
|
||||||
|
* MaxFrameIndex-2.
|
||||||
|
*/
|
||||||
|
extern void modbusSendMessage(unsigned char packtop);
|
||||||
|
|
||||||
|
/* @brief: Sends a Modbus exception.
|
||||||
|
*
|
||||||
|
* Arguments: - exceptionCode
|
||||||
|
*/
|
||||||
|
extern void modbusSendException(unsigned char exceptionCode);
|
||||||
|
|
||||||
|
/* @brief: Discards the current transaction. For MULTIPLE_ADR-mode and general
|
||||||
|
* testing purposes. Call this function if you don't want to reply at all.
|
||||||
|
*/
|
||||||
|
void modbusReset(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Call this function whenever possible and check if its return value has the ReceiveCompleted Bit set.
|
||||||
|
* Preferably do this in the main while. I do not recommend calling this function within ISRs.
|
||||||
|
* @example if (modbusGetBusState() & (1<<ReceiveCompleted)) {
|
||||||
|
* modbusSendExcepton(ecIllegalFunction);
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
extern uint8_t modbusGetBusState(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Call every 100us using a timer ISR.
|
||||||
|
*/
|
||||||
|
extern void modbusTickTimer(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns amount of bits/registers requested.
|
||||||
|
*/
|
||||||
|
extern uint16_t modbusRequestedAmount(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the address of the first requested bit/register.
|
||||||
|
*/
|
||||||
|
extern uint16_t modbusRequestedAddress(void);
|
||||||
|
|
||||||
|
/* A fairly simple and hopefully Modbus compliant 16 Bit CRC algorithm.
|
||||||
|
* Returns 1 if the crc check is positive, returns 0 if it fails.
|
||||||
|
* Appends two crc bytes to the array.
|
||||||
|
*/
|
||||||
|
extern uint8_t crc16(volatile uint8_t *ptrToArray,uint8_t inputSize);
|
||||||
|
|
||||||
|
/* @brief: Handles single/multiple input/coil reading and single/multiple coil writing.
|
||||||
|
*
|
||||||
|
* Arguments: - ptrToInArray: pointer to the user's data array containing bits
|
||||||
|
* - startAddress: address of the first bit in the supplied array
|
||||||
|
* - size: input array size in the requested format (bits)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
extern uint8_t modbusExchangeBits(volatile uint8_t *ptrToInArray, uint16_t startAddress, uint16_t size);
|
||||||
|
|
||||||
|
/* @brief: Handles single/multiple register reading and single/multiple register writing.
|
||||||
|
*
|
||||||
|
* Arguments: - ptrToInArray: pointer to the user's data array containing registers
|
||||||
|
* - startAddress: address of the first register in the supplied array
|
||||||
|
* - size: input array size in the requested format (16bit-registers)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
extern uint8_t modbusExchangeRegisters(volatile uint16_t *ptrToInArray, uint16_t startAddress, uint16_t size);
|
||||||
|
|
||||||
|
/* @brief: returns 1 if data location adr is touched by current command
|
||||||
|
*
|
||||||
|
* Arguments: - adr: address of the data object
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
extern uint8_t modbusIsInRange(uint16_t adr);
|
||||||
|
|
||||||
|
/* @brief: returns 1 if range of data locations is touched by current command
|
||||||
|
*
|
||||||
|
* Arguments: - startAdr: address of first data object in range
|
||||||
|
* - lastAdr: address of last data object in range
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
extern uint8_t modbusIsRangeInRange(uint16_t startAdr, uint16_t lastAdr);
|
||||||
|
|
||||||
|
extern volatile uint16_t modbusDataAmount;
|
||||||
|
extern volatile uint16_t modbusDataLocation;
|
||||||
|
#endif
|
||||||
|
|
||||||
66
mqtt.c
66
mqtt.c
@@ -1,66 +0,0 @@
|
|||||||
#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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
18
mqtt.h
18
mqtt.h
@@ -1,18 +0,0 @@
|
|||||||
#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
|
|
||||||
37
spi.c
37
spi.c
@@ -1,37 +0,0 @@
|
|||||||
#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
|
|
||||||
}
|
|
||||||
20
spi.h
20
spi.h
@@ -1,20 +0,0 @@
|
|||||||
#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
|
|
||||||
Reference in New Issue
Block a user