This commit is contained in:
2025-12-10 17:55:05 +03:00
commit 441b6563d6
77 changed files with 42614 additions and 0 deletions

22
.gitattributes vendored Normal file
View File

@@ -0,0 +1,22 @@
# Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
*.sln merge=union
*.csproj merge=union
*.vbproj merge=union
*.fsproj merge=union
*.dbproj merge=union
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain

1940
.gitignore vendored Normal file

File diff suppressed because it is too large Load Diff

0
.gitmodules vendored Normal file
View File

18
Application/Application.h Normal file
View File

@@ -0,0 +1,18 @@
#ifndef _APPLICATION_H_
#define _APPLICATION_H_
#include <stdint.h>
#define SOCK_TCP4 (Sn_MR_TCP)
#define SOCK_TCP6 (Sn_MR_TCP6)
#define SOCK_TCPD (Sn_MR_TCPD)
#define SOCK_UDP4 (Sn_MR_UDP4)
#define SOCK_UDP6 (Sn_MR_UDP6)
#define SOCK_UDPD (Sn_MR_UDPD)
#define AS_IPV4 2
#define AS_IPV6 23
#define AS_IPDUAL 11
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,50 @@
#ifndef _LOOPBACK_H_
#define _LOOPBACK_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include "wizchip_conf.h"
/* Loopback test debug message printout enable */
#if 0
#define _LOOPBACK_DEBUG_
#endif
/* DATA_BUF_SIZE define for Loopback example */
#ifndef DATA_BUF_SIZE
#define DATA_BUF_SIZE 2048
#endif
/************************/
/* Select LOOPBACK_MODE */
/************************/
#define LOOPBACK_MAIN_NOBLOCK 0
#define LOOPBACK_MODE LOOPBACK_MAIN_NOBLOCK
#if ((_WIZCHIP_ == 6100) || (_WIZCHIP_ == 6300))
int8_t set_loopback_mode_W6x00(uint8_t get_loopback_mode) ;
int8_t check_loopback_mode_W6x00();
#endif
/* TCP server Loopback test example */
int32_t loopback_tcps(uint8_t sn, uint8_t* buf, uint16_t port);
/* TCP client Loopback test example */
int32_t loopback_tcpc(uint8_t sn, uint8_t* buf, uint8_t* destip, uint16_t destport);
/* UDP Loopback test example */
int32_t loopback_udps(uint8_t sn, uint8_t* buf, uint16_t port);
/* UDP Client Loopback test example */
int32_t loopback_udpc(uint8_t sn, uint8_t* buf, uint8_t* destip, uint16_t destport);
//teddy 240122
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,145 @@
#include "multicast.h"
#include <stdio.h>
#include "socket.h"
#include "wizchip_conf.h"
int32_t multicast_loopback(uint8_t sn, uint8_t* buf, uint8_t* multicast_ip, uint16_t multicast_port) {
int32_t ret;
uint16_t size, sentsize;
uint8_t destip[4];
uint16_t destport, port = 3000;
#if 1
// 20231019 taylor
uint8_t addr_len;
#endif
switch (getSn_SR(sn)) {
case SOCK_UDP :
if ((size = getSn_RX_RSR(sn)) > 0) {
if (size > DATA_BUF_SIZE) {
size = DATA_BUF_SIZE;
}
#if 1
// 20231019 taylor//teddy 240122
#if ((_WIZCHIP_ == 6100)|| (_WIZCHIP_ == 6300))
ret = recvfrom(sn, buf, size, destip, (uint16_t*)&destport, &addr_len);
#else
ret = recvfrom(sn, buf, size, destip, (uint16_t*)&destport);
#endif
#else
ret = recvfrom(sn, buf, size, destip, (uint16_t*)&destport);
#endif
if (ret <= 0) {
#ifdef _MULTICAST_DEBUG_
printf("%d: recvfrom error. %ld\r\n", sn, ret);
#endif
return ret;
}
size = (uint16_t) ret;
sentsize = 0;
while (sentsize != size) {
#if 1
// 20231016 taylor//teddy 240122
#if ((_WIZCHIP_ == 6100) || (_WIZCHIP_ == 6300))
ret = sendto(sn, buf + sentsize, size - sentsize, destip, destport, 4);
#else
ret = sendto(sn, buf + sentsize, size - sentsize, destip, destport);
#endif
#else
ret = sendto(sn, buf + sentsize, size - sentsize, destip, destport);
#endif
if (ret < 0) {
#ifdef _MULTICAST_DEBUG_
printf("%d: sendto error. %ld\r\n", sn, ret);
#endif
return ret;
}
sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero.
}
}
break;
case SOCK_CLOSED:
#ifdef _MULTICAST_DEBUG_
printf("%d:Multicast Loopback start\r\n", sn);
#endif
setSn_DIPR(0, multicast_ip);
setSn_DPORT(0, multicast_port);
if ((ret = socket(sn, Sn_MR_UDP, port, Sn_MR_MULTI)) != sn) {
return ret;
}
#ifdef _MULTICAST_DEBUG_
printf("%d:Opened, UDP Multicast Socket\r\n", sn);
printf("%d:Multicast Group IP - %d.%d.%d.%d\r\n", sn, multicast_ip[0], multicast_ip[1], multicast_ip[2], multicast_ip[3]);
printf("%d:Multicast Group Port - %d\r\n", sn, multicast_port);
#endif
break;
default :
break;
}
return 1;
}
int32_t multicast_recv(uint8_t sn, uint8_t* buf, uint8_t* multicast_ip, uint16_t multicast_port) {
int32_t ret;
uint16_t size, port = 3000;
uint8_t destip[4];
uint16_t destport;
#if 1
// 20231019 taylor
uint8_t addr_len;
#endif
switch (getSn_SR(sn)) {
case SOCK_UDP :
if ((size = getSn_RX_RSR(sn)) > 0) {
if (size > DATA_BUF_SIZE) {
size = DATA_BUF_SIZE;
}
#if 1
// 20231019 taylor//teddy 240122
#if ((_WIZCHIP_ == 6100) || (_WIZCHIP_ == 6300))
ret = recvfrom(sn, buf, size, destip, (uint16_t*)&destport, &addr_len);
#else
ret = recvfrom(sn, buf, size, destip, (uint16_t*)&destport);
#endif
#else
ret = recvfrom(sn, buf, size, destip, (uint16_t*)&destport);
#endif
if (ret <= 0) {
#ifdef _MULTICAST_DEBUG_
printf("%d: recvfrom error. %ld\r\n", sn, ret);
#endif
return ret;
}
size = (uint16_t) ret;
#ifdef _MULTICAST_DEBUG_
printf("\r\nrecv size : %d\r\n", size);
for (int i = 0; i < size; i++) {
printf("%c", buf[i]);
}
printf("\r\n");
#endif
}
break;
case SOCK_CLOSED:
#ifdef _MULTICAST_DEBUG_
printf("%d:Multicast Recv start\r\n", sn);
#endif
setSn_DIPR(sn, multicast_ip);
setSn_DPORT(sn, multicast_port);
if ((ret = socket(sn, Sn_MR_UDP, port, Sn_MR_MULTI)) != sn) {
return ret;
}
#ifdef _MULTICAST_DEBUG_
printf("%d:Opened, UDP Multicast Socket\r\n", sn);
printf("%d:Multicast Group IP - %d.%d.%d.%d\r\n", sn, multicast_ip[0], multicast_ip[1], multicast_ip[2], multicast_ip[3]);
printf("%d:Multicast Group Port - %d\r\n", sn, multicast_port);
#endif
break;
default :
break;
}
return 1;
}

View File

@@ -0,0 +1,28 @@
#ifndef _MULTICAST_H_
#define _MULTICAST_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
/* Multicast test debug message printout enable */
#define _MULTICAST_DEBUG_
#ifndef DATA_BUF_SIZE
#define DATA_BUF_SIZE 2048
#endif
/* UDP Multicast Loopback test example */
int32_t multicast_loopback(uint8_t sn, uint8_t* buf, uint8_t* multicast_ip, uint16_t multicast_port);
/* UDP Multicast Recv test example */
int32_t multicast_recv(uint8_t sn, uint8_t* buf, uint8_t* multicast_ip, uint16_t multicast_port);
#ifdef __cplusplus
}
#endif
#endif

Binary file not shown.

371
Ethernet/W5100/w5100.c Normal file
View File

@@ -0,0 +1,371 @@
//*****************************************************************************
//
//! \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

1875
Ethernet/W5100/w5100.h Normal file

File diff suppressed because it is too large Load Diff

499
Ethernet/W5100S/w5100s.c Normal file
View File

@@ -0,0 +1,499 @@
//*****************************************************************************
//
//! \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) {
uint8_t spi_data[4];
WIZCHIP_CRITICAL_ENTER();
WIZCHIP.CS._select();
#if( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_))
if (!WIZCHIP.IF.SPI._write_burst) { // byte operation
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)
} else { // burst operation
spi_data[0] = 0xF0;
spi_data[1] = (AddrSel & 0xFF00) >> 8;
spi_data[2] = (AddrSel & 0x00FF) >> 0;
spi_data[3] = wb;
WIZCHIP.IF.SPI._write_burst(spi_data, 4);
}
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_5500_) )
if (!WIZCHIP.IF.SPI._write_burst) { // byte operation
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)
} else { // burst operation
spi_data[0] = (AddrSel & 0xFF00) >> 8;
spi_data[1] = (AddrSel & 0x00FF) >> 0;
spi_data[2] = 0xF0;
spi_data[3] = wb;
WIZCHIP.IF.SPI._write_burst(spi_data, 4);
}
#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;
uint8_t spi_data[3];
WIZCHIP_CRITICAL_ENTER();
WIZCHIP.CS._select();
#if( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_))
if (!WIZCHIP.IF.SPI._read_burst || !WIZCHIP.IF.SPI._write_burst) { // byte operation
WIZCHIP.IF.SPI._write_byte(0x0F);
WIZCHIP.IF.SPI._write_byte((AddrSel & 0xFF00) >> 8);
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF) >> 0);
} else {
spi_data[0] = 0x0F;
spi_data[1] = (AddrSel & 0xFF00) >> 8;
spi_data[2] = (AddrSel & 0x00FF) >> 0;
WIZCHIP.IF.SPI._write_burst(spi_data, 3);
}
ret = WIZCHIP.IF.SPI._read_byte();
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_5500_) )
if (!WIZCHIP.IF.SPI._read_burst || !WIZCHIP.IF.SPI._write_burst) { // burst operation
WIZCHIP.IF.SPI._write_byte((AddrSel & 0xFF00) >> 8);
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF) >> 0);
WIZCHIP.IF.SPI._write_byte(0x0F);
} else {
spi_data[0] = (AddrSel & 0xFF00) >> 8;
spi_data[1] = (AddrSel & 0x00FF) >> 0;
spi_data[2] = 0x0F
WIZCHIP.IF.SPI._write_burst(spi_data, 3);
}
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) {
uint8_t spi_data[3];
uint16_t i = 0;
WIZCHIP_CRITICAL_ENTER();
WIZCHIP.CS._select(); //M20150601 : Moved here.
#if((_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_))
if (!WIZCHIP.IF.SPI._write_burst) { // byte operation
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)
}
} else { // burst operation
spi_data[0] = 0xF0;
spi_data[1] = (((uint16_t)(AddrSel + i)) & 0xFF00) >> 8;
spi_data[2] = (((uint16_t)(AddrSel + i)) & 0x00FF) >> 0;
WIZCHIP.IF.SPI._write_burst(spi_data, 3);
WIZCHIP.IF.SPI._write_burst(pBuf, len);
}
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_5500_) )
if (!WIZCHIP.IF.SPI._write_burst) { // byte operation
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)
}
} else { // burst operation
spi_data[0] = (((uint16_t)(AddrSel + i)) & 0xFF00) >> 8;
spi_data[1] = (((uint16_t)(AddrSel + i)) & 0x00FF) >> 0;
spi_data[2] = 0xF0;
WIZCHIP.IF.SPI._write_burst(spi_data, 3);
WIZCHIP.IF.SPI._write_burst(pBuf, len);
}
#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);
#if 1
// 20231108 taylor
uint8_t tAD[2];
tAD[0] = (uint8_t)((AddrSel & 0x0000FF00) >> 8);
tAD[1] = (uint8_t)(AddrSel & 0x000000FF);
WIZCHIP.IF.BUS._write_data_buf(IDM_AR0, tAD, 2, 1);
#else
WIZCHIP.IF.BUS._write_data(IDM_AR0, (AddrSel & 0xFF00) >> 8);
WIZCHIP.IF.BUS._write_data(IDM_AR1, (AddrSel & 0x00FF));
#endif
#if 1
// 20231108 taylor
WIZCHIP.IF.BUS._write_data_buf(IDM_DR, pBuf, len, 0);
#else
for (i = 0 ; i < len; i++) {
WIZCHIP.IF.BUS._write_data(IDM_DR, pBuf[i]);
}
#endif
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) {
uint8_t spi_data[3];
uint16_t i = 0;
WIZCHIP_CRITICAL_ENTER();
WIZCHIP.CS._select(); //M20150601 : Moved here.
#if( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_) )
if (!WIZCHIP.IF.SPI._read_burst || !WIZCHIP.IF.SPI._write_burst) { // byte operation
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();
}
} else { // burst operation
spi_data[0] = 0x0F;
spi_data[1] = (uint16_t)((AddrSel + i) & 0xFF00) >> 8;
spi_data[2] = (uint16_t)((AddrSel + i) & 0x00FF) >> 0;
WIZCHIP.IF.SPI._write_burst(spi_data, 3);
WIZCHIP.IF.SPI._read_burst(pBuf, len);
}
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_5500_) )
if (!WIZCHIP.IF.SPI._read_burst || !WIZCHIP.IF.SPI._write_burst) { // byte operation
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();
}
} else { // burst operation
spi_data[0] = (uint16_t)((AddrSel + i) & 0xFF00) >> 8;
spi_data[1] = (uint16_t)((AddrSel + i) & 0x00FF) >> 0;
spi_data[2] = 0x0F;
WIZCHIP.IF.SPI._write_burst(spi_data, 3);
WIZCHIP.IF.SPI._read_burst(pBuf, len);
}
#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);
#if 1
// 20231108 taylor
uint8_t tAD[2];
tAD[0] = (uint8_t)((AddrSel & 0x0000FF00) >> 8);
tAD[1] = (uint8_t)(AddrSel & 0x000000FF);
WIZCHIP.IF.BUS._write_data_buf(IDM_AR0, tAD, 2, 1);
#else
WIZCHIP.IF.BUS._write_data(IDM_AR0, (AddrSel & 0xFF00) >> 8);
WIZCHIP.IF.BUS._write_data(IDM_AR1, (AddrSel & 0x00FF));
#endif
#if 1
// 20231108 taylor
WIZCHIP.IF.BUS._read_data_buf(IDM_DR, pBuf, len, 0);
#else
for (i = 0 ; i < len; i++) {
pBuf[i] = WIZCHIP.IF.BUS._read_data(IDM_DR);
}
#endif
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

3322
Ethernet/W5100S/w5100s.h Normal file

File diff suppressed because it is too large Load Diff

338
Ethernet/W5200/w5200.c Normal file
View File

@@ -0,0 +1,338 @@
//*****************************************************************************
//
//! \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

2118
Ethernet/W5200/w5200.h Normal file

File diff suppressed because it is too large Load Diff

229
Ethernet/W5300/w5300.c Normal file
View File

@@ -0,0 +1,229 @@
//*****************************************************************************
//
//! \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

2336
Ethernet/W5300/w5300.h Normal file

File diff suppressed because it is too large Load Diff

248
Ethernet/W5500/w5500.c Normal file
View File

@@ -0,0 +1,248 @@
//*****************************************************************************
//
//! \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

2164
Ethernet/W5500/w5500.h Normal file

File diff suppressed because it is too large Load Diff

272
Ethernet/W6100/w6100.c Normal file
View File

@@ -0,0 +1,272 @@
//*****************************************************************************
//
//! \file w6100.c
//! \brief W6100 HAL Implements file.
//! \version 1.0.0
//! \date 2019/01/01
//! \par Revision history
//! <2019/01/01> 1st Release
//! \author MidnightCow
//! \copyright
//!
//! Copyright (c) 2019, WIZnet Co., LTD.
//!
//! Permission is hereby granted, free of charge, to any person obtaining a copy
//! of this software and associated documentation files (the "Software"), to deal
//! in the Software without restriction, including without limitation the rights
//! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//! copies of the Software, and to permit persons to whom the Software is
//! furnished to do so, subject to the following conditions:
//!
//! The above copyright notice and this permission notice shall be included in
//! all copies or substantial portions of the Software.
//!
//! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//! SOFTWARE.
//!
//*****************************************************************************
#include "w6100.h"
#define _WIZCHIP_SPI_VDM_OP_ 0x00
#define _WIZCHIP_SPI_FDM_LEN1_ 0x01
#define _WIZCHIP_SPI_FDM_LEN2_ 0x02
#define _WIZCHIP_SPI_FDM_LEN4_ 0x03
//
// If you want to use SPI FDM mode, Feel free contact to WIZnet.
// http://forum.wiznet.io
//
#if _WIZCHIP_ == 6100
////////////////////////////////////////////////////////////////////////////////////////
#define _W6100_SPI_OP_ _WIZCHIP_SPI_VDM_OP_
//////////////////////////////////////////////////
void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb) {
uint8_t tAD[4];
tAD[0] = (uint8_t)((AddrSel & 0x00FF0000) >> 16);
tAD[1] = (uint8_t)((AddrSel & 0x0000FF00) >> 8);
tAD[2] = (uint8_t)(AddrSel & 0x000000ff);
tAD[3] = wb;
WIZCHIP_CRITICAL_ENTER();
WIZCHIP.CS._select();
#if( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_VDM_))
tAD[2] |= (_W6100_SPI_WRITE_ | _W6100_SPI_OP_);
if (!WIZCHIP.IF.SPI._write_burst) { // byte operation
WIZCHIP.IF.SPI._write_byte(tAD[0]);
WIZCHIP.IF.SPI._write_byte(tAD[1]);
WIZCHIP.IF.SPI._write_byte(tAD[2]);
WIZCHIP.IF.SPI._write_byte(tAD[3]);
} else {
WIZCHIP.IF.SPI._write_burst(tAD, 4);
}
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
#if 1
// 20231103 taylor
WIZCHIP.IF.BUS._write_data_buf(IDM_AR0, tAD, 4, 1);
#else
WIZCHIP.IF.BUS._write_data(IDM_AR0, tAD, 4, 1);
#endif
#else
#error "Unknown _WIZCHIP_IO_MODE_ in W6100. !!!"
#endif
WIZCHIP.CS._deselect();
WIZCHIP_CRITICAL_EXIT();
}
uint8_t WIZCHIP_READ(uint32_t AddrSel) {
uint8_t ret;
uint8_t tAD[3];
tAD[0] = (uint8_t)((AddrSel & 0x00FF0000) >> 16);
tAD[1] = (uint8_t)((AddrSel & 0x0000FF00) >> 8);
tAD[2] = (uint8_t)(AddrSel & 0x000000ff);
WIZCHIP_CRITICAL_ENTER();
WIZCHIP.CS._select();
#if( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_VDM_))
tAD[2] |= (_W6100_SPI_READ_ | _W6100_SPI_OP_);
if (!WIZCHIP.IF.SPI._read_burst || !WIZCHIP.IF.SPI._write_burst) { // byte operation
WIZCHIP.IF.SPI._write_byte(tAD[0]);
WIZCHIP.IF.SPI._write_byte(tAD[1]);
WIZCHIP.IF.SPI._write_byte(tAD[2]);
} else {
WIZCHIP.IF.SPI._write_burst(tAD, 3);
}
ret = WIZCHIP.IF.SPI._read_byte();
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
WIZCHIP.IF.BUS._write_data_buf(IDM_AR0, tAD, 3, 1);
ret = WIZCHIP.IF.BUS._read_data(IDM_DR);
#else
#error "Unknown _WIZCHIP_IO_MODE_ in W6100. !!!"
#endif
WIZCHIP.CS._deselect();
WIZCHIP_CRITICAL_EXIT();
return ret;
}
void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) {
uint8_t tAD[3];
uint16_t i = 0;
tAD[0] = (uint8_t)((AddrSel & 0x00FF0000) >> 16);
tAD[1] = (uint8_t)((AddrSel & 0x0000FF00) >> 8);
tAD[2] = (uint8_t)(AddrSel & 0x000000ff);
WIZCHIP_CRITICAL_ENTER();
WIZCHIP.CS._select();
#if((_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_VDM_))
tAD[2] |= (_W6100_SPI_WRITE_ | _W6100_SPI_OP_);
if (!WIZCHIP.IF.SPI._write_burst) { // byte operation
WIZCHIP.IF.SPI._write_byte(tAD[0]);
WIZCHIP.IF.SPI._write_byte(tAD[1]);
WIZCHIP.IF.SPI._write_byte(tAD[2]);
for (i = 0; i < len; i++) {
WIZCHIP.IF.SPI._write_byte(pBuf[i]);
}
} else {
WIZCHIP.IF.SPI._write_burst(tAD, 3);
WIZCHIP.IF.SPI._write_burst(pBuf, len);
}
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
WIZCHIP.IF.BUS._write_data_buf(IDM_AR0, tAD, 3, 1);
WIZCHIP.IF.BUS._write_data_buf(IDM_DR, pBuf, len, 0);
#else
#error "Unknown _WIZCHIP_IO_MODE_ in W6100. !!!!"
#endif
WIZCHIP.CS._deselect();
WIZCHIP_CRITICAL_EXIT();
}
void WIZCHIP_READ_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) {
uint8_t tAD[3];
uint16_t i;
tAD[0] = (uint8_t)((AddrSel & 0x00FF0000) >> 16);
tAD[1] = (uint8_t)((AddrSel & 0x0000FF00) >> 8);
tAD[2] = (uint8_t)(AddrSel & 0x000000ff);
WIZCHIP_CRITICAL_ENTER();
WIZCHIP.CS._select();
#if((_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_VDM_))
tAD[2] |= (_W6100_SPI_READ_ | _W6100_SPI_OP_);
if (!WIZCHIP.IF.SPI._read_burst || !WIZCHIP.IF.SPI._write_burst) { // byte operation
WIZCHIP.IF.SPI._write_byte(tAD[0]);
WIZCHIP.IF.SPI._write_byte(tAD[1]);
WIZCHIP.IF.SPI._write_byte(tAD[2]);
for (i = 0; i < len; len++) {
pBuf[i] = WIZCHIP.IF.SPI._read_byte();
}
} else {
WIZCHIP.IF.SPI._write_burst(tAD, 3);
WIZCHIP.IF.SPI._read_burst(pBuf, len);
}
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
WIZCHIP.IF.BUS._write_data_buf(IDM_AR0, tAD, 3, 1);
WIZCHIP.IF.BUS._read_data_buf(IDM_DR, pBuf, len, 0);
#else
#error "Unknown _WIZCHIP_IO_MODE_ in W6100. !!!!"
#endif
WIZCHIP.CS._deselect();
WIZCHIP_CRITICAL_EXIT();
}
uint16_t getSn_TX_FSR(uint8_t sn) {
uint16_t prev_val = -1, val = 0;
do {
prev_val = val;
val = WIZCHIP_READ(_Sn_TX_FSR_(sn));
val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(_Sn_TX_FSR_(sn), 1));
} while (val != prev_val);
return val;
}
uint16_t getSn_RX_RSR(uint8_t sn) {
uint16_t prev_val = -1, val = 0;
do {
prev_val = val;
val = WIZCHIP_READ(_Sn_RX_RSR_(sn));
val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(_Sn_RX_RSR_(sn), 1));
} while (val != prev_val);
return val;
}
void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len) {
uint16_t ptr = 0;
uint32_t addrsel = 0;
ptr = getSn_TX_WR(sn);
addrsel = ((uint32_t)ptr << 8) + WIZCHIP_TXBUF_BLOCK(sn);
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);
addrsel = ((uint32_t)ptr << 8) + WIZCHIP_RXBUF_BLOCK(sn);
WIZCHIP_READ_BUF(addrsel, wizdata, len);
ptr += len;
setSn_RX_RD(sn, ptr);
}
void wiz_recv_ignore(uint8_t sn, uint16_t len) {
setSn_RX_RD(sn, getSn_RX_RD(sn) + len);
}
#if 1
// 20231019 taylor
void wiz_delay_ms(uint32_t milliseconds) {
uint32_t i;
for (i = 0 ; i < milliseconds ; i++) {
//Write any values to clear the TCNTCLKR register
setTCNTRCLR(0xff);
// Wait until counter register value reaches 10.(10 = 1ms : TCNTR is 100us tick counter register)
while (getTCNTR() < 0x0a) {}
}
}
#endif
/// @cond DOXY_APPLY_CODE
#if (_PHY_IO_MODE_ == _PHY_IO_MODE_MII_)
/// @endcond
void wiz_mdio_write(uint8_t phyregaddr, uint16_t var) {
setPHYRAR(phyregaddr);
setPHYDIR(var);
setPHYACR(PHYACR_WRITE);
while (getPHYACR()); //wait for command complete
}
uint16_t wiz_mdio_read(uint8_t phyregaddr) {
setPHYRAR(phyregaddr);
setPHYACR(PHYACR_READ);
while (getPHYACR()); //wait for command complete
return getPHYDOR();
}
/// @cond DOXY_APPLY_CODE
#endif
/// @endcond
////////////////////////////////////////////////////////////////////////////////////////
#endif

4086
Ethernet/W6100/w6100.h Normal file

File diff suppressed because it is too large Load Diff

273
Ethernet/W6300/w6300.c Normal file
View File

@@ -0,0 +1,273 @@
//*****************************************************************************
//
//! \file W6300.c
//! \brief W6300 HAL Implements file.
//! \version 1.0.0
//! \date 2019/01/01
//! \par Revision history
//! <2019/01/01> 1st Release
//! \author MidnightCow
//! \copyright
//!
//! Copyright (c) 2019, WIZnet Co., LTD.
//!
//! Permission is hereby granted, free of charge, to any person obtaining a copy
//! of this software and associated documentation files (the "Software"), to deal
//! in the Software without restriction, including without limitation the rights
//! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//! copies of the Software, and to permit persons to whom the Software is
//! furnished to do so, subject to the following conditions:
//!
//! The above copyright notice and this permission notice shall be included in
//! all copies or substantial portions of the Software.
//!
//! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//! SOFTWARE.
//!
//*****************************************************************************
#include "w6300.h"
#if 0
#define _WIZCHIP_SPI_VDM_OP_ 0x00
#define _WIZCHIP_SPI_FDM_LEN1_ 0x01
#define _WIZCHIP_SPI_FDM_LEN2_ 0x02
#define _WIZCHIP_SPI_FDM_LEN4_ 0x03
#endif
//
// If you want to use SPI FDM mode, Feel free contact to WIZnet.
// http://forum.wiznet.io
//
#if _WIZCHIP_ == 6300
////////////////////////////////////////////////////////////////////////////////////////
#define _W6300_SPI_OP_ _WIZCHIP_SPI_VDM_OP_
#define _W6300_SPI_READ_ (0x00 << 5) ///< SPI interface Read operation in Control Phase
#define _W6300_SPI_WRITE_ (0x01 << 5) ///< SPI interface Write operation in Control Phase
//////////////////////////////////////////////////
void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb) {
uint8_t opcode = 0;
uint16_t ADDR = 0;
WIZCHIP_CRITICAL_ENTER();
WIZCHIP.CS._select();
#if (_WIZCHIP_IO_MODE_ & 0xff00) & _WIZCHIP_IO_MODE_BUS_
uint8_t tAD[4];
tAD[0] = (uint8_t)((AddrSel & 0x00FF0000) >> 16);
tAD[1] = (uint8_t)((AddrSel & 0x0000FF00) >> 8);
tAD[2] = (uint8_t)(AddrSel & 0x000000ff);
tAD[3] = wb;
WIZCHIP.IF.BUS._write_data_buf(IDM_AR0, tAD, 4, 1);
#else //w6300 QSPI MODE
opcode = (uint8_t)((AddrSel & 0x000000FF) | (_W6300_SPI_WRITE_) | (_WIZCHIP_QSPI_MODE_));
ADDR = (uint16_t)((AddrSel & 0x00ffff00) >> 8);
WIZCHIP.IF.QSPI._write_qspi(opcode, ADDR, &wb, 1);
#endif
WIZCHIP.CS._deselect();
WIZCHIP_CRITICAL_EXIT();
}
uint8_t WIZCHIP_READ(uint32_t AddrSel) {
//uint8_t ret;
uint8_t ret[2] = {0,};
uint8_t opcode = 0;
uint16_t ADDR = 0;
WIZCHIP_CRITICAL_ENTER();
WIZCHIP.CS._select();
#if (_WIZCHIP_IO_MODE_ & 0xff00) & _WIZCHIP_IO_MODE_BUS_
uint8_t tAD[3];
tAD[0] = (uint8_t)((AddrSel & 0x00FF0000) >> 16);
tAD[1] = (uint8_t)((AddrSel & 0x0000FF00) >> 8);
tAD[2] = (uint8_t)(AddrSel & 0x000000ff);
WIZCHIP.IF.BUS._write_data_buf(IDM_AR0, tAD, 3, 1);
ret[0] = WIZCHIP.IF.BUS._read_data(IDM_DR);
#else
opcode = (uint8_t)((AddrSel & 0x000000FF) | (_W6300_SPI_READ_) | (_WIZCHIP_QSPI_MODE_));
ADDR = (uint16_t)((AddrSel & 0x00ffff00) >> 8);
WIZCHIP.IF.QSPI._read_qspi(opcode, ADDR, ret, 1);
#endif
WIZCHIP.CS._deselect();
WIZCHIP_CRITICAL_EXIT();
return ret[0];
}
void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, datasize_t len) {
uint8_t opcode = 0;
uint16_t ADDR = 0;
WIZCHIP_CRITICAL_ENTER();
WIZCHIP.CS._select();
#if (_WIZCHIP_IO_MODE_ & 0xff00) & _WIZCHIP_IO_MODE_BUS_
uint8_t tAD[3];
tAD[0] = (uint8_t)((AddrSel & 0x00FF0000) >> 16);
tAD[1] = (uint8_t)((AddrSel & 0x0000FF00) >> 8);
tAD[2] = (uint8_t)(AddrSel & 0x000000ff);
WIZCHIP.IF.BUS._write_data_buf(IDM_AR0, tAD, 3, 1);
WIZCHIP.IF.BUS._write_data_buf(IDM_DR, pBuf, len, 0);
#else
opcode = (uint8_t)((AddrSel & 0x000000FF) | (_W6300_SPI_WRITE_) | (_WIZCHIP_QSPI_MODE_));
ADDR = (uint16_t)((AddrSel & 0x00ffff00) >> 8);
WIZCHIP.IF.QSPI._write_qspi(opcode, ADDR, pBuf, len);//by_lihan
//qspi_write_buf(opcode, ADDR, pBuf, len);
WIZCHIP.CS._deselect();
WIZCHIP_CRITICAL_EXIT();
#endif
}
void WIZCHIP_READ_BUF(uint32_t AddrSel, uint8_t* pBuf, datasize_t len) {
uint8_t ret;
uint8_t opcode = 0;
uint16_t ADDR = 0;
WIZCHIP_CRITICAL_ENTER();
WIZCHIP.CS._select();
#if _WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_
uint8_t tAD[3];
tAD[0] = (uint8_t)((AddrSel & 0x00FF0000) >> 16);
tAD[1] = (uint8_t)((AddrSel & 0x0000FF00) >> 8);
tAD[2] = (uint8_t)(AddrSel & 0x000000ff);
WIZCHIP.IF.BUS._write_data_buf(IDM_AR0, tAD, 3, 1);
WIZCHIP.IF.BUS._read_data_buf(IDM_DR, pBuf, len, 0);
#else
opcode = (uint8_t)((AddrSel & 0x000000FF) | (_W6300_SPI_READ_) | (_WIZCHIP_QSPI_MODE_));
ADDR = (uint16_t)((AddrSel & 0x00ffff00) >> 8);
WIZCHIP.IF.QSPI._read_qspi(opcode, ADDR, pBuf, len);//by_lihan
//qspi_read_buf(opcode, ADDR, pBuf, len);
WIZCHIP.CS._deselect();
WIZCHIP_CRITICAL_EXIT();
#endif
}
uint16_t getSn_TX_FSR(uint8_t sn) {
uint16_t prev_val = -1, val = 0;
do {
prev_val = val;
val = WIZCHIP_READ(_Sn_TX_FSR_(sn));
val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(_Sn_TX_FSR_(sn), 1));
} while (val != prev_val);
return val;
}
uint16_t getSn_RX_RSR(uint8_t sn) {
uint16_t prev_val = -1, val = 0;
do {
prev_val = val;
val = WIZCHIP_READ(_Sn_RX_RSR_(sn));
val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(_Sn_RX_RSR_(sn), 1));
} while (val != prev_val);
return val;
}
void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len) {
uint16_t ptr = 0;
uint32_t addrsel = 0;
ptr = getSn_TX_WR(sn);
addrsel = ((uint32_t)ptr << 8) + WIZCHIP_TXBUF_BLOCK(sn);
WIZCHIP_WRITE_BUF(addrsel, wizdata, len);
ptr += len;
setSn_TX_WR(sn, ptr);
}
#if 0
#define ETHERNET_BUF_MAX_SIZE_TEMP (1024 * 32 )
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);
if (ptr + len > 0xFFFF) {
addrsel = ((uint32_t)ptr << 8) + WIZCHIP_RXBUF_BLOCK(sn);
uint16_t size = 0xFFFF - ptr;
WIZCHIP_READ_BUF(addrsel, wizdata, size);
wizdata += size;
size = len - size;
addrsel = WIZCHIP_RXBUF_BLOCK(sn);
WIZCHIP_READ_BUF(addrsel, wizdata, size);
} else {
addrsel = ((uint32_t)ptr << 8) + WIZCHIP_RXBUF_BLOCK(sn);
WIZCHIP_READ_BUF(addrsel, wizdata, len);
}
ptr += len;
ptr %= 0xFFFF ;
setSn_RX_RD(sn, ptr);
}
#else
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);
addrsel = ((uint32_t)ptr << 8) + WIZCHIP_RXBUF_BLOCK(sn);
WIZCHIP_READ_BUF(addrsel, wizdata, len);
ptr += len;
setSn_RX_RD(sn, ptr);
}
#endif
void wiz_recv_ignore(uint8_t sn, uint16_t len) {
setSn_RX_RD(sn, getSn_RX_RD(sn) + len);
}
#if 1
// 20231019 taylor
void wiz_delay_ms(uint32_t milliseconds) {
uint32_t i;
for (i = 0 ; i < milliseconds ; i++) {
//Write any values to clear the TCNTCLKR register
setTCNTRCLR(0xff);
// Wait until counter register value reaches 10.(10 = 1ms : TCNTR is 100us tick counter register)
while (getTCNTR() < 0x0a) {}
}
}
#endif
/// @cond DOXY_APPLY_CODE
#if (_PHY_IO_MODE_ == _PHY_IO_MODE_MII_)
/// @endcond
void wiz_mdio_write(uint8_t phyregaddr, uint16_t var) {
setPHYRAR(phyregaddr);
setPHYDIR(var);
setPHYACR(PHYACR_WRITE);
while (getPHYACR()); //wait for command complete
}
uint16_t wiz_mdio_read(uint8_t phyregaddr) {
setPHYRAR(phyregaddr);
setPHYACR(PHYACR_READ);
while (getPHYACR()); //wait for command complete
return getPHYDOR();
}
/// @cond DOXY_APPLY_CODE
#endif
/// @endcond
////////////////////////////////////////////////////////////////////////////////////////
#endif

4103
Ethernet/W6300/w6300.h Normal file

File diff suppressed because it is too large Load Diff

1473
Ethernet/socket.c Normal file

File diff suppressed because it is too large Load Diff

736
Ethernet/socket.h Normal file
View File

