up
This commit is contained in:
22
.gitattributes
vendored
Normal file
22
.gitattributes
vendored
Normal 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
1940
.gitignore
vendored
Normal file
File diff suppressed because it is too large
Load Diff
0
.gitmodules
vendored
Normal file
0
.gitmodules
vendored
Normal file
18
Application/Application.h
Normal file
18
Application/Application.h
Normal 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
|
||||
1029
Application/loopback/loopback.c
Normal file
1029
Application/loopback/loopback.c
Normal file
File diff suppressed because it is too large
Load Diff
50
Application/loopback/loopback.h
Normal file
50
Application/loopback/loopback.h
Normal 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
|
||||
145
Application/multicast/multicast.c
Normal file
145
Application/multicast/multicast.c
Normal 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;
|
||||
}
|
||||
28
Application/multicast/multicast.h
Normal file
28
Application/multicast/multicast.h
Normal 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
|
||||
BIN
Ethernet/Socket_APIs_V3.0.3.chm
Normal file
BIN
Ethernet/Socket_APIs_V3.0.3.chm
Normal file
Binary file not shown.
371
Ethernet/W5100/w5100.c
Normal file
371
Ethernet/W5100/w5100.c
Normal 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
1875
Ethernet/W5100/w5100.h
Normal file
File diff suppressed because it is too large
Load Diff
499
Ethernet/W5100S/w5100s.c
Normal file
499
Ethernet/W5100S/w5100s.c
Normal 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
3322
Ethernet/W5100S/w5100s.h
Normal file
File diff suppressed because it is too large
Load Diff
338
Ethernet/W5200/w5200.c
Normal file
338
Ethernet/W5200/w5200.c
Normal 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
2118
Ethernet/W5200/w5200.h
Normal file
File diff suppressed because it is too large
Load Diff
229
Ethernet/W5300/w5300.c
Normal file
229
Ethernet/W5300/w5300.c
Normal 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
2336
Ethernet/W5300/w5300.h
Normal file
File diff suppressed because it is too large
Load Diff
248
Ethernet/W5500/w5500.c
Normal file
248
Ethernet/W5500/w5500.c
Normal 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
2164
Ethernet/W5500/w5500.h
Normal file
File diff suppressed because it is too large
Load Diff
272
Ethernet/W6100/w6100.c
Normal file
272
Ethernet/W6100/w6100.c
Normal 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
4086
Ethernet/W6100/w6100.h
Normal file
File diff suppressed because it is too large
Load Diff
273
Ethernet/W6300/w6300.c
Normal file
273
Ethernet/W6300/w6300.c
Normal 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
4103
Ethernet/W6300/w6300.h
Normal file
File diff suppressed because it is too large
Load Diff
1473
Ethernet/socket.c
Normal file
1473
Ethernet/socket.c
Normal file
File diff suppressed because it is too large
Load Diff
736
Ethernet/socket.h
Normal file
736
Ethernet/socket.h
Normal 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
1515
Ethernet/wizchip_conf.c
Normal file
File diff suppressed because it is too large
Load Diff
1348
Ethernet/wizchip_conf.h
Normal file
1348
Ethernet/wizchip_conf.h
Normal file
File diff suppressed because it is too large
Load Diff
681
Internet/AAC/AddressAutoConfig.c
Normal file
681
Internet/AAC/AddressAutoConfig.c
Normal 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
|
||||
133
Internet/AAC/AddressAutoConfig.h
Normal file
133
Internet/AAC/AddressAutoConfig.h
Normal 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
1118
Internet/DHCP/dhcp.c
Normal file
File diff suppressed because it is too large
Load Diff
163
Internet/DHCP/dhcp.h
Normal file
163
Internet/DHCP/dhcp.h
Normal 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
1219
Internet/DHCP6/dhcpv6.c
Normal file
File diff suppressed because it is too large
Load Diff
162
Internet/DHCP6/dhcpv6.h
Normal file
162
Internet/DHCP6/dhcpv6.h
Normal 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
615
Internet/DNS/dns.c
Normal 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
109
Internet/DNS/dns.h
Normal 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
572
Internet/MQTT/MQTTClient.c
Normal 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
178
Internet/MQTT/MQTTClient.h
Normal 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
|
||||
128
Internet/MQTT/MQTTPacket/src/MQTTConnect.h
Normal file
128
Internet/MQTT/MQTTPacket/src/MQTTConnect.h
Normal 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_ */
|
||||
211
Internet/MQTT/MQTTPacket/src/MQTTConnectClient.c
Normal file
211
Internet/MQTT/MQTTPacket/src/MQTTConnectClient.c
Normal 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);
|
||||
}
|
||||
148
Internet/MQTT/MQTTPacket/src/MQTTConnectServer.c
Normal file
148
Internet/MQTT/MQTTPacket/src/MQTTConnectServer.c
Normal 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;
|
||||
}
|
||||
|
||||
109
Internet/MQTT/MQTTPacket/src/MQTTDeserializePublish.c
Normal file
109
Internet/MQTT/MQTTPacket/src/MQTTDeserializePublish.c
Normal 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;
|
||||
}
|
||||
|
||||
241
Internet/MQTT/MQTTPacket/src/MQTTFormat.c
Normal file
241
Internet/MQTT/MQTTPacket/src/MQTTFormat.c
Normal 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;
|
||||
}
|
||||
37
Internet/MQTT/MQTTPacket/src/MQTTFormat.h
Normal file
37
Internet/MQTT/MQTTPacket/src/MQTTFormat.h
Normal 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
|
||||
401
Internet/MQTT/MQTTPacket/src/MQTTPacket.c
Normal file
401
Internet/MQTT/MQTTPacket/src/MQTTPacket.c
Normal 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;
|
||||
}
|
||||
|
||||
126
Internet/MQTT/MQTTPacket/src/MQTTPacket.h
Normal file
126
Internet/MQTT/MQTTPacket/src/MQTTPacket.h
Normal 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_ */
|
||||
38
Internet/MQTT/MQTTPacket/src/MQTTPublish.h
Normal file
38
Internet/MQTT/MQTTPacket/src/MQTTPublish.h
Normal 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_ */
|
||||
163
Internet/MQTT/MQTTPacket/src/MQTTSerializePublish.c
Normal file
163
Internet/MQTT/MQTTPacket/src/MQTTSerializePublish.c
Normal 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);
|
||||
}
|
||||
|
||||
|
||||
39
Internet/MQTT/MQTTPacket/src/MQTTSubscribe.h
Normal file
39
Internet/MQTT/MQTTPacket/src/MQTTSubscribe.h
Normal 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_ */
|
||||
133
Internet/MQTT/MQTTPacket/src/MQTTSubscribeClient.c
Normal file
133
Internet/MQTT/MQTTPacket/src/MQTTSubscribeClient.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
112
Internet/MQTT/MQTTPacket/src/MQTTSubscribeServer.c
Normal file
112
Internet/MQTT/MQTTPacket/src/MQTTSubscribeServer.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
38
Internet/MQTT/MQTTPacket/src/MQTTUnsubscribe.h
Normal file
38
Internet/MQTT/MQTTPacket/src/MQTTUnsubscribe.h
Normal 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_ */
|
||||
105
Internet/MQTT/MQTTPacket/src/MQTTUnsubscribeClient.c
Normal file
105
Internet/MQTT/MQTTPacket/src/MQTTUnsubscribeClient.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
100
Internet/MQTT/MQTTPacket/src/MQTTUnsubscribeServer.c
Normal file
100
Internet/MQTT/MQTTPacket/src/MQTTUnsubscribeServer.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
78
Internet/MQTT/MQTTPacket/src/StackTrace.h
Normal file
78
Internet/MQTT/MQTTPacket/src/StackTrace.h
Normal 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_ */
|
||||
190
Internet/MQTT/mqtt_interface.c
Normal file
190
Internet/MQTT/mqtt_interface.c
Normal 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;
|
||||
}
|
||||
270
Internet/MQTT/mqtt_interface.h
Normal file
270
Internet/MQTT/mqtt_interface.h
Normal 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
917
Internet/SNMP/snmp.c
Normal 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
122
Internet/SNMP/snmp.h
Normal 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
178
Internet/SNMP/snmp_custom.c
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
41
Internet/SNMP/snmp_custom.h
Normal file
41
Internet/SNMP/snmp_custom.h
Normal 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
|
||||
45
Internet/SNMP/tools/OID_Converter/Readme.txt
Normal file
45
Internet/SNMP/tools/OID_Converter/Readme.txt
Normal 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
|
||||
|
||||
===============================================================================================
|
||||
33
Internet/SNMP/tools/net-snmp-5.7(win32-bin)/snmptrapd.conf
Normal file
33
Internet/SNMP/tools/net-snmp-5.7(win32-bin)/snmptrapd.conf
Normal 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
469
Internet/SNTP/sntp.c
Normal 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±00:00 Cote d'Ivoire, Faroe Islands, Ghana, Iceland, Senegal; (Summer) Ireland, Portugal (continental and Madeira)
|
||||
22) UTC±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
74
Internet/SNTP/sntp.h
Normal 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
151
Internet/TFTP/netutil.c
Normal 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
27
Internet/TFTP/netutil.h
Normal 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
639
Internet/TFTP/tftp.c
Normal 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
102
Internet/TFTP/tftp.h
Normal 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__ */
|
||||
430
Internet/httpServer/httpParser.c
Normal file
430
Internet/httpServer/httpParser.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
157
Internet/httpServer/httpParser.h
Normal file
157
Internet/httpServer/httpParser.h
Normal 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__ */
|
||||
707
Internet/httpServer/httpServer.c
Normal file
707
Internet/httpServer/httpServer.c
Normal 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;
|
||||
}
|
||||
108
Internet/httpServer/httpServer.h
Normal file
108
Internet/httpServer/httpServer.h
Normal 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
|
||||
65
Internet/httpServer/httpUtil.c
Normal file
65
Internet/httpServer/httpUtil.c
Normal 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) {
|
||||
;
|
||||
}
|
||||
32
Internet/httpServer/httpUtil.h
Normal file
32
Internet/httpServer/httpUtil.h
Normal 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
140
README.md
Normal 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 -->
|
||||
<!--  -->
|
||||
```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
BIN
iolibrary.chm
Normal file
Binary file not shown.
22
license.txt
Normal file
22
license.txt
Normal 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.
|
||||
Reference in New Issue
Block a user