@@ -0,0 +1,736 @@
//*****************************************************************************
//
//! \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.
#if (_WIZCHIP_ == W5100 || _WIZCHIP_ == W5100S || _WIZCHIP_ == W5200 || _WIZCHIP_ == W5300 || _WIZCHIP_ == W5500)
/*
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.
#define Sn_MR2_DHAM (1<<1)
#define SF_DHA_MANUAL (Sn_MR2_DHAM)
#define Sn_MR2_FARP (1<<0)
#define SF_FORCE_ARP (Sn_MR2_FARP)
#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.
//
//teddy 240122
#define PACK_IPv6 (1<<7) ///< It indicates the destination IP address of the received packet is IPv6 or IPv4.
#define PACK_IPV6_ALLNODE (PACK_IPv6 | (1<<6)) ///< It indicates the destination IP address of the received packet is allnode multicast(broadcast) address or not.
#define PACK_IPV6_MULTI (PACK_IPv6 | (1<<5)) ///< It indicates the destination IP address of the received packet is multicast address or not.
#define PACK_IPV6_LLA (PACK_IPv6 | (1<<4)) ///< It indicates the destination IP address of the received packet is lla or gua.
#define PACK_NONE (0x00) ///< It indicates no information of a packet
#elif ((_WIZCHIP_ == 6100) || (_WIZCHIP_ == 6300))
/*
- @ref Sn_MR_MULTI : Support UDP Multicasting
- @ref Sn_MR_MF : Support MAC Filter Enable
- @ref Sn_MR_BRDB : Broadcast Block
- @ref Sn_MR_FPSH : Force PSH flag
- @ref Sn_MR_ND : No Delay ACK flag
- @ref Sn_MR_MC : IGMP ver2, ver1
- @ref Sn_MR_SMB : Solicited Multicast Block
- @ref Sn_MR_MMB : IPv4 Multicast block
- @ref Sn_MR_UNIB : Unicast Block
- @ref Sn_MR_MMB6 : IPv6 UDP Multicast Block </b>
- @ref Sn_MR2_DHAM : @ref Sn_MR2_DHAM_AUTO, @ref Sn_MR2_DHAM_MANUAL
- @ref Sn_MR_FARP
*/
/*
SOCKET FLAG
*/
/**
@brief In UDP mode such as @ref Sn_MR_UDP4 and @ref Sn_MR_UDP6, @ref Sn_MR_UDP6, Enable multicast mode. When @ref Sn_MR_UDP6, Enable only IPv6 Multicating.
*/
#define SF_MULTI_ENABLE (Sn_MR_MULTI)
#define SF_ETHER_OWN (Sn_MR_MF) ///< In MACRAW mode such as @ref Sn_MR_MACRAW, Receive only the packet as broadcast, multicast and own packet
/**
@brief In UDP mode such as @ref Sn_MR_UDP4, @ref Sn_MR_UDP6 and @ref Sn_MR_UDPD, or In MACRAW mode sucha as @ref Sn_MR_MACRAW, Block a broadcast packet.
*/
#define SF_BROAD_BLOCK (Sn_MR_BRDB)
#define SF_TCP_FPSH (Sn_MR_FPSH) ///< In TCP mode such as @ref Sn_MR_TCP4, @ref Sn_MR_TCP6 and @ref Sn_MR_TCPD, Use to forced push flag.
#define SF_TCP_NODELAY (Sn_MR_ND) ///< In TCP mode such as @ref Sn_MR_TCP4, @ref Sn_MR_TCP6 and @ref Sn_MR_TCPD, Use to nodelayed ack.
#define SF_IGMP_VER2 (Sn_MR_MC) ///< In UDP mode such as @ref Sn_MR_UDP4 with @ref SF_MULTI_ENABLE, Select IGMP version 2.
#define SF_SOLICIT_BLOCK (Sn_MR_SMB) ///< In UDP mode such as @ref Sn_MR_UDP6 and @ref Sn_MR_UDPD, Block a solicited mutlicast packet.
#define SF_ETHER_MULTI4B (Sn_MR_MMB4) ///< In MACRAW mode such as @ref Sn_MR_MACRAW with @ref SF_MULTI_ENABLE, Block a IPv4 multicast packet.
#define SF_UNI_BLOCK (Sn_MR_UNIB) ///< In UDP mdoe such as @ref Sn_MR_UDP4, @ref Sn_MR_UDP6 and @ref Sn_MR_UDPD with @ref SF_MULTI_ENABLE, Block a unicast packet.
#define SF_ETHER_MULIT6B (Sn_MR_MMB6) ///< In MACRAW mode such as @ref Sn_MR_MACRAW with @ref SF_MULTI_ENABLE, Block a IPv6 multicast packet.
/**
@brief Force to APR.
@details In datagram mode such as @ref Sn_MR_IPRAW4, @ref Sn_MR_IPRAW6, @ref Sn_MR_UDP4, @ref Sn_MR_UDP6, and @ref Sn_MR_UDPD,
Force to request ARP before a packet is sent to a destination.\n
In TCP mode such as @ref Sn_MR_TCP4, @ref Sn_MR_TCP6, and @ref Sn_MR_TCPD and <b>TCP SERVER</b> operation mode,
Force to request ARP before SYN/ACK packet is sent to a <b>TCP CLIENT</b>. \n
When @ref SF_DHA_MANUAL is set, the ARP is process but the destination hardware address is fixed by user.
*/
#define SF_FORCE_ARP (Sn_MR2_FARP)
/**
@brief The destination hardware address of packet to be transmitted is set by user through @ref _Sn_DHAR_. It is invalid in MACRAW mode such as @ref Sn_MR_MACRAW.
*/
#define SF_DHA_MANUAL (Sn_MR2_DHAM)
#define SF_IO_NONBLOCK (0x01 << 3) ///< Socket nonblock io mode. It used parameter in @ref socket().
/*
UDP, IPRAW, MACRAW Packet Infomation
*/
#define PACK_IPv6 (1<<7) ///< It indicates the destination IP address of the received packet is IPv6 or IPv4.
#define PACK_IPV6_ALLNODE (PACK_IPv6 | (1<<6)) ///< It indicates the destination IP address of the received packet is allnode multicast(broadcast) address or not.
#define PACK_IPV6_MULTI (PACK_IPv6 | (1<<5)) ///< It indicates the destination IP address of the received packet is multicast address or not.
#define PACK_IPV6_LLA (PACK_IPv6 | (1<<4)) ///< It indicates the destination IP address of the received packet is lla or gua.
#define PACK_COMPLETED (1<<3) ///< It indicates the read data is last in the received packet.
#define PACK_REMAINED (1<<2) ///< It indicates to remain data in the received packet
#define PACK_FIRST (1<<1) ///< It indicates the read data is first in the received packet.
#define PACK_NONE (0x00) ///< It indicates no information of a packet
#define SRCV6_PREFER_AUTO (PSR_AUTO) ///< Soruce IPv6 address is preferred to auto-selection. Refer to @ref _Sn_PSR_
#define SRCV6_PREFER_LLA (PSR_LLA) ///< Soruce IPv6 address is preferred to link local address. Refer to @ref _Sn_PSR_
#define SRCV6_PREFER_GUA (PSR_GUA) ///< Soruce IPv6 address is preferred to global unique address. Refer to @ref _Sn_PSR_
#define TCPSOCK_MODE (Sn_ESR_TCPM) ///< It indicates the IP version when SOCKETn is opened as TCP6 or TCPD mode.(0 - IPv4 , 1 - IPv6)
#define TCPSOCK_OP (Sn_ESR_TCPOP) ///< It indicates the operation mode when SOCKETn is connected.(0 - <b>TCP CLIENT</b> , 1 - <b>TCP SERVER</b>)
#define TCPSOCK_SIP (Sn_ESR_IP6T) ///< It indicates the source ip address type when SOCKET is connected. (0 - Link Local, 1 - Global Unique)
/////////////////////////////
// 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().
#endif
/**
@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);
//teddy 240122
/**
@ingroup WIZnet_socket_APIs
@brief Try to connect to a <b>TCP SERVER</b>.
@details It sends a connection-reqeust message to the server with destination IP address and port number passed as parameter.\n
SOCKET <i>sn</i> is used as active(<b>TCP CLIENT</b>) mode.
@param sn SOCKET number. It should be <b>0 ~ @ref _WIZCHIP_SOCK_NUM_</b>.
@param addr Pointer variable of destination IPv6 or IPv4 address.
@param port Destination port number.
@param addrlen the length of <i>addr</i>. \n <- removed
If addr is IPv6 address it should be 16,else if addr is IPv4 address it should be 4. Otherwize, return @ref SOCKERR_IPINVALID.
@return Success : @ref SOCK_OK \n
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 returns immediately\n
@note It is valid only in TCP client mode. \n
In block io mode, it does not return until connection is completed. \n
In Non-block io mode(@ref SF_IO_NONBLOCK), it returns @ref SOCK_BUSY immediately.
*/
static int8_t connect_IO_6(uint8_t sn, uint8_t * addr, uint16_t port, uint8_t addrlen);
//int8_t connect(uint8_t sn, uint8_t * addr, uint16_t port, uint8_t addrlen);
/**
@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 Send datagram to the peer specifed by destination IP address and port number passed as parameter.
@details It sends datagram data by using UDP,IPRAW, or MACRAW mode SOCKET.
@param sn SOCKET number. It should be <b>0 ~ @ref _WIZCHIP_SOCK_NUM_</b>.
@param buf Pointer of data buffer to be sent.
@param len The byte length of data in buf.
@param addr Pointer variable of destination IPv6 or IPv4 address.
@param port Destination port number.
@param addrlen the length of <i>addr</i>. \n
If addr is IPv6 address it should be 16,else if addr is IPv4 address it should be 4. Otherwize, return @ref SOCKERR_IPINVALID.
@return Success : The real sent data size. It may be equal to <i>len</i> or small.\n
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_IPINVALID - Invalid IP address\n
@ref SOCKERR_PORTZERO - Destination port number is zero\n
@ref SOCKERR_DATALEN - Invalid data length \n
@ref SOCKERR_SOCKCLOSED - SOCKET unexpectedly closed \n
@ref SOCKERR_TIMEOUT - Timeout occurred \n
@ref SOCK_BUSY - SOCKET is busy.
@note It is valid only in @ref Sn_MR_UDP4, @ref Sn_MR_UDP6, @ref Sn_MR_UDPD, @ref Sn_MR_IPRAW4, @ref Sn_MR_IPRAW6, and @ref Sn_MR_MACRAW. \n
In UDP mode, It can send data as many as SOCKET RX buffer size if data is greater than SOCKET TX buffer size. \n
In IPRAW and MACRAW mode, It should send data as many as MTU(maxium transmission unit) if data is greater than MTU. That is, <i>len</i> can't exceed to MTU.
In block io mode, It doesn't return until data send is completed.
In non-block io mode(@ref SF_IO_NONBLOCK), It return @ref SOCK_BUSY immediately when SOCKET transimttable buffer size is not enough.
*/
//int32_t sendto(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port, uint8_t addrlen);
static int32_t sendto_IO_6(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port, uint8_t addrlen);
/**
@ingroup WIZnet_socket_APIs
@brief Receive datagram from a peer
@details It can read a data received from a peer by using UDP, IPRAW, or MACRAW mode SOCKET.
@param sn SOCKET number. It should be <b>0 ~ @ref _WIZCHIP_SOCK_NUM_</b>.
@param buf Pointer buffer to be saved the received data.
@param len The max read data length. \n
When the received packet size <= <i>len</i>, it can read data as many as the packet size. \n
When others, it can read data as many as len and remain to the rest data of the packet.
@param addr Pointer variable of destination IP address.\n
It is valid only when @ref recvfrom() is first called for receiving the datagram packet.
You can check it valid or not through @ref PACK_FIRST. You can get it through @ref getsockopt(sn, @ref SO_PACKINFO, &packinfo).\n
In UDP4, IPRAW mode SOCKET, it should be allocated over 4bytes. \n
In UDP6, UDPD mode SOCKET, it should be allocated over 16bytes.
@param port Pointer variable of destination port number. \n
It is valid only when @ref recvfrom() is first called for receiving the datagram packet, same as <i>port</i> case.
@param addrlen The byte length of destination IP address. \n
It is valid only when @ref recvfrom() is first called for receiving the datagram packet, same as <i>port</i> case.\n
When the destination has a IPv4 address, it is set to 4. \n
when the destination has a IPv6 address, it is set to 16.
@return Success : The real received data size. It may be equal to <i>len</i> or small.\n
Fail : @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n
@ref SOCKERR_SOCKNUM - Invalid socket number \n
@ref SOCKERR_ARG - Invalid parameter such as <i>addr</i>, <i>port</i>
@ref SOCK_BUSY - SOCKET is busy.
@note It is valid only in @ref Sn_MR_UDP4, @ref Sn_MR_UDP6, @ref Sn_MR_UDPD, @ref Sn_MR_IPRAW4, @ref Sn_MR_IPRAW6, and @ref Sn_MR_MACRAW. \n
When SOCKET is opened with @ref Sn_MR_MACRAW or When it reads the the remained data of the previous datagram packet,
the parameters such as <i>addr</i>, <i>port</i>, <i>addrlen</i> is ignored. \n
Also, It can read data as many as the received datagram packet size if <i>len</i> is greater than the datagram packet size. \n
In block io mode, it doesn't return until data reception is completed. that is, it waits until any datagram packet is received in SOCKET RX buffer. \n
In non-block io mode(@ref SF_IO_NONBLOCK), it return @ref SOCK_BUSY immediately when SOCKET RX buffer is empty. \n
*/
//int32_t recvfrom(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port, uint8_t *addrlen);
static int32_t recvfrom_IO_6(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port, uint8_t *addrlen);
/////////////////////////////
// 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
//teddy 240122
//#if _WIZCHIP_ == W6100 || _WIZCHIP_ == W6300
CS_SET_PREFER, ///< set the preferred source IPv6 address of transmission packet.\n Refer to @ref SRCV6_PREFER_AUTO, @ref SRCV6_PREFER_LLA and @ref SRCV6_PREFER_GUA.
CS_GET_PREFER, ///< get the preferred source IPv6 address of transmission packet.\n Refer to @ref SRCV6_PREFER_AUTO, @ref SRCV6_PREFER_LLA and @ref SRCV6_PREFER_GUA.
//#endif
#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()
//teddy 240122
//#if _WIZCHIP_ == W6100 || _WIZCHIP_ == W6300
SO_EXTSTATUS, ///< Valid only in @ref getsockopt(). Get the extended TCP SOCKETn status. @ref getSn_ESR()
SO_MODE,
//#endif
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);
//teddy 240122
#if _WIZCHIP_ == W6100 || _WIZCHIP_ == W6300
/**
@ingroup WIZnet_socket_APIs
@brief Peeks a sub-message in SOCKETn RX buffer
@details It peeks the incoming message of SOCKETn RX buffer. \n
It can find the specified sub-message in the incoming message and
return the length of incoming message before the sub-message. \n
It is useful when you need to read each messages from multiple message in SOCKET RX buffer.
@param sn SOCKET number
@param submsg sub-message pointer to find
@param subsize the length of <i>submsg</i>
@return
- Success : the length of incoming message length before the <i>submsg</i> \n
- Fail : -1
@note
It is just return the length of incoming message before the found sub-message. It does not receive the message.\n
So, after calling peeksockmsg, @ref _Sn_RX_RD_ is not changed.
*/
int16_t peeksockmsg(uint8_t sn, uint8_t* submsg, uint16_t subsize);
#endif
// void setAddrlen_W6x00( uint8_t num) ;
// uint8_t checkAddrlen_W6x00() ;
// void inline_setAddrlen_W6x00( uint8_t num);
// uint8_t inline_CheckAddrlen_W6x00( void );
#if 1 // by_Lihan
/**
@ingroup WIZnet_socket_APIs
@brief by_Lihan_W5x00
*/
int8_t connect_W5x00(uint8_t sn, uint8_t * addr, uint16_t port);
/**
@ingroup WIZnet_socket_APIs
@brief by_Lihan_Wx00
*/
int8_t connect_W6x00(uint8_t sn, uint8_t * addr, uint16_t port, uint8_t addrlen);
#define GET_MACRO_connect(_1, _2, _3, _4, NAME, ...) NAME
#define CHOOSE_TESTCODE_MACRO(...) GET_MACRO_connect(__VA_ARGS__, connect_4, connect_3)
/**
// by_LIhan for overroading
// NOTE_LIHAN: Some sections of this code are not yet fully defined.
@note
In case of get 3 arguments - int8_t connect_W5x00(uint8_t sn, uint8_t * addr, uint16_t port );\n
In case of get 4 arguments - int8_t connect_W6x00(uint8_t sn, uint8_t * addr, uint16_t port, uint8_t addrlen );
*/
#define connect(...) CHOOSE_TESTCODE_MACRO(__VA_ARGS__)(__VA_ARGS__)
// In case of get 3 arguments
#define connect_3(sn , addr , port ) connect_W5x00(sn , addr , port)
// In case of get 4 arguments
#define connect_4(sn , addr , port, addrlen ) connect_W6x00(sn , addr , port,addrlen)
/**
@ingroup WIZnet_socket_APIs
@brief by_Lihan
*/
int32_t sendto_W5x00(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port);
/**
@ingroup WIZnet_socket_APIs
@brief by_Lihan
*/
int32_t sendto_W6x00(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port, uint8_t addrlen);
#define GET_MACRO_sendto(_1, _2, _3, _4, _5 , _6, NAME, ...) NAME
#define CHOOSE_sendto_MACRO(...) GET_MACRO_sendto(__VA_ARGS__, sendto_6, sendto_5)
// by_LIhan for overroading
// NOTE_LIHAN: Some sections of this code are not yet fully defined.
// In case of get 3 arguments - int8_t sendto_W5x00(uint8_t sn, uint8_t * addr, uint16_t port );
// In case of get 4 arguments - int8_t sendto_W6x00(uint8_t sn, uint8_t * addr, uint16_t port,uint8_t addrlen );
#define sendto(...) CHOOSE_sendto_MACRO(__VA_ARGS__)(__VA_ARGS__)
// In case of get 3 arguments
#define sendto_5( sn, buf, len, addr, port ) sendto_W5x00( sn, buf, len, addr, port)
// In case of get 4 arguments
#define sendto_6( sn, buf, len, addr, port, addrlen ) sendto_W6x00( sn, buf, len, addr, port, addrlen)
/**
@ingroup WIZnet_socket_APIs
@brief byLihan_W5x00
*/
int32_t recvfrom_W5x00(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port);
/**
@ingroup WIZnet_socket_APIs
@brief byLihan_Wx00
*/
int32_t recvfrom_W6x00(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port, uint8_t *addrlen);
#define GET_MACRO_recvfrom(_1, _2, _3, _4, _5, _6 ,NAME, ...) NAME
#define CHOOSE_recvfrom_MACRO(...) GET_MACRO_recvfrom(__VA_ARGS__, recvfrom_6, recvfrom_5)
// by_LIhanfor overroading
// In case of get 3 arguments - int8_t recvfrom_W5x00(uint8_t sn, uint8_t * addr, uint16_t port );
// In case of get 4 arguments - int8_t recvfrom_W6x00(uint8_t sn, uint8_t * addr, uint16_t port,uint8_t addrlen );
#define recvfrom(...) CHOOSE_recvfrom_MACRO(__VA_ARGS__)(__VA_ARGS__)
// In case of get 3 arguments
#define recvfrom_5(sn, buf, len, addr, port ) recvfrom_W5x00(sn, buf, len, addr, port)
// In case of get 4 arguments
#define recvfrom_6(sn, buf, len, addr, port, addrlen ) recvfrom_W6x00(sn, buf, len, addr, port, addrlen )
#endif
#ifdef __cplusplus
}
#endif
#endif // _SOCKET_H_

1515
Ethernet/wizchip_conf.c Normal file

File diff suppressed because it is too large Load Diff

1348
Ethernet/wizchip_conf.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,681 @@
//* ****************************************************************************
//! \file AddressAutoConfig.c
//! \brief IPv6 AddressAutoConfig Source File.
//! \version 1.0.0
//! \date 2019/01/01
//! \par Revision history
//! <2019/01/01> 1st Release
//! \author WIZnet
//! \copyright
//!
//! Copyright (c) 2019, WIZnet Co., LTD.
//!
//! Permission is hereby granted, free of charge, to any person obtaining a copy
//! of this software and associated documentation files (the "Software"), to deal
//! in the Software without restriction, including without limitation the rights
//! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//! copies of the Software, and to permit persons to whom the Software is
//! furnished to do so, subject to the following conditions:
//!
//! The above copyright notice and this permission notice shall be included in
//! all copies or substantial portions of the Software.
//!
//! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//! SOFTWARE.
//!
//*****************************************************************************
#include "AddressAutoConfig.h"
#if (_WIZCHIP_ == W6100)
#define MY_MAX_DHCP6_RETRY 3
uint8_t AAC_SOCKET; // Socket number for AddressAutoConfi
/**
@brief
*/
extern uint8_t DNS6_Address[16];
/**
@brief
@param netinfo
@param test_buf
@return uint8_t
*/
uint8_t AddressAutoConfig_Init(uint8_t s, wiz_NetInfo *netinfo) {
uint8_t MO_flag;
uint8_t result_aac = 0;
uint8_t data_buf[2048] = {
0,
};
AAC_SOCKET = s; // SOCK_AAC
// DAD LLA
printf("Duplicate_Address_Detection\r\n");
Duplicate_Address_Detection(netinfo);
ctlnetwork(CN_SET_NETINFO, netinfo);
print_network_information();
// RSRA
printf("Address_Auto_Configuration Start\r\n");
MO_flag = Address_Auto_Config_RA(AAC_SOCKET, data_buf, sizeof(data_buf), netinfo);
ctlnetwork(CN_SET_NETINFO, netinfo);
print_network_information();
if (MO_flag == SLAAC_RDNSS) {
// Completed
printf("Address_Auto_Configuration Succeed\r\n");
result_aac = 1;
} else if (MO_flag == SLAAC_DHCP6) {
// Need Stateless DHCP
// Get Other Information
printf("Address_Auto_Configuration Failed\r\n");
printf("Stateless DHCP Start\r\n");
memset(data_buf, 0, sizeof(data_buf));
result_aac = Address_Auto_Config_SLDHCP(AAC_SOCKET, data_buf);
if (result_aac == 1) {
printf(" Stateless DHCP Succeed\r\n");
} else {
printf(" Stateless DHCP Failed\r\n");
}
} else if (MO_flag == SFAAC_DHCP6) {
// Need Stateful DHCP
// Get Managed Information
printf("Address_Auto_Configuration Failed\r\n");
printf("Stateful DHCP Start\r\n");
memset(data_buf, 0, sizeof(data_buf));
result_aac = Address_Auto_Config_SFDHCP(AAC_SOCKET, data_buf, netinfo);
if (result_aac == 1) {
printf("Stateful DHCP Succeed\r\n");
} else {
printf("Stateful DHCP Failed\r\n");
}
ctlnetwork(CN_SET_NETINFO, netinfo);
print_network_information();
} else {
printf("Address_Auto_Configuration Failed MO_Flag : 0x%x\r\n", MO_flag);
result_aac = 0;
}
while (SOCK_OK != close(AAC_SOCKET));
return result_aac;
}
/**
@brief
@param sn
@param test_buf
@return uint8_t
*/
uint8_t Address_Auto_Config_SLDHCP(uint8_t sn, uint8_t *test_buf) {
uint8_t result = 0;
uint8_t tmp[16];
uint32_t toggle = 1;
uint32_t my_dhcp_retry = 0;
DHCP6_init(sn, test_buf);
while (1) {
switch (DHCP6_run2()) {
case DHCP6_IP_ASSIGN:
case DHCP6_IP_CHANGED:
/* If this block empty, act with default_ip_assign & default_ip_update */
//
// This example calls the registered 'my_ip_assign' in the two case.
//
// Add to ...
//
//
toggle = 1;
if (toggle) {
getGAR(tmp);
printf("> DHCP GW : %d.%d.%d.%d\r\n", tmp[0], tmp[1], tmp[2], tmp[3]);
getSUBR(tmp);
printf("> DHCP SN : %d.%d.%d.%d\r\n", tmp[0], tmp[1], tmp[2], tmp[3]);
getSIPR(tmp);
printf("> DHCP IP : %d.%d.%d.%d\r\n", tmp[0], tmp[1], tmp[2], tmp[3]);
toggle = 0;
close(sn); /*
If renewal IP address was defferent previous IP address,
socket becomes to disconnect or close for new connection.
*/
}
break;
case DHCP6_IP_LEASED:
//
if (toggle) {
getSHAR(tmp);
printf("Mac address : %.2x:%.2x:%.2x:%.2x:%.2x:%.2x \r\n", tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5]);
getLLAR(tmp);
printf("your Link Local IP is %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x \r\n", tmp[0], tmp[1], tmp[2], tmp[3],
tmp[4], tmp[5], tmp[6], tmp[7],
tmp[8], tmp[9], tmp[10], tmp[11],
tmp[12], tmp[13], tmp[14], tmp[15]);
getGUAR(tmp);
printf("your Global IP is %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x \r\n", tmp[0], tmp[1], tmp[2], tmp[3],
tmp[4], tmp[5], tmp[6], tmp[7],
tmp[8], tmp[9], tmp[10], tmp[11],
tmp[12], tmp[13], tmp[14], tmp[15]);
getGA6R(tmp);
printf("your Gateway IP is %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x \r\n", tmp[0], tmp[1], tmp[2], tmp[3],
tmp[4], tmp[5], tmp[6], tmp[7],
tmp[8], tmp[9], tmp[10], tmp[11],
tmp[12], tmp[13], tmp[14], tmp[15]);
printf("your DNSv6 is %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x \r\n", DNS6_Address[0], DNS6_Address[1], DNS6_Address[2], DNS6_Address[3],
DNS6_Address[4], DNS6_Address[5], DNS6_Address[6], DNS6_Address[7],
DNS6_Address[8], DNS6_Address[9], DNS6_Address[10], DNS6_Address[11],
DNS6_Address[12], DNS6_Address[13], DNS6_Address[14], DNS6_Address[15]);
toggle = 0;
}
return 1;
case DHCP6_FAILED:
/* ===== Example pseudo code ===== */
// The below code can be replaced your code or omitted.
// if omitted, retry to process DHCP
my_dhcp_retry++;
if (my_dhcp_retry > MY_MAX_DHCP6_RETRY) {
#if DEBUG_MODE != DEBUG_NO
printf(">> DHCP %d Failed\r\n", my_dhcp_retry);
#endif
my_dhcp_retry = 0;
DHCP6_stop(); // if restart, recall DHCP6_init()
}
break;
default:
break;
}
}
return result;
}
/**
@brief
@param sn
@param test_buf
@return uint8_t
*/
uint8_t Address_Auto_Config_SFDHCP(uint8_t sn, uint8_t *test_buf, wiz_NetInfo *netinfo) {
uint8_t result;
uint8_t tmp[16];
uint32_t toggle = 1;
uint32_t my_dhcp_retry = 0;
DHCP6_init(sn, test_buf);
while (1) {
switch (DHCP6_run(netinfo)) {
case DHCP6_IP_ASSIGN:
case DHCP6_IP_CHANGED:
/* If this block empty, act with default_ip_assign & default_ip_update */
//
// This example calls the registered 'my_ip_assign' in the two case.
//
// Add to ...
//
//
toggle = 1;
if (toggle) {
// getGAR(tmp); printf("> DHCP GW : %d.%d.%d.%d\r\n", tmp[0], tmp[1], tmp[2], tmp[3]);
// getSUBR(tmp); printf("> DHCP SN : %d.%d.%d.%d\r\n", tmp[0], tmp[1], tmp[2], tmp[3]);
// getSIPR(tmp); printf("> DHCP IP : %d.%d.%d.%d\r\n", tmp[0], tmp[1], tmp[2], tmp[3]);
toggle = 0;
close(sn); /*
If renewal IP address was defferent previous IP address,
socket becomes to disconnect or close for new connection.
*/
}
break;
case DHCP6_IP_LEASED:
//
if (toggle) {
getSHAR(tmp);
printf("Mac address : %.2x:%.2x:%.2x:%.2x:%.2x:%.2x \r\n", tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5]);
getLLAR(tmp);
printf("your Link Local IP is %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x \r\n", tmp[0], tmp[1], tmp[2], tmp[3],
tmp[4], tmp[5], tmp[6], tmp[7],
tmp[8], tmp[9], tmp[10], tmp[11],
tmp[12], tmp[13], tmp[14], tmp[15]);
getGUAR(tmp);
printf("your Global IP is %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x \r\n", tmp[0], tmp[1], tmp[2], tmp[3],
tmp[4], tmp[5], tmp[6], tmp[7],
tmp[8], tmp[9], tmp[10], tmp[11],
tmp[12], tmp[13], tmp[14], tmp[15]);
getGA6R(tmp);
printf("your Gateway IP is %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x \r\n", tmp[0], tmp[1], tmp[2], tmp[3],
tmp[4], tmp[5], tmp[6], tmp[7],
tmp[8], tmp[9], tmp[10], tmp[11],
tmp[12], tmp[13], tmp[14], tmp[15]);
printf("your DNSv6 is %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x \r\n", DNS6_Address[0], DNS6_Address[1], DNS6_Address[2], DNS6_Address[3],
DNS6_Address[4], DNS6_Address[5], DNS6_Address[6], DNS6_Address[7],
DNS6_Address[8], DNS6_Address[9], DNS6_Address[10], DNS6_Address[11],
DNS6_Address[12], DNS6_Address[13], DNS6_Address[14], DNS6_Address[15]);
toggle = 0;
}
return 1;
case DHCP6_FAILED:
/* ===== Example pseudo code ===== */
// The below code can be replaced your code or omitted.
// if omitted, retry to process DHCP
my_dhcp_retry++;
if (my_dhcp_retry > MY_MAX_DHCP6_RETRY) {
#if DEBUG_MODE != DEBUG_NO
printf(">> DHCP %d Failed\r\n", my_dhcp_retry);
#endif
my_dhcp_retry = 0;
DHCP6_stop(); // if restart, recall DHCP6_init()
return 0;
}
break;
default:
break;
}
}
return result;
}
/**
@brief
@param sn
@param icmpbuf
@param buf_size
@param netinfo
@return uint8_t
*/
uint8_t Address_Auto_Config_RA(uint8_t sn, uint8_t *icmpbuf, uint16_t buf_size, wiz_NetInfo *netinfo) {
uint8_t result;
volatile uint16_t size;
uint8_t destip[16];
uint16_t destport;
uint8_t addr_len, o_len;
uint8_t flags;
uint8_t *p;
uint8_t *e;
int i;
uint8_t o_type, type, code, RA_flag, MO_flag; //, O_flag;
uint16_t Router_lifetime;
uint32_t Reachable_time, Retrans_time;
uint32_t end_point;
uint8_t prefix_len, pi_flag;
uint32_t validtime, prefertime, dnstime;
uint8_t prefix[16];
if (getSLCR() != 0x00) { //check clear CMD
#if (AutoConfig_debug == debug_on)
printf("ERROR : RQCMD is not clear\r\n");
#endif
result = ERROR_SLCMD;
return result;
}
setICMP6BLKR(ICMP6BLKR_RA);
printf("getICMP6BLKR() = 0x%x\r\n", getICMP6BLKR()); // 0X4
setSn_PNR(sn, PROTOCOL_NUM_ICMPv6); //ICMPv6 : 58
printf("getSn_PROTOR(%d) = 0x%x\r\n", sn, getSn_PNR(sn)); // 0X3a
socket(sn, Sn_MR_IPRAW6, 0, 0);
#if 1
printf("Sn_SR : %x \r\n", getSn_SR(sn)); // 0X21 33
#else
#if (AutoConfig_debug == debug_on)
printf("Sn_SR : %x \r\n", getSn_SR(sn));
#endif
#endif
setSLRTR(4000);
printf("getSLRTR() = 0x%x\r\n", getSLRTR()); // 0xfa0 4000
setSLRCR(0);
printf("getSLRCR() = 0x%x\r\n", getSLRCR()); // 0
setSLCR(SLCR_RS);
printf("getSLCR() = 0x%x\r\n", getSLCR()); // 0
printf("getSLIR() = 0x%x\r\n", getSLIR()); // 0
#if (AutoConfig_debug == debug_on)
printf("Wait SLIR.....\r\n");
#endif
do {
if (getSn_RX_RSR(sn) > 0) {
printf("getSLIR() = 0x%x\r\n", getSLIR()); // 0
printf("getSn_RX_RSR(%d) = 0x%x\r\n", sn, getSn_RX_RSR(sn)); // 0x4a 74
printf("size : %d \r\n", sizeof(icmpbuf));
size = recvfrom(sn, icmpbuf, buf_size, destip, &destport, &addr_len);
printf("recvfrom IP : %x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x \r\n", destip[0], destip[1], destip[2], destip[3], destip[4], destip[5], destip[6], destip[7], destip[8], destip[9], destip[10], destip[11], destip[12], destip[13], destip[14], destip[15]);
// =================================================
// 20190402
// Taylor
//
// Set Gateway from source
memcpy(netinfo->gw6, destip, 16);
// =================================================
}
p = icmpbuf;
} while (*p != ROUTER_ADVERTISEMENT);
e = p + size;
switch (*p) {
case ROUTER_ADVERTISEMENT:
printf("RA\r\n");
type = *p++;
printf("type : %x \r\n", type);
code = *p++;
printf("code : %x \r\n", code);
p++;
p++; //checksum
p++; //Cur hop limit
RA_flag = *p++;
printf("RA_flag : %x \r\n", RA_flag);
Router_lifetime = *p++ << 8;
Router_lifetime = Router_lifetime + (*p++);
printf("Router_lifetime : %d s \r\n", Router_lifetime);
Reachable_time = *p++ << 24;
Reachable_time = Reachable_time + (*p++ << 16);
Reachable_time = Reachable_time + (*p++ << 8);
Reachable_time = Reachable_time + (*p++);
printf("Reachable_time : %d ms \r\n", Reachable_time);
Retrans_time = *p++ << 24;
Retrans_time = Retrans_time + (*p++ << 16);
Retrans_time = Retrans_time + (*p++ << 8);
Retrans_time = Retrans_time + (*p++);
printf("Retrans_time : %d ms \r\n", Retrans_time);
while (p < e) {
switch (*p) {
case RAO_SLLA:
o_type = *p++;
printf("Option Type : %d (Source LLA) \r\n", o_type);
o_len = (*p++) * 8;
printf("Option length : %d \r\n", o_len);
p += (o_len - 2);
break;
case RAO_TLLA:
o_type = *p++;
printf("Option Type : %d (Target LLA) \r\n", o_type);
o_len = (*p++) * 8;
printf("Option length : %d \r\n", o_len);
p += (o_len - 2);
break;
case RAO_PI:
o_type = *p++;
printf("Option Type : %d (Prefix information) \r\n", o_type);
o_len = (*p++) * 8;
printf("Option length : %d \r\n", o_len);
end_point = (uint32_t)p - 2 + o_len;
prefix_len = *p++;
printf("Prefix Length : %d \r\n", prefix_len);
pi_flag = *p++;
printf("Prefix Information Flag : %.2x \r\n", pi_flag);
validtime = (*p++ << 24);
validtime += (*p++ << 16);
validtime += (*p++ << 8);
validtime += (*p++);
printf("valid lifetime : %d \r\n", validtime);
prefertime = (*p++ << 24);
prefertime += (*p++ << 16);
prefertime += (*p++ << 8);
prefertime += (*p++);
printf("preferred lifetime : %d \r\n", prefertime);
p++;
p++;
p++;
p++; //reserved
getLLAR(prefix);
for (int i = 0; i < prefix_len / 8; i++) {
prefix[i] = *p++;
// =================================================
// 20190416
// Taylor
//
// Set Subnet Mask from prefix
netinfo->sn6[i] = 0xFF;
// =================================================
}
memcpy(netinfo->gua, prefix, 16);
while ((uint32_t)p != end_point) {
p++;
}
printf("prefix : ");
for (i = 0; i < prefix_len / 8; i++) {
printf("%.2x", prefix[i]);
if (1 == (i % 2)) {
printf(":");
}
}
printf(":\r\n");
break;
case RAO_RH:
o_type = *p++;
printf("Option Type : %d (Redirected Header) \r\n", o_type);
o_len = (*p++) * 8;
printf("Option length : %d \r\n", o_len);
p += (o_len - 2);
break;
case RAO_MTU:
o_type = *p++;
printf("Option Type : %d (MTU) \r\n", o_type);
o_len = (*p++) * 8;
printf("Option length : %d \r\n", o_len);
p += (o_len - 2);
break;
case RAO_RDNS:
o_type = *p++;
printf("Option Type : %d (Recursive DNS Server) \r\n", o_type);
o_len = (*p++) * 8;
printf("Option length : %d \r\n", o_len);
end_point = (uint32_t)p - 2 + o_len;
p++;
p++; //reserved
dnstime = (*p++ << 24);
dnstime += (*p++ << 16);
dnstime += (*p++ << 8);
dnstime += (*p++);
printf("DNS lifetime : %d \r\n", dnstime);
DNS6_Address[0] = *p++;
DNS6_Address[1] = *p++;
DNS6_Address[2] = *p++;
DNS6_Address[3] = *p++;
DNS6_Address[4] = *p++;
DNS6_Address[5] = *p++;
DNS6_Address[6] = *p++;
DNS6_Address[7] = *p++;
DNS6_Address[8] = *p++;
DNS6_Address[9] = *p++;
DNS6_Address[10] = *p++;
DNS6_Address[11] = *p++;
DNS6_Address[12] = *p++;
DNS6_Address[13] = *p++;
DNS6_Address[14] = *p++;
DNS6_Address[15] = *p++;
while ((uint32_t)p != end_point) {
p++;
}
printf("DNS IP : ");
for (i = 0; i < 15; i++) {
printf("%.2x", DNS6_Address[i]);
if (1 == (i % 2)) {
printf(":");
}
}
printf("%x\r\n", DNS6_Address[15]);
break;
default:
printf("default\r\n");
o_type = *p++;
printf("o_type : %d \r\n", o_type);
o_len = (*p++) * 8;
printf("o_len : %d \r\n", o_len);
#if 1
// 20231106 taylor
if (o_len > 0) {
p += (o_len - 2);
} else {
p ++;
}
#else
p += (o_len - 2);
#endif
break;
} // ICMP option
} //while
}
close(sn);
printf("RA : %x \r\n", RA_flag);
//M_flag = RA_flag >> 7;
MO_flag = RA_flag >> 6;
printf("MO : %x \r\n", MO_flag);
result = MO_flag;
return result;
}
/**
@brief
@param netinfo
@return uint8_t
*/
uint8_t Duplicate_Address_Detection(wiz_NetInfo *netinfo) {
uint8_t result;
uint8_t WIZ_LLA[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint8_t flags;
uint8_t tmp_array[16];
uint16_t i;
setSLRTR(2000);
setSLRCR(5);
Generate_EUI64(netinfo->mac, WIZ_LLA);
setSLDIP6R(WIZ_LLA); //target address setting
//setSLIMR(SLIR_TIOUT|SLIR_NS); //only external interrupt???
if (getSLCR() != 0x00) { //check clear CMD
#if (AutoConfig_debug == debug_on)
printf("ERROR : RQCMD is not clear %x \r\n", getSLCR());
#endif
while (1)
;
}
setSLCR(SLCR_NS);
#if (AutoConfig_debug == debug_on)
printf("Wait RQIR.....\r\n");
#endif
do {
flags = getSLIR();
if (flags & SLIR_TOUT) {
#if (AutoConfig_debug == debug_on)
printf("\r\nTimeout !!! DAD SUCCESSED\r\n");
#endif
#if 0
// 20190401
NETCFG_UNLOCK();
#endif
//-- Set Link Local Address
memcpy(netinfo->lla, WIZ_LLA, 16);
#if 0
// 20190404
// Display memcpy result
printf("WIZ_LLA:\r\n");
for (i = 0; i < 16; i += 2) {
printf("%.2x%.2x:", WIZ_LLA[i], WIZ_LLA[i + 1]);
}
printf("\r\n");
printf("netinfo->mac:\r\n");
for (i = 0; i < 16; i += 2) {
printf("%.2x%.2x:", netinfo->lla[i], netinfo->lla[i + 1]);
}
printf("\r\n");
#endif
#if 0
// 20190401
NETCFG_LOCK();
#endif
result = SUCCESS;
} else if (flags & SLIR_NS) {
#if (AutoConfig_debug == debug_on)
printf("\r\nReceived NA !!! DAD FAILED\r\n");
#endif
result = ERROR_DAD_FAIL;
}
} while (!((flags & SLIR_TOUT) || (flags & SLIR_NS)));
printf("\r\nflags = 0x%x\r\n", flags);
setSLIRCLR(flags);
return result;
}
/**
@brief
@param mac_addr
@param Link_Local_Addr
*/
void Generate_EUI64(uint8_t *mac_addr, uint8_t *Link_Local_Addr) {
*Link_Local_Addr = 0xfe;
*(Link_Local_Addr + 1) = 0x80;
//00:00:00:00:00:00
*(Link_Local_Addr + 8) = *(mac_addr); //flip the 7th bit of 1st byte
*(Link_Local_Addr + 8) ^= 1 << 1;
*(Link_Local_Addr + 9) = *(mac_addr + 1);
*(Link_Local_Addr + 10) = *(mac_addr + 2);
*(Link_Local_Addr + 11) = 0xFF;
*(Link_Local_Addr + 12) = 0xFE;
*(Link_Local_Addr + 13) = *(mac_addr + 3);
*(Link_Local_Addr + 14) = *(mac_addr + 4);
*(Link_Local_Addr + 15) = *(mac_addr + 5);
}
#endif

View File

@@ -0,0 +1,133 @@
//* ****************************************************************************
//! \file AddressAutoConfig.h
//! \brief IPv6 AddressAutoConfig Header File.
//! \version 1.0.0
//! \date 2019/01/01
//! \par Revision history
//! <2019/01/01> 1st Release
//! \author WIZnet
//! \copyright
//!
//! Copyright (c) 2019, WIZnet Co., LTD.
//!
//! Permission is hereby granted, free of charge, to any person obtaining a copy
//! of this software and associated documentation files (the "Software"), to deal
//! in the Software without restriction, including without limitation the rights
//! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//! copies of the Software, and to permit persons to whom the Software is
//! furnished to do so, subject to the following conditions:
//!
//! The above copyright notice and this permission notice shall be included in
//! all copies or substantial portions of the Software.
//!
//! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//! SOFTWARE.
//!
//*****************************************************************************
#ifndef _ADDRESSAUTOCONFIG_H_
#define _ADDRESSAUTOCONFIG_H_
#include "stdio.h"
#include "stdint.h"
#if 1
// 20231020 taylor
#if 0
#endif
#else
#include "w6100.h"
#endif
#include "socket.h"
#if 1
// 20231020 taylor
#include "../DHCP6/dhcpv6.h"
#else
#include "dhcpv6.h"
#endif
#if (_WIZCHIP_ == W6100)
#define AutoConfig_debug debug_on
#define debug_on 1
#define debug_off 0
#define PROTOCOL_NUM_ICMPv6 58
#define ROUTER_ADVERTISEMENT 134
#define SUCCESS 0
#define ERROR_DAD_FAIL -1
#define ERROR_SLCMD -2
#define ERROR_TIMEOUT -3
#define SLAAC_RDNSS 0
#define SLAAC_DHCP6 1
#define SFAAC_DHCP6 3
#define RAO_SLLA 1
#define RAO_TLLA 2
#define RAO_PI 3
#define RAO_RH 4
#define RAO_MTU 5
#define RAO_RDNS 25
/**
@brief
@param netinfo
@return uint8_t
*/
uint8_t AddressAutoConfig_Init(uint8_t s, wiz_NetInfo* netinfo);
/**
@brief
@param mac_addr
@param Link_Local_Addr
*/
void Generate_EUI64(uint8_t *mac_addr, uint8_t *Link_Local_Addr);
/**
@brief
@param netinfo
@return uint8_t
*/
uint8_t Duplicate_Address_Detection(wiz_NetInfo* netinfo);
/**
@brief
@param sn
@param icmpbuf
@param buf_size
@param netinfo
@return uint8_t
*/
uint8_t Address_Auto_Config_RA(uint8_t sn, uint8_t *icmpbuf, uint16_t buf_size, wiz_NetInfo* netinfo);
/**
@brief
@param sn
@param test_buf
@return uint8_t
*/
uint8_t Address_Auto_Config_SLDHCP(uint8_t sn, uint8_t* test_buf);
/**
@brief
@param sn
@param test_buf
@return uint8_t
*/
uint8_t Address_Auto_Config_SFDHCP(uint8_t sn, uint8_t* test_buf, wiz_NetInfo* netinfo);
#endif
#endif // _ADDRESSAUTOCONFIG_H_

1118
Internet/DHCP/dhcp.c Normal file

File diff suppressed because it is too large Load Diff

163
Internet/DHCP/dhcp.h Normal file
View File

@@ -0,0 +1,163 @@
//*****************************************************************************
//
//! \file dhcp.h
//! \brief DHCP APIs Header file.
//! \details Processig DHCP protocol as DISCOVER, OFFER, REQUEST, ACK, NACK and DECLINE.
//! \version 1.1.1
//! \date 2019/10/08
//! \par Revision history
//! <2019/10/08> compare DHCP server ip address
//! <2013/11/18> 1st Release
//! <2012/12/20> V1.1.0
//! 1. Move unreferenced DEFINE to dhcp.c
//! <2012/12/26> V1.1.1
//! \author Eric Jung & 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.
//
//*****************************************************************************
#ifndef _DHCP_H_
#define _DHCP_H_
#ifdef __cplusplus
extern "C" {
#endif
/*
@brief
@details If you want to display debug & processing message, Define _DHCP_DEBUG_
@note If defined, it depends on <stdio.h>
*/
#if 0
// 20231023 taylor
#define _DHCP_DEBUG_
#endif
/* Retry to processing DHCP */
#define MAX_DHCP_RETRY 2 ///< Maximum retry count
#define DHCP_WAIT_TIME 10 ///< Wait Time 10s
/* UDP port numbers for DHCP */
#define DHCP_SERVER_PORT 67 ///< DHCP server port number
#define DHCP_CLIENT_PORT 68 ///< DHCP client port number
#define MAGIC_COOKIE 0x63825363 ///< You should not modify it number.
#define DCHP_HOST_NAME "WIZnet\0"
/*
@brief return value of @ref DHCP_run()
*/
enum {
DHCP_FAILED = 0, ///< Processing Fail
DHCP_RUNNING, ///< Processing DHCP protocol
DHCP_IP_ASSIGN, ///< First Occupy IP from DHPC server (if cbfunc == null, act as default default_ip_assign)
DHCP_IP_CHANGED, ///< Change IP address by new ip from DHCP (if cbfunc == null, act as default default_ip_update)
DHCP_IP_LEASED, ///< Stand by
DHCP_STOPPED ///< Stop processing DHCP protocol
};
/*
@brief DHCP client initialization (outside of the main loop)
@param s - socket number
@param buf - buffer for processing DHCP message
*/
void DHCP_init(uint8_t s, uint8_t * buf);
/*
@brief DHCP 1s Tick Timer handler
@note SHOULD BE register to your system 1s Tick timer handler
*/
void DHCP_time_handler(void);
/*
@brief Register call back function
@param ip_assign - callback func when IP is assigned from DHCP server first
@param ip_update - callback func when IP is changed
@param ip_conflict - callback func when the assigned IP is conflict with others.
*/
void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void));
/*
@brief DHCP client in the main loop
@return The value is as the follow \n
@ref DHCP_FAILED \n
@ref DHCP_RUNNING \n
@ref DHCP_IP_ASSIGN \n
@ref DHCP_IP_CHANGED \n
@ref DHCP_IP_LEASED \n
@ref DHCP_STOPPED \n
@note This function is always called by you main task.
*/
uint8_t DHCP_run(void);
/*
@brief Stop DHCP processing
@note If you want to restart. call DHCP_init() and DHCP_run()
*/
void DHCP_stop(void);
/* Get Network information assigned from DHCP server */
/*
@brief Get IP address
@param ip - IP address to be returned
*/
void getIPfromDHCP(uint8_t* ip);
/*
@brief Get Gateway address
@param ip - Gateway address to be returned
*/
void getGWfromDHCP(uint8_t* ip);
/*
@brief Get Subnet mask value
@param ip - Subnet mask to be returned
*/
void getSNfromDHCP(uint8_t* ip);
/*
@brief Get DNS address
@param ip - DNS address to be returned
*/
void getDNSfromDHCP(uint8_t* ip);
/*
@brief Get the leased time by DHCP sever
@return unit 1s
*/
uint32_t getDHCPLeasetime(void);
#ifdef __cplusplus
}
#endif
#endif /* _DHCP_H_ */

1219
Internet/DHCP6/dhcpv6.c Normal file

File diff suppressed because it is too large Load Diff

162
Internet/DHCP6/dhcpv6.h Normal file
View File

@@ -0,0 +1,162 @@
//*****************************************************************************
//
//! \file dhcpv6.h
//! \brief DHCPv6 APIs Header file.
//! \details Processig DHCPv6 protocol as SOLICIT, ADVERTISE.
//! \version 0.0.1
//! \date 2016/06/08
//! \par Revision history
//! <2016/07/18> 1st Release
//! \author JustinKim
//! \copyright
//!
//! Copyright (c) 2016, 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.
//
//*****************************************************************************
#ifndef _DHCP6_H_
#define _DHCP6_H_
#include <stdint.h>
#if 1
// 20231020 taylor
#if 0
#include "W6100.h"
#endif
#else
#include "W6100.h"
#endif
#include "socket.h"
#if (_WIZCHIP_ == W6100)
/*
@brief
@details If you want to display debug & procssing message, Define _DHCP_DEBUG_
@note If defined, it dependens on <stdio.h>
*/
#if 0
#define _DHCP6_DEBUG_
#endif
/* Retry to processing DHCPv6 */
#define MAX_DHCP6_RETRY 2 ///< Maxium retry count
#define DHCP6_WAIT_TIME 10 ///< Wait Time 10s
/* UDP port numbers for DHCPv6 */
#define DHCP6_SERVER_PORT 547 ///< DHCP6 server port number
#define DHCP6_CLIENT_PORT 546 ///< DHCP6 client port number
#define DCHP6_HOST_NAME "WIZnet\0"
/*
@brief return value of @ref DHCP6_run()
*/
enum {
DHCP6_FAILED = 0, ///< Procssing Fail
DHCP6_RUNNING, ///< Procssing DHCPv6 proctocol
DHCP6_IP_ASSIGN, ///< First Occupy IP from DHCPv6 server (if cbfunc == null, act as default default_ip_assign)
DHCP6_IP_CHANGED, ///< Change IP address by new ip from DHCPv6 (if cbfunc == null, act as default default_ip_update)
DHCP6_IP_LEASED, ///< Stand by
DHCP6_STOPPED ///< Stop procssing DHCPv6 protocol
};
/**
@brief
@param asize
@param agrowby
*/
void InitDhcp6Option(unsigned asize, unsigned agrowby);
/**
@brief
@param value
*/
void AppendDhcp6Option(uint8_t value);
/**
@brief
@param sMark
*/
void DumpDhcp6Option(char *sMark);
/**
@brief
@param Option
*/
void DHCP6_Option_Select(uint8_t Option);
/*
@brief DHCPv6 client initialization (outside of the main loop)
@param s - socket number
@param buf - buffer for procssing DHCPv6 message
*/
void DHCP6_init(uint8_t s, uint8_t *buf);
/*
@brief DHCPv6 1s Tick Timer handler
@note SHOULD BE register to your system 1s Tick timer handler
*/
void DHCP6_time_handler(void);
/**
@brief
@param netinfo
@return uint8_t
*/
uint8_t DHCP6_run(wiz_NetInfo *netinfo);
/**
@brief
@return uint8_t
*/
uint8_t DHCP6_run2(void);
/*
@brief Stop DHCPv6 procssing
@note If you want to restart. call DHCP6_init() and DHCP_run()
*/
void DHCP6_stop(void);
/* send DISCOVER message to DHCPv6 server */
void send_DHCP6_SOLICIT(void);
uint8_t send_DHCP6_REQUEST(void);
/* check the timeout in DHCPv6 process */
uint8_t check_DHCP6_timeout(void);
/* Intialize to timeout process. */
void reset_DHCP6_timeout(void);
int8_t parseDHCP6MSG(void);
uint8_t DHCP6_run2(void);
#endif
#endif /* _DHCP6_H_ */

615
Internet/DNS/dns.c Normal file
View File

@@ -0,0 +1,615 @@
//*****************************************************************************
//
//! \file dns.c
//! \brief DNS APIs Implement file.
//! \details Send DNS query & Receive DNS reponse. \n
//! It depends on stdlib.h & string.h in ansi-c library
//! \version 1.1.0
//! \date 2013/11/18
//! \par Revision history
//! <2013/10/21> 1st Release
//! <2013/12/20> V1.1.0
//! 1. Remove secondary DNS server in DNS_run
//! If 1st DNS_run failed, call DNS_run with 2nd DNS again
//! 2. DNS_timerHandler -> DNS_time_handler
//! 3. Remove the unused define
//! 4. Integrated dns.h dns.c & dns_parse.h dns_parse.c into dns.h & dns.c
//! <2013/12/20> V1.1.0
//!
//! \author Eric Jung & 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 <string.h>
#include <stdlib.h>
#include "socket.h"
#include "dns.h"
#ifdef _DNS_DEBUG_
#include <stdio.h>
#endif
#define INITRTT 2000L /* Initial smoothed response time */
#define MAXCNAME (MAX_DOMAIN_NAME + (MAX_DOMAIN_NAME>>1)) /* Maximum amount of cname recursion */
#define TYPE_A 1 /* Host address */
#define TYPE_NS 2 /* Name server */
#define TYPE_MD 3 /* Mail destination (obsolete) */
#define TYPE_MF 4 /* Mail forwarder (obsolete) */
#define TYPE_CNAME 5 /* Canonical name */
#define TYPE_SOA 6 /* Start of Authority */
#define TYPE_MB 7 /* Mailbox name (experimental) */
#define TYPE_MG 8 /* Mail group member (experimental) */
#define TYPE_MR 9 /* Mail rename name (experimental) */
#define TYPE_NULL 10 /* Null (experimental) */
#define TYPE_WKS 11 /* Well-known sockets */
#define TYPE_PTR 12 /* Pointer record */
#define TYPE_HINFO 13 /* Host information */
#define TYPE_MINFO 14 /* Mailbox information (experimental)*/
#define TYPE_MX 15 /* Mail exchanger */
#define TYPE_TXT 16 /* Text strings */
#define TYPE_ANY 255 /* Matches any type */
#define CLASS_IN 1 /* The ARPA Internet */
/* Round trip timing parameters */
#define AGAIN 8 /* Average RTT gain = 1/8 */
#define LAGAIN 3 /* Log2(AGAIN) */
#define DGAIN 4 /* Mean deviation gain = 1/4 */
#define LDGAIN 2 /* log2(DGAIN) */
/* Header for all domain messages */
struct dhdr {
uint16_t id; /* Identification */
uint8_t qr; /* Query/Response */
#define QUERY 0
#define RESPONSE 1
uint8_t opcode;
#define IQUERY 1
uint8_t aa; /* Authoratative answer */
uint8_t tc; /* Truncation */
uint8_t rd; /* Recursion desired */
uint8_t ra; /* Recursion available */
uint8_t rcode; /* Response code */
#define NO_ERROR 0
#define FORMAT_ERROR 1
#define SERVER_FAIL 2
#define NAME_ERROR 3
#define NOT_IMPL 4
#define REFUSED 5
uint16_t qdcount; /* Question count */
uint16_t ancount; /* Answer count */
uint16_t nscount; /* Authority (name server) count */
uint16_t arcount; /* Additional record count */
};
uint8_t* pDNSMSG; // DNS message buffer
uint8_t DNS_SOCKET; // SOCKET number for DNS
uint16_t DNS_MSGID; // DNS message ID
uint32_t dns_1s_tick; // for timout of DNS processing
static uint8_t retry_count;
/* converts uint16_t from network buffer to a host byte order integer. */
uint16_t get16(uint8_t * s) {
uint16_t i;
i = *s++ << 8;
i = i + *s;
return i;
}
/* copies uint16_t to the network buffer with network byte order. */
uint8_t * put16(uint8_t * s, uint16_t i) {
*s++ = i >> 8;
*s++ = i;
return s;
}
/*
CONVERT A DOMAIN NAME TO THE HUMAN-READABLE FORM
Description : This function converts a compressed domain name to the human-readable form
Arguments : msg - is a pointer to the reply message
compressed - is a pointer to the domain name in reply message.
buf - is a pointer to the buffer for the human-readable form name.
len - is the MAX. size of buffer.
Returns : the length of compressed message
*/
int parse_name(uint8_t * msg, uint8_t * compressed, char * buf, int16_t len) {
uint16_t slen; /* Length of current segment */
uint8_t * cp;
int clen = 0; /* Total length of compressed name */
int indirect = 0; /* Set if indirection encountered */
int nseg = 0; /* Total number of segments in name */
cp = compressed;
for (;;) {
slen = *cp++; /* Length of this segment */
if (!indirect) {
clen++;
}
if ((slen & 0xc0) == 0xc0) {
if (!indirect) {
clen++;
}
indirect = 1;
/* Follow indirection */
cp = &msg[((slen & 0x3f) << 8) + *cp];
slen = *cp++;
}
if (slen == 0) { /* zero length == all done */
break;
}
len -= slen + 1;
if (len < 0) {
return -1;
}
if (!indirect) {
clen += slen;
}
while (slen-- != 0) {
*buf++ = (char) * cp++;
}
*buf++ = '.';
nseg++;
}
if (nseg == 0) {
/* Root name; represent as single dot */
*buf++ = '.';
len--;
}
*buf++ = '\0';
len--;
return clen; /* Length of compressed message */
}
/*
PARSE QUESTION SECTION
Description : This function parses the qeustion record of the reply message.
Arguments : msg - is a pointer to the reply message
cp - is a pointer to the qeustion record.
Returns : a pointer the to next record.
*/
uint8_t * dns_question(uint8_t * msg, uint8_t * cp) {
int len;
char name[MAXCNAME];
len = parse_name(msg, cp, name, MAXCNAME);
if (len == -1) {
return 0;
}
cp += len;
cp += 2; /* type */
cp += 2; /* class */
return cp;
}
/*
PARSE ANSER SECTION
Description : This function parses the answer record of the reply message.
Arguments : msg - is a pointer to the reply message
cp - is a pointer to the answer record.
Returns : a pointer the to next record.
*/
uint8_t * dns_answer(uint8_t * msg, uint8_t * cp, uint8_t * ip_from_dns) {
int len, type;
char name[MAXCNAME];
len = parse_name(msg, cp, name, MAXCNAME);
if (len == -1) {
return 0;
}
cp += len;
type = get16(cp);
cp += 2; /* type */
cp += 2; /* class */
cp += 4; /* ttl */
cp += 2; /* len */
switch (type) {
case TYPE_A:
/* Just read the address directly into the structure */
ip_from_dns[0] = *cp++;
ip_from_dns[1] = *cp++;
ip_from_dns[2] = *cp++;
ip_from_dns[3] = *cp++;
break;
case TYPE_CNAME:
case TYPE_MB:
case TYPE_MG:
case TYPE_MR:
case TYPE_NS:
case TYPE_PTR:
/* These types all consist of a single domain name */
/* convert it to ascii format */
len = parse_name(msg, cp, name, MAXCNAME);
if (len == -1) {
return 0;
}
cp += len;
break;
case TYPE_HINFO:
len = *cp++;
cp += len;
len = *cp++;
cp += len;
break;
case TYPE_MX:
cp += 2;
/* Get domain name of exchanger */
len = parse_name(msg, cp, name, MAXCNAME);
if (len == -1) {
return 0;
}
cp += len;
break;
case TYPE_SOA:
/* Get domain name of name server */
len = parse_name(msg, cp, name, MAXCNAME);
if (len == -1) {
return 0;
}
cp += len;
/* Get domain name of responsible person */
len = parse_name(msg, cp, name, MAXCNAME);
if (len == -1) {
return 0;
}
cp += len;
cp += 4;
cp += 4;
cp += 4;
cp += 4;
cp += 4;
break;
case TYPE_TXT:
/* Just stash */
break;
default:
/* Ignore */
break;
}
return cp;
}
/*
PARSE THE DNS REPLY
Description : This function parses the reply message from DNS server.
Arguments : dhdr - is a pointer to the header for DNS message
buf - is a pointer to the reply message.
len - is the size of reply message.
Returns : -1 - Domain name lenght is too big
0 - Fail (Timout or parse error)
1 - Success,
*/
int8_t parseDNSMSG(struct dhdr * pdhdr, uint8_t * pbuf, uint8_t * ip_from_dns) {
uint16_t tmp;
uint16_t i;
uint8_t * msg;
uint8_t * cp;
msg = pbuf;
memset(pdhdr, 0, sizeof(*pdhdr));
pdhdr->id = get16(&msg[0]);
tmp = get16(&msg[2]);
if (tmp & 0x8000) {
pdhdr->qr = 1;
}
pdhdr->opcode = (tmp >> 11) & 0xf;
if (tmp & 0x0400) {
pdhdr->aa = 1;
}
if (tmp & 0x0200) {
pdhdr->tc = 1;
}
if (tmp & 0x0100) {
pdhdr->rd = 1;
}
if (tmp & 0x0080) {
pdhdr->ra = 1;
}
pdhdr->rcode = tmp & 0xf;
pdhdr->qdcount = get16(&msg[4]);
pdhdr->ancount = get16(&msg[6]);
pdhdr->nscount = get16(&msg[8]);
pdhdr->arcount = get16(&msg[10]);
/* Now parse the variable length sections */
cp = &msg[12];
/* Question section */
for (i = 0; i < pdhdr->qdcount; i++) {
cp = dns_question(msg, cp);
#ifdef _DNS_DEUBG_
printf("MAX_DOMAIN_NAME is too small, it should be redfine in dns.h");
#endif
if (!cp) {
return -1;
}
}
/* Answer section */
for (i = 0; i < pdhdr->ancount; i++) {
cp = dns_answer(msg, cp, ip_from_dns);
#ifdef _DNS_DEUBG_
printf("MAX_DOMAIN_NAME is too small, it should be redfine in dns.h");
#endif
if (!cp) {
return -1;
}
}
/* Name server (authority) section */
for (i = 0; i < pdhdr->nscount; i++) {
;
}
/* Additional section */
for (i = 0; i < pdhdr->arcount; i++) {
;
}
if (pdhdr->rcode == 0) {
return 1; // No error
} else {
return 0;
}
}
/*
MAKE DNS QUERY MESSAGE
Description : This function makes DNS query message.
Arguments : op - Recursion desired
name - is a pointer to the domain name.
buf - is a pointer to the buffer for DNS message.
len - is the MAX. size of buffer.
Returns : the pointer to the DNS message.
*/
int16_t dns_makequery(uint16_t op, char * name, uint8_t * buf, uint16_t len) {
uint8_t *cp;
char *cp1;
char sname[MAXCNAME];
char *dname;
uint16_t p;
uint16_t dlen;
cp = buf;
DNS_MSGID++;
cp = put16(cp, DNS_MSGID);
p = (op << 11) | 0x0100; /* Recursion desired */
cp = put16(cp, p);
cp = put16(cp, 1);
cp = put16(cp, 0);
cp = put16(cp, 0);
cp = put16(cp, 0);
strcpy(sname, name);
dname = sname;
dlen = strlen(dname);
for (;;) {
/* Look for next dot */
cp1 = strchr(dname, '.');
if (cp1 != NULL) {
len = cp1 - dname; /* More to come */
} else {
len = dlen; /* Last component */
}
*cp++ = len; /* Write length of component */
if (len == 0) {
break;
}
/* Copy component up to (but not including) dot */
strncpy((char *)cp, dname, len);
cp += len;
if (cp1 == NULL) {
*cp++ = 0; /* Last one; write null and finish */
break;
}
dname += len + 1;
dlen -= len + 1;
}
cp = put16(cp, 0x0001); /* type */
cp = put16(cp, 0x0001); /* class */
return ((int16_t)((uint32_t)(cp) - (uint32_t)(buf)));
}
/*
CHECK DNS TIMEOUT
Description : This function check the DNS timeout
Arguments : None.
Returns : -1 - timeout occurred, 0 - timer over, but no timeout, 1 - no timer over, no timeout occur
Note : timeout : retry count and timer both over.
*/
int8_t check_DNS_timeout(void) {
if (dns_1s_tick >= DNS_WAIT_TIME) {
dns_1s_tick = 0;
if (retry_count >= MAX_DNS_RETRY) {
retry_count = 0;
return -1; // timeout occurred
}
retry_count++;
return 0; // timer over, but no timeout
}
return 1; // no timer over, no timeout occur
}
/* DNS CLIENT INIT */
void DNS_init(uint8_t s, uint8_t * buf) {
DNS_SOCKET = s; // SOCK_DNS
pDNSMSG = buf; // User's shared buffer
DNS_MSGID = DNS_MSG_ID;
}
/* DNS CLIENT RUN */
int8_t DNS_run(uint8_t * dns_ip, uint8_t * name, uint8_t * ip_from_dns) {
int8_t ret;
struct dhdr dhp;
uint8_t ip[4];
uint16_t len, port;
int8_t ret_check_timeout;
retry_count = 0;
dns_1s_tick = 0;
#if 1
// 20231019 taylor
uint8_t addr_len;
#endif
// Socket open
socket(DNS_SOCKET, Sn_MR_UDP, 0, 0);
#ifdef _DNS_DEBUG_
printf("> DNS Query to DNS Server : %d.%d.%d.%d\r\n", dns_ip[0], dns_ip[1], dns_ip[2], dns_ip[3]);
#endif
len = dns_makequery(0, (char *)name, pDNSMSG, MAX_DNS_BUF_SIZE);
#if 1
// 20231016 taylor//teddy 240122
#if ((_WIZCHIP_ == 6100) || (_WIZCHIP_ == 6300))
sendto(DNS_SOCKET, pDNSMSG, len, dns_ip, IPPORT_DOMAIN, 4);
#else
sendto(DNS_SOCKET, pDNSMSG, len, dns_ip, IPPORT_DOMAIN);
#endif
#else
sendto(DNS_SOCKET, pDNSMSG, len, dns_ip, IPPORT_DOMAIN);
#endif
while (1) {
if ((len = getSn_RX_RSR(DNS_SOCKET)) > 0) {
if (len > MAX_DNS_BUF_SIZE) {
len = MAX_DNS_BUF_SIZE;
}
#if 1
// 20231019 taylor//teddy 240122
#if ((_WIZCHIP_ == 6100) || (_WIZCHIP_ == 6300))
len = recvfrom(DNS_SOCKET, pDNSMSG, len, ip, &port, &addr_len);
#else
len = recvfrom(DNS_SOCKET, pDNSMSG, len, ip, &port);
#endif
#else
len = recvfrom(DNS_SOCKET, pDNSMSG, len, ip, &port);
#endif
#ifdef _DNS_DEBUG_
printf("> Receive DNS message from %d.%d.%d.%d(%d). len = %d\r\n", ip[0], ip[1], ip[2], ip[3], port, len);
#endif
ret = parseDNSMSG(&dhp, pDNSMSG, ip_from_dns);
break;
}
// Check Timeout
ret_check_timeout = check_DNS_timeout();
if (ret_check_timeout < 0) {
#ifdef _DNS_DEBUG_
printf("> DNS Server is not responding : %d.%d.%d.%d\r\n", dns_ip[0], dns_ip[1], dns_ip[2], dns_ip[3]);
#endif
close(DNS_SOCKET);
return 0; // timeout occurred
} else if (ret_check_timeout == 0) {
#ifdef _DNS_DEBUG_
printf("> DNS Timeout\r\n");
#endif
#if 1
// 20231016 taylor//teddy 240122
#if ((_WIZCHIP_ == 6100) || (_WIZCHIP_ == 6300))
sendto(DNS_SOCKET, pDNSMSG, len, dns_ip, IPPORT_DOMAIN, 4);
#else
sendto(DNS_SOCKET, pDNSMSG, len, dns_ip, IPPORT_DOMAIN);
#endif
#else
sendto(DNS_SOCKET, pDNSMSG, len, dns_ip, IPPORT_DOMAIN);
#endif
}
}
close(DNS_SOCKET);
// Return value
// 0 > : failed / 1 - success
return ret;
}
/* DNS TIMER HANDLER */
void DNS_time_handler(void) {
dns_1s_tick++;
}

109
Internet/DNS/dns.h Normal file
View File

@@ -0,0 +1,109 @@
//*****************************************************************************
//
//! \file dns.h
//! \brief DNS APIs Header file.
//! \details Send DNS query & Receive DNS reponse.
//! \version 1.1.0
//! \date 2013/11/18
//! \par Revision history
//! <2013/10/21> 1st Release
//! <2013/12/20> V1.1.0
//! 1. Remove secondary DNS server in DNS_run
//! If 1st DNS_run failed, call DNS_run with 2nd DNS again
//! 2. DNS_timerHandler -> DNS_time_handler
//! 3. Move the no reference define to dns.c
//! 4. Integrated dns.h dns.c & dns_parse.h dns_parse.c into dns.h & dns.c
//! <2013/12/20> V1.1.0
//!
//! \author Eric Jung & 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.
//
//*****************************************************************************
#ifndef _DNS_H_
#define _DNS_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
/*
@brief Define it for Debug & Monitor DNS processing.
@note If defined, it dependens on <stdio.h>
*/
//#define _DNS_DEBUG_
#define MAX_DNS_BUF_SIZE 256 ///< maximum size of DNS buffer. */
/*
@brief Maxium length of your queried Domain name
@todo SHOULD BE defined it equal as or greater than your Domain name lenght + null character(1)
@note SHOULD BE careful to stack overflow because it is allocated 1.5 times as MAX_DOMAIN_NAME in stack.
*/
#define MAX_DOMAIN_NAME 128 // for example "www.google.com"
#define MAX_DNS_RETRY 2 ///< Requery Count
#define DNS_WAIT_TIME 3 ///< Wait response time. unit 1s.
#define IPPORT_DOMAIN 53 ///< DNS server port number
#define DNS_MSG_ID 0x1122 ///< ID for DNS message. You can be modifyed it any number
/*
@brief DNS process initialize
@param s : Socket number for DNS
@param buf : Buffer for DNS message
*/
void DNS_init(uint8_t s, uint8_t * buf);
/*
@brief DNS process
@details Send DNS query and receive DNS response
@param dns_ip : DNS server ip
@param name : Domain name to be queryed
@param ip_from_dns : IP address from DNS server
@return -1 : failed. @ref MAX_DOMIN_NAME is too small \n
0 : failed (Timeout or Parse error)\n
1 : success
@note This funtion blocks until success or fail. max time = @ref MAX_DNS_RETRY * @ref DNS_WAIT_TIME
*/
int8_t DNS_run(uint8_t * dns_ip, uint8_t * name, uint8_t * ip_from_dns);
/*
@brief DNS 1s Tick Timer handler
@note SHOULD BE register to your system 1s Tick timer handler
*/
void DNS_time_handler(void);
#ifdef __cplusplus
}
#endif
#endif /* _DNS_H_ */

572
Internet/MQTT/MQTTClient.c Normal file
View File

@@ -0,0 +1,572 @@
/*******************************************************************************
Copyright (c) 2014, 2015 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"
static void NewMessageData(MessageData* md, MQTTString* aTopicName, MQTTMessage* aMessage) {
md->topicName = aTopicName;
md->message = aMessage;
}
static int getNextPacketId(MQTTClient *c) {
return c->next_packetid = (c->next_packetid == MAX_PACKET_ID) ? 1 : c->next_packetid + 1;
}
static int sendPacket(MQTTClient* c, int length, Timer* timer) {
int rc = FAILURE,
sent = 0;
while (sent < length && !TimerIsExpired(timer)) {
rc = c->ipstack->mqttwrite(c->ipstack, &c->buf[sent], length, TimerLeftMS(timer));
if (rc < 0) { // there was an error writing the data
break;
}
sent += rc;
}
if (sent == length) {
TimerCountdown(&c->ping_timer, c->keepAliveInterval); // record the fact that we have successfully sent the packet
rc = SUCCESSS;
} else {
rc = FAILURE;
}
return rc;
}
void MQTTClientInit(MQTTClient* c, Network* network, unsigned int command_timeout_ms,
unsigned char* sendbuf, size_t sendbuf_size, unsigned char* readbuf, size_t readbuf_size) {
int i;
c->ipstack = network;
for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i) {
c->messageHandlers[i].topicFilter = 0;
}
c->command_timeout_ms = command_timeout_ms;
c->buf = sendbuf;
c->buf_size = sendbuf_size;
c->readbuf = readbuf;
c->readbuf_size = readbuf_size;
c->isconnected = 0;
c->ping_outstanding = 0;
c->defaultMessageHandler = NULL;
c->next_packetid = 1;
TimerInit(&c->ping_timer);
#if defined(MQTT_TASK)
MutexInit(&c->mutex);
#endif
}
static int decodePacket(MQTTClient* c, int* value, int timeout) {
unsigned char i;
int multiplier = 1;
int len = 0;
const int MAX_NO_OF_REMAINING_LENGTH_BYTES = 4;
*value = 0;
do {
int 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;
}
static int readPacket(MQTTClient* c, Timer* timer) {
int rc = FAILURE;
MQTTHeader header = {0};
int len = 0;
int rem_len = 0;
/* 1. read the header byte. This has the packet type in it */
if (c->ipstack->mqttread(c->ipstack, c->readbuf, 1, TimerLeftMS(timer)) != 1) {
goto exit;
}
len = 1;
/* 2. read the remaining length. This is variable in itself */
decodePacket(c, &rem_len, TimerLeftMS(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, TimerLeftMS(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
static 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');
}
int deliverMessage(MQTTClient* c, MQTTString* topicName, MQTTMessage* message) {
int i;
int rc = FAILURE;
// we have to find the right message handler - indexed by topic
for (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;
}
int keepalive(MQTTClient* c) {
int rc = FAILURE;
if (c->keepAliveInterval == 0) {
rc = SUCCESSS;
goto exit;
}
if (TimerIsExpired(&c->ping_timer)) {
if (!c->ping_outstanding) {
Timer timer;
TimerInit(&timer);
TimerCountdownMS(&timer, 1000);
int 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;
}
int cycle(MQTTClient* c, Timer* timer) {
// read the socket, see what work is due
unsigned short packet_type = readPacket(c, timer);
int len = 0,
rc = SUCCESSS;
switch (packet_type) {
case CONNACK:
case PUBACK:
case SUBACK:
break;
case PUBLISH: {
MQTTString topicName;
MQTTMessage msg;
int intQoS;
if (MQTTDeserialize_publish(&msg.dup, &intQoS, &msg.retained, &msg.id, &topicName,
(unsigned char * *)&msg.payload, (int *)&msg.payloadlen, c->readbuf, c->readbuf_size) != 1) {
goto exit;
}
msg.qos = (enum QoS)intQoS;
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: {
unsigned short mypacketid;
unsigned char 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;
}
int MQTTYield(MQTTClient* c, int timeout_ms) {
int rc = SUCCESSS;
Timer timer;
TimerInit(&timer);
TimerCountdownMS(&timer, timeout_ms);
if (cycle(c, &timer) == FAILURE) {
rc = FAILURE;
}
return rc;
}
void MQTTRun(void* parm) {
Timer timer;
MQTTClient* c = (MQTTClient*)parm;
TimerInit(&timer);
while (1) {
#if defined(MQTT_TASK)
MutexLock(&c->mutex);
#endif
TimerCountdownMS(&timer, 500); /* Don't wait too long if no traffic is incoming */
cycle(c, &timer);
#if defined(MQTT_TASK)
MutexUnlock(&c->mutex);
#endif
}
}
#if defined(MQTT_TASK)
int MQTTStartTask(MQTTClient* client) {
return ThreadStart(&client->thread, &MQTTRun, client);
}
#endif
int waitfor(MQTTClient* c, int packet_type, Timer* timer) {
int rc = FAILURE;
do {
if (TimerIsExpired(timer)) {
break; // we timed out
}
} while ((rc = cycle(c, timer)) != packet_type);
return rc;
}
int MQTTConnect(MQTTClient* c, MQTTPacket_connectData* options) {
Timer connect_timer;
int rc = FAILURE;
MQTTPacket_connectData default_options = MQTTPacket_connectData_initializer;
int len = 0;
#if defined(MQTT_TASK)
MutexLock(&c->mutex);
#endif
if (c->isconnected) { /* don't send connect packet again if we are already connected */
goto exit;
}
TimerInit(&connect_timer);
TimerCountdownMS(&connect_timer, c->command_timeout_ms);
if (options == 0) {
options = &default_options; /* set default options if none were supplied */
}
c->keepAliveInterval = options->keepAliveInterval;
TimerCountdown(&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) {
unsigned char connack_rc = 255;
unsigned char sessionPresent = 0;
if (MQTTDeserialize_connack(&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;
}
#if defined(MQTT_TASK)
MutexUnlock(&c->mutex);
#endif
return rc;
}
int MQTTSubscribe(MQTTClient* c, const char* topicFilter, enum QoS qos, messageHandler messageHandler) {
int rc = FAILURE;
Timer timer;
int len = 0;
MQTTString topic = MQTTString_initializer;
topic.cstring = (char *)topicFilter;
// This was added because enum QoS was previously typed to *int which resulted in HardFault and unaligned integer read.
// This coping below makes sure the parameter for MQTTSerialize_subscribe is always char no matter what compiler is using for enums
char charQos = (char)qos;
#if defined(MQTT_TASK)
MutexLock(&c->mutex);
#endif
if (!c->isconnected) {
goto exit;
}
TimerInit(&timer);
TimerCountdownMS(&timer, c->command_timeout_ms);
len = MQTTSerialize_subscribe(c->buf, c->buf_size, 0, getNextPacketId(c), 1, &topic, &charQos);
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
int count = 0, grantedQoS = -1;
unsigned short mypacketid;
if (MQTTDeserialize_suback(&mypacketid, 1, &count, &grantedQoS, c->readbuf, c->readbuf_size) == 1) {
rc = grantedQoS; // 0, 1, 2 or 0x80
}
if (rc != 0x80) {
int i;
for (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:
#if defined(MQTT_TASK)
MutexUnlock(&c->mutex);
#endif
return rc;
}
int MQTTUnsubscribe(MQTTClient* c, const char* topicFilter) {
int rc = FAILURE;
Timer timer;
MQTTString topic = MQTTString_initializer;
topic.cstring = (char *)topicFilter;
int len = 0;
#if defined(MQTT_TASK)
MutexLock(&c->mutex);
#endif
if (!c->isconnected) {
goto exit;
}
TimerInit(&timer);
TimerCountdownMS(&timer, c->command_timeout_ms);
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) {
unsigned short 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:
#if defined(MQTT_TASK)
MutexUnlock(&c->mutex);
#endif
return rc;
}
int MQTTPublish(MQTTClient* c, const char* topicName, MQTTMessage* message) {
int rc = FAILURE;
Timer timer;
MQTTString topic = MQTTString_initializer;
topic.cstring = (char *)topicName;
int len = 0;
#if defined(MQTT_TASK)
MutexLock(&c->mutex);
#endif
if (!c->isconnected) {
goto exit;
}
TimerInit(&timer);
TimerCountdownMS(&timer, c->command_timeout_ms);
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, (unsigned char*)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) {
unsigned short mypacketid;
unsigned char 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) {
unsigned short mypacketid;
unsigned char dup, type;
if (MQTTDeserialize_ack(&type, &dup, &mypacketid, c->readbuf, c->readbuf_size) != 1) {
rc = FAILURE;
}
} else {
rc = FAILURE;
}
}
exit:
#if defined(MQTT_TASK)
MutexUnlock(&c->mutex);
#endif
return rc;
}
int MQTTDisconnect(MQTTClient* c) {
int rc = FAILURE;
Timer timer; // we might wait for incomplete incoming publishes to complete
int len = 0;
#if defined(MQTT_TASK)
MutexLock(&c->mutex);
#endif
TimerInit(&timer);
TimerCountdownMS(&timer, c->command_timeout_ms);
len = MQTTSerialize_disconnect(c->buf, c->buf_size);
if (len > 0) {
rc = sendPacket(c, len, &timer); // send the disconnect packet
}
c->isconnected = 0;
#if defined(MQTT_TASK)
MutexUnlock(&c->mutex);
#endif
return rc;
}

178
Internet/MQTT/MQTTClient.h Normal file
View File

@@ -0,0 +1,178 @@
/*******************************************************************************
Copyright (c) 2014, 2015 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
Ian Craggs - documentation and platform specific header
*******************************************************************************/
#if !defined(__MQTT_CLIENT_C_)
#define __MQTT_CLIENT_C_
#if defined(__cplusplus)
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
#include "./MQTTPacket/src/MQTTPacket.h"
#include "stdio.h"
#include "mqtt_interface.h"
#define MAX_PACKET_ID 65535 /* according to the MQTT specification - do not change! */
#if !defined(MAX_MESSAGE_HANDLERS)
#define MAX_MESSAGE_HANDLERS 5 /* redefinable - how many subscriptions do you want? */
#endif
enum QoS { QOS0, QOS1, QOS2 };
/* all failure return codes must be negative */
enum returnCode { BUFFER_OVERFLOW = -2, FAILURE = -1, SUCCESSS = 0 };
/* The Platform specific header must define the Network and Timer structures and functions
which operate on them.
typedef struct Network
{
int (*mqttread)(Network*, unsigned char* read_buffer, int, int);
int (*mqttwrite)(Network*, unsigned char* send_buffer, int, int);
} Network;*/
/* The Timer structure must be defined in the platform specific header,
and have the following functions to operate on it. */
extern void TimerInit(Timer*);
extern char TimerIsExpired(Timer*);
extern void TimerCountdownMS(Timer*, unsigned int);
extern void TimerCountdown(Timer*, unsigned int);
extern int TimerLeftMS(Timer*);
typedef struct MQTTMessage {
enum QoS qos;
unsigned char retained;
unsigned char dup;
unsigned short id;
void *payload;
size_t payloadlen;
} MQTTMessage;
typedef struct MessageData {
MQTTMessage* message;
MQTTString* topicName;
} MessageData;
typedef void (*messageHandler)(MessageData*);
typedef struct MQTTClient {
unsigned int next_packetid,
command_timeout_ms;
size_t buf_size,
readbuf_size;
unsigned char *buf,
*readbuf;
unsigned int keepAliveInterval;
char ping_outstanding;
int 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;
#if defined(MQTT_TASK)
Mutex mutex;
Thread thread;
#endif
} MQTTClient;
#define DefaultClient {0, 0, 0, 0, NULL, NULL, 0, 0, 0}
/**
Create an MQTT client object
@param client
@param network
@param command_timeout_ms
@param
*/
DLLExport void MQTTClientInit(MQTTClient* client, Network* network, unsigned int command_timeout_ms,
unsigned char* sendbuf, size_t sendbuf_size, unsigned char* readbuf, size_t readbuf_size);
/** MQTT Connect - send an MQTT connect packet down the network and wait for a Connack
The nework object must be connected to the network endpoint before calling this
@param options - connect options
@return success code
*/
DLLExport int MQTTConnect(MQTTClient* client, MQTTPacket_connectData* options);
/** MQTT Publish - send an MQTT publish packet and wait for all acks to complete for all QoSs
@param client - the client object to use
@param topic - the topic to publish to
@param message - the message to send
@return success code
*/
DLLExport int MQTTPublish(MQTTClient* client, const char*, MQTTMessage*);
/** MQTT Subscribe - send an MQTT subscribe packet and wait for suback before returning.
@param client - the client object to use
@param topicFilter - the topic filter to subscribe to
@param message - the message to send
@return success code
*/
DLLExport int MQTTSubscribe(MQTTClient* client, const char* topicFilter, enum QoS, messageHandler);
/** MQTT Subscribe - send an MQTT unsubscribe packet and wait for unsuback before returning.
@param client - the client object to use
@param topicFilter - the topic filter to unsubscribe from
@return success code
*/
DLLExport int MQTTUnsubscribe(MQTTClient* client, const char* topicFilter);
/** MQTT Disconnect - send an MQTT disconnect packet and close the connection
@param client - the client object to use
@return success code
*/
DLLExport int MQTTDisconnect(MQTTClient* client);
/** MQTT Yield - MQTT background
@param client - the client object to use
@param time - the time, in milliseconds, to yield for
@return success code
*/
DLLExport int MQTTYield(MQTTClient* client, int time);
#if defined(MQTT_TASK)
/** MQTT start background thread for a client. After this, MQTTYield should not be called.
@param client - the client object to use
@return success code
*/
DLLExport int MQTTStartTask(MQTTClient* client);
#endif
#if defined(__cplusplus)
}
#endif
#endif

View File

@@ -0,0 +1,128 @@
/*******************************************************************************
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_
#if !defined(DLLImport)
#define DLLImport
#endif
#if !defined(DLLExport)
#define DLLExport
#endif
typedef union {
unsigned char all; /**< all connect flags */
#if defined(REVERSED)
struct {
unsigned int username : 1; /**< 3.1 user name */
unsigned int password : 1; /**< 3.1 password */
unsigned int willRetain : 1; /**< will retain setting */
unsigned int willQoS : 2; /**< will QoS value */
unsigned int will : 1; /**< will flag */
unsigned int cleansession : 1; /**< clean session flag */
unsigned int : 1; /**< unused */
} bits;
#else
struct {
unsigned int : 1; /**< unused */
unsigned int cleansession : 1; /**< cleansession flag */
unsigned int will : 1; /**< will flag */
unsigned int willQoS : 2; /**< will QoS value */
unsigned int willRetain : 1; /**< will retain setting */
unsigned int password : 1; /**< 3.1 password */
unsigned int 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. */
char struct_id[4];
/** The version number of this structure. Must be 0 */
int 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).
*/
unsigned char retained;
/**
The quality of service setting for the LWT message (see
MQTTAsync_message.qos and @ref qos).
*/
char 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. */
char struct_id[4];
/** The version number of this structure. Must be 0 */
int struct_version;
/** Version of MQTT to be used. 3 = 3.1 4 = 3.1.1
*/
unsigned char MQTTVersion;
MQTTString clientID;
unsigned short keepAliveInterval;
unsigned char cleansession;
unsigned char willFlag;
MQTTPacket_willOptions will;
MQTTString username;
MQTTString password;
} MQTTPacket_connectData;
typedef union {
unsigned char all; /**< all connack flags */
#if defined(REVERSED)
struct {
unsigned int sessionpresent : 1; /**< session present flag */
unsigned int : 7; /**< unused */
} bits;
#else
struct {
unsigned int : 7; /**< unused */
unsigned int 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 int MQTTSerialize_connect(unsigned char* buf, int buflen, MQTTPacket_connectData* options);
DLLExport int MQTTDeserialize_connect(MQTTPacket_connectData* data, unsigned char* buf, int len);
DLLExport int MQTTSerialize_connack(unsigned char* buf, int buflen, unsigned char connack_rc, unsigned char sessionPresent);
DLLExport int MQTTDeserialize_connack(unsigned char* sessionPresent, unsigned char* connack_rc, unsigned char* buf, int buflen);
DLLExport int MQTTSerialize_disconnect(unsigned char* buf, int buflen);
DLLExport int MQTTSerialize_pingreq(unsigned char* buf, int buflen);
#endif /* MQTTCONNECT_H_ */

View File

@@ -0,0 +1,211 @@
/*******************************************************************************
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
*/
int MQTTSerialize_connectLength(MQTTPacket_connectData* options) {
int 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
*/
int MQTTSerialize_connect(unsigned char* buf, int buflen, MQTTPacket_connectData* options) {
unsigned char *ptr = buf;
MQTTHeader header = {0};
MQTTConnectFlags flags = {0};
int len = 0;
int 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
*/
int MQTTDeserialize_connack(unsigned char* sessionPresent, unsigned char* connack_rc, unsigned char* buf, int buflen) {
MQTTHeader header = {0};
unsigned char* curdata = buf;
unsigned char* enddata = NULL;
int rc = 0;
int 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
*/
int MQTTSerialize_zero(unsigned char* buf, int buflen, unsigned char packettype) {
MQTTHeader header = {0};
int rc = -1;
unsigned char *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
*/
int MQTTSerialize_disconnect(unsigned char* buf, int 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
*/
int MQTTSerialize_pingreq(unsigned char* buf, int buflen) {
return MQTTSerialize_zero(buf, buflen, PINGREQ);
}

View File

@@ -0,0 +1,148 @@
/*******************************************************************************
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
*/
int MQTTPacket_checkVersion(MQTTString* protocol, int version) {
int 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
*/
int MQTTDeserialize_connect(MQTTPacket_connectData* data, unsigned char* buf, int len) {
MQTTHeader header = {0};
MQTTConnectFlags flags = {0};
unsigned char* curdata = buf;
unsigned char* enddata = &buf[len];
int rc = 0;
MQTTString Protocol;
int version;
int mylen = 0;
FUNC_ENTRY;
header.byte = readChar(&curdata);
if (header.bits.type != CONNECT) {
goto exit;
}
curdata += MQTTPacket_decodeBuf(curdata, &mylen); /* read remaining length */
if (!readMQTTLenString(&Protocol, &curdata, enddata) ||
enddata - curdata < 0) { /* do we have enough data to read the protocol version byte? */
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
*/
int MQTTSerialize_connack(unsigned char* buf, int buflen, unsigned char connack_rc, unsigned char sessionPresent) {
MQTTHeader header = {0};
int rc = 0;
unsigned char *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;
}

View File

@@ -0,0 +1,109 @@
/*******************************************************************************
Copyright (c) 2014 IBM Corp.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Ian Craggs - initial API and implementation and/or initial documentation
*******************************************************************************/
#include "StackTrace.h"
#include "MQTTPacket.h"
#include <string.h>
#define min(a, b) ((a < b) ? 1 : 0)
/**
Deserializes the supplied (wire) buffer into publish data
@param dup returned integer - the MQTT dup flag
@param qos returned integer - the MQTT QoS value
@param retained returned integer - the MQTT retained flag
@param packetid returned integer - the MQTT packet identifier
@param topicName returned MQTTString - the MQTT topic in the publish
@param payload returned byte buffer - the MQTT publish payload
@param payloadlen returned integer - the length of the MQTT payload
@param buf the raw buffer data, of the correct length determined by the remaining length field
@param buflen the length in bytes of the data in the supplied buffer
@return error code. 1 is success
*/
int MQTTDeserialize_publish(unsigned char* dup, int* qos, unsigned char* retained, unsigned short* packetid, MQTTString* topicName,
unsigned char** payload, int* payloadlen, unsigned char* buf, int buflen) {
MQTTHeader header = {0};
unsigned char* curdata = buf;
unsigned char* enddata = NULL;
int rc = 0;
int 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;
if (!readMQTTLenString(topicName, &curdata, enddata) ||
enddata - curdata < 0) { /* do we have enough data to read the protocol version byte? */
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
*/
int MQTTDeserialize_ack(unsigned char* packettype, unsigned char* dup, unsigned short* packetid, unsigned char* buf, int buflen) {
MQTTHeader header = {0};
unsigned char* curdata = buf;
unsigned char* enddata = NULL;
int rc = 0;
int 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;
}

View File

@@ -0,0 +1,241 @@
/*******************************************************************************
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(unsigned short packetid) {
return MQTTPacket_names[packetid];
}
int MQTTStringFormat_connect(char* strbuf, int strbuflen, MQTTPacket_connectData* data) {
int strindex = 0;
strindex = snprintf(strbuf, strbuflen,
"CONNECT MQTT version %d, client id %.*s, clean session %d, keep alive %d",
(int)data->MQTTVersion, data->clientID.lenstring.len, data->clientID.lenstring.data,
(int)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,
data->will.topicName.lenstring.len, data->will.topicName.lenstring.data,
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", 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", data->password.lenstring.len, data->password.lenstring.data);
return strindex;
}
int MQTTStringFormat_connack(char* strbuf, int strbuflen, unsigned char connack_rc, unsigned char sessionPresent) {
int strindex = snprintf(strbuf, strbuflen, "CONNACK session present %d, rc %d", sessionPresent, connack_rc);
return strindex;
}
int MQTTStringFormat_publish(char* strbuf, int strbuflen, unsigned char dup, int qos, unsigned char retained,
unsigned short packetid, MQTTString topicName, unsigned char* payload, int payloadlen) {
int strindex = snprintf(strbuf, strbuflen,
"PUBLISH dup %d, QoS %d, retained %d, packet id %d, topic %.*s, payload length %d, payload %.*s",
dup, qos, retained, packetid,
(topicName.lenstring.len < 20) ? topicName.lenstring.len : 20, topicName.lenstring.data,
payloadlen, (payloadlen < 20) ? payloadlen : 20, payload);
return strindex;
}
int MQTTStringFormat_ack(char* strbuf, int strbuflen, unsigned char packettype, unsigned char dup, unsigned short packetid) {
int 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;
}
int MQTTStringFormat_subscribe(char* strbuf, int strbuflen, unsigned char dup, unsigned short packetid, int count,
MQTTString topicFilters[], int requestedQoSs[]) {
return snprintf(strbuf, strbuflen,
"SUBSCRIBE dup %d, packet id %d count %d topic %.*s qos %d",
dup, packetid, count,
topicFilters[0].lenstring.len, topicFilters[0].lenstring.data,
requestedQoSs[0]);
}
int MQTTStringFormat_suback(char* strbuf, int strbuflen, unsigned short packetid, int count, int* grantedQoSs) {
return snprintf(strbuf, strbuflen,
"SUBACK packet id %d count %d granted qos %d", packetid, count, grantedQoSs[0]);
}
int MQTTStringFormat_unsubscribe(char* strbuf, int strbuflen, unsigned char dup, unsigned short packetid,
int count, MQTTString topicFilters[]) {
return snprintf(strbuf, strbuflen,
"UNSUBSCRIBE dup %d, packet id %d count %d topic %.*s",
dup, packetid, count,
topicFilters[0].lenstring.len, topicFilters[0].lenstring.data);
}
char* MQTTFormat_toClientString(char* strbuf, int strbuflen, unsigned char* buf, int buflen) {
int index = 0;
int rem_length = 0;
MQTTHeader header = {0};
header.byte = buf[index++];
index += MQTTPacket_decodeBuf(&buf[index], &rem_length);
switch (header.bits.type) {
case CONNACK: {
unsigned char sessionPresent, connack_rc;
if (MQTTDeserialize_connack(&sessionPresent, &connack_rc, buf, buflen) == 1) {
MQTTStringFormat_connack(strbuf, strbuflen, connack_rc, sessionPresent);
}
}
break;
case PUBLISH: {
unsigned char dup, retained, *payload;
unsigned short packetid;
int qos, payloadlen;
MQTTString topicName = MQTTString_initializer;
if (MQTTDeserialize_publish(&dup, &qos, &retained, &packetid, &topicName,
&payload, &payloadlen, buf, buflen) == 1)
MQTTStringFormat_publish(strbuf, strbuflen, dup, qos, retained, packetid,
topicName, payload, payloadlen);
}
break;
case PUBACK:
case PUBREC:
case PUBREL:
case PUBCOMP: {
unsigned char packettype, dup;
unsigned short packetid;
if (MQTTDeserialize_ack(&packettype, &dup, &packetid, buf, buflen) == 1) {
MQTTStringFormat_ack(strbuf, strbuflen, packettype, dup, packetid);
}
}
break;
case SUBACK: {
unsigned short packetid;
int maxcount = 1, count = 0;
int grantedQoSs[1];
if (MQTTDeserialize_suback(&packetid, maxcount, &count, grantedQoSs, buf, buflen) == 1) {
MQTTStringFormat_suback(strbuf, strbuflen, packetid, count, grantedQoSs);
}
}
break;
case UNSUBACK: {
unsigned short packetid;
if (MQTTDeserialize_unsuback(&packetid, buf, buflen) == 1) {
MQTTStringFormat_ack(strbuf, strbuflen, UNSUBACK, 0, packetid);
}
}
break;
case PINGREQ:
case PINGRESP:
case DISCONNECT:
snprintf(strbuf, strbuflen, "%s", MQTTPacket_names[header.bits.type]);
break;
}
return strbuf;
}
char* MQTTFormat_toServerString(char* strbuf, int strbuflen, unsigned char* buf, int buflen) {
int index = 0;
int rem_length = 0;
MQTTHeader header = {0};
header.byte = buf[index++];
index += MQTTPacket_decodeBuf(&buf[index], &rem_length);
switch (header.bits.type) {
case CONNECT: {
MQTTPacket_connectData data;
int rc;
if ((rc = MQTTDeserialize_connect(&data, buf, buflen)) == 1) {
MQTTStringFormat_connect(strbuf, strbuflen, &data);
}
}
break;
case PUBLISH: {
unsigned char dup, retained, *payload;
unsigned short packetid;
int qos, payloadlen;
MQTTString topicName = MQTTString_initializer;
if (MQTTDeserialize_publish(&dup, &qos, &retained, &packetid, &topicName,
&payload, &payloadlen, buf, buflen) == 1)
MQTTStringFormat_publish(strbuf, strbuflen, dup, qos, retained, packetid,
topicName, payload, payloadlen);
}
break;
case PUBACK:
case PUBREC:
case PUBREL:
case PUBCOMP: {
unsigned char packettype, dup;
unsigned short packetid;
if (MQTTDeserialize_ack(&packettype, &dup, &packetid, buf, buflen) == 1) {
MQTTStringFormat_ack(strbuf, strbuflen, packettype, dup, packetid);
}
}
break;
case SUBSCRIBE: {
unsigned char dup;
unsigned short packetid;
int maxcount = 1, count = 0;
MQTTString topicFilters[1];
int requestedQoSs[1];
if (MQTTDeserialize_subscribe(&dup, &packetid, maxcount, &count,
topicFilters, requestedQoSs, buf, buflen) == 1) {
MQTTStringFormat_subscribe(strbuf, strbuflen, dup, packetid, count, topicFilters, requestedQoSs);
};
}
break;
case UNSUBSCRIBE: {
unsigned char dup;
unsigned short packetid;
int maxcount = 1, count = 0;
MQTTString topicFilters[1];
if (MQTTDeserialize_unsubscribe(&dup, &packetid, maxcount, &count, topicFilters, buf, buflen) == 1) {
MQTTStringFormat_unsubscribe(strbuf, strbuflen, dup, packetid, count, topicFilters);
}
}
break;
case PINGREQ:
case PINGRESP:
case DISCONNECT:
snprintf(strbuf, strbuflen, "%s", MQTTPacket_names[header.bits.type]);
break;
}
strbuf[strbuflen] = '\0';
return strbuf;
}

View File

@@ -0,0 +1,37 @@
/*******************************************************************************
Copyright (c) 2014 IBM Corp.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Ian Craggs - initial API and implementation and/or initial documentation
*******************************************************************************/
#if !defined(MQTTFORMAT_H)
#define MQTTFORMAT_H
#include "StackTrace.h"
#include "MQTTPacket.h"
const char* MQTTPacket_getName(unsigned short packetid);
int MQTTStringFormat_connect(char* strbuf, int strbuflen, MQTTPacket_connectData* data);
int MQTTStringFormat_connack(char* strbuf, int strbuflen, unsigned char connack_rc, unsigned char sessionPresent);
int MQTTStringFormat_publish(char* strbuf, int strbuflen, unsigned char dup, int qos, unsigned char retained,
unsigned short packetid, MQTTString topicName, unsigned char* payload, int payloadlen);
int MQTTStringFormat_ack(char* strbuf, int strbuflen, unsigned char packettype, unsigned char dup, unsigned short packetid);
int MQTTStringFormat_subscribe(char* strbuf, int strbuflen, unsigned char dup, unsigned short packetid, int count,
MQTTString topicFilters[], int requestedQoSs[]);
int MQTTStringFormat_suback(char* strbuf, int strbuflen, unsigned short packetid, int count, int* grantedQoSs);
int MQTTStringFormat_unsubscribe(char* strbuf, int strbuflen, unsigned char dup, unsigned short packetid,
int count, MQTTString topicFilters[]);
char* MQTTFormat_toClientString(char* strbuf, int strbuflen, unsigned char* buf, int buflen);
char* MQTTFormat_toServerString(char* strbuf, int strbuflen, unsigned char* buf, int buflen);
#endif

View File

@@ -0,0 +1,401 @@
/*******************************************************************************
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
*/
int MQTTPacket_encode(unsigned char* buf, int length) {
int rc = 0;
FUNC_ENTRY;
do {
char 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
*/
int MQTTPacket_decode(int (*getcharfn)(unsigned char*, int), int* value) {
unsigned char c;
int multiplier = 1;
int len = 0;
#define MAX_NO_OF_REMAINING_LENGTH_BYTES 4
FUNC_ENTRY;
*value = 0;
do {
int 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;
}
int MQTTPacket_len(int 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 unsigned char* bufptr;
int bufchar(unsigned char* c, int count) {
int i;
for (i = 0; i < count; ++i) {
*c = *bufptr++;
}
return count;
}
int MQTTPacket_decodeBuf(unsigned char* buf, int* 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
*/
int readInt(unsigned char** pptr) {
unsigned char* ptr = *pptr;
int 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(unsigned char** 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(unsigned char** 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(unsigned char** pptr, int anInt) {
**pptr = (unsigned char)(anInt / 256);
(*pptr)++;
**pptr = (unsigned char)(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(unsigned char** pptr, const char* string) {
int len = strlen(string);
writeInt(pptr, len);
memcpy(*pptr, string, len);
*pptr += len;
}
int getLenStringLen(char* ptr) {
int len = 256 * ((unsigned char)(*ptr)) + (unsigned char)(*(ptr + 1));
return len;
}
void writeMQTTString(unsigned char** 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
*/
int readMQTTLenString(MQTTString* mqttstring, unsigned char** pptr, unsigned char* enddata) {
int 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
*/
int 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
*/
int MQTTPacket_equals(MQTTString* a, char* bptr) {
int 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
*/
int MQTTPacket_read(unsigned char* buf, int buflen, int (*getfn)(unsigned char*, int)) {
int rc = -1;
MQTTHeader header = {0};
int len = 0;
int 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 int MQTTPacket_decodenb(MQTTTransport *trp) {
unsigned char c;
int rc = MQTTPACKET_READ_ERROR;
FUNC_ENTRY;
if (trp->len == 0) { /* initialize on first call */
trp->multiplier = 1;
trp->rem_len = 0;
}
do {
int 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->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
*/
int MQTTPacket_readnb(unsigned char* buf, int buflen, MQTTTransport *trp) {
int 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;
}

View File

@@ -0,0 +1,126 @@
/*******************************************************************************
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_
#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 {
unsigned char byte; /**< the whole byte */
#if defined(REVERSED)
struct {
unsigned int type : 4; /**< message type nibble */
unsigned int dup : 1; /**< DUP flag bit */
unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */
unsigned int retain : 1; /**< retained flag bit */
} bits;
#else
struct {
unsigned int retain : 1; /**< retained flag bit */
unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */
unsigned int dup : 1; /**< DUP flag bit */
unsigned int type : 4; /**< message type nibble */
} bits;
#endif
} MQTTHeader;
typedef struct {
int len;
char* data;
} MQTTLenString;
typedef struct {
char* cstring;
MQTTLenString lenstring;
} MQTTString;
#define MQTTString_initializer {NULL, {0, NULL}}
int MQTTstrlen(MQTTString mqttstring);
#include "MQTTConnect.h"
#include "MQTTPublish.h"
#include "MQTTSubscribe.h"
#include "MQTTUnsubscribe.h"
#include "MQTTFormat.h"
int MQTTSerialize_ack(unsigned char* buf, int buflen, unsigned char type, unsigned char dup, unsigned short packetid);
int MQTTDeserialize_ack(unsigned char* packettype, unsigned char* dup, unsigned short* packetid, unsigned char* buf, int buflen);
int MQTTPacket_len(int rem_len);
int MQTTPacket_equals(MQTTString* a, char* b);
int MQTTPacket_encode(unsigned char* buf, int length);
int MQTTPacket_decode(int (*getcharfn)(unsigned char*, int), int* value);
int MQTTPacket_decodeBuf(unsigned char* buf, int* value);
int readInt(unsigned char** pptr);
char readChar(unsigned char** pptr);
void writeChar(unsigned char** pptr, char c);
void writeInt(unsigned char** pptr, int anInt);
int readMQTTLenString(MQTTString* mqttstring, unsigned char** pptr, unsigned char* enddata);
void writeCString(unsigned char** pptr, const char* string);
void writeMQTTString(unsigned char** pptr, MQTTString mqttstring);
DLLExport int MQTTPacket_read(unsigned char* buf, int buflen, int (*getfn)(unsigned char*, int));
typedef struct {
int (*getfn)(void *, unsigned char*, int); /* 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 */
int multiplier;
int rem_len;
int len;
char state;
} MQTTTransport;
int MQTTPacket_readnb(unsigned char* buf, int buflen, MQTTTransport *trp);
#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
}
#endif
#endif /* MQTTPACKET_H_ */

View File

@@ -0,0 +1,38 @@
/*******************************************************************************
Copyright (c) 2014 IBM Corp.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Ian Craggs - initial API and implementation and/or initial documentation
Xiang Rong - 442039 Add makefile to Embedded C client
*******************************************************************************/
#ifndef MQTTPUBLISH_H_
#define MQTTPUBLISH_H_
#if !defined(DLLImport)
#define DLLImport
#endif
#if !defined(DLLExport)
#define DLLExport
#endif
DLLExport int MQTTSerialize_publish(unsigned char* buf, int buflen, unsigned char dup, int qos, unsigned char retained, unsigned short packetid,
MQTTString topicName, unsigned char* payload, int payloadlen);
DLLExport int MQTTDeserialize_publish(unsigned char* dup, int* qos, unsigned char* retained, unsigned short* packetid, MQTTString* topicName,
unsigned char** payload, int* payloadlen, unsigned char* buf, int len);
DLLExport int MQTTSerialize_puback(unsigned char* buf, int buflen, unsigned short packetid);
DLLExport int MQTTSerialize_pubrel(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid);
DLLExport int MQTTSerialize_pubcomp(unsigned char* buf, int buflen, unsigned short packetid);
#endif /* MQTTPUBLISH_H_ */

View File

@@ -0,0 +1,163 @@
/*******************************************************************************
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
*/
int MQTTSerialize_publishLength(int qos, MQTTString topicName, int payloadlen) {
int len = 0;
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
*/
int MQTTSerialize_publish(unsigned char* buf, int buflen, unsigned char dup, int qos, unsigned char retained, unsigned short packetid,
MQTTString topicName, unsigned char* payload, int payloadlen) {
unsigned char *ptr = buf;
MQTTHeader header = {0};
int rem_len = 0;
int 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
*/
int MQTTSerialize_ack(unsigned char* buf, int buflen, unsigned char packettype, unsigned char dup, unsigned short packetid) {
MQTTHeader header = {0};
int rc = 0;
unsigned char *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
*/
int MQTTSerialize_puback(unsigned char* buf, int buflen, unsigned short 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
*/
int MQTTSerialize_pubrel(unsigned char* buf, int buflen, unsigned char dup, unsigned short 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
*/
int MQTTSerialize_pubcomp(unsigned char* buf, int buflen, unsigned short packetid) {
return MQTTSerialize_ack(buf, buflen, PUBCOMP, 0, packetid);
}

View File

@@ -0,0 +1,39 @@
/*******************************************************************************
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 int MQTTSerialize_subscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid,
int count, MQTTString topicFilters[], char requestedQoSs[]);
DLLExport int MQTTDeserialize_subscribe(unsigned char* dup, unsigned short* packetid,
int maxcount, int* count, MQTTString topicFilters[], int requestedQoSs[], unsigned char* buf, int len);
DLLExport int MQTTSerialize_suback(unsigned char* buf, int buflen, unsigned short packetid, int count, int* grantedQoSs);
DLLExport int MQTTDeserialize_suback(unsigned short* packetid, int maxcount, int* count, int grantedQoSs[], unsigned char* buf, int len);
#endif /* MQTTSUBSCRIBE_H_ */

View File

@@ -0,0 +1,133 @@
/*******************************************************************************
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
*/
int MQTTSerialize_subscribeLength(int count, MQTTString topicFilters[]) {
int i;
int len = 2; /* packetid */
for (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
*/
int MQTTSerialize_subscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid, int count,
MQTTString topicFilters[], char requestedQoSs[]) {
unsigned char *ptr = buf;
MQTTHeader header = {0};
int rem_len = 0;
int rc = 0;
int i = 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 (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
*/
int MQTTDeserialize_suback(unsigned short* packetid, int maxcount, int* count, int grantedQoSs[], unsigned char* buf, int buflen) {
MQTTHeader header = {0};
unsigned char* curdata = buf;
unsigned char* enddata = NULL;
int rc = 0;
int 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;
}

View File

@@ -0,0 +1,112 @@
/*******************************************************************************
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
*/
int MQTTDeserialize_subscribe(unsigned char* dup, unsigned short* packetid, int maxcount, int* count, MQTTString topicFilters[],
int requestedQoSs[], unsigned char* buf, int buflen) {
MQTTHeader header = {0};
unsigned char* curdata = buf;
unsigned char* enddata = NULL;
int rc = -1;
int 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
*/
int MQTTSerialize_suback(unsigned char* buf, int buflen, unsigned short packetid, int count, int* grantedQoSs) {
MQTTHeader header = {0};
int rc = -1;
unsigned char *ptr = buf;
int i;
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 (i = 0; i < count; ++i) {
writeChar(&ptr, grantedQoSs[i]);
}
rc = ptr - buf;
exit:
FUNC_EXIT_RC(rc);
return rc;
}

View File

@@ -0,0 +1,38 @@
/*******************************************************************************
Copyright (c) 2014 IBM Corp.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Ian Craggs - initial API and implementation and/or initial documentation
Xiang Rong - 442039 Add makefile to Embedded C client
*******************************************************************************/
#ifndef MQTTUNSUBSCRIBE_H_
#define MQTTUNSUBSCRIBE_H_
#if !defined(DLLImport)
#define DLLImport
#endif
#if !defined(DLLExport)
#define DLLExport
#endif
DLLExport int MQTTSerialize_unsubscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid,
int count, MQTTString topicFilters[]);
DLLExport int MQTTDeserialize_unsubscribe(unsigned char* dup, unsigned short* packetid, int max_count, int* count, MQTTString topicFilters[],
unsigned char* buf, int len);
DLLExport int MQTTSerialize_unsuback(unsigned char* buf, int buflen, unsigned short packetid);
DLLExport int MQTTDeserialize_unsuback(unsigned short* packetid, unsigned char* buf, int len);
#endif /* MQTTUNSUBSCRIBE_H_ */

View File

@@ -0,0 +1,105 @@
/*******************************************************************************
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
*/
int MQTTSerialize_unsubscribeLength(int count, MQTTString topicFilters[]) {
int i;
int len = 2; /* packetid */
for (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
*/
int MQTTSerialize_unsubscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid,
int count, MQTTString topicFilters[]) {
unsigned char *ptr = buf;
MQTTHeader header = {0};
int rem_len = 0;
int rc = -1;
int i = 0;
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 (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
*/
int MQTTDeserialize_unsuback(unsigned short* packetid, unsigned char* buf, int buflen) {
unsigned char type = 0;
unsigned char dup = 0;
int rc = 0;
FUNC_ENTRY;
rc = MQTTDeserialize_ack(&type, &dup, packetid, buf, buflen);
if (type == UNSUBACK) {
rc = 1;
}
FUNC_EXIT_RC(rc);
return rc;
}

View File

@@ -0,0 +1,100 @@
/*******************************************************************************
Copyright (c) 2014 IBM Corp.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Ian Craggs - initial API and implementation and/or initial documentation
*******************************************************************************/
#include "MQTTPacket.h"
#include "StackTrace.h"
#include <string.h>
/**
Deserializes the supplied (wire) buffer into unsubscribe data
@param dup integer returned - the MQTT dup flag
@param packetid integer returned - the MQTT packet identifier
@param maxcount - the maximum number of members allowed in the topicFilters and requestedQoSs arrays
@param count - number of members in the topicFilters and requestedQoSs arrays
@param topicFilters - array of topic filter names
@param buf the raw buffer data, of the correct length determined by the remaining length field
@param buflen the length in bytes of the data in the supplied buffer
@return the length of the serialized data. <= 0 indicates error
*/
int MQTTDeserialize_unsubscribe(unsigned char* dup, unsigned short* packetid, int maxcount, int* count, MQTTString topicFilters[],
unsigned char* buf, int len) {
MQTTHeader header = {0};
unsigned char* curdata = buf;
unsigned char* enddata = NULL;
int rc = 0;
int 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
*/
int MQTTSerialize_unsuback(unsigned char* buf, int buflen, unsigned short packetid) {
MQTTHeader header = {0};
int rc = 0;
unsigned char *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;
}

View File

@@ -0,0 +1,78 @@
/*******************************************************************************
Copyright (c) 2014 IBM Corp.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Ian Craggs - initial API and implementation and/or initial documentation
Ian Craggs - fix for bug #434081
*******************************************************************************/
#ifndef STACKTRACE_H_
#define STACKTRACE_H_
#include <stdio.h>
#define NOSTACKTRACE 1
#if defined(NOSTACKTRACE)
#define FUNC_ENTRY
#define FUNC_ENTRY_NOLOG
#define FUNC_ENTRY_MED
#define FUNC_ENTRY_MAX
#define FUNC_EXIT
#define FUNC_EXIT_NOLOG
#define FUNC_EXIT_MED
#define FUNC_EXIT_MAX
#define FUNC_EXIT_RC(x)
#define FUNC_EXIT_MED_RC(x)
#define FUNC_EXIT_MAX_RC(x)
#else
#if defined(WIN32)
#define inline __inline
#define FUNC_ENTRY StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MINIMUM)
#define FUNC_ENTRY_NOLOG StackTrace_entry(__FUNCTION__, __LINE__, -1)
#define FUNC_ENTRY_MED StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MEDIUM)
#define FUNC_ENTRY_MAX StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MAXIMUM)
#define FUNC_EXIT StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MINIMUM)
#define FUNC_EXIT_NOLOG StackTrace_exit(__FUNCTION__, __LINE__, -1)
#define FUNC_EXIT_MED StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MEDIUM)
#define FUNC_EXIT_MAX StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MAXIMUM)
#define FUNC_EXIT_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MINIMUM)
#define FUNC_EXIT_MED_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MEDIUM)
#define FUNC_EXIT_MAX_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MAXIMUM)
#else
#define FUNC_ENTRY StackTrace_entry(__func__, __LINE__, TRACE_MINIMUM)
#define FUNC_ENTRY_NOLOG StackTrace_entry(__func__, __LINE__, -1)
#define FUNC_ENTRY_MED StackTrace_entry(__func__, __LINE__, TRACE_MEDIUM)
#define FUNC_ENTRY_MAX StackTrace_entry(__func__, __LINE__, TRACE_MAXIMUM)
#define FUNC_EXIT StackTrace_exit(__func__, __LINE__, NULL, TRACE_MINIMUM)
#define FUNC_EXIT_NOLOG StackTrace_exit(__func__, __LINE__, NULL, -1)
#define FUNC_EXIT_MED StackTrace_exit(__func__, __LINE__, NULL, TRACE_MEDIUM)
#define FUNC_EXIT_MAX StackTrace_exit(__func__, __LINE__, NULL, TRACE_MAXIMUM)
#define FUNC_EXIT_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MINIMUM)
#define FUNC_EXIT_MED_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MEDIUM)
#define FUNC_EXIT_MAX_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MAXIMUM)
void StackTrace_entry(const char* name, int line, int trace);
void StackTrace_exit(const char* name, int line, void* return_value, int trace);
void StackTrace_printStack(FILE* dest);
char* StackTrace_get(unsigned long);
#endif
#endif
#endif /* STACKTRACE_H_ */

View File

@@ -0,0 +1,190 @@
//*****************************************************************************
//! \file mqtt_interface.c
//! \brief Paho MQTT to WIZnet Chip interface implement file.
//! \details The process of porting an interface to use paho MQTT.
//! \version 1.0.0
//! \date 2016/12/06
//! \par Revision history
//! <2016/12/06> 1st Release
//!
//! \author Peter Bang & Justin Kim
//! \copyright
//!
//! Copyright (c) 2016, 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 "mqtt_interface.h"
#include "wizchip_conf.h"
#include "socket.h"
unsigned long MilliTimer;
/*
@brief MQTT MilliTimer handler
@note MUST BE register to your system 1m Tick timer handler.
*/
void MilliTimer_Handler(void) {
MilliTimer++;
}
/*
@brief Timer Initialize
@param timer : pointer to a Timer structure
that contains the configuration information for the Timer.
*/
void TimerInit(Timer* timer) {
timer->end_time = 0;
}
/*
@brief expired Timer
@param timer : pointer to a Timer structure
that contains the configuration information for the Timer.
*/
char TimerIsExpired(Timer* timer) {
long left = timer->end_time - MilliTimer;
return (left < 0);
}
/*
@brief Countdown millisecond Timer
@param timer : pointer to a Timer structure
that contains the configuration information for the Timer.
timeout : setting timeout millisecond.
*/
void TimerCountdownMS(Timer* timer, unsigned int timeout) {
timer->end_time = MilliTimer + timeout;
}
/*
@brief Countdown second Timer
@param timer : pointer to a Timer structure
that contains the configuration information for the Timer.
timeout : setting timeout millisecond.
*/
void TimerCountdown(Timer* timer, unsigned int timeout) {
timer->end_time = MilliTimer + (timeout * 1000);
}
/*
@brief left millisecond Timer
@param timer : pointer to a Timer structure
that contains the configuration information for the Timer.
*/
int TimerLeftMS(Timer* timer) {
long left = timer->end_time - MilliTimer;
return (left < 0) ? 0 : left;
}
/*
@brief New network setting
@param n : pointer to a Network structure
that contains the configuration information for the Network.
sn : socket number where x can be (0..7).
@retval None
*/
void NewNetwork(Network* n, int sn) {
n->my_socket = sn;
n->mqttread = w5x00_read;
n->mqttwrite = w5x00_write;
n->disconnect = w5x00_disconnect;
}
/*
@brief read function
@param n : pointer to a Network structure
that contains the configuration information for the Network.
buffer : pointer to a read buffer.
len : buffer length.
@retval received data length or SOCKERR code
*/
int w5x00_read(Network* n, unsigned char* buffer, int len, long time) {
if ((getSn_SR(n->my_socket) == SOCK_ESTABLISHED) && (getSn_RX_RSR(n->my_socket) > 0)) {
return recv(n->my_socket, buffer, len);
}
return SOCK_ERROR;
}
/*
@brief write function
@param n : pointer to a Network structure
that contains the configuration information for the Network.
buffer : pointer to a read buffer.
len : buffer length.
@retval length of data sent or SOCKERR code
*/
int w5x00_write(Network* n, unsigned char* buffer, int len, long time) {
if (getSn_SR(n->my_socket) == SOCK_ESTABLISHED) {
return send(n->my_socket, buffer, len);
}
return SOCK_ERROR;
}
/*
@brief disconnect function
@param n : pointer to a Network structure
that contains the configuration information for the Network.
*/
void w5x00_disconnect(Network* n) {
disconnect(n->my_socket);
}
/*
@brief connect network function
@param n : pointer to a Network structure
that contains the configuration information for the Network.
ip : server iP.
port : server port.
@retval SOCKOK code or SOCKERR code
*/
int ConnectNetwork(Network* n, uint8_t* ip, uint16_t port) {
uint16_t myport = 12345;
if (socket(n->my_socket, Sn_MR_TCP, myport, 0) != n->my_socket) {
return SOCK_ERROR;
}
#if 1
// 20231016 taylor//teddy 240122
#if ((_WIZCHIP_ == 6100) || (_WIZCHIP_ == 6300))
if (connect(n->my_socket, ip, port, 4) != SOCK_OK)
#else
if (connect(n->my_socket, ip, port) != SOCK_OK)
#endif
#else
if (connect(n->my_socket, ip, port) != SOCK_OK)
#endif
return SOCK_ERROR;
return SOCK_OK;
}

View File

@@ -0,0 +1,270 @@
//*****************************************************************************
//! \file mqtt_interface.h
//! \brief Paho MQTT to WIZnet Chip interface Header file.
//! \details The process of porting an interface to use paho MQTT.
//! \version 1.0.0
//! \date 2016/12/06
//! \par Revision history
//! <2016/12/06> 1st Release
//!
//! \author Peter Bang & Justin Kim
//! \copyright
//!
//! Copyright (c) 2016, 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.
//
//*****************************************************************************
/* MQTT subscribe Example.... W5500 + STM32F103(IoT board)
//Include: Board configuration
#include "IoTEVB.h"
//Include: MCU peripheral Library
#include "stm32f10x_rcc.h"
#include "stm32f10x.h"
//Include: W5500 iolibrary
#include "w5500.h"
#include "wizchip_conf.h"
#include "misc.h"
//Include: Internet iolibrary
#include "MQTTClient.h"
//Include: MCU Specific W5500 driver
#include "W5500HardwareDriver.h"
//Include: Standard IO Library
#include <stdio.h>
//Socket number defines
#define TCP_SOCKET 0
//Receive Buffer Size define
#define BUFFER_SIZE 2048
//Global variables
unsigned char targetIP[4] = {}; // mqtt server IP
unsigned int targetPort = 1883; // mqtt server port
uint8_t mac_address[6] = {};
wiz_NetInfo gWIZNETINFO = { .mac = {}, //user MAC
.ip = {}, //user IP
.sn = {},
.gw = {},
.dns = {},
.dhcp = NETINFO_STATIC};
unsigned char tempBuffer[BUFFER_SIZE] = {};
struct opts_struct
{
char* clientid;
int nodelimiter;
char* delimiter;
enum QoS qos;
char* username;
char* password;
char* host;
int port;
int showtopics;
} opts ={ (char*)"stdout-subscriber", 0, (char*)"\n", QOS0, NULL, NULL, targetIP, targetPort, 0 };
// @brief messageArrived callback function
void messageArrived(MessageData* md)
{
unsigned char testbuffer[100];
MQTTMessage* message = md->message;
if (opts.showtopics)
{
memcpy(testbuffer,(char*)message->payload,(int)message->payloadlen);
(testbuffer + (int)message->payloadlen + 1) = "\n";
printf("%s\r\n",testbuffer);
}
if (opts.nodelimiter)
printf("%.*s", (int)message->payloadlen, (char*)message->payload);
else
printf("%.*s%s", (int)message->payloadlen, (char*)message->payload, opts.delimiter);
}
// @brief 1 millisecond Tick Timer setting
void NVIC_configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
SysTick_Config(72000);
NVIC_InitStructure.NVIC_IRQChannel = SysTick_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // Highest priority
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
// @brief 1 millisecond Tick Timer Handler setting
void SysTick_Handler(void)
{
MilliTimer_Handler();
}
int main(void)
{
led_ctrl led1,led2;
int i;
int rc = 0;
unsigned char buf[100];
//Usart initialization for Debug.
USART1Initialze();
printf("USART initialized.\n\r");
I2C1Initialize();
printf("I2C initialized.\n\r");
MACEEP_Read(mac_address,0xfa,6);
printf("Mac address\n\r");
for(i = 0 ; i < 6 ; i++)
{
printf("%02x ",mac_address[i]);
}
printf("\n\r");
//LED initialization.
led_initialize();
led1 = led2 = ON;
led2Ctrl(led2);
led1Ctrl(led1);
//W5500 initialization.
W5500HardwareInitilize();
printf("W5500 hardware interface initialized.\n\r");
W5500Initialze();
printf("W5500 IC initialized.\n\r");
//Set network informations
wizchip_setnetinfo(&gWIZNETINFO);
setSHAR(mac_address);
print_network_information();
Network n;
MQTTClient c;
NewNetwork(&n, TCP_SOCKET);
ConnectNetwork(&n, targetIP, targetPort);
MQTTClientInit(&c,&n,1000,buf,100,tempBuffer,2048);
MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
data.willFlag = 0;
data.MQTTVersion = 3;
data.clientID.cstring = opts.clientid;
data.username.cstring = opts.username;
data.password.cstring = opts.password;
data.keepAliveInterval = 60;
data.cleansession = 1;
rc = MQTTConnect(&c, &data);
printf("Connected %d\r\n", rc);
opts.showtopics = 1;
printf("Subscribing to %s\r\n", "hello/wiznet");
rc = MQTTSubscribe(&c, "hello/wiznet", opts.qos, messageArrived);
printf("Subscribed %d\r\n", rc);
while(1)
{
MQTTYield(&c, data.keepAliveInterval);
}
}
*/
#ifndef __MQTT_INTERFACE_H_
#define __MQTT_INTERFACE_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
@brief MQTT MilliTimer handler
@note MUST BE register to your system 1m Tick timer handler
*/
void MilliTimer_Handler(void);
/*
@brief Timer structure
*/
typedef struct Timer Timer;
struct Timer {
unsigned long systick_period;
unsigned long end_time;
};
/*
@brief Network structure
*/
typedef struct Network Network;
struct Network {
int my_socket;
int (*mqttread) (Network*, unsigned char*, int, long);
int (*mqttwrite) (Network*, unsigned char*, int, long);
void (*disconnect) (Network*);
};
/*
@brief Timer function
*/
void TimerInit(Timer*);
char TimerIsExpired(Timer*);
void TimerCountdownMS(Timer*, unsigned int);
void TimerCountdown(Timer*, unsigned int);
int TimerLeftMS(Timer*);
/*
@brief Network interface porting
*/
int w5x00_read(Network*, unsigned char*, int, long);
int w5x00_write(Network*, unsigned char*, int, long);
void w5x00_disconnect(Network*);
void NewNetwork(Network* n, int sn);
int ConnectNetwork(Network* n, uint8_t* ip, uint16_t port);
#ifdef __cplusplus
}
#endif
#endif //__MQTT_INTERFACE_H_

917
Internet/SNMP/snmp.c Normal file
View File

@@ -0,0 +1,917 @@
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <time.h>
#include "socket.h"
#include "snmp.h"
#include "snmp_custom.h"
/********************************************************************************************/
/* SNMP : Functions declaration */
/********************************************************************************************/
// SNMP Parsing functions
int32_t findEntry(uint8_t *oid, int32_t len);
int32_t getOID(int32_t id, uint8_t *oid, uint8_t *len);
int32_t getValue(uint8_t *vptr, int32_t vlen);
int32_t getEntry(int32_t id, uint8_t *dataType, void *ptr, int32_t *len);
int32_t setEntry(int32_t id, void *val, int32_t vlen, uint8_t dataType, int32_t index);
int32_t makeTrapVariableBindings(dataEntryType *oid_data, void *ptr, uint32_t *len);
int32_t parseLength(const uint8_t *msg, int32_t *len);
int32_t parseTLV(const uint8_t *msg, int32_t index, tlvStructType *tlv);
void insertRespLen(int32_t reqStart, int32_t respStart, int32_t size);
int32_t parseVarBind(int32_t reqType, int32_t index);
int32_t parseSequence(int32_t reqType, int32_t index);
int32_t parseSequenceOf(int32_t reqType);
int32_t parseRequest();
int32_t parseCommunity();
int32_t parseVersion();
int32_t parseSNMPMessage();
// Debugging function
#ifdef _SNMP_DEBUG_
void dumpCode(uint8_t* header, uint8_t* tail, uint8_t *buff, int32_t len);
#endif
// Utils
void ipToByteArray(int8_t *ip, uint8_t *pDes);
/********************************************************************************************/
/* SNMP : Variable declaration */
/********************************************************************************************/
// SNMP message structures
struct messageStruct request_msg;
struct messageStruct response_msg;
// SNMP Time counter
static time_t startTime = 0;
volatile uint32_t snmp_tick_10ms = 0; //volatile uint32_t snmp_tick_1ms = 0;
// SNMP Sockets
static uint8_t SOCK_SNMP_AGENT;
static uint8_t SOCK_SNMP_TRAP;
uint8_t packet_trap[MAX_TRAPMSG_LEN] = {0,};
uint8_t errorStatus, errorIndex;
/********************************************************************************************/
/* SNMP : Time handler */
/********************************************************************************************/
void currentUptime(void *ptr, uint8_t *len) {
time_t curTime = getSNMPTimeTick();
//*(uint32_t *)ptr = (uint32_t)(curTime - startTime) / 10; // calculation for 1ms tick
*(uint32_t *)ptr = (uint32_t)(curTime - startTime); // calculation for 10ms tick
*len = 4;
}
void SNMP_time_handler(void) {
//snmp_tick_1ms++;
snmp_tick_10ms++;
}
uint32_t getSNMPTimeTick(void) {
//return snmp_tick_1ms;
return snmp_tick_10ms;
}
/********************************************************************************************/
/* SNMP : Library Part */
/********************************************************************************************/
/**
@addtogroup snmp_module
@{
*/
/**
Initialize SNMP Daemon.
This should be called just one time at first time
@param none
@return none
*/
void snmpd_init(uint8_t * managerIP, uint8_t * agentIP, uint8_t sn_agent, uint8_t sn_trap) {
#ifdef _SNMP_DEBUG_
printf("\r\n - SNMP : Start SNMP Agent Daemon\r\n");
#endif
SOCK_SNMP_AGENT = sn_agent;
SOCK_SNMP_TRAP = sn_trap;
if ((SOCK_SNMP_AGENT > _WIZCHIP_SOCK_NUM_) || (SOCK_SNMP_TRAP > _WIZCHIP_SOCK_NUM_)) {
return;
}
startTime = getSNMPTimeTick(); // Start time (unit: 10ms)
initTable(); // Settings for OID entry values
initial_Trap(managerIP, agentIP);
/*
// Example Codes for SNMP Trap
{
dataEntryType enterprise_oid = {0x0a, {0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0x9b, 0x19, 0x01, 0x00},
SNMPDTYPE_OBJ_ID, 0x0a, {"\x2b\x06\x01\x04\x01\x81\x9b\x19\x10\x00"}, NULL, NULL};
dataEntryType trap_oid1 = {8, {0x2b, 6, 1, 4, 1, 0, 11, 0}, SNMPDTYPE_OCTET_STRING, 30, {""}, NULL, NULL};
dataEntryType trap_oid2 = {8, {0x2b, 6, 1, 4, 1, 0, 12, 0}, SNMPDTYPE_INTEGER, 4, {""}, NULL, NULL};
strcpy((char *)trap_oid1.u.octetstring, "Alert!!!"); // String added
trap_oid2.u.intval = 123456; // Integer value added
// Generic Trap: warmStart
snmp_sendTrap((void *)"192.168.0.214", (void *)"192.168.0.112", (void *)"public", enterprise_oid, SNMPTRAP_WARMSTART, 0, 0);
// Enterprise-Specific Trap
snmp_sendTrap((void *)"192.168.0.214", (void *)"192.168.0.112", (void *)"public", enterprise_oid, 6, 0, 2, &trap_oid1, &trap_oid2);
}
*/
}
/**
SNMP Process Handler.
UDP Socket and SNMP Agent transaction handling.
@param none
@return none
*/
int32_t snmpd_run(void) {
int32_t ret;
int32_t len = 0;
uint8_t svr_addr[6];
uint16_t svr_port;
#if 1
// 20231019 taylor
uint8_t addr_len;
#endif
if (SOCK_SNMP_AGENT > _WIZCHIP_SOCK_NUM_) {
return -99;
}
switch (getSn_SR(SOCK_SNMP_AGENT)) {
case SOCK_UDP :
if ((len = getSn_RX_RSR(SOCK_SNMP_AGENT)) > 0) {
#if 1
// 20231019 taylor//teddy 240122
#if ((_WIZCHIP_ == 6100) || (_WIZCHIP_ == 6300))
request_msg.len = recvfrom(SOCK_SNMP_AGENT, request_msg.buffer, len, svr_addr, &svr_port, &addr_len);
#else
request_msg.len = recvfrom(SOCK_SNMP_AGENT, request_msg.buffer, len, svr_addr, &svr_port);
#endif
#else
request_msg.len = recvfrom(SOCK_SNMP_AGENT, request_msg.buffer, len, svr_addr, &svr_port);
#endif
} else {
request_msg.len = 0;
}
if (request_msg.len > 0) {
#ifdef _SNMP_DEBUG_
dumpCode((void *)"\r\n[Request]\r\n", (void *)"\r\n", request_msg.buffer, request_msg.len);
#endif
// Initialize
request_msg.index = 0;
response_msg.index = 0;
errorStatus = errorIndex = 0;
memset(response_msg.buffer, 0x00, MAX_SNMPMSG_LEN);
// Received message parsing and send response process
if (parseSNMPMessage() != -1) {
#if 1
// 20231016 taylor//teddy 240122
#if ((_WIZCHIP_ == 6100) || (_WIZCHIP_ == 6300))
sendto(SOCK_SNMP_AGENT, response_msg.buffer, response_msg.index, svr_addr, svr_port, 4);
#else
sendto(SOCK_SNMP_AGENT, response_msg.buffer, response_msg.index, svr_addr, svr_port);
#endif
#else
sendto(SOCK_SNMP_AGENT, response_msg.buffer, response_msg.index, svr_addr, svr_port);
#endif
}
#ifdef _SNMP_DEBUG_
dumpCode((void *)"\r\n[Response]\r\n", (void *)"\r\n", response_msg.buffer, response_msg.index);
#endif
}
break;
case SOCK_CLOSED :
if ((ret = socket(SOCK_SNMP_AGENT, Sn_MR_UDP, PORT_SNMP_AGENT, 0x00)) != SOCK_SNMP_AGENT) {
return ret;
}
#ifdef _SNMP_DEBUG_
printf(" - [%d] UDP Socket for SNMP Agent, port [%d]\r\n", SOCK_SNMP_AGENT, PORT_SNMP_AGENT);
#endif
break;
default :
break;
}
return 1;
}
int32_t findEntry(uint8_t *oid, int32_t len) {
int32_t i;
for (i = 0 ; i < maxData ; i++) {
if (len == snmpData[i].oidlen) {
if (!memcmp(snmpData[i].oid, oid, len)) {
return (i);
}
}
}
return OID_NOT_FOUND;
}
int32_t getOID(int32_t id, uint8_t *oid, uint8_t *len) {
int32_t j;
if (!((id >= 0) && (id < maxData))) {
return INVALID_ENTRY_ID;
}
*len = snmpData[id].oidlen;
for (j = 0 ; j < *len ; j++) {
oid[j] = snmpData[id].oid[j];
}
return SNMP_SUCCESS;
}
int32_t getValue(uint8_t *vptr, int32_t vlen) {
int32_t index = 0;
int32_t value = 0;
while (index < vlen) {
if (index != 0) {
value <<= 8;
}
value |= vptr[index++];
}
return value;
}
int32_t getEntry(int32_t id, uint8_t *dataType, void *ptr, int32_t *len) {
uint8_t * ptr_8;
int32_t value;
uint8_t * string;
int32_t j;
if (!((id >= 0) && (id < maxData))) {
return INVALID_ENTRY_ID;
}
*dataType = snmpData[id].dataType;
switch (*dataType) {
case SNMPDTYPE_OCTET_STRING :
case SNMPDTYPE_OBJ_ID : {
string = ptr;
if (snmpData[id].getfunction != NULL) {
snmpData[id].getfunction((void *)&snmpData[id].u.octetstring, &snmpData[id].dataLen);
}
if ((*dataType) == SNMPDTYPE_OCTET_STRING) {
snmpData[id].dataLen = (uint8_t)strlen((char const*)&snmpData[id].u.octetstring);
}
*len = snmpData[id].dataLen;
for (j = 0 ; j < *len ; j++) {
string[j] = snmpData[id].u.octetstring[j];
}
}
break;
case SNMPDTYPE_INTEGER :
case SNMPDTYPE_TIME_TICKS :
case SNMPDTYPE_COUNTER :
case SNMPDTYPE_GAUGE : {
if (snmpData[id].getfunction != NULL) {
snmpData[id].getfunction((void *)&snmpData[id].u.intval, &snmpData[id].dataLen);
}
if (snmpData[id].dataLen) {
*len = snmpData[id].dataLen;
} else {
*len = sizeof(uint32_t);
}
/*
// Original code (IAR, STM32)
// This code is not working in NXP+LPCXpresso (32-bit pointer operation error)
value = (int32_t *)ptr;
value = HTONL(snmpData[id].u.intval);
*/
ptr_8 = ptr;
//value = HTONL(snmpData[id].u.intval); // Endian convert when processing 32bit pointer operation
value = snmpData[id].u.intval;
for (j = 0 ; j < *len ; j++) {
ptr_8[j] = (uint8_t)((value >> ((*len - j - 1) * 8)));
}
}
break;
default :
return INVALID_DATA_TYPE;
}
return SNMP_SUCCESS;
}
int32_t setEntry(int32_t id, void *val, int32_t vlen, uint8_t dataType, int32_t index) {
int32_t retStatus = OID_NOT_FOUND;
int32_t j;
if (snmpData[id].dataType != dataType) {
errorStatus = BAD_VALUE;
errorIndex = index;
return INVALID_DATA_TYPE;
}
switch (snmpData[id].dataType) {
case SNMPDTYPE_OCTET_STRING :
case SNMPDTYPE_OBJ_ID : {
uint8_t *string = val;
for (j = 0 ; j < vlen ; j++) {
snmpData[id].u.octetstring[j] = string[j];
}
snmpData[id].dataLen = vlen;
}
retStatus = SNMP_SUCCESS;
break;
case SNMPDTYPE_INTEGER :
case SNMPDTYPE_TIME_TICKS :
case SNMPDTYPE_COUNTER :
case SNMPDTYPE_GAUGE : {
snmpData[id].u.intval = getValue((uint8_t *)val, vlen);
snmpData[id].dataLen = vlen;
if (snmpData[id].setfunction != NULL) {
snmpData[id].setfunction(snmpData[id].u.intval);
}
}
retStatus = SNMP_SUCCESS;
break;
default :
retStatus = INVALID_DATA_TYPE;
break;
}
return retStatus;
}
int32_t parseLength(const uint8_t *msg, int32_t *len) {
int32_t i = 1;
if (msg[0] & 0x80) {
int32_t tlen = (msg[0] & 0x7f) - 1;
*len = msg[i++];
while (tlen--) {
*len <<= 8;
*len |= msg[i++];
}
} else {
*len = msg[0];
}
return i;
}
int32_t parseTLV(const uint8_t *msg, int32_t index, tlvStructType *tlv) {
int32_t Llen = 0;
tlv->start = index;
Llen = parseLength((const uint8_t *)&msg[index + 1], &tlv->len);
tlv->vstart = index + Llen + 1;
switch (msg[index]) {
case SNMPDTYPE_SEQUENCE:
case GET_REQUEST:
case GET_NEXT_REQUEST:
case SET_REQUEST:
tlv->nstart = tlv->vstart;
break;
default:
tlv->nstart = tlv->vstart + tlv->len;
break;
}
return 0;
}
void insertRespLen(int32_t reqStart, int32_t respStart, int32_t size) {
int32_t indexStart, lenLength;
uint32_t mask = 0xff;
int32_t shift = 0;
if (request_msg.buffer[reqStart + 1] & 0x80) {
lenLength = request_msg.buffer[reqStart + 1] & 0x7f;
indexStart = respStart + 2;
while (lenLength--) {
response_msg.buffer[indexStart + lenLength] =
(uint8_t)((size & mask) >> shift);
shift += 8;
mask <<= shift;
}
} else {
response_msg.buffer[respStart + 1] = (uint8_t)(size & 0xff);
}
}
int32_t parseVarBind(int32_t reqType, int32_t index) {
int32_t seglen = 0, id;
tlvStructType name, value;
int32_t size = 0;
//extern const int32_t maxData;
parseTLV(request_msg.buffer, request_msg.index, &name);
if (request_msg.buffer[name.start] != SNMPDTYPE_OBJ_ID) {
return -1;
}
id = findEntry(&request_msg.buffer[name.vstart], name.len);
if ((reqType == GET_REQUEST) || (reqType == SET_REQUEST)) {
seglen = name.nstart - name.start;
COPY_SEGMENT(name);
size = seglen;
} else if (reqType == GET_NEXT_REQUEST) {
response_msg.buffer[response_msg.index] = request_msg.buffer[name.start];
if (++id >= maxData) {
id = OID_NOT_FOUND;
seglen = name.nstart - name.start;
COPY_SEGMENT(name);
size = seglen;
} else {
request_msg.index += name.nstart - name.start;
getOID(id, &response_msg.buffer[response_msg.index + 2], &response_msg.buffer[response_msg.index + 1]);
seglen = response_msg.buffer[response_msg.index + 1] + 2;
response_msg.index += seglen ;
size = seglen;
}
}
parseTLV(request_msg.buffer, request_msg.index, &value);
if (id != OID_NOT_FOUND) {
uint8_t dataType;
int32_t len;
if ((reqType == GET_REQUEST) || (reqType == GET_NEXT_REQUEST)) {
getEntry(id, &dataType, &response_msg.buffer[response_msg.index + 2], &len);
response_msg.buffer[response_msg.index] = dataType;
response_msg.buffer[response_msg.index + 1] = len;
seglen = (2 + len);
response_msg.index += seglen;
request_msg.index += (value.nstart - value.start);
} else if (reqType == SET_REQUEST) {
setEntry(id, &request_msg.buffer[value.vstart], value.len, request_msg.buffer[value.start], index);
seglen = value.nstart - value.start;
COPY_SEGMENT(value);
}
} else {
seglen = value.nstart - value.start;
COPY_SEGMENT(value);
errorIndex = index;
errorStatus = NO_SUCH_NAME;
}
size += seglen;
return size;
}
int32_t parseSequence(int32_t reqType, int32_t index) {
int32_t seglen;
tlvStructType seq;
int32_t size = 0, respLoc;
parseTLV(request_msg.buffer, request_msg.index, &seq);
if (request_msg.buffer[seq.start] != SNMPDTYPE_SEQUENCE) {
return -1;
}
seglen = seq.vstart - seq.start;
respLoc = response_msg.index;
COPY_SEGMENT(seq);
size = parseVarBind(reqType, index);
insertRespLen(seq.start, respLoc, size);
size += seglen;
return size;
}
int32_t parseSequenceOf(int32_t reqType) {
int32_t seglen;
tlvStructType seqof;
int32_t size = 0, respLoc;
int32_t index = 0;
parseTLV(request_msg.buffer, request_msg.index, &seqof);
if (request_msg.buffer[seqof.start] != SNMPDTYPE_SEQUENCE_OF) {
return -1;
}
seglen = seqof.vstart - seqof.start;
respLoc = response_msg.index;
COPY_SEGMENT(seqof);
while (request_msg.index < request_msg.len) {
size += parseSequence(reqType, index++);
}
insertRespLen(seqof.start, respLoc, size);
return size;
}
int32_t parseRequest() {
int32_t ret, seglen;
tlvStructType snmpreq, requestid, errStatus, errIndex;
int32_t size = 0, respLoc, reqType;
parseTLV(request_msg.buffer, request_msg.index, &snmpreq);
reqType = request_msg.buffer[snmpreq.start];
if (!VALID_REQUEST(reqType)) {
return -1;
}
seglen = snmpreq.vstart - snmpreq.start;
respLoc = snmpreq.start;
size += seglen;
COPY_SEGMENT(snmpreq);
response_msg.buffer[snmpreq.start] = GET_RESPONSE;
parseTLV(request_msg.buffer, request_msg.index, &requestid);
seglen = requestid.nstart - requestid.start;
size += seglen;
COPY_SEGMENT(requestid);
parseTLV(request_msg.buffer, request_msg.index, &errStatus);
seglen = errStatus.nstart - errStatus.start;
size += seglen;
COPY_SEGMENT(errStatus);
parseTLV(request_msg.buffer, request_msg.index, &errIndex);
seglen = errIndex.nstart - errIndex.start;
size += seglen;
COPY_SEGMENT(errIndex);
ret = parseSequenceOf(reqType);
if (ret == -1) {
return -1;
} else {
size += ret;
}
insertRespLen(snmpreq.start, respLoc, size);
if (errorStatus) {
response_msg.buffer[errStatus.vstart] = errorStatus;
response_msg.buffer[errIndex.vstart] = errorIndex + 1;
}
return size;
}
int32_t parseCommunity() {
int32_t seglen;
tlvStructType community;
int32_t size = 0;
parseTLV(request_msg.buffer, request_msg.index, &community);
if (!((request_msg.buffer[community.start] == SNMPDTYPE_OCTET_STRING) && (community.len == COMMUNITY_SIZE))) {
return -1;
}
if (!memcmp(&request_msg.buffer[community.vstart], (int8_t *)COMMUNITY, COMMUNITY_SIZE)) {
seglen = community.nstart - community.start;
size += seglen;
COPY_SEGMENT(community);
size += parseRequest();
} else {
return -1;
}
return size;
}
int32_t parseVersion() {
int32_t size = 0, seglen;
tlvStructType tlv;
size = parseTLV(request_msg.buffer, request_msg.index, &tlv);
if (!((request_msg.buffer[tlv.start] == SNMPDTYPE_INTEGER) && (request_msg.buffer[tlv.vstart] == SNMP_V1))) {
return -1;
}
seglen = tlv.nstart - tlv.start;
size += seglen;
COPY_SEGMENT(tlv);
size = parseCommunity();
if (size == -1) {
return size;
} else {
return (size + seglen);
}
}
int32_t parseSNMPMessage() {
int32_t size = 0, seglen, respLoc;
tlvStructType tlv;
parseTLV(request_msg.buffer, request_msg.index, &tlv);
if (request_msg.buffer[tlv.start] != SNMPDTYPE_SEQUENCE_OF) {
return -1;
}
seglen = tlv.vstart - tlv.start;
respLoc = tlv.start;
COPY_SEGMENT(tlv);
size = parseVersion();
if (size == -1) {
return -1;
} else {
size += seglen;
}
insertRespLen(tlv.start, respLoc, size);
return 0;
}
void ipToByteArray(int8_t *ip, uint8_t *pDes) {
uint32_t i, ip1 = 0, ip2 = 0, ip3 = 0, ip4 = 0;
int8_t buff[32];
uint32_t len = (uint32_t)strlen((char const*)ip);
strcpy((char *)buff, (char const*)ip);
for (i = 0; i < len; i++) {
if (buff[i] == '.') {
buff[i] = ' ';
}
}
sscanf((char const*)buff, "%u %u %u %u", &ip1, &ip2, &ip3, &ip4);
pDes[0] = ip1; pDes[1] = ip2; pDes[2] = ip3; pDes[3] = ip4;
}
int32_t makeTrapVariableBindings(dataEntryType *oid_data, void *ptr, uint32_t *len) {
uint32_t j;
((uint8_t*)ptr)[0] = 0x30;
((uint8_t*)ptr)[1] = 0xff;
((uint8_t*)ptr)[2] = 0x06;
((uint8_t*)ptr)[3] = oid_data->oidlen;
for (j = 0 ; j < oid_data->oidlen ; j++) {
((uint8_t*)ptr)[j + 4] = oid_data->oid[j];
}
switch (oid_data->dataType) {
case SNMPDTYPE_OCTET_STRING :
case SNMPDTYPE_OBJ_ID : {
uint8_t *string = &((uint8_t*)ptr)[4 + oid_data->oidlen + 2];
if (oid_data->dataType == SNMPDTYPE_OCTET_STRING) {
oid_data->dataLen = (uint8_t)strlen((char const*)&oid_data->u.octetstring);
}
for (j = 0 ; j < oid_data->dataLen ; j++) {
string[j] = oid_data->u.octetstring[j];
}
((uint8_t*)ptr)[4 + oid_data->oidlen] = oid_data->dataType;
((uint8_t*)ptr)[4 + oid_data->oidlen + 1] = oid_data->dataLen;
((uint8_t*)ptr)[1] = 2 + oid_data->oidlen + 2 + oid_data->dataLen;
*len = 4 + oid_data->oidlen + 2 + oid_data->dataLen;
}
break;
case SNMPDTYPE_INTEGER :
case SNMPDTYPE_TIME_TICKS :
case SNMPDTYPE_COUNTER :
case SNMPDTYPE_GAUGE : {
oid_data->dataLen = 4;
*(int32_t*)(&((uint8_t*)ptr)[4 + oid_data->oidlen + 2]) = HTONL(oid_data->u.intval);
((uint8_t*)ptr)[4 + oid_data->oidlen] = oid_data->dataType;
((uint8_t*)ptr)[4 + oid_data->oidlen + 1] = oid_data->dataLen;
((uint8_t*)ptr)[1] = 2 + oid_data->oidlen + 2 + oid_data->dataLen;
*len = 4 + oid_data->oidlen + 2 + oid_data->dataLen;
}
break;
default :
return INVALID_DATA_TYPE;
}
return SNMP_SUCCESS;
}
int32_t snmp_sendTrap(uint8_t * managerIP, uint8_t * agentIP, int8_t* community, dataEntryType enterprise_oid, uint32_t genericTrap, uint32_t specificTrap, uint32_t va_count, ...) {
uint32_t i;
int32_t packet_index = 0;
int32_t packet_buff1 = 0;
int32_t packet_buff2 = 0;
int32_t packet_buff3 = 0;
va_list ap;
uint32_t length_var_bindings = 0;
uint32_t length_buff = 0;
//SNMP Trap packet generation
packet_trap[packet_index++] = 0x30; // ASN.1 Header
packet_trap[packet_index] = 0xff; // pdu_length, temp
packet_buff1 = packet_index++;
packet_trap[packet_index++] = 0x02; // Version
packet_trap[packet_index++] = 0x01;
packet_trap[packet_index++] = 0x00;
packet_trap[packet_index++] = 0x04; // Community
packet_trap[packet_index++] = (uint8_t)strlen((char const*)community);
memcpy(&(packet_trap[packet_index]), community, strlen((char const*)community));
packet_index = packet_index + (uint8_t)strlen((char const*)community);
packet_trap[packet_index++] = 0xa4; // trap
packet_trap[packet_index] = 0xff; // length, temp
packet_buff2 = packet_index++;
packet_trap[packet_index++] = 0x06; // enterprise_oid
packet_trap[packet_index++] = enterprise_oid.oidlen;
for (i = 0; i < enterprise_oid.oidlen; i++) {
packet_trap[packet_index++] = enterprise_oid.oid[i];
}
packet_trap[packet_index++] = 0x40; // agent ip
packet_trap[packet_index++] = 0x04;
packet_trap[packet_index++] = agentIP[0];
packet_trap[packet_index++] = agentIP[1];
packet_trap[packet_index++] = agentIP[2];
packet_trap[packet_index++] = agentIP[3];
packet_trap[packet_index++] = 0x02; // Generic Trap
packet_trap[packet_index++] = 0x01;
packet_trap[packet_index++] = (uint8_t)genericTrap;
packet_trap[packet_index++] = 0x02; // Specific Trap
packet_trap[packet_index++] = 0x01;
packet_trap[packet_index++] = (uint8_t)specificTrap;
packet_trap[packet_index++] = 0x43; // Timestamp
packet_trap[packet_index++] = 0x01;
packet_trap[packet_index++] = 0x00;
packet_trap[packet_index++] = 0x30; // Sequence of variable-bindings
packet_trap[packet_index] = 0xff;
packet_buff3 = packet_index++;
// variable-bindings
{
va_start(ap, va_count);
for (i = 0; i < va_count; i++) {
dataEntryType* fff = va_arg(ap, dataEntryType*);
makeTrapVariableBindings(fff, &(packet_trap[packet_index]), &length_buff);
packet_index = packet_index + length_buff;
length_var_bindings = length_var_bindings + length_buff;
}
packet_trap[packet_buff3] = length_var_bindings;
va_end(ap);
}
packet_trap[packet_buff1] = packet_index - 2;
packet_trap[packet_buff2] = packet_index - (9 + (uint8_t)strlen((char const*)community));
// Send SNMP Trap Packet to NMS
{
socket(SOCK_SNMP_TRAP, Sn_MR_UDP, PORT_SNMP_TRAP, 0);
#if 1
// 20231016 taylor//teddy 240122
#if ((_WIZCHIP_ == 6100) || (_WIZCHIP_ == 6300))
sendto(SOCK_SNMP_TRAP, packet_trap, packet_index, managerIP, PORT_SNMP_TRAP, 4);
#else
sendto(SOCK_SNMP_TRAP, packet_trap, packet_index, managerIP, PORT_SNMP_TRAP);
#endif
#else
sendto(SOCK_SNMP_TRAP, packet_trap, packet_index, managerIP, PORT_SNMP_TRAP);
#endif
close(SOCK_SNMP_TRAP);
return 0;
}
}
#ifdef _SNMP_DEBUG_
void dumpCode(uint8_t* header, uint8_t* tail, uint8_t *buff, int32_t len) {
int i;
printf((char const*)header);
for (i = 0; i < len; i++) {
if (i % 16 == 0) {
printf("0x%04x : ", i);
}
printf("%02x ", buff[i]);
if (i % 16 - 15 == 0) {
int j;
printf(" ");
for (j = i - 15; j <= i; j++) {
if (isprint(buff[j])) {
printf("%c", buff[j]);
} else {
printf(".");
}
}
printf("\r\n");
}
}
if (i % 16 != 0) {
int j;
int spaces = (len - i + 16 - i % 16) * 3 + 2;
for (j = 0; j < spaces; j++) {
printf(" ");
}
for (j = i - i % 16; j < len; j++) {
if (isprint(buff[j])) {
printf("%c", buff[j]);
} else {
printf(".");
}
}
}
printf((char const*)tail);
}
#endif

122
Internet/SNMP/snmp.h Normal file
View File

@@ -0,0 +1,122 @@
#ifndef _SNMP_H_
#define _SNMP_H_
#ifdef __cplusplus
extern "C" {
#endif
// SNMP Debug Message (dump) Enable
#define _SNMP_DEBUG_
#define PORT_SNMP_AGENT 161
#define PORT_SNMP_TRAP 162
#define SNMP_V1 0
#define MAX_OID 12
#define MAX_STRING 64
#define MAX_SNMPMSG_LEN 512
#define MAX_TRAPMSG_LEN 512
// SNMP Error code
#define SNMP_SUCCESS 0
#define OID_NOT_FOUND -1
#define TABLE_FULL -2
#define ILLEGAL_LENGTH -3
#define INVALID_ENTRY_ID -4
#define INVALID_DATA_TYPE -5
#define NO_SUCH_NAME 2
#define BAD_VALUE 3
// SNMPv1 Commands
#define GET_REQUEST 0xa0
#define GET_NEXT_REQUEST 0xa1
#define GET_RESPONSE 0xa2
#define SET_REQUEST 0xa3
// Macros: SNMPv1 request validation checker
#define VALID_REQUEST(x) ((x == GET_REQUEST) || (x == GET_NEXT_REQUEST) || (x == SET_REQUEST))
// SNMPv1 Return Types
#define SNMPDTYPE_INTEGER 0x02
#define SNMPDTYPE_OCTET_STRING 0x04
#define SNMPDTYPE_NULL_ITEM 0x05
#define SNMPDTYPE_OBJ_ID 0x06
#define SNMPDTYPE_SEQUENCE 0x30
#define SNMPDTYPE_SEQUENCE_OF SNMPDTYPE_SEQUENCE
#define SNMPDTYPE_COUNTER 0x41
#define SNMPDTYPE_GAUGE 0x42
#define SNMPDTYPE_TIME_TICKS 0x43
#define SNMPDTYPE_OPAQUE 0x44
// SNMP Trap: Standard Trap Types (Generic)
#define SNMPTRAP_COLDSTART 0x00 // Generic trap-type 0: Cold Start
#define SNMPTRAP_WARMSTART 0x01 // Generic trap-type 1: Warm Start
#define SNMPTRAP_LINKDOWN 0x02 // Generic trap-type 2: Link Down
#define SNMPTRAP_LINKUP 0x03 // Generic trap-type 3: Link Up
#define SNMPTRAP_AUTHENTICATION 0x04 // Generic trap-type 4: Authentication Failure
#define SNMPTRAP_EGPNEIGHBORLOSS 0x05 // Generic trap-type 5: EGP Neighbor Loss
// Macros
#define COPY_SEGMENT(x) \
{ \
request_msg.index += seglen; \
memcpy(&response_msg.buffer[response_msg.index], &request_msg.buffer[x.start], seglen ); \
response_msg.index += seglen; \
}
#ifndef HTONL
#define HTONL(x) \
((((x) >> 24) & 0x000000ff) | \
(((x) >> 8) & 0x0000ff00) | \
(((x) << 8) & 0x00ff0000) | \
(((x) << 24) & 0xff000000))
#endif
typedef struct {
uint8_t oidlen;
uint8_t oid[MAX_OID];
uint8_t dataType;
uint8_t dataLen;
union {
uint8_t octetstring[MAX_STRING];
uint32_t intval;
} u;
void (*getfunction)(void *, uint8_t *);
void (*setfunction)(int32_t);
} dataEntryType;
struct messageStruct {
uint8_t buffer[MAX_SNMPMSG_LEN];
int32_t len;
int32_t index;
};
typedef struct {
int32_t start; /* Absolute Index of the TLV */
int32_t len; /* The L value of the TLV */
int32_t vstart; /* Absolute Index of this TLV's Value */
int32_t nstart; /* Absolute Index of the next TLV */
} tlvStructType;
/********************************************************************************************/
/* SNMP : Functions */
/********************************************************************************************/
// SNMP Main functions
void snmpd_init(uint8_t * managerIP, uint8_t * agentIP, uint8_t sn_agent, uint8_t sn_trap);
int32_t snmpd_run(void);
int32_t snmp_sendTrap(uint8_t * managerIP, uint8_t * agentIP, int8_t* community, dataEntryType enterprise_oid, uint32_t genericTrap, uint32_t specificTrap, uint32_t va_count, ...);
// SNMP Time handler functions
void SNMP_time_handler(void);
uint32_t getSNMPTimeTick(void);
void currentUptime(void *ptr, uint8_t *len);
#ifdef __cplusplus
}
#endif
#endif

178
Internet/SNMP/snmp_custom.c Normal file
View File

@@ -0,0 +1,178 @@
/********************************************************************************************
SNMP : User Customization Part
- OID Registration
- User defined functions for OID related
+ Integer value, String
+ I/O control / Chip registers
+ Network Informations
+ Etc.
*********************************************************************************************/
#include "snmp_custom.h"
#ifdef _USE_WIZNET_W5500_EVB_
#include "board.h"
#endif
dataEntryType snmpData[] = {
// System MIB
// SysDescr Entry
{
8, {0x2b, 6, 1, 2, 1, 1, 1, 0},
SNMPDTYPE_OCTET_STRING, 30, {"WIZnet Embedded SNMP Agent"},
NULL, NULL
},
// SysObjectID Entry
{
8, {0x2b, 6, 1, 2, 1, 1, 2, 0},
SNMPDTYPE_OBJ_ID, 8, {"\x2b\x06\x01\x02\x01\x01\x02\x00"},
NULL, NULL
},
// SysUptime Entry
{
8, {0x2b, 6, 1, 2, 1, 1, 3, 0},
SNMPDTYPE_TIME_TICKS, 0, {""},
currentUptime, NULL
},
// sysContact Entry
{
8, {0x2b, 6, 1, 2, 1, 1, 4, 0},
SNMPDTYPE_OCTET_STRING, 30, {"http://www.wizwiki.net/forum"},
NULL, NULL
},
// sysName Entry
{
8, {0x2b, 6, 1, 2, 1, 1, 5, 0},
SNMPDTYPE_OCTET_STRING, 30, {"http://www.wiznet.co.kr"},
NULL, NULL
},
// Location Entry
{
8, {0x2b, 6, 1, 2, 1, 1, 6, 0},
SNMPDTYPE_OCTET_STRING, 30, {"4F Humax Village"},
NULL, NULL
},
// SysServices
{
8, {0x2b, 6, 1, 2, 1, 1, 7, 0},
SNMPDTYPE_INTEGER, 4, {""},
NULL, NULL
},
#ifdef _USE_WIZNET_W5500_EVB_
// Get the WIZnet W5500-EVB LED Status
{
8, {0x2b, 6, 1, 4, 1, 6, 1, 0},
SNMPDTYPE_OCTET_STRING, 40, {""},
get_LEDStatus_all, NULL
},
// Set the LED_R (RGB LED)
{
8, {0x2b, 6, 1, 4, 1, 6, 1, 1},
SNMPDTYPE_INTEGER, 4, {""},
NULL, set_LEDStatus_R
},
// Set the LED_G (RGB LED)
{
8, {0x2b, 6, 1, 4, 1, 6, 1, 2},
SNMPDTYPE_INTEGER, 4, {""},
NULL, set_LEDStatus_G
},
// Set the LED_B (RGB LED)
{
8, {0x2b, 6, 1, 4, 1, 6, 1, 3},
SNMPDTYPE_INTEGER, 4, {""},
NULL, set_LEDStatus_B
},
#endif
// OID Test #1 (long-length OID example, 19865)
{
0x0a, {0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0x9b, 0x19, 0x01, 0x00},
SNMPDTYPE_OCTET_STRING, 30, {"long-length OID Test #1"},
NULL, NULL
},
// OID Test #2 (long-length OID example, 22210)
{
0x0a, {0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0xad, 0x42, 0x01, 0x00},
SNMPDTYPE_OCTET_STRING, 35, {"long-length OID Test #2"},
NULL, NULL
},
// OID Test #2: SysObjectID Entry
{
0x0a, {0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0xad, 0x42, 0x02, 0x00},
SNMPDTYPE_OBJ_ID, 0x0a, {"\x2b\x06\x01\x04\x01\x81\xad\x42\x02\x00"},
NULL, NULL
},
};
const int32_t maxData = (sizeof(snmpData) / sizeof(dataEntryType));
void initTable() {
// Example integer value for [OID 1.3.6.1.2.1.1.7.0]
snmpData[6].u.intval = -5;
}
// W5500-EVB: LED Control ///////////////////////////////////////////////////////////////////////////
#ifdef _USE_WIZNET_W5500_EVB_
void get_LEDStatus_all(void *ptr, uint8_t *len) {
uint8_t led_status[3] = {0, };
led_status[LED_R] = (uint8_t)Board_LED_Test(LED_R);
led_status[LED_G] = (uint8_t)Board_LED_Test(LED_G);
led_status[LED_B] = (uint8_t)Board_LED_Test(LED_B);
*len = sprintf((char *)ptr, "LED R [%s] / G [%s] / B [%s]", led_status[LED_R] ? "On" : "Off", led_status[LED_G] ? "On" : "Off", led_status[LED_B] ? "On" : "Off");
}
void set_LEDStatus_R(int32_t val) {
if (val == 0) {
Board_LED_Set(LED_R, false);
} else {
Board_LED_Set(LED_R, true);
}
}
void set_LEDStatus_G(int32_t val) {
if (val == 0) {
Board_LED_Set(LED_G, false);
} else {
Board_LED_Set(LED_G, true);
}
}
void set_LEDStatus_B(int32_t val) {
if (val == 0) {
Board_LED_Set(LED_B, false);
} else {
Board_LED_Set(LED_B, true);
}
}
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////
void initial_Trap(uint8_t * managerIP, uint8_t * agentIP) {
// SNMP Trap: WarmStart(1) Trap
{
dataEntryType enterprise_oid = {0x0a, {0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0x9b, 0x19, 0x01, 0x00},
SNMPDTYPE_OBJ_ID, 0x0a, {"\x2b\x06\x01\x04\x01\x81\x9b\x19\x10\x00"}, NULL, NULL
};
// Generic Trap: warmStart COMMUNITY
snmp_sendTrap(managerIP, agentIP, (void *)COMMUNITY, enterprise_oid, SNMPTRAP_WARMSTART, 0, 0);
}
}

View File

@@ -0,0 +1,41 @@
#ifndef _SNMP_CUSTOM_H_
#define _SNMP_CUSTOM_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdint.h>
#include "snmp.h"
extern dataEntryType snmpData[];
extern const int32_t maxData;
// Define for using W5500-EVB: H/W Dependency (e.g., LEDs...)
//#define _USE_WIZNET_W5500_EVB_
#define COMMUNITY "public\0"
#define COMMUNITY_SIZE (strlen(COMMUNITY))
/* Predefined function: Response value control */
void initTable();
/* User defined functions: LED control examples */
#ifdef _USE_WIZNET_W5500_EVB_
void get_LEDStatus_all(void *ptr, uint8_t *len);
void set_LEDStatus_R(int32_t val);
void set_LEDStatus_G(int32_t val);
void set_LEDStatus_B(int32_t val);
#endif
/* SNMP Trap: warmStart(1) */
void initial_Trap(uint8_t * managerIP, uint8_t * agentIP);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,45 @@
============================================================
<OID encoding steps for WIZnet SNMP Agent>
============================================================
+ Example OID for convert
1.3.6.1.4.1.19865.1.0
(1) Convert Usage
CMD>>oid 1.3.6.1.4.1.19865.1.0
=> 06 0A 2B 06 01 04 01 81 9B 19 01 00
>> TLV(tag-length-value) Example OID
(06) Tag
(0A) Length
[2B] 1(iso).3(identified-organization) (in ASN.1 BER encoding, i.e. 1*40+3 = 0x2b)
[06] 6(dod)
[01] 1(internet)
[04] 4(private)
[01] 1(enterprise)
[81 9B 19] 19865(Vendor-Specific)
...
(2) Add the entry to OID table in source code (DataEntryType, put the converted value to array)
{0x0a, {0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0x9b, 0x19, 0x01, 0x00},
SNMPDTYPE_OCTET_STRING, 30, {"long-length OID Test"},
NULL, NULL},
============================================================
OID Converter: OID encoder/decoder
v1.3 - Matthias Gaertner 1999/2001 - Freeware
============================================================
The OID converter is a handy little tool to convert ASN.1 OIDs from readable dotted decimal notation to binary hexadecimal Distinguished Encoding Rules (DER) representation and vice versa.
If you're into x.509 certificates, this may be useful to you, too.
Usage:
OID [-c|-C] [-o] {-i|1.2.3.4}
converts dotted form to ASCII HEX DER output.
OID -x [-o] {-i|hex-digits}
decodes ASCII HEX DER and gives dotted form.
If you need more information, please refer to Matthias Gaertner's page,
http://www.rtner.de/software/oid.html
===============================================================================================

View File

@@ -0,0 +1,33 @@
#
# net-snmp (or ucd-snmp) persistent data file.
#
############################################################################
# STOP STOP STOP STOP STOP STOP STOP STOP STOP
#
# **** DO NOT EDIT THIS FILE ****
#
# STOP STOP STOP STOP STOP STOP STOP STOP STOP
############################################################################
#
# DO NOT STORE CONFIGURATION ENTRIES HERE.
# Please save normal configuration tokens for snmptrapd in SNMPCONFPATH/snmptrapd.conf.
# Only "createUser" tokens should be placed here by snmptrapd administrators.
# (Did I mention: do not edit this file?)
#
authCommunity log,execute,net public
engineBoots 1
oldEngineID 0x80001f88803d6f00001ba7934e00000000

469
Internet/SNTP/sntp.c Normal file
View File

@@ -0,0 +1,469 @@
/*
sntp.c
Created on: 2014. 12. 15.
Author: Administrator
*/
#include <string.h>
#include "sntp.h"
#include "socket.h"
ntpformat NTPformat;
datetime Nowdatetime;
uint8_t ntpmessage[48];
uint8_t *data_buf;
uint8_t NTP_SOCKET;
uint8_t time_zone;
uint16_t ntp_retry_cnt = 0; //counting the ntp retry number
/*
00)UTC-12:00 Baker Island, Howland Island (both uninhabited)
01) UTC-11:00 American Samoa, Samoa
02) UTC-10:00 (Summer)French Polynesia (most), United States (Aleutian Islands, Hawaii)
03) UTC-09:30 Marquesas Islands
04) UTC-09:00 Gambier Islands;(Summer)United States (most of Alaska)
05) UTC-08:00 (Summer)Canada (most of British Columbia), Mexico (Baja California)
06) UTC-08:00 United States (California, most of Nevada, most of Oregon, Washington (state))
07) UTC-07:00 Mexico (Sonora), United States (Arizona); (Summer)Canada (Alberta)
08) UTC-07:00 Mexico (Chihuahua), United States (Colorado)
09) UTC-06:00 Costa Rica, El Salvador, Ecuador (Galapagos Islands), Guatemala, Honduras
10) UTC-06:00 Mexico (most), Nicaragua;(Summer)Canada (Manitoba, Saskatchewan), United States (Illinois, most of Texas)
11) UTC-05:00 Colombia, Cuba, Ecuador (continental), Haiti, Jamaica, Panama, Peru
12) UTC-05:00 (Summer)Canada (most of Ontario, most of Quebec)
13) UTC-05:00 United States (most of Florida, Georgia, Massachusetts, most of Michigan, New York, North Carolina, Ohio, Washington D.C.)
14) UTC-04:30 Venezuela
15) UTC-04:00 Bolivia, Brazil (Amazonas), Chile (continental), Dominican Republic, Canada (Nova Scotia), Paraguay,
16) UTC-04:00 Puerto Rico, Trinidad and Tobago
17) UTC-03:30 Canada (Newfoundland)
18) UTC-03:00 Argentina; (Summer) Brazil (Brasilia, Rio de Janeiro, Sao Paulo), most of Greenland, Uruguay
19) UTC-02:00 Brazil (Fernando de Noronha), South Georgia and the South Sandwich Islands
20) UTC-01:00 Portugal (Azores), Cape Verde
21) UTC&#177;00:00 Cote d'Ivoire, Faroe Islands, Ghana, Iceland, Senegal; (Summer) Ireland, Portugal (continental and Madeira)
22) UTC&#177;00:00 Spain (Canary Islands), Morocco, United Kingdom
23) UTC+01:00 Angola, Cameroon, Nigeria, Tunisia; (Summer)Albania, Algeria, Austria, Belgium, Bosnia and Herzegovina,
24) UTC+01:00 Spain (continental), Croatia, Czech Republic, Denmark, Germany, Hungary, Italy, Kinshasa, Kosovo,
25) UTC+01:00 Macedonia, France (metropolitan), the Netherlands, Norway, Poland, Serbia, Slovakia, Slovenia, Sweden, Switzerland
26) UTC+02:00 Libya, Egypt, Malawi, Mozambique, South Africa, Zambia, Zimbabwe, (Summer)Bulgaria, Cyprus, Estonia,
27) UTC+02:00 Finland, Greece, Israel, Jordan, Latvia, Lebanon, Lithuania, Moldova, Palestine, Romania, Syria, Turkey, Ukraine
28) UTC+03:00 Belarus, Djibouti, Eritrea, Ethiopia, Iraq, Kenya, Madagascar, Russia (Kaliningrad Oblast), Saudi Arabia,
29) UTC+03:00 South Sudan, Sudan, Somalia, South Sudan, Tanzania, Uganda, Yemen
30) UTC+03:30 (Summer)Iran
31) UTC+04:00 Armenia, Azerbaijan, Georgia, Mauritius, Oman, Russia (European), Seychelles, United Arab Emirates
32) UTC+04:30 Afghanistan
33) UTC+05:00 Kazakhstan (West), Maldives, Pakistan, Uzbekistan
34) UTC+05:30 India, Sri Lanka
35) UTC+05:45 Nepal
36) UTC+06:00 Kazakhstan (most), Bangladesh, Russia (Ural: Sverdlovsk Oblast, Chelyabinsk Oblast)
37) UTC+06:30 Cocos Islands, Myanmar
38) UTC+07:00 Jakarta, Russia (Novosibirsk Oblast), Thailand, Vietnam
39) UTC+08:00 China, Hong Kong, Russia (Krasnoyarsk Krai), Malaysia, Philippines, Singapore, Taiwan, most of Mongolia, Western Australia
40) UTC+09:00 Korea, East Timor, Russia (Irkutsk Oblast), Japan
41) UTC+09:30 Australia (Northern Territory);(Summer)Australia (South Australia))
42) UTC+10:00 Russia (Zabaykalsky Krai); (Summer)Australia (New South Wales, Queensland, Tasmania, Victoria)
43) UTC+10:30 Lord Howe Island
44) UTC+11:00 New Caledonia, Russia (Primorsky Krai), Solomon Islands
45) UTC+11:30 Norfolk Island
46) UTC+12:00 Fiji, Russia (Kamchatka Krai);(Summer)New Zealand
47) UTC+12:45 (Summer)New Zealand
48) UTC+13:00 Tonga
49) UTC+14:00 Kiribati (Line Islands)
*/
void get_seconds_from_ntp_server(uint8_t *buf, uint16_t idx) {
tstamp seconds = 0;
uint8_t i = 0;
for (i = 0; i < 4; i++) {
seconds = (seconds << 8) | buf[idx + i];
}
switch (time_zone) {
case 0:
seconds -= 12 * 3600;
break;
case 1:
seconds -= 11 * 3600;
break;
case 2:
seconds -= 10 * 3600;
break;
case 3:
seconds -= (9 * 3600 + 30 * 60);
break;
case 4:
seconds -= 9 * 3600;
break;
case 5:
case 6:
seconds -= 8 * 3600;
break;
case 7:
case 8:
seconds -= 7 * 3600;
break;
case 9:
case 10:
seconds -= 6 * 3600;
break;
case 11:
case 12:
case 13:
seconds -= 5 * 3600;
break;
case 14:
seconds -= (4 * 3600 + 30 * 60);
break;
case 15:
case 16:
seconds -= 4 * 3600;
break;
case 17:
seconds -= (3 * 3600 + 30 * 60);
break;
case 18:
seconds -= 3 * 3600;
break;
case 19:
seconds -= 2 * 3600;
break;
case 20:
seconds -= 1 * 3600;
break;
case 21: //<2F>?
case 22:
break;
case 23:
case 24:
case 25:
seconds += 1 * 3600;
break;
case 26:
case 27:
seconds += 2 * 3600;
break;
case 28:
case 29:
seconds += 3 * 3600;
break;
case 30:
seconds += (3 * 3600 + 30 * 60);
break;
case 31:
seconds += 4 * 3600;
break;
case 32:
seconds += (4 * 3600 + 30 * 60);
break;
case 33:
seconds += 5 * 3600;
break;
case 34:
seconds += (5 * 3600 + 30 * 60);
break;
case 35:
seconds += (5 * 3600 + 45 * 60);
break;
case 36:
seconds += 6 * 3600;
break;
case 37:
seconds += (6 * 3600 + 30 * 60);
break;
case 38:
seconds += 7 * 3600;
break;
case 39:
seconds += 8 * 3600;
break;
case 40:
seconds += 9 * 3600;
break;
case 41:
seconds += (9 * 3600 + 30 * 60);
break;
case 42:
seconds += 10 * 3600;
break;
case 43:
seconds += (10 * 3600 + 30 * 60);
break;
case 44:
seconds += 11 * 3600;
break;
case 45:
seconds += (11 * 3600 + 30 * 60);
break;
case 46:
seconds += 12 * 3600;
break;
case 47:
seconds += (12 * 3600 + 45 * 60);
break;
case 48:
seconds += 13 * 3600;
break;
case 49:
seconds += 14 * 3600;
break;
}
//calculation for date
calcdatetime(seconds);
}
void SNTP_init(uint8_t s, uint8_t *ntp_server, uint8_t tz, uint8_t *buf) {
NTP_SOCKET = s;
NTPformat.dstaddr[0] = ntp_server[0];
NTPformat.dstaddr[1] = ntp_server[1];
NTPformat.dstaddr[2] = ntp_server[2];
NTPformat.dstaddr[3] = ntp_server[3];
time_zone = tz;
data_buf = buf;
uint8_t Flag;
NTPformat.leap = 0; /* leap indicator */
NTPformat.version = 4; /* version number */
NTPformat.mode = 3; /* mode */
NTPformat.stratum = 0; /* stratum */
NTPformat.poll = 0; /* poll interval */
NTPformat.precision = 0; /* precision */
NTPformat.rootdelay = 0; /* root delay */
NTPformat.rootdisp = 0; /* root dispersion */
NTPformat.refid = 0; /* reference ID */
NTPformat.reftime = 0; /* reference time */
NTPformat.org = 0; /* origin timestamp */
NTPformat.rec = 0; /* receive timestamp */
NTPformat.xmt = 1; /* transmit timestamp */
Flag = (NTPformat.leap << 6) + (NTPformat.version << 3) + NTPformat.mode; //one byte Flag
memcpy(ntpmessage, (void const*)(&Flag), 1);
}
int8_t SNTP_run(datetime *time) {
uint16_t RSR_len;
uint32_t destip = 0;
uint16_t destport;
uint16_t startindex = 40; //last 8-byte of data_buf[size is 48 byte] is xmt, so the startindex should be 40
#if 1
// 20231019 taylor
uint8_t addr_len;
#endif
switch (getSn_SR(NTP_SOCKET)) {
case SOCK_UDP:
if ((RSR_len = getSn_RX_RSR(NTP_SOCKET)) > 0) {
if (RSR_len > MAX_SNTP_BUF_SIZE) {
RSR_len = MAX_SNTP_BUF_SIZE; // if Rx data size is lager than TX_RX_MAX_BUF_SIZE
}
#if 1
// 20231019 taylor//teddy 240122
#if ((_WIZCHIP_ == 6100) || (_WIZCHIP_ == 6300))
recvfrom(NTP_SOCKET, data_buf, RSR_len, (uint8_t *)&destip, &destport, &addr_len);
#else
recvfrom(NTP_SOCKET, data_buf, RSR_len, (uint8_t *)&destip, &destport);
#endif
#else
recvfrom(NTP_SOCKET, data_buf, RSR_len, (uint8_t *)&destip, &destport);
#endif
get_seconds_from_ntp_server(data_buf, startindex);
time->yy = Nowdatetime.yy;
time->mo = Nowdatetime.mo;
time->dd = Nowdatetime.dd;
time->hh = Nowdatetime.hh;
time->mm = Nowdatetime.mm;
time->ss = Nowdatetime.ss;
ntp_retry_cnt = 0;
close(NTP_SOCKET);
return 1;
}
if (ntp_retry_cnt < 0xFFFF) {
if (ntp_retry_cnt == 0) { //first send request, no need to wait
#if 1
// 20231016 taylor//teddy 240122
#if ((_WIZCHIP_ == 6100) || (_WIZCHIP_ == 6300))
sendto(NTP_SOCKET, ntpmessage, sizeof(ntpmessage), NTPformat.dstaddr, ntp_port, 4);
#else
sendto(NTP_SOCKET, ntpmessage, sizeof(ntpmessage), NTPformat.dstaddr, ntp_port);
#endif
#else
sendto(NTP_SOCKET, ntpmessage, sizeof(ntpmessage), NTPformat.dstaddr, ntp_port);
#endif
ntp_retry_cnt++;
} else { // send request again? it should wait for a while
if ((ntp_retry_cnt % 0xFFF) == 0) { //wait time
#if 1
// 20231016 taylor//teddy 240122
#if ((_WIZCHIP_ == 6100) || (_WIZCHIP_ == 6300))
sendto(NTP_SOCKET, ntpmessage, sizeof(ntpmessage), NTPformat.dstaddr, ntp_port, 4);
#else
sendto(NTP_SOCKET, ntpmessage, sizeof(ntpmessage), NTPformat.dstaddr, ntp_port);
#endif
#else
sendto(NTP_SOCKET, ntpmessage, sizeof(ntpmessage), NTPformat.dstaddr, ntp_port);
#endif
#ifdef _SNTP_DEBUG_
printf("ntp retry: %d\r\n", ntp_retry_cnt);
#endif
ntp_retry_cnt++;
}
}
} else { //ntp retry fail
ntp_retry_cnt = 0;
#ifdef _SNTP_DEBUG_
printf("ntp retry failed!\r\n");
#endif
close(NTP_SOCKET);
}
break;
case SOCK_CLOSED:
socket(NTP_SOCKET, Sn_MR_UDP, ntp_port, 0);
break;
}
// Return value
// 0 - failed / 1 - success
return 0;
}
void calcdatetime(tstamp seconds) {
uint8_t yf = 0;
uint8_t leap;
tstamp n = 0, d = 0, total_d = 0, rz = 0;
uint16_t y = 0, r = 0, yr = 0;
signed long long yd = 0;
n = seconds;
total_d = seconds / (SECS_PERDAY);
d = 0;
uint32_t p_year_total_sec = SECS_PERDAY * 365;
uint32_t r_year_total_sec = SECS_PERDAY * 366;
while (1) {
leap = 0;
if (((EPOCH + r) % 400 == 0) ||
(((EPOCH + r) % 100 != 0) && ((EPOCH + r) % 4 == 0))) {
leap = 1;
}
if (leap) {
if (n < r_year_total_sec) {
break;
}
n -= r_year_total_sec;
d += 366;
} else {
if (n < p_year_total_sec) {
break;
}
n -= p_year_total_sec;
d += 365;
}
r++;
y++;
}
y += EPOCH;
Nowdatetime.yy = y;
yd = 0;
yd = total_d - d;
yf = 1;
while (yd >= 28) {
if (yf == 1 || yf == 3 || yf == 5 || yf == 7 || yf == 8 || yf == 10 || yf == 12) {
yd -= 31;
if (yd < 0) {
break;
}
rz += 31;
}
if (yf == 2) {
if (y % 400 == 0 || (y % 100 != 0 && y % 4 == 0)) {
yd -= 29;
if (yd < 0) {
break;
}
rz += 29;
} else {
yd -= 28;
if (yd < 0) {
break;
}
rz += 28;
}
}
if (yf == 4 || yf == 6 || yf == 9 || yf == 11) {
yd -= 30;
if (yd < 0) {
break;
}
rz += 30;
}
yf += 1;
}
Nowdatetime.mo = yf;
yr = total_d - d - rz;
yr += 1;
Nowdatetime.dd = yr;
//calculation for time
seconds = seconds % SECS_PERDAY;
Nowdatetime.hh = seconds / 3600;
Nowdatetime.mm = (seconds % 3600) / 60;
Nowdatetime.ss = (seconds % 3600) % 60;
}
tstamp changedatetime_to_seconds(void) {
tstamp seconds = 0;
uint32_t total_day = 0;
uint16_t i = 0, run_year_cnt = 0, l = 0;
l = Nowdatetime.yy;//low
for (i = EPOCH; i < l; i++) {
if ((i % 400 == 0) || ((i % 100 != 0) && (i % 4 == 0))) {
run_year_cnt += 1;
}
}
total_day = (l - EPOCH - run_year_cnt) * 365 + run_year_cnt * 366;
for (i = 1; i <= Nowdatetime.mo; i++) {
if (i == 5 || i == 7 || i == 10 || i == 12) {
total_day += 30;
}
if (i == 3) {
if (l % 400 == 0 || l % 100 != 0 && l % 4 == 0) {
total_day += 29;
} else {
total_day += 28;
}
}
if (i == 2 || i == 4 || i == 6 || i == 8 || i == 9 || i == 11) {
total_day += 31;
}
}
seconds = (total_day + Nowdatetime.dd - 1) * 24 * 3600;
seconds += Nowdatetime.ss;//seconds
seconds += Nowdatetime.mm * 60; //minute
seconds += Nowdatetime.hh * 3600; //hour
return seconds;
}

74
Internet/SNTP/sntp.h Normal file
View File

@@ -0,0 +1,74 @@
/*
sntp.h
Created on: 2014. 12. 15.
Author: Administrator
*/
#ifndef SNTP_H_
#define SNTP_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
/*
@brief Define it for Debug & Monitor DNS processing.
@note If defined, it dependens on <stdio.h>
*/
//#define _SNTP_DEBUG_
#define MAX_SNTP_BUF_SIZE sizeof(ntpformat) ///< maximum size of DNS buffer. */
/* for ntpclient */
typedef signed char s_char;
typedef unsigned long long tstamp;
typedef unsigned int tdist;
typedef struct _ntpformat {
uint8_t dstaddr[4]; /* destination (local) address */
char version; /* version number */
char leap; /* leap indicator */
char mode; /* mode */
char stratum; /* stratum */
char poll; /* poll interval */
s_char precision; /* precision */
tdist rootdelay; /* root delay */
tdist rootdisp; /* root dispersion */
char refid; /* reference ID */
tstamp reftime; /* reference time */
tstamp org; /* origin timestamp */
tstamp rec; /* receive timestamp */
tstamp xmt; /* transmit timestamp */
} ntpformat;
typedef struct _datetime {
uint16_t yy;
uint8_t mo;
uint8_t dd;
uint8_t hh;
uint8_t mm;
uint8_t ss;
} datetime;
#define ntp_port 123 //ntp server port number
#define SECS_PERDAY 86400UL // seconds in a day = 60*60*24
#define UTC_ADJ_HRS 9 // SEOUL : GMT+9
#define EPOCH 1900 // NTP start year
void get_seconds_from_ntp_server(uint8_t *buf, uint16_t idx);
void SNTP_init(uint8_t s, uint8_t *ntp_server, uint8_t tz, uint8_t *buf);
int8_t SNTP_run(datetime *time);
tstamp changedatetime_to_seconds(void);
void calcdatetime(tstamp seconds);
#ifdef __cplusplus
}
#endif
#endif /* SNTP_H_ */

151
Internet/TFTP/netutil.c Normal file
View File

@@ -0,0 +1,151 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "netutil.h"
/**
Convert a 32bit Address into a Dotted Decimal Format string.
@param addr 32bit address.
@return Dotted Decimal Format string.
*/
int8_t* inet_ntoa(uint32_t addr) {
static int8_t addr_str[16];
memset(addr_str, 0, 16);
sprintf((char*)addr_str, "%d.%d.%d.%d", (int32_t)(addr >> 24 & 0xFF), (int32_t)(addr >> 16 & 0xFF), (int32_t)(addr >> 8 & 0xFF), (int32_t)(addr & 0xFF));
return addr_str;
}
/**
Convert a 32bit Address into a Dotted Decimal Format string.
This is differ from inet_ntoa in fixed length.
@param addr 32bit address.
@return Dotted Decimal Format string.
*/
int8_t* inet_ntoa_pad(uint32_t addr) {
static int8_t addr_str[16];
memset(addr_str, 0, 16);
sprintf((char*)addr_str, "%03d.%03d.%03d.%03d", (int32_t)(addr >> 24 & 0xFF), (int32_t)(addr >> 16 & 0xFF), (int32_t)(addr >> 8 & 0xFF), (int32_t)(addr & 0xFF));
return addr_str;
}
/**
Converts a string containing an (Ipv4) Internet Protocol decimal dotted address into a 32bit address.
@param addr Dotted Decimal Format string.
@return 32bit address.
*/
uint32_t inet_addr(uint8_t* addr) {
int8_t i;
uint32_t inetaddr = 0;
int8_t taddr[30];
int8_t * nexttok;
int32_t num;
strcpy((char*)taddr, (char*)addr);
nexttok = taddr;
for (i = 0; i < 4 ; i++) {
nexttok = (int8_t*)strtok((char*)nexttok, ".");
if (nexttok[0] == '0' && nexttok[1] == 'x') {
num = strtol((char*)nexttok + 2, NULL, 16);
} else {
num = strtol((char*)nexttok, NULL, 10);
}
inetaddr = inetaddr << 8;
inetaddr |= (num & 0xFF);
nexttok = NULL;
}
return inetaddr;
}
/**
Swap the byte order of 16bit(short) wide variable.
@param i 16bit value to swap
@return Swapped value
*/
uint16_t swaps(uint16_t i) {
uint16_t ret = 0;
ret = (i & 0xFF) << 8;
ret |= ((i >> 8) & 0xFF);
return ret;
}
/**
Swap the byte order of 32bit(long) wide variable.
@param l 32bit value to convert
@return Swapped value
*/
uint32_t swapl(uint32_t l) {
uint32_t ret = 0;
ret = (l & 0xFF) << 24;
ret |= ((l >> 8) & 0xFF) << 16;
ret |= ((l >> 16) & 0xFF) << 8;
ret |= ((l >> 24) & 0xFF);
return ret;
}
/**
htons function converts a unsigned short from host to TCP/IP network byte order (which is big-endian).
@param hostshort The value to convert.
@return The value in TCP/IP network byte order.
*/
uint16_t htons(uint16_t hostshort) {
#ifdef SYSTEM_LITTLE_ENDIAN
return swaps(hostshort);
#else
return hostshort;
#endif
}
/**
htonl function converts a unsigned long from host to TCP/IP network byte order (which is big-endian).
@param hostlong The value to convert.
@return The value in TCP/IP network byte order.
*/
uint32_t htonl(uint32_t hostlong) {
#ifdef SYSTEM_LITTLE_ENDIAN
return swapl(hostlong);
#else
return hostlong;
#endif
}
/**
ntohs function converts a unsigned short from TCP/IP network byte order
to host byte order (which is little-endian on Intel processors).
@param netshort The value to convert.
@return A 16-bit number in host byte order
*/
uint32_t ntohs(uint16_t netshort) {
#ifdef SYSTEM_LITTLE_ENDIAN
return htons(netshort);
#else
return netshort;
#endif
}
/**
converts a unsigned long from TCP/IP network byte order to host byte order
(which is little-endian on Intel processors).
@param netlong The value to convert.
@return A 16-bit number in host byte order
*/
uint32_t ntohl(uint32_t netlong) {
#ifdef SYSTEM_LITTLE_ENDIAN
return swapl(netlong);
#else
return netlong;
#endif
}
/**
@}
*/

27
Internet/TFTP/netutil.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef __NETUTIL_H__
#define __NETUTIL_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#define SYSTEM_LITTLE_ENDIAN
int8_t* inet_ntoa(uint32_t addr);
int8_t* inet_ntoa_pad(uint32_t addr);
uint32_t inet_addr(uint8_t* addr);
uint16_t swaps(uint16_t i);
uint32_t swapl(uint32_t l);
uint16_t htons(uint16_t hostshort);
uint32_t htonl(uint32_t hostlong);
uint32_t ntohs(uint16_t netshort);
uint32_t ntohl(uint32_t netlong);
#ifdef __cplusplus
}
#endif
#endif

639
Internet/TFTP/tftp.c Normal file
View File

@@ -0,0 +1,639 @@
/**
@file tftp.c
@brief TFTP Source File.
@version 0.1.0
@author Sang-sik Kim
*/
/* Includes -----------------------------------------------------*/
#include <string.h>
#include "tftp.h"
#include "socket.h"
#include "netutil.h"
/* define -------------------------------------------------------*/
/* typedef ------------------------------------------------------*/
/* Extern Variable ----------------------------------------------*/
/* Extern Functions ---------------------------------------------*/
#ifdef F_STORAGE
extern void save_data(uint8_t *data, uint32_t data_len, uint16_t block_number);
#endif
/* Global Variable ----------------------------------------------*/
static int g_tftp_socket = -1;
static uint8_t g_filename[FILE_NAME_SIZE];
static uint32_t g_server_ip = 0;
static uint16_t g_server_port = 0;
static uint16_t g_local_port = 0;
static uint32_t g_tftp_state = STATE_NONE;
static uint16_t g_block_num = 0;
static uint32_t g_timeout = 5;
static uint32_t g_resend_flag = 0;
static uint32_t tftp_time_cnt = 0;
static uint32_t tftp_retry_cnt = 0;
static uint8_t *g_tftp_rcv_buf = NULL;
static TFTP_OPTION default_tftp_opt = {
.code = (uint8_t *)"timeout",
.value = (uint8_t *)"5"
};
uint8_t g_progress_state = TFTP_PROGRESS;
#ifdef __TFTP_DEBUG__
int dbg_level = (INFO_DBG | ERROR_DBG | IPC_DBG);
#endif
/* static function define ---------------------------------------*/
static void set_filename(uint8_t *file, uint32_t file_size) {
memcpy(g_filename, file, file_size);
}
static inline void set_server_ip(uint32_t ipaddr) {
g_server_ip = ipaddr;
}
static inline uint32_t get_server_ip() {
return g_server_ip;
}
static inline void set_server_port(uint16_t port) {
g_server_port = port;
}
static inline uint16_t get_server_port() {
return g_server_port;
}
static inline void set_local_port(uint16_t port) {
g_local_port = port;
}
static inline uint16_t get_local_port() {
return g_local_port;
}
static inline uint16_t genernate_port() {
/* TODO */
return 0;
}
static inline void set_tftp_state(uint32_t state) {
g_tftp_state = state;
}
static inline uint32_t get_tftp_state() {
return g_tftp_state;
}
static inline void set_tftp_timeout(uint32_t timeout) {
g_timeout = timeout;
}
static inline uint32_t get_tftp_timeout() {
return g_timeout;
}
static inline void set_block_number(uint16_t block_number) {
g_block_num = block_number;
}
static inline uint16_t get_block_number() {
return g_block_num;
}
static int open_tftp_socket(uint8_t sock) {
uint8_t sd, sck_state;
sd = socket(sock, Sn_MR_UDP, 51000, SF_IO_NONBLOCK);
if (sd != sock) {
//DBG_PRINT(ERROR_DBG, "[%s] socket error\r\n", __func__);
return -1;
}
do {
getsockopt(sd, SO_STATUS, &sck_state);
} while (sck_state != SOCK_UDP);
return sd;
}
static int send_udp_packet(int socket, uint8_t *packet, uint32_t len, uint32_t ip, uint16_t port) {
int snd_len;
ip = htonl(ip);
#if 1
// 20231016 taylor//teddy 240122
#if ((_WIZCHIP_ == 6100) || (_WIZCHIP_ == 6300))
snd_len = sendto(socket, packet, len, (uint8_t *)&ip, port, 4);
#else
snd_len = sendto(socket, packet, len, (uint8_t *)&ip, port);
#endif
#else
snd_len = sendto(socket, packet, len, (uint8_t *)&ip, port);
#endif
if (snd_len != len) {
//DBG_PRINT(ERROR_DBG, "[%s] sendto error\r\n", __func__);
return -1;
}
return snd_len;
}
static int recv_udp_packet(int socket, uint8_t *packet, uint32_t len, uint32_t *ip, uint16_t *port) {
int ret;
uint8_t sck_state;
uint16_t recv_len;
#if 1
// 20231019 taylor
uint8_t addr_len;
#endif
/* Receive Packet Process */
ret = getsockopt(socket, SO_STATUS, &sck_state);
if (ret != SOCK_OK) {
//DBG_PRINT(ERROR_DBG, "[%s] getsockopt SO_STATUS error\r\n", __func__);
return -1;
}
if (sck_state == SOCK_UDP) {
ret = getsockopt(socket, SO_RECVBUF, &recv_len);
if (ret != SOCK_OK) {
//DBG_PRINT(ERROR_DBG, "[%s] getsockopt SO_RECVBUF error\r\n", __func__);
return -1;
}
if (recv_len) {
#if 1
// 20231019 taylor//teddy 240122
#if ((_WIZCHIP_ == 6100) || (_WIZCHIP_ == 6300))
recv_len = recvfrom(socket, packet, len, (uint8_t *)ip, port, &addr_len);
#else
recv_len = recvfrom(socket, packet, len, (uint8_t *)ip, port);
#endif
#else
recv_len = recvfrom(socket, packet, len, (uint8_t *)ip, port);
#endif
if (recv_len < 0) {
//DBG_PRINT(ERROR_DBG, "[%s] recvfrom error\r\n", __func__);
return -1;
}
*ip = ntohl(*ip);
return recv_len;
}
}
return -1;
}
static void close_tftp_socket(int socket) {
close(socket);
}
static void init_tftp(void) {
g_filename[0] = 0;
set_server_ip(0);
set_server_port(0);
set_local_port(0);
set_tftp_state(STATE_NONE);
set_block_number(0);
/* timeout flag */
g_resend_flag = 0;
tftp_retry_cnt = tftp_time_cnt = 0;
g_progress_state = TFTP_PROGRESS;
}
static void tftp_cancel_timeout(void) {
if (g_resend_flag) {
g_resend_flag = 0;
tftp_retry_cnt = tftp_time_cnt = 0;
}
}
static void tftp_reg_timeout() {
if (g_resend_flag == 0) {
g_resend_flag = 1;
tftp_retry_cnt = tftp_time_cnt = 0;
}
}
static void process_tftp_option(uint8_t *msg, uint32_t msg_len) {
/* TODO Option Process */
}
static void send_tftp_rrq(uint8_t *filename, uint8_t *mode, TFTP_OPTION *opt, uint8_t opt_len) {
uint8_t snd_buf[MAX_MTU_SIZE];
uint8_t *pkt = snd_buf;
uint32_t i, len;
*((uint16_t *)pkt) = htons(TFTP_RRQ);
pkt += 2;
strcpy((char *)pkt, (const char *)filename);
pkt += strlen((char *)filename) + 1;
strcpy((char *)pkt, (const char *)mode);
pkt += strlen((char *)mode) + 1;
for (i = 0 ; i < opt_len ; i++) {
strcpy((char *)pkt, (const char *)opt[i].code);
pkt += strlen((char *)opt[i].code) + 1;
strcpy((char *)pkt, (const char *)opt[i].value);
pkt += strlen((char *)opt[i].value) + 1;
}
len = pkt - snd_buf;
send_udp_packet(g_tftp_socket, snd_buf, len, get_server_ip(), TFTP_SERVER_PORT);
set_tftp_state(STATE_RRQ);
set_filename(filename, strlen((char *)filename) + 1);
tftp_reg_timeout();
#ifdef __TFTP_DEBUG__
DBG_PRINT(IPC_DBG, ">> TFTP RRQ : FileName(%s), Mode(%s)\r\n", filename, mode);
#endif
}
#if 0 // 2014.07.01 sskim
static void send_tftp_wrq(uint8_t *filename, uint8_t *mode, TFTP_OPTION *opt, uint8_t opt_len) {
uint8_t snd_buf[MAX_MTU_SIZE];
uint8_t *pkt = snd_buf;
uint32_t i, len;
*((uint16_t *)pkt) = htons((uint16_t)TFTP_WRQ);
pkt += 2;
strcpy((char *)pkt, (const char *)filename);
pkt += strlen((char *)filename) + 1;
strcpy((char *)pkt, (const char *)mode);
pkt += strlen((char *)mode) + 1;
for (i = 0 ; i < opt_len ; i++) {
strcpy((char *)pkt, (const char *)opt[i].code);
pkt += strlen((char *)opt[i].code) + 1;
strcpy((char *)pkt, (const char *)opt[i].value);
pkt += strlen((char *)opt[i].value) + 1;
}
len = pkt - snd_buf;
send_udp_packet(g_tftp_socket, snd_buf, len, get_server_ip(), TFTP_SERVER_PORT);
set_tftp_state(STATE_WRQ);
set_filename(filename, strlen((char *)filename) + 1);
tftp_reg_timeout();
#ifdef __TFTP_DEBUG__
DBG_PRINT(IPC_DBG, ">> TFTP WRQ : FileName(%s), Mode(%s)\r\n", filename, mode);
#endif
}
#endif
#if 0 // 2014.07.01 sskim
static void send_tftp_data(uint16_t block_number, uint8_t *data, uint16_t data_len) {
uint8_t snd_buf[MAX_MTU_SIZE];
uint8_t *pkt = snd_buf;
uint32_t len;
*((uint16_t *)pkt) = htons((uint16_t)TFTP_DATA);
pkt += 2;
*((uint16_t *)pkt) = htons(block_number);
pkt += 2;
memcpy(pkt, data, data_len);
pkt += data_len;
len = pkt - snd_buf;
send_udp_packet(g_tftp_socket, snd_buf, len, get_server_ip(), get_server_port());
tftp_reg_timeout();
#ifdef __TFTP_DEBUG__
DBG_PRINT(IPC_DBG, ">> TFTP DATA : Block Number(%d), Data Length(%d)\r\n", block_number, data_len);
#endif
}
#endif
static void send_tftp_ack(uint16_t block_number) {
uint8_t snd_buf[4];
uint8_t *pkt = snd_buf;
*((uint16_t *)pkt) = htons((uint16_t)TFTP_ACK);
pkt += 2;
*((uint16_t *)pkt) = htons(block_number);
pkt += 2;
send_udp_packet(g_tftp_socket, snd_buf, 4, get_server_ip(), get_server_port());
tftp_reg_timeout();
#ifdef __TFTP_DEBUG__
DBG_PRINT(IPC_DBG, ">> TFTP ACK : Block Number(%d)\r\n", block_number);
#endif
}
#if 0 // 2014.07.01 sskim
static void send_tftp_oack(TFTP_OPTION *opt, uint8_t opt_len) {
uint8_t snd_buf[MAX_MTU_SIZE];
uint8_t *pkt = snd_buf;
uint32_t i, len;
*((uint16_t *)pkt) = htons((uint16_t)TFTP_OACK);
pkt += 2;
for (i = 0 ; i < opt_len ; i++) {
strcpy((char *)pkt, (const char *)opt[i].code);
pkt += strlen((char *)opt[i].code) + 1;
strcpy((char *)pkt, (const char *)opt[i].value);
pkt += strlen((char *)opt[i].value) + 1;
}
len = pkt - snd_buf;
send_udp_packet(g_tftp_socket, snd_buf, len, get_server_ip(), get_server_port());
tftp_reg_timeout();
#ifdef __TFTP_DEBUG__
DBG_PRINT(IPC_DBG, ">> TFTP OACK \r\n");
#endif
}
#endif
#if 0 // 2014.07.01 sskim
static void send_tftp_error(uint16_t error_number, uint8_t *error_message) {
uint8_t snd_buf[MAX_MTU_SIZE];
uint8_t *pkt = snd_buf;
uint32_t len;
*((uint16_t *)pkt) = htons((uint16_t)TFTP_ERROR);
pkt += 2;
*((uint16_t *)pkt) = htons(error_number);
pkt += 2;
strcpy((char *)pkt, (const char *)error_message);
pkt += strlen((char *)error_message) + 1;
len = pkt - snd_buf;
send_udp_packet(g_tftp_socket, snd_buf, len, get_server_ip(), get_server_port());
tftp_reg_timeout();
#ifdef __TFTP_DEBUG__
DBG_PRINT(IPC_DBG, ">> TFTP ERROR : Error Number(%d)\r\n", error_number);
#endif
}
#endif
static void recv_tftp_rrq(uint8_t *msg, uint32_t msg_len) {
/* When TFTP Server Mode */
}
static void recv_tftp_wrq(uint8_t *msg, uint32_t msg_len) {
/* When TFTP Server Mode */
}
static void recv_tftp_data(uint8_t *msg, uint32_t msg_len) {
TFTP_DATA_T *data = (TFTP_DATA_T *)msg;
data->opcode = ntohs(data->opcode);
data->block_num = ntohs(data->block_num);
#ifdef __TFTP_DEBUG__
DBG_PRINT(IPC_DBG, "<< TFTP_DATA : opcode(%d), block_num(%d)\r\n", data->opcode, data->block_num);
#endif
switch (get_tftp_state()) {
case STATE_RRQ :
case STATE_OACK :
if (data->block_num == 1) {
set_tftp_state(STATE_DATA);
set_block_number(data->block_num);
#ifdef F_STORAGE
save_data(data->data, msg_len - 4, data->block_num);
#endif
tftp_cancel_timeout();
}
send_tftp_ack(data->block_num);
if ((msg_len - 4) < TFTP_BLK_SIZE) {
init_tftp();
g_progress_state = TFTP_SUCCESS;
}
break;
case STATE_DATA :
if (data->block_num == (get_block_number() + 1)) {
set_block_number(data->block_num);
#ifdef F_STORAGE
save_data(data->data, msg_len - 4, data->block_num);
#endif
tftp_cancel_timeout();
}
send_tftp_ack(data->block_num);
if ((msg_len - 4) < TFTP_BLK_SIZE) {
init_tftp();
g_progress_state = TFTP_SUCCESS;
}
break;
default :
/* invalid message */
break;
}
}
static void recv_tftp_ack(uint8_t *msg, uint32_t msg_len) {
#ifdef __TFTP_DEBUG__
DBG_PRINT(IPC_DBG, "<< TFTP_ACK : \r\n");
#endif
switch (get_tftp_state()) {
case STATE_WRQ :
break;
case STATE_ACK :
break;
default :
/* invalid message */
break;
}
}
static void recv_tftp_oack(uint8_t *msg, uint32_t msg_len) {
#ifdef __TFTP_DEBUG__
DBG_PRINT(IPC_DBG, "<< TFTP_OACK : \r\n");
#endif
switch (get_tftp_state()) {
case STATE_RRQ :
process_tftp_option(msg, msg_len);
set_tftp_state(STATE_OACK);
tftp_cancel_timeout();
send_tftp_ack(0);
break;
case STATE_WRQ :
process_tftp_option(msg, msg_len);
set_tftp_state(STATE_ACK);
tftp_cancel_timeout();
/* TODO DATA Transfer */
//send_tftp_data(...);
break;
default :
/* invalid message */
break;
}
}
static void recv_tftp_error(uint8_t *msg, uint32_t msg_len) {
TFTP_ERROR_T *data = (TFTP_ERROR_T *)msg;
data->opcode = ntohs(data->opcode);
data->error_code = ntohs(data->error_code);
#ifdef __TFTP_DEBUG__
DBG_PRINT(IPC_DBG, "<< TFTP_ERROR : %d (%s)\r\n", data->error_code, data->error_msg);
DBG_PRINT(ERROR_DBG, "[%s] Error Code : %d (%s)\r\n", __func__, data->error_code, data->error_msg);
#endif
init_tftp();
g_progress_state = TFTP_FAIL;
}
static void recv_tftp_packet(uint8_t *packet, uint32_t packet_len, uint32_t from_ip, uint16_t from_port) {
uint16_t opcode;
/* Verify Server IP */
if (from_ip != get_server_ip()) {
#ifdef __TFTP_DEBUG__
DBG_PRINT(ERROR_DBG, "[%s] Server IP faults\r\n", __func__);
DBG_PRINT(ERROR_DBG, "from IP : %08x, Server IP : %08x\r\n", from_ip, get_server_ip());
#endif
return;
}
opcode = ntohs(*((uint16_t *)packet));
/* Set Server Port */
if ((get_tftp_state() == STATE_WRQ) || (get_tftp_state() == STATE_RRQ)) {
set_server_port(from_port);
#ifdef __TFTP_DEBUG__
DBG_PRINT(INFO_DBG, "[%s] Set Server Port : %d\r\n", __func__, from_port);
#endif
}
switch (opcode) {
case TFTP_RRQ : /* When Server */
recv_tftp_rrq(packet, packet_len);
break;
case TFTP_WRQ : /* When Server */
recv_tftp_wrq(packet, packet_len);
break;
case TFTP_DATA :
recv_tftp_data(packet, packet_len);
break;
case TFTP_ACK :
recv_tftp_ack(packet, packet_len);
break;
case TFTP_OACK :
recv_tftp_oack(packet, packet_len);
break;
case TFTP_ERROR :
recv_tftp_error(packet, packet_len);
break;
default :
// Unknown Mesage
break;
}
}
/* Functions ----------------------------------------------------*/
void TFTP_init(uint8_t socket, uint8_t *buf) {
init_tftp();
g_tftp_socket = open_tftp_socket(socket);
g_tftp_rcv_buf = buf;
}
void TFTP_exit(void) {
init_tftp();
close_tftp_socket(g_tftp_socket);
g_tftp_socket = -1;
g_tftp_rcv_buf = NULL;
}
int TFTP_run(void) {
uint16_t len, from_port;
uint32_t from_ip;
/* Timeout Process */
if (g_resend_flag) {
if (tftp_time_cnt >= g_timeout) {
switch (get_tftp_state()) {
case STATE_WRQ: // 미구현
break;
case STATE_RRQ:
send_tftp_rrq(g_filename, (uint8_t *)TRANS_BINARY, &default_tftp_opt, 1);
break;
case STATE_OACK:
case STATE_DATA:
send_tftp_ack(get_block_number());
break;
case STATE_ACK: // 미구현
break;
default:
break;
}
tftp_time_cnt = 0;
tftp_retry_cnt++;
if (tftp_retry_cnt >= 5) {
init_tftp();
g_progress_state = TFTP_FAIL;
}
}
}
/* Receive Packet Process */
len = recv_udp_packet(g_tftp_socket, g_tftp_rcv_buf, MAX_MTU_SIZE, &from_ip, &from_port);
if (len < 0) {
#ifdef __TFTP_DEBUG__
DBG_PRINT(ERROR_DBG, "[%s] recv_udp_packet error\r\n", __func__);
#endif
return g_progress_state;
}
recv_tftp_packet(g_tftp_rcv_buf, len, from_ip, from_port);
return g_progress_state;
}
void TFTP_read_request(uint32_t server_ip, uint8_t *filename) {
set_server_ip(server_ip);
#ifdef __TFTP_DEBUG__
DBG_PRINT(INFO_DBG, "[%s] Set Tftp Server : %x\r\n", __func__, server_ip);
#endif
g_progress_state = TFTP_PROGRESS;
send_tftp_rrq(filename, (uint8_t *)TRANS_BINARY, &default_tftp_opt, 1);
}
void tftp_timeout_handler(void) {
if (g_resend_flag) {
tftp_time_cnt++;
}
}

102
Internet/TFTP/tftp.h Normal file
View File

@@ -0,0 +1,102 @@
/**
@file tftp.h
@brief TFTP Header File.
@version 0.1.0
@author Sang-sik Kim
*/
#ifndef __TFTP_H__
#define __TFTP_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdint.h>
#define F_APP_TFTP
#define __TFTP_DEBUG__
// #define F_STORAGE // If your target support a storage, you have to activate this feature and implement.
#define SOCK_TFTP 1
#define INFO_DBG 0x01
#define ERROR_DBG 0x02
#define DEBUG_DBG 0x04
#define IPC_DBG 0x08
#define DBG_PRINT(level, format, args...) { \
if(dbg_level & level) \
printf(format, ##args); \
}
#define NORMAL_MODE 0
#define TFTP_MODE 1
extern int dbg_level;
/* tftp message */
#define TFTP_RRQ 1
#define TFTP_WRQ 2
#define TFTP_DATA 3
#define TFTP_ACK 4
#define TFTP_ERROR 5
#define TFTP_OACK 6
/* tftp state */
#define STATE_NONE 0
#define STATE_RRQ 1
#define STATE_WRQ 2
#define STATE_DATA 3
#define STATE_ACK 4
#define STATE_OACK 5
/* tftp transfer mode */
#define TRANS_ASCII "netascii"
#define TRANS_BINARY "octet"
/* tftp progress state */
#define TFTP_PROGRESS 0
#define TFTP_FAIL 1
#define TFTP_SUCCESS 2
/* define */
#define TFTP_SERVER_PORT 69
#define TFTP_TEMP_PORT 51000
#define TFTP_BLK_SIZE 512
#define MAX_MTU_SIZE 1514
#define FILE_NAME_SIZE 20
//#define __TFTP_DEBUG__
/* typedef */
typedef struct tftp_data {
uint16_t opcode;
uint16_t block_num;
uint8_t data[0];
} TFTP_DATA_T;
typedef struct tftp_error {
uint16_t opcode;
uint16_t error_code;
uint8_t error_msg[0];
} TFTP_ERROR_T;
typedef struct tftp_option {
uint8_t *code;
uint8_t *value;
} TFTP_OPTION;
/* Functions */
void TFTP_init(uint8_t socket, uint8_t *buf);
void TFTP_exit(void);
int TFTP_run(void);
void TFTP_read_request(uint32_t server_ip, uint8_t *filename);
void tftp_timeout_handler(void);
#ifdef __cplusplus
}
#endif
#endif /*__TFTP_H__ */

View File

@@ -0,0 +1,430 @@
/**
@file httpd.c
@brief functions associated http processing
*/
#include <stdio.h>
#include <string.h>
#include "socket.h"
#include "httpParser.h"
/*****************************************************************************
Public types/enumerations/variables
****************************************************************************/
//uint8_t BUFPUB[2048];
uint8_t BUFPUB[256];
/*****************************************************************************
Private functions
****************************************************************************/
static void replacetochar(uint8_t * str, uint8_t oldchar, uint8_t newchar); /* Replace old character with new character in the string */
static uint8_t C2D(uint8_t c); /* Convert a character to HEX */
/**
@brief convert escape characters(%XX) to ASCII character
*/
void unescape_http_url(
char * url /**< pointer to be converted ( escape characters )*/
) {
int x, y;
for (x = 0, y = 0; url[y]; ++x, ++y) {
if ((url[x] = url[y]) == '%') {
url[x] = C2D(url[y + 1]) * 0x10+C2D(url[y + 2]);
y += 2;
}
}
url[x] = '\0';
}
/**
@brief make response header such as html, gif, jpeg,etc.
*/
void make_http_response_head(
char * buf, /**< pointer to response header to be made */
char type, /**< response type */
uint32_t len /**< size of response header */
) {
char * head;
char tmp[10];
/* file type*/
if (type == PTYPE_HTML) {
head = RES_HTMLHEAD_OK;
} else if (type == PTYPE_GIF) {
head = RES_GIFHEAD_OK;
} else if (type == PTYPE_TEXT) {
head = RES_TEXTHEAD_OK;
} else if (type == PTYPE_JPEG) {
head = RES_JPEGHEAD_OK;
} else if (type == PTYPE_FLASH) {
head = RES_FLASHHEAD_OK;
} else if (type == PTYPE_XML) {
head = RES_XMLHEAD_OK;
} else if (type == PTYPE_CSS) {
head = RES_CSSHEAD_OK;
} else if (type == PTYPE_JSON) {
head = RES_JSONHEAD_OK;
} else if (type == PTYPE_JS) {
head = RES_JSHEAD_OK;
} else if (type == PTYPE_CGI) {
head = RES_CGIHEAD_OK;
} else if (type == PTYPE_PNG) {
head = RES_PNGHEAD_OK;
} else if (type == PTYPE_ICO) {
head = RES_ICOHEAD_OK;
} else if (type == PTYPE_TTF) {
head = RES_TTFHEAD_OK;
} else if (type == PTYPE_OTF) {
head = RES_OTFHEAD_OK;
} else if (type == PTYPE_WOFF) {
head = RES_WOFFHEAD_OK;
} else if (type == PTYPE_EOT) {
head = RES_EOTHEAD_OK;
} else if (type == PTYPE_SVG) {
head = RES_SVGHEAD_OK;
}
#ifdef _HTTPPARSER_DEBUG_
else {
head = NULL;
printf("\r\n\r\n-MAKE HEAD UNKNOWN-\r\n");
}
#else
else {
head = NULL;
}
#endif
sprintf(tmp, "%ld", len);
strcpy(buf, head);
strcat(buf, tmp);
strcat(buf, "\r\n\r\n");
}
/**
@brief find MIME type of a file
*/
void find_http_uri_type(
uint8_t * type, /**< type to be returned */
uint8_t * buff /**< file name */
) {
/* Decide type according to extension*/
char * buf;
buf = (char *)buff;
if (strstr(buf, ".htm") || strstr(buf, ".html")) {
*type = PTYPE_HTML;
} else if (strstr(buf, ".gif")) {
*type = PTYPE_GIF;
} else if (strstr(buf, ".text") || strstr(buf, ".txt")) {
*type = PTYPE_TEXT;
} else if (strstr(buf, ".jpeg") || strstr(buf, ".jpg")) {
*type = PTYPE_JPEG;
} else if (strstr(buf, ".swf")) {
*type = PTYPE_FLASH;
} else if (strstr(buf, ".cgi") || strstr(buf, ".CGI")) {
*type = PTYPE_CGI;
} else if (strstr(buf, ".json") || strstr(buf, ".JSON")) {
*type = PTYPE_JSON;
} else if (strstr(buf, ".js") || strstr(buf, ".JS")) {
*type = PTYPE_JS;
} else if (strstr(buf, ".CGI") || strstr(buf, ".cgi")) {
*type = PTYPE_CGI;
} else if (strstr(buf, ".xml") || strstr(buf, ".XML")) {
*type = PTYPE_XML;
} else if (strstr(buf, ".css") || strstr(buf, ".CSS")) {
*type = PTYPE_CSS;
} else if (strstr(buf, ".png") || strstr(buf, ".PNG")) {
*type = PTYPE_PNG;
} else if (strstr(buf, ".ico") || strstr(buf, ".ICO")) {
*type = PTYPE_ICO;
} else if (strstr(buf, ".ttf") || strstr(buf, ".TTF")) {
*type = PTYPE_TTF;
} else if (strstr(buf, ".otf") || strstr(buf, ".OTF")) {
*type = PTYPE_OTF;
} else if (strstr(buf, ".woff") || strstr(buf, ".WOFF")) {
*type = PTYPE_WOFF;
} else if (strstr(buf, ".eot") || strstr(buf, ".EOT")) {
*type = PTYPE_EOT;
} else if (strstr(buf, ".svg") || strstr(buf, ".SVG")) {
*type = PTYPE_SVG;
} else {
*type = PTYPE_ERR;
}
}
/**
@brief parse http request from a peer
*/
void parse_http_request(
st_http_request * request, /**< request to be returned */
uint8_t * buf /**< pointer to be parsed */
) {
char * nexttok;
nexttok = strtok((char*)buf, " ");
if (!nexttok) {
request->METHOD = METHOD_ERR;
return;
}
if (!strcmp(nexttok, "GET") || !strcmp(nexttok, "get")) {
request->METHOD = METHOD_GET;
nexttok = strtok(NULL, " ");
} else if (!strcmp(nexttok, "HEAD") || !strcmp(nexttok, "head")) {
request->METHOD = METHOD_HEAD;
nexttok = strtok(NULL, " ");
} else if (!strcmp(nexttok, "POST") || !strcmp(nexttok, "post")) {
nexttok = strtok(NULL, "\0");
request->METHOD = METHOD_POST;
} else {
request->METHOD = METHOD_ERR;
}
if (!nexttok) {
request->METHOD = METHOD_ERR;
return;
}
strcpy((char *)request->URI, nexttok);
}
#ifdef _OLD_
/**
@brief get next parameter value in the request
*/
uint8_t * get_http_param_value(
char* uri,
char* param_name
) {
char tempURI[MAX_URI_SIZE];
uint8_t * name = 0;
if (!uri || !param_name) {
return 0;
}
strcpy((char*)tempURI, uri);
if ((name = (uint8_t *)strstr(tempURI, param_name))) {
name += strlen(param_name) + 1; // strlen(para_name) + strlen("=")
if ((name = (uint8_t *)strtok((char *)name, "& \r\n\t\0"))) {
unescape_http_url((char *)name);
replacetochar(name, '+', ' ');
}
}
#ifdef _HTTPPARSER_DEBUG_
printf(" %s=%s", param_name, name);
#endif
return name;
}
#else
/**
@brief get next parameter value in the request
*/
uint8_t * get_http_param_value(char* uri, char* param_name) {
uint8_t * name = 0;
uint8_t * ret = BUFPUB;
uint8_t * pos2;
uint16_t len = 0, content_len = 0;
uint8_t tmp_buf[10] = {0x00, };
if (!uri || !param_name) {
return 0;
}
/***************/
mid(uri, "Content-Length: ", "\r\n", (char *)tmp_buf);
content_len = ATOI(tmp_buf, 10);
uri = strstr(uri, "\r\n\r\n");
uri += 4;
uri[content_len] = 0;
/***************/
if ((name = (uint8_t *)strstr(uri, param_name))) {
name += strlen(param_name) + 1;
pos2 = (uint8_t*)strstr((char*)name, "&");
if (!pos2) {
pos2 = name + strlen((char*)name);
}
len = pos2 - name;
if (len) {
ret[len] = 0;
strncpy((char*)ret, (char*)name, len);
unescape_http_url((char *)ret);
replacetochar(ret, '+', ' ');
//ret[len] = 0;
//ret[strlen((int8*)ret)] = 0;
//printf("len=%d\r\n",len);
} else {
ret[0] = 0;
}
} else {
return 0;
}
#ifdef _HTTPPARSER_DEBUG_
printf(" %s=%s\r\n", param_name, ret);
#endif
return ret;
}
#endif
#ifdef _OLD_
uint8_t * get_http_uri_name(uint8_t * uri) {
char tempURI[MAX_URI_SIZE];
uint8_t * uri_name;
if (!uri) {
return 0;
}
strcpy(tempURI, (char *)uri);
uri_name = (uint8_t *)strtok(tempURI, " ?");
if (strcmp((char *)uri_name, "/")) {
uri_name++;
}
#ifdef _HTTPPARSER_DEBUG_
printf(" uri_name = %s\r\n", uri_name);
#endif
return uri_name;
}
#else
uint8_t get_http_uri_name(uint8_t * uri, uint8_t * uri_buf) {
uint8_t * uri_ptr;
if (!uri) {
return 0;
}
strcpy((char *)uri_buf, (char *)uri);
uri_ptr = (uint8_t *)strtok((char *)uri_buf, " ?");
if (strcmp((char *)uri_ptr, "/")) {
uri_ptr++;
}
strcpy((char *)uri_buf, (char *)uri_ptr);
#ifdef _HTTPPARSER_DEBUG_
printf(" uri_name = %s\r\n", uri_buf);
#endif
return 1;
}
#endif
void inet_addr_(uint8_t * addr, uint8_t *ip) {
uint8_t i;
uint8_t taddr[30];
uint8_t * nexttok;
uint8_t num;
strcpy((char *)taddr, (char *)addr);
nexttok = taddr;
for (i = 0; i < 4 ; i++) {
nexttok = (uint8_t *)strtok((char *)nexttok, ".");
if (nexttok[0] == '0' && nexttok[1] == 'x') {
num = ATOI(nexttok + 2, 0x10);
} else {
num = ATOI(nexttok, 10);
}
ip[i] = num;
nexttok = NULL;
}
}
/**
@brief CONVERT STRING INTO INTEGER
@return a integer number
*/
uint16_t ATOI(
uint8_t * str, /**< is a pointer to convert */
uint8_t base /**< is a base value (must be in the range 2 - 16) */
) {
unsigned int num = 0;
// debug_2013_11_25
// while (*str !=0)
while ((*str != 0) && (*str != 0x20)) { // not include the space(0x020)
num = num * base + C2D(*str++);
}
return num;
}
/**
@brief Check strings and then execute callback function by each string.
@param src The information of URI
@param s1 The start string to be researched
@param s2 The end string to be researched
@param sub The string between s1 and s2
@return The length value atfer working
*/
void mid(char* src, char* s1, char* s2, char* sub) {
char* sub1;
char* sub2;
uint16_t n;
sub1 = strstr((char*)src, (char*)s1);
sub1 += strlen((char*)s1);
sub2 = strstr((char*)sub1, (char*)s2);
n = sub2 - sub1;
strncpy((char*)sub, (char*)sub1, n);
sub[n] = '\0';
}
////////////////////////////////////////////////////////////////////
// Static functions
////////////////////////////////////////////////////////////////////
/**
@brief replace the specified character in a string with new character
*/
static void replacetochar(
uint8_t * str, /**< pointer to be replaced */
uint8_t oldchar, /**< old character */
uint8_t newchar /**< new character */
) {
int x;
for (x = 0; str[x]; x++)
if (str[x] == oldchar) {
str[x] = newchar;
}
}
/**
@brief CONVERT CHAR INTO HEX
@return HEX
This function converts HEX(0-F) to a character
*/
static uint8_t C2D(
uint8_t c /**< is a character('0'-'F') to convert to HEX */
) {
if (c >= '0' && c <= '9') {
return c - '0';
}
if (c >= 'a' && c <= 'f') {
return 10 + c - 'a';
}
if (c >= 'A' && c <= 'F') {
return 10 + c - 'A';
}
return (char)c;
}

View File

@@ -0,0 +1,157 @@
/**
@file httpd.h
@brief Define Constants and fucntions associated with HTTP protocol.
*/
#include <stdint.h>
#ifndef __HTTPPARSER_H__
#define __HTTPPARSER_H__
#ifdef __cplusplus
extern "C" {
#endif
//#define _HTTPPARSER_DEBUG_
#define HTTP_SERVER_PORT 80 /**< HTTP server well-known port number */
/* HTTP Method */
#define METHOD_ERR 0 /**< Error Method. */
#define METHOD_GET 1 /**< GET Method. */
#define METHOD_HEAD 2 /**< HEAD Method. */
#define METHOD_POST 3 /**< POST Method. */
/* HTTP GET Method */
#define PTYPE_ERR 0 /**< Error file. */
#define PTYPE_HTML 1 /**< HTML file. */
#define PTYPE_GIF 2 /**< GIF file. */
#define PTYPE_TEXT 3 /**< TEXT file. */
#define PTYPE_JPEG 4 /**< JPEG file. */
#define PTYPE_FLASH 5 /**< FLASH file. */
#define PTYPE_MPEG 6 /**< MPEG file. */
#define PTYPE_PDF 7 /**< PDF file. */
#define PTYPE_CGI 8 /**< CGI file. */
#define PTYPE_XML 9 /**< XML file. */
#define PTYPE_CSS 10 /**< CSS file. */
#define PTYPE_JS 11 /**< JavaScript file. */
#define PTYPE_JSON 12 /**< JSON (JavaScript Standard Object Notation) file. */
#define PTYPE_PNG 13 /**< PNG file. */
#define PTYPE_ICO 14 /**< ICON file. */
#define PTYPE_TTF 20 /**< Font type: TTF file. */
#define PTYPE_OTF 21 /**< Font type: OTF file. */
#define PTYPE_WOFF 22 /**< Font type: WOFF file. */
#define PTYPE_EOT 23 /**< Font type: EOT file. */
#define PTYPE_SVG 24 /**< Font type: SVG file. */
/* HTTP response */
#define STATUS_OK 200
#define STATUS_CREATED 201
#define STATUS_ACCEPTED 202
#define STATUS_NO_CONTENT 204
#define STATUS_MV_PERM 301
#define STATUS_MV_TEMP 302
#define STATUS_NOT_MODIF 304
#define STATUS_BAD_REQ 400
#define STATUS_UNAUTH 401
#define STATUS_FORBIDDEN 403
#define STATUS_NOT_FOUND 404
#define STATUS_INT_SERR 500
#define STATUS_NOT_IMPL 501
#define STATUS_BAD_GATEWAY 502
#define STATUS_SERV_UNAVAIL 503
/* HTML Doc. for ERROR */
static const char ERROR_HTML_PAGE[] = "HTTP/1.1 404 Not Found\r\nContent-Type: text/html\r\nContent-Length: 78\r\n\r\n<HTML>\r\n<BODY>\r\nSorry, the page you requested was not found.\r\n</BODY>\r\n</HTML>\r\n\0";
static const char ERROR_REQUEST_PAGE[] = "HTTP/1.1 400 OK\r\nContent-Type: text/html\r\nContent-Length: 50\r\n\r\n<HTML>\r\n<BODY>\r\nInvalid request.\r\n</BODY>\r\n</HTML>\r\n\0";
/* HTML Doc. for CGI result */
#define HTML_HEADER "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: "
/* Response header for HTML*/
#define RES_HTMLHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: keep-alive\r\nContent-Length: "
/* Response head for TEXT */
#define RES_TEXTHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: "
/* Response head for GIF */
#define RES_GIFHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: image/gif\r\nContent-Length: "
/* Response head for JPEG */
#define RES_JPEGHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: image/jpeg\r\nContent-Length: "
/* Response head for PNG */
#define RES_PNGHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: image/png\r\nContent-Length: "
/* Response head for FLASH */
#define RES_FLASHHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: application/x-shockwave-flash\r\nContent-Length: "
/* Response head for XML */
#define RES_XMLHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: text/xml\r\nConnection: keep-alive\r\nContent-Length: "
/* Response head for CSS */
#define RES_CSSHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: text/css\r\nContent-Length: "
/* Response head for JavaScript */
#define RES_JSHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: application/javascript\r\nContent-Length: "
/* Response head for JSON */
#define RES_JSONHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: "
/* Response head for ICO */
#define RES_ICOHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: image/x-icon\r\nContent-Length: "
/* Response head for CGI */
#define RES_CGIHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: "
/* Response head for TTF, Font */
#define RES_TTFHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: application/x-font-truetype\r\nContent-Length: "
/* Response head for OTF, Font */
#define RES_OTFHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: application/x-font-opentype\r\nContent-Length: "
/* Response head for WOFF, Font */
#define RES_WOFFHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: application/font-woff\r\nContent-Length: "
/* Response head for EOT, Font */
#define RES_EOTHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.ms-fontobject\r\nContent-Length: "
/* Response head for SVG, Font */
#define RES_SVGHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: image/svg+xml\r\nContent-Length: "
/**
@brief Structure of HTTP REQUEST
*/
//#define MAX_URI_SIZE 1461
#define MAX_URI_SIZE 512
typedef struct _st_http_request {
uint8_t METHOD; /**< request method(METHOD_GET...). */
uint8_t TYPE; /**< request type(PTYPE_HTML...). */
uint8_t URI[MAX_URI_SIZE]; /**< request file name. */
} st_http_request;
// HTTP Parsing functions
void unescape_http_url(char * url); /* convert escape character to ascii */
void parse_http_request(st_http_request *, uint8_t *); /* parse request from peer */
void find_http_uri_type(uint8_t *, uint8_t *); /* find MIME type of a file */
void make_http_response_head(char *, char, uint32_t); /* make response header */
uint8_t * get_http_param_value(char* uri, char* param_name); /* get the user-specific parameter value */
uint8_t get_http_uri_name(uint8_t * uri, uint8_t * uri_buf); /* get the requested URI name */
#ifdef _OLD_
uint8_t * get_http_uri_name(uint8_t * uri);
#endif
// Utility functions
uint16_t ATOI(uint8_t * str, uint8_t base);
void mid(char* src, char* s1, char* s2, char* sub);
void inet_addr_(uint8_t * addr, uint8_t * ip);
#ifdef __cplusplus
}
#endif
#endif /* end of __HTTPPARSER_H__ */

View File

@@ -0,0 +1,707 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "socket.h"
#include "wizchip_conf.h"
#include "httpServer.h"
#include "httpParser.h"
#include "httpUtil.h"
#ifdef _USE_SDCARD_
#include "ff.h" // header file for FatFs library (FAT file system)
#endif
#ifndef DATA_BUF_SIZE
#define DATA_BUF_SIZE 2048
#endif
/*****************************************************************************
Private types/enumerations/variables
****************************************************************************/
static uint8_t HTTPSock_Num[_WIZCHIP_SOCK_NUM_] = {0, };
static st_http_request * http_request; /**< Pointer to received HTTP request */
static st_http_request * parsed_http_request; /**< Pointer to parsed HTTP request */
static uint8_t * http_response; /**< Pointer to HTTP response */
// ## For Debugging
//static uint8_t uri_buf[128];
// Number of registered web content in code flash memory
static uint16_t total_content_cnt = 0;
/*****************************************************************************
Public types/enumerations/variables
****************************************************************************/
uint8_t * pHTTP_TX;
uint8_t * pHTTP_RX;
volatile uint32_t httpServer_tick_1s = 0;
st_http_socket HTTPSock_Status[_WIZCHIP_SOCK_NUM_] = { {STATE_HTTP_IDLE, }, };
httpServer_webContent web_content[MAX_CONTENT_CALLBACK];
#ifdef _USE_SDCARD_
FIL fs; // FatFs: File object
FRESULT fr; // FatFs: File function return code
#endif
/*****************************************************************************
Private functions
****************************************************************************/
void httpServer_Sockinit(uint8_t cnt, uint8_t * socklist);
static uint8_t getHTTPSocketNum(uint8_t seqnum);
static int8_t getHTTPSequenceNum(uint8_t socket);
static int8_t http_disconnect(uint8_t sn);
static void http_process_handler(uint8_t s, st_http_request * p_http_request);
static void send_http_response_header(uint8_t s, uint8_t content_type, uint32_t body_len, uint16_t http_status);
static void send_http_response_body(uint8_t s, uint8_t * uri_name, uint8_t * buf, uint32_t start_addr, uint32_t file_len);
static void send_http_response_cgi(uint8_t s, uint8_t * buf, uint8_t * http_body, uint16_t file_len);
/*****************************************************************************
Public functions
****************************************************************************/
// Callback functions definition: MCU Reset / WDT Reset
void default_mcu_reset(void) {;}
void default_wdt_reset(void) {;}
void (*HTTPServer_ReStart)(void) = default_mcu_reset;
void (*HTTPServer_WDT_Reset)(void) = default_wdt_reset;
void httpServer_Sockinit(uint8_t cnt, uint8_t * socklist) {
uint8_t i;
for (i = 0; i < cnt; i++) {
// Mapping the H/W socket numbers to the sequential index numbers
HTTPSock_Num[i] = socklist[i];
}
}
static uint8_t getHTTPSocketNum(uint8_t seqnum) {
// Return the 'H/W socket number' corresponding to the index number
return HTTPSock_Num[seqnum];
}
static int8_t getHTTPSequenceNum(uint8_t socket) {
uint8_t i;
for (i = 0; i < _WIZCHIP_SOCK_NUM_; i++)
if (HTTPSock_Num[i] == socket) {
return i;
}
return -1;
}
void httpServer_init(uint8_t * tx_buf, uint8_t * rx_buf, uint8_t cnt, uint8_t * socklist) {
// User's shared buffer
pHTTP_TX = tx_buf;
pHTTP_RX = rx_buf;
// H/W Socket number mapping
httpServer_Sockinit(cnt, socklist);
}
/* Register the call back functions for HTTP Server */
void reg_httpServer_cbfunc(void(*mcu_reset)(void), void(*wdt_reset)(void)) {
// Callback: HW Reset and WDT reset function for each MCU platforms
if (mcu_reset) {
HTTPServer_ReStart = mcu_reset;
}
if (wdt_reset) {
HTTPServer_WDT_Reset = wdt_reset;
}
}
void httpServer_run(uint8_t seqnum) {
uint8_t s; // socket number
uint16_t len;
uint32_t gettime = 0;
#ifdef _HTTPSERVER_DEBUG_
uint8_t destip[4] = {0, };
uint16_t destport = 0;
#endif
http_request = (st_http_request *)pHTTP_RX; // Structure of HTTP Request
parsed_http_request = (st_http_request *)pHTTP_TX;
// Get the H/W socket number
s = getHTTPSocketNum(seqnum);
/* HTTP Service Start */
switch (getSn_SR(s)) {
case SOCK_ESTABLISHED:
// Interrupt clear
if (getSn_IR(s) & Sn_IR_CON) {
setSn_IR(s, Sn_IR_CON);
}
// HTTP Process states
switch (HTTPSock_Status[seqnum].sock_status) {
case STATE_HTTP_IDLE :
if ((len = getSn_RX_RSR(s)) > 0) {
if (len > DATA_BUF_SIZE) {
len = DATA_BUF_SIZE;
}
len = recv(s, (uint8_t *)http_request, len);
*(((uint8_t *)http_request) + len) = '\0';
parse_http_request(parsed_http_request, (uint8_t *)http_request);
#ifdef _HTTPSERVER_DEBUG_
getSn_DIPR(s, destip);
destport = getSn_DPORT(s);
printf("\r\n");
printf("> HTTPSocket[%d] : HTTP Request received ", s);
printf("from %d.%d.%d.%d : %d\r\n", destip[0], destip[1], destip[2], destip[3], destport);
#endif
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : [State] STATE_HTTP_REQ_DONE\r\n", s);
#endif
// HTTP 'response' handler; includes send_http_response_header / body function
http_process_handler(s, parsed_http_request);
gettime = get_httpServer_timecount();
// Check the TX socket buffer for End of HTTP response sends
while (getSn_TX_FSR(s) != (getSn_TxMAX(s))) {
if ((get_httpServer_timecount() - gettime) > 3) {
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : [State] STATE_HTTP_REQ_DONE: TX Buffer clear timeout\r\n", s);
#endif
break;
}
}
if (HTTPSock_Status[seqnum].file_len > 0) {
HTTPSock_Status[seqnum].sock_status = STATE_HTTP_RES_INPROC;
} else {
HTTPSock_Status[seqnum].sock_status = STATE_HTTP_RES_DONE; // Send the 'HTTP response' end
}
}
break;
case STATE_HTTP_RES_INPROC :
/* Repeat: Send the remain parts of HTTP responses */
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : [State] STATE_HTTP_RES_INPROC\r\n", s);
#endif
// Repeatedly send remaining data to client
send_http_response_body(s, 0, http_response, 0, 0);
if (HTTPSock_Status[seqnum].file_len == 0) {
HTTPSock_Status[seqnum].sock_status = STATE_HTTP_RES_DONE;
}
break;
case STATE_HTTP_RES_DONE :
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : [State] STATE_HTTP_RES_DONE\r\n", s);
#endif
// Socket file info structure re-initialize
HTTPSock_Status[seqnum].file_len = 0;
HTTPSock_Status[seqnum].file_offset = 0;
HTTPSock_Status[seqnum].file_start = 0;
HTTPSock_Status[seqnum].sock_status = STATE_HTTP_IDLE;
//#ifdef _USE_SDCARD_
// f_close(&fs);
//#endif
#ifdef _USE_WATCHDOG_
HTTPServer_WDT_Reset();
#endif
http_disconnect(s);
break;
default :
break;
}
break;
case SOCK_CLOSE_WAIT:
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : ClOSE_WAIT\r\n", s); // if a peer requests to close the current connection
#endif
disconnect(s);
break;
case SOCK_CLOSED:
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : CLOSED\r\n", s);
#endif
if (socket(s, Sn_MR_TCP, HTTP_SERVER_PORT, 0x00) == s) { /* Reinitialize the socket */
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : OPEN\r\n", s);
#endif
}
break;
case SOCK_INIT:
listen(s);
break;
case SOCK_LISTEN:
break;
default :
break;
} // end of switch
#ifdef _USE_WATCHDOG_
HTTPServer_WDT_Reset();
#endif
}
////////////////////////////////////////////
// Private Functions
////////////////////////////////////////////
static void send_http_response_header(uint8_t s, uint8_t content_type, uint32_t body_len, uint16_t http_status) {
switch (http_status) {
case STATUS_OK: // HTTP/1.1 200 OK
if ((content_type != PTYPE_CGI) && (content_type != PTYPE_XML)) { // CGI/XML type request does not respond HTTP header
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : HTTP Response Header - STATUS_OK\r\n", s);
#endif
make_http_response_head((char*)http_response, content_type, body_len);
} else {
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : HTTP Response Header - NONE / CGI or XML\r\n", s);
#endif
// CGI/XML type request does not respond HTTP header to client
http_status = 0;
}
break;
case STATUS_BAD_REQ: // HTTP/1.1 400 OK
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : HTTP Response Header - STATUS_BAD_REQ\r\n", s);
#endif
memcpy(http_response, ERROR_REQUEST_PAGE, sizeof(ERROR_REQUEST_PAGE));
break;
case STATUS_NOT_FOUND: // HTTP/1.1 404 Not Found
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : HTTP Response Header - STATUS_NOT_FOUND\r\n", s);
#endif
memcpy(http_response, ERROR_HTML_PAGE, sizeof(ERROR_HTML_PAGE));
break;
default:
break;
}
// Send the HTTP Response 'header'
if (http_status) {
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : [Send] HTTP Response Header [ %d ]byte\r\n", s, (uint16_t)strlen((char *)http_response));
#endif
send(s, http_response, strlen((char *)http_response));
}
}
static void send_http_response_body(uint8_t s, uint8_t * uri_name, uint8_t * buf, uint32_t start_addr, uint32_t file_len) {
int8_t get_seqnum;
uint32_t send_len;
uint8_t flag_datasend_end = 0;
#ifdef _USE_SDCARD_
uint16_t blocklen;
#endif
#ifdef _USE_FLASH_
uint32_t addr = 0;
#endif
if ((get_seqnum = getHTTPSequenceNum(s)) == -1) {
return; // exception handling; invalid number
}
// Send the HTTP Response 'body'; requested file
if (!HTTPSock_Status[get_seqnum].file_len) { // ### Send HTTP response body: First part ###
if (file_len > DATA_BUF_SIZE - 1) {
HTTPSock_Status[get_seqnum].file_start = start_addr;
HTTPSock_Status[get_seqnum].file_len = file_len;
send_len = DATA_BUF_SIZE - 1;
/////////////////////////////////////////////////////////////////////////////////////////////////
// ## 20141219 Eric added, for 'File object structure' (fs) allocation reduced (8 -> 1)
memset(HTTPSock_Status[get_seqnum].file_name, 0x00, MAX_CONTENT_NAME_LEN);
strcpy((char *)HTTPSock_Status[get_seqnum].file_name, (char *)uri_name);
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : HTTP Response body - file name [ %s ]\r\n", s, HTTPSock_Status[get_seqnum].file_name);
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : HTTP Response body - file len [ %ld ]byte\r\n", s, file_len);
#endif
} else {
// Send process end
send_len = file_len;
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : HTTP Response end - file len [ %ld ]byte\r\n", s, send_len);
#endif
}
#ifdef _USE_FLASH_
if (HTTPSock_Status[get_seqnum]->storage_type == DATAFLASH) {
addr = start_addr;
}
#endif
} else { // remained parts
#ifdef _USE_FLASH_
if (HTTPSock_Status[get_seqnum]->storage_type == DATAFLASH) {
addr = HTTPSock_Status[get_seqnum].file_start + HTTPSock_Status[get_seqnum].file_offset;
}
#endif
send_len = HTTPSock_Status[get_seqnum].file_len - HTTPSock_Status[get_seqnum].file_offset;
if (send_len > DATA_BUF_SIZE - 1) {
send_len = DATA_BUF_SIZE - 1;
//HTTPSock_Status[get_seqnum]->file_offset += send_len;
} else {
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : HTTP Response end - file len [ %ld ]byte\r\n", s, HTTPSock_Status[get_seqnum].file_len);
#endif
// Send process end
flag_datasend_end = 1;
}
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : HTTP Response body - send len [ %ld ]byte\r\n", s, send_len);
#endif
}
/*****************************************************/
//HTTPSock_Status[get_seqnum]->storage_type == NONE
//HTTPSock_Status[get_seqnum]->storage_type == CODEFLASH
//HTTPSock_Status[get_seqnum]->storage_type == SDCARD
//HTTPSock_Status[get_seqnum]->storage_type == DATAFLASH
/*****************************************************/
if (HTTPSock_Status[get_seqnum].storage_type == CODEFLASH) {
if (HTTPSock_Status[get_seqnum].file_len) {
start_addr = HTTPSock_Status[get_seqnum].file_start;
}
read_userReg_webContent(start_addr, &buf[0], HTTPSock_Status[get_seqnum].file_offset, send_len);
}
#ifdef _USE_SDCARD_
else if (HTTPSock_Status[get_seqnum].storage_type == SDCARD) {
// Data read from SD Card
fr = f_read(&fs, &buf[0], send_len, (void *)&blocklen);
if (fr != FR_OK) {
send_len = 0;
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : [FatFs] Error code return: %d (File Read) / HTTP Send Failed - %s\r\n", s, fr, HTTPSock_Status[get_seqnum].file_name);
#endif
} else {
*(buf + send_len + 1) = 0; // Insert '/0' for indicates the 'End of String' (null terminated)
}
}
#endif
#ifdef _USE_FLASH_
else if (HTTPSock_Status[get_seqnum]->storage_type == DATAFLASH) {
// Data read from external data flash memory
read_from_flashbuf(addr, &buf[0], send_len);
*(buf + send_len + 1) = 0; // Insert '/0' for indicates the 'End of String' (null terminated)
}
#endif
else {
send_len = 0;
}
// Requested content send to HTTP client
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : [Send] HTTP Response body [ %ld ]byte\r\n", s, send_len);
#endif
if (send_len) {
send(s, buf, send_len);
} else {
flag_datasend_end = 1;
}
if (flag_datasend_end) {
HTTPSock_Status[get_seqnum].file_start = 0;
HTTPSock_Status[get_seqnum].file_len = 0;
HTTPSock_Status[get_seqnum].file_offset = 0;
flag_datasend_end = 0;
} else {
HTTPSock_Status[get_seqnum].file_offset += send_len;
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : HTTP Response body - offset [ %ld ]\r\n", s, HTTPSock_Status[get_seqnum].file_offset);
#endif
}
// ## 20141219 Eric added, for 'File object structure' (fs) allocation reduced (8 -> 1)
#ifdef _USE_SDCARD_
f_close(&fs);
#endif
// ## 20141219 added end
}
static void send_http_response_cgi(uint8_t s, uint8_t * buf, uint8_t * http_body, uint16_t file_len) {
uint16_t send_len = 0;
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : HTTP Response Header + Body - CGI\r\n", s);
#endif
send_len = sprintf((char *)buf, "%s%d\r\n\r\n%s", RES_CGIHEAD_OK, file_len, http_body);
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : HTTP Response Header + Body - send len [ %d ]byte\r\n", s, send_len);
#endif
send(s, buf, send_len);
}
static int8_t http_disconnect(uint8_t sn) {
setSn_CR(sn, Sn_CR_DISCON);
/* wait to process the command... */
while (getSn_CR(sn));
return SOCK_OK;
}
static void http_process_handler(uint8_t s, st_http_request * p_http_request) {
uint8_t * uri_name;
uint32_t content_addr = 0;
uint16_t content_num = 0;
uint32_t file_len = 0;
uint8_t uri_buf[MAX_URI_SIZE] = {0x00, };
uint16_t http_status;
int8_t get_seqnum;
uint8_t content_found;
if ((get_seqnum = getHTTPSequenceNum(s)) == -1) {
return; // exception handling; invalid number
}
http_status = 0;
http_response = pHTTP_RX;
file_len = 0;
//method Analyze
switch (p_http_request->METHOD) {
case METHOD_ERR :
http_status = STATUS_BAD_REQ;
send_http_response_header(s, 0, 0, http_status);
break;
case METHOD_HEAD :
case METHOD_GET :
get_http_uri_name(p_http_request->URI, uri_buf);
uri_name = uri_buf;
if (!strcmp((char *)uri_name, "/")) {
strcpy((char *)uri_name, INITIAL_WEBPAGE); // If URI is "/", respond by index.html
}
if (!strcmp((char *)uri_name, "m")) {
strcpy((char *)uri_name, M_INITIAL_WEBPAGE);
}
if (!strcmp((char *)uri_name, "mobile")) {
strcpy((char *)uri_name, MOBILE_INITIAL_WEBPAGE);
}
find_http_uri_type(&p_http_request->TYPE, uri_name); // Checking requested file types (HTML, TEXT, GIF, JPEG and Etc. are included)
#ifdef _HTTPSERVER_DEBUG_
printf("\r\n> HTTPSocket[%d] : HTTP Method GET\r\n", s);
printf("> HTTPSocket[%d] : Request Type = %d\r\n", s, p_http_request->TYPE);
printf("> HTTPSocket[%d] : Request URI = %s\r\n", s, uri_name);
#endif
if (p_http_request->TYPE == PTYPE_CGI) {
content_found = http_get_cgi_handler(uri_name, pHTTP_TX, &file_len);
if (content_found && (file_len <= (DATA_BUF_SIZE - (strlen(RES_CGIHEAD_OK) +8)))) {
send_http_response_cgi(s, http_response, pHTTP_TX, (uint16_t)file_len);
} else {
send_http_response_header(s, PTYPE_CGI, 0, STATUS_NOT_FOUND);
}
} else {
// Find the User registered index for web content
if (find_userReg_webContent(uri_buf, &content_num, &file_len)) {
content_found = 1; // Web content found in code flash memory
content_addr = (uint32_t)content_num;
HTTPSock_Status[get_seqnum].storage_type = CODEFLASH;
}
// Not CGI request, Web content in 'SD card' or 'Data flash' requested
#ifdef _USE_SDCARD_
#ifdef _HTTPSERVER_DEBUG_
printf("\r\n> HTTPSocket[%d] : Searching the requested content\r\n", s);
#endif
if ((fr = f_open(&fs, (const char *)uri_name, FA_READ)) == 0) {
content_found = 1; // file open succeed
file_len = fs.fsize;
content_addr = fs.sclust;
HTTPSock_Status[get_seqnum].storage_type = SDCARD;
}
#elif _USE_FLASH_
else if (/* Read content from Dataflash */) {
content_found = 1;
HTTPSock_Status[get_seqnum]->storage_type = DATAFLASH;
; // To do
}
#endif
else {
content_found = 0; // fail to find content
}
if (!content_found) {
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : Unknown Page Request\r\n", s);
#endif
http_status = STATUS_NOT_FOUND;
} else {
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : Find Content [%s] ok - Start [%ld] len [ %ld ]byte\r\n", s, uri_name, content_addr, file_len);
#endif
http_status = STATUS_OK;
}
// Send HTTP header
if (http_status) {
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : Requested content len = [ %ld ]byte\r\n", s, file_len);
#endif
send_http_response_header(s, p_http_request->TYPE, file_len, http_status);
}
// Send HTTP body (content)
if (http_status == STATUS_OK) {
send_http_response_body(s, uri_name, http_response, content_addr, file_len);
}
}
break;
case METHOD_POST :
mid((char *)p_http_request->URI, "/", " HTTP", (char *)uri_buf);
uri_name = uri_buf;
find_http_uri_type(&p_http_request->TYPE, uri_name); // Check file type (HTML, TEXT, GIF, JPEG are included)
#ifdef _HTTPSERVER_DEBUG_
printf("\r\n> HTTPSocket[%d] : HTTP Method POST\r\n", s);
printf("> HTTPSocket[%d] : Request URI = %s ", s, uri_name);
printf("Type = %d\r\n", p_http_request->TYPE);
#endif
if (p_http_request->TYPE == PTYPE_CGI) { // HTTP POST Method; CGI Process
content_found = http_post_cgi_handler(uri_name, p_http_request, http_response, &file_len);
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : [CGI: %s] / Response len [ %ld ]byte\r\n", s, content_found ? "Content found" : "Content not found", file_len);
#endif
if (content_found && (file_len <= (DATA_BUF_SIZE - (strlen(RES_CGIHEAD_OK) +8)))) {
send_http_response_cgi(s, pHTTP_TX, http_response, (uint16_t)file_len);
// Reset the H/W for apply to the change configuration information
if (content_found == HTTP_RESET) {
HTTPServer_ReStart();
}
} else {
send_http_response_header(s, PTYPE_CGI, 0, STATUS_NOT_FOUND);
}
} else { // HTTP POST Method; Content not found
send_http_response_header(s, 0, 0, STATUS_NOT_FOUND);
}
break;
default :
http_status = STATUS_BAD_REQ;
send_http_response_header(s, 0, 0, http_status);
break;
}
}
void httpServer_time_handler(void) {
httpServer_tick_1s++;
}
uint32_t get_httpServer_timecount(void) {
return httpServer_tick_1s;
}
void reg_httpServer_webContent(uint8_t * content_name, uint8_t * content) {
uint16_t name_len;
uint32_t content_len;
if (content_name == NULL || content == NULL) {
return;
} else if (total_content_cnt >= MAX_CONTENT_CALLBACK) {
return;
}
name_len = strlen((char *)content_name);
content_len = strlen((char *)content);
web_content[total_content_cnt].content_name = malloc(name_len + 1);
strcpy((char *)web_content[total_content_cnt].content_name, (const char *)content_name);
web_content[total_content_cnt].content_len = content_len;
web_content[total_content_cnt].content = content;
total_content_cnt++;
}
uint8_t display_reg_webContent_list(void) {
uint16_t i;
uint8_t ret;
if (total_content_cnt == 0) {
printf(">> Web content file not found\r\n");
ret = 0;
} else {
printf("\r\n=== List of Web content in code flash ===\r\n");
for (i = 0; i < total_content_cnt; i++) {
printf(" [%d] ", i + 1);
printf("%s, ", web_content[i].content_name);
printf("%ld byte, ", web_content[i].content_len);
if (web_content[i].content_len < 30) {
printf("[%s]\r\n", web_content[i].content);
} else {
printf("[ ... ]\r\n");
}
}
printf("=========================================\r\n\r\n");
ret = 1;
}
return ret;
}
uint8_t find_userReg_webContent(uint8_t * content_name, uint16_t * content_num, uint32_t * file_len) {
uint16_t i;
uint8_t ret = 0; // '0' means 'File Not Found'
for (i = 0; i < total_content_cnt; i++) {
if (!strcmp((char *)content_name, (char *)web_content[i].content_name)) {
*file_len = web_content[i].content_len;
*content_num = i;
ret = 1; // If the requested content found, ret set to '1' (Found)
break;
}
}
return ret;
}
uint16_t read_userReg_webContent(uint16_t content_num, uint8_t * buf, uint32_t offset, uint16_t size) {
uint16_t ret = 0;
uint8_t * ptr;
if (content_num > total_content_cnt) {
return 0;
}
ptr = web_content[content_num].content;
if (offset) {
ptr += offset;
}
strncpy((char *)buf, (char *)ptr, size);
*(buf + size) = 0; // Insert '/0' for indicates the 'End of String' (null terminated)
ret = strlen((void *)buf);
return ret;
}

View File

@@ -0,0 +1,108 @@
/**
@file httpServer.h
@brief Define constants and functions related HTTP Web server.
*/
#include <stdint.h>
#ifndef __HTTPSERVER_H__
#define __HTTPSERVER_H__
#ifdef __cplusplus
extern "C" {
#endif
// HTTP Server debug message enable
#define _HTTPSERVER_DEBUG_
#define INITIAL_WEBPAGE "index.html"
#define M_INITIAL_WEBPAGE "m/index.html"
#define MOBILE_INITIAL_WEBPAGE "mobile/index.html"
/* Web Server Content Storage Select */
//#define _USE_SDCARD_
#ifndef _USE_SDCARD_
//#define _USE_FLASH_
#endif
#if !defined(_USE_SDCARD_) && !defined(_USE_FLASH_)
#define _NOTUSED_STORAGE_
#endif
/* Watchdog timer */
//#define _USE_WATCHDOG_
/*********************************************
HTTP Process states list
*********************************************/
#define STATE_HTTP_IDLE 0 /* IDLE, Waiting for data received (TCP established) */
#define STATE_HTTP_REQ_INPROC 1 /* Received HTTP request from HTTP client */
#define STATE_HTTP_REQ_DONE 2 /* The end of HTTP request parse */
#define STATE_HTTP_RES_INPROC 3 /* Sending the HTTP response to HTTP client (in progress) */
#define STATE_HTTP_RES_DONE 4 /* The end of HTTP response send (HTTP transaction ended) */
/*********************************************
HTTP Simple Return Value
*********************************************/
#define HTTP_FAILED 0
#define HTTP_OK 1
#define HTTP_RESET 2
/*********************************************
HTTP Content NAME length
*********************************************/
#define MAX_CONTENT_NAME_LEN 128
/*********************************************
HTTP Timeout
*********************************************/
#define HTTP_MAX_TIMEOUT_SEC 3 // Sec.
typedef enum {
NONE, ///< Web storage none
CODEFLASH, ///< Code flash memory
SDCARD, ///< SD card
DATAFLASH ///< External data flash memory
} StorageType;
typedef struct _st_http_socket {
uint8_t sock_status;
uint8_t file_name[MAX_CONTENT_NAME_LEN];
uint32_t file_start;
uint32_t file_len;
uint32_t file_offset; // (start addr + sent size...)
uint8_t storage_type; // Storage type; Code flash, SDcard, Data flash ...
} st_http_socket;
// Web content structure for file in code flash memory
#define MAX_CONTENT_CALLBACK 20
typedef struct _httpServer_webContent {
uint8_t * content_name;
uint32_t content_len;
uint8_t * content;
} httpServer_webContent;
void httpServer_init(uint8_t * tx_buf, uint8_t * rx_buf, uint8_t cnt, uint8_t * socklist);
void reg_httpServer_cbfunc(void(*mcu_reset)(void), void(*wdt_reset)(void));
void httpServer_run(uint8_t seqnum);
void reg_httpServer_webContent(uint8_t * content_name, uint8_t * content);
uint8_t find_userReg_webContent(uint8_t * content_name, uint16_t * content_num, uint32_t * file_len);
uint16_t read_userReg_webContent(uint16_t content_num, uint8_t * buf, uint32_t offset, uint16_t size);
uint8_t display_reg_webContent_list(void);
/*
@brief HTTP Server 1sec Tick Timer handler
@note SHOULD BE register to your system 1s Tick timer handler
*/
void httpServer_time_handler(void);
uint32_t get_httpServer_timecount(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,65 @@
/**
@file httpUtil.c
@brief HTTP Server Utilities
@version 1.0
@date 2014/07/15
@par Revision
2014/07/15 - 1.0 Release
@author
\n\n @par Copyright (C) 1998 - 2014 WIZnet. All rights reserved.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "httpUtil.h"
uint8_t http_get_cgi_handler(uint8_t * uri_name, uint8_t * buf, uint32_t * file_len) {
uint8_t ret = HTTP_OK;
uint16_t len = 0;
if (predefined_get_cgi_processor(uri_name, buf, &len)) {
;
} else if (strcmp((const char *)uri_name, "example.cgi") == 0) {
// To do
;
} else {
// CGI file not found
ret = HTTP_FAILED;
}
if (ret) {
*file_len = len;
}
return ret;
}
uint8_t http_post_cgi_handler(uint8_t * uri_name, st_http_request * p_http_request, uint8_t * buf, uint32_t * file_len) {
uint8_t ret = HTTP_OK;
uint16_t len = 0;
uint8_t val = 0;
if (predefined_set_cgi_processor(uri_name, p_http_request->URI, buf, &len)) {
;
} else if (strcmp((const char *)uri_name, "example.cgi") == 0) {
// To do
val = 1;
len = sprintf((char *)buf, "%d", val);
} else {
// CGI file not found
ret = HTTP_FAILED;
}
if (ret) {
*file_len = len;
}
return ret;
}
uint8_t predefined_get_cgi_processor(uint8_t * uri_name, uint8_t * buf, uint16_t * len) {
;
}
uint8_t predefined_set_cgi_processor(uint8_t * uri_name, uint8_t * uri, uint8_t * buf, uint16_t * en) {
;
}

View File

@@ -0,0 +1,32 @@
/**
@file httpUtil.h
@brief Header File for HTTP Server Utilities
@version 1.0
@date 2014/07/15
@par Revision
2014/07/15 - 1.0 Release
@author
\n\n @par Copyright (C) 1998 - 2014 WIZnet. All rights reserved.
*/
#ifndef __HTTPUTIL_H__
#define __HTTPUTIL_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "httpServer.h"
#include "httpParser.h"
uint8_t http_get_cgi_handler(uint8_t * uri_name, uint8_t * buf, uint32_t * file_len);
uint8_t http_post_cgi_handler(uint8_t * uri_name, st_http_request * p_http_request, uint8_t * buf, uint32_t * file_len);
uint8_t predefined_get_cgi_processor(uint8_t * uri_name, uint8_t * buf, uint16_t * len);
uint8_t predefined_set_cgi_processor(uint8_t * uri_name, uint8_t * uri, uint8_t * buf, uint16_t * len);
#ifdef __cplusplus
}
#endif
#endif

140
README.md Normal file
View File

@@ -0,0 +1,140 @@
# ioLibrary Driver
The ioLibrary means “Internet Offload Library” for WIZnet chip. It includes drivers and application protocols.
The driver (ioLibrary) can be used for the application design of WIZnet TCP/IP chips as W6300, W6100, [W5500](https://docs.wiznet.io/Product/iEthernet/W5500/overview), W5300, W5200, W5100 [W5100S](https://docs.wiznet.io/Product/iEthernet/W5100S/overview).
## ioLibrary
This driver provides the Berkeley Socket type APIs.
- The tree of Directory
<!-- ioLibrary pic -->
<!-- ![ioLibrary](http://wizwiki.net/wiki/lib/exe/fetch.php?media=products:w5500:iolibrary_bsd.jpg "ioLibrary") -->
```1
ioLibrary
┣ Application
┃ ┣ loopback
┃ ┃ ┣ loopback.c
┃ ┃ ┗ loopback.h
┃ ┗ multicast
┃ ┣ multicast.c
┃ ┗ multicast.h
┣ Ethernet
┃ ┣ W5100
┃ ┃ ┣ w5100.c
┃ ┃ ┗ w5100.h
┃ ┣ W5100S
┃ ┃ ┣ w5100s.c
┃ ┃ ┗ w5100s.h
┃ ┣ W5200
┃ ┃ ┣ w5200.c
┃ ┃ ┗ w5200.h
┃ ┣ W5300
┃ ┃ ┣ w5300.c
┃ ┃ ┗ w5300.h
┃ ┣ W5500
┃ ┃ ┣ w5500.c
┃ ┃ ┗ w5500.h
┃ ┣ W6100
┃ ┃ ┣ w6100.c
┃ ┃ ┗ w6100.h
┃ ┗ W6300
┃ ┣ w6300.c
┃ ┗ w6300.h
┗ Internet
┣ AAC
┃ ┣ AddressAutoConfig.c
┃ ┗ AddressAutoConfig.h
┣ DHCP
┃ ┣ dhcp.c
┃ ┗ dhcp.h
┣ DHCP6
┃ ┣ dhcp6.c
┃ ┗ dhcp6.h
┣ DNS
┃ ┣ dns.c
┃ ┗ dns.h
┣ FTPClient
┃ ┣ ftpc.c
┃ ┣ ftpc.h
┃ ┗ stdio_private.h
┣ FTPServer
┃ ┣ ftpd.c
┃ ┣ ftpd.h
┃ ┣ REAME.md
┃ ┗ stdio_private.h
┣ httpServer
┃ ┣ httpParser.c
┃ ┣ httpParser.h
┃ ┣ httpServer.c
┃ ┣ httpServer.h
┃ ┣ httpUtil.c
┃ ┗ httpUtil.h
┣ MQTT
┃ ┣ MQTTPacket
┃ ┣ mqtt_interface.c
┃ ┣ mqtt_interface.h
┃ ┣ MQTTClient.c
┃ ┗ MQTTClient.h
┣ SNMP
┃ ┣ tools
┃ ┣ snmp.c
┃ ┣ snmp.h
┃ ┣ snmp_custom.c
┃ ┗ snmp_custom.h
┣ SNTP
┃ ┣ sntp.c
┃ ┗ sntp.h
┗ TFTP
┣ netutil.c
┣ netutil.h
┣ tftp.c
┗ tftp.h
```
- Ethernet : SOCKET APIs like BSD & WIZCHIP([W5500](https://docs.wiznet.io/Product/iEthernet/W5500/overview) / W5300 / W5200 / W5100 / [W5100S](https://docs.wiznet.io/Product/iEthernet/W5100S/overview)) Driver
- Internet :
- DHCP client
- DNS client
- FTP client
- FTP server
- SNMP agent/trap
- SNTP client
- TFTP client
- HTTP server
- MQTT Client
- Others will be added.
## How to add an ioLibrary in project through github site.
- Example, refer to https://www.youtube.com/watch?v=mt815RBGdsA
- [ioLibrary Doxygen doument](https://github.com/Wiznet/ioLibrary_Driver/blob/master/Ethernet/Socket_APIs_V3.0.3.chm) : Refer to **TODO** in this document
- Define what chip is used in **wizchip_conf.h**
- Define what Host I/F mode is used in **wizchip_conf.h**
## Revision History
* ioLibrary V4.0.0 Released : 29, MAR, 2018
* New features added: Library for W5100S added.
* ioLibrary V3.1.1 Released : 14, Dec, 2016
* Bug fixed : In Socket.c Fixed MACraw & IPraw sendto function.
* ioLibrary V3.1.0 Released : 05, Dec, 2016
* Internet application protocol add to MQTT Client (using paho MQTT 3.11)
* ioLibrary V3.0.3 Released : 03, May, 2016
* In W5300, Fixed some compile errors in close(). Refer to M20160503
* In close(), replace socket() with some command sequences.
* ioLibrary V3.0.2 Released : 26, April, 2016
* Applied the erratum #1 in close() of socket.c (Refer to A20160426)
* ioLibrary V3.0.1 Released : 15, July, 2015
* Bug fixed : In W5100, Fixed CS control problem in read/write buffer with SPI. Refer to M20150715.
* ioLibrary V3.0 Released : 01, June, 2015
* Add to W5300
* Typing Error in comments
* Refer to 20150601 in sources.
* Type casting error Fixed : 09, April. 2015
In socket.c, send() : Refer to M20150409
* ioLibrary V2.0 released : April. 2015
* Added to W5100, W5200
* Correct to some typing error
* Fixed the warning of type casting.
* Last release : Nov. 2014

BIN
iolibrary.chm Normal file

Binary file not shown.

22
license.txt Normal file
View File

@@ -0,0 +1,22 @@
Copyright (c) 2014 WIZnet Co.,Ltd.
Copyright (c) WIZnet ioLibrary Project.
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.