mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-21 10:26:06 +03:00
Sketch emulation on host (#5342)
* WIP compile examples on host with 'make examples' * WIP bufferize tcp input * WIP Makefile * WIP network to rework, tcp/udp to factorize, udp addresses broken * minor changes to the core * WIP basic udp working * WIP mdns * WIP mcast receiving, not sending * WIP mdns OK * beta version * SSL + doc * update travis host test command * licenses * typo * doc: arduino builder is not around: declare functions before calling them * fix with latest SSL PR, compile in 32 bits mode * fix make clean * make -m32 optional * 32bits compiler ability tester * WIP * WIP (fix 1 vtable error, still another one to hunt with using spiffs) * example astyle * fix os_printf_plus * load / save mock spiffs * fix style * fix using spiffs/mock * don't mess ram * update doc * remove leftover * optimization -Os except for CI, rename ARCH32 to FORCE32 * revert useless cast (not even compiled) * remove unused function * use proper type for pointer arithmetics * makefile: sketch object and cpp file moved to bin/ directories easier to clean, and IDE don't like them * changes for review * make use of %zd * less verbose makefile by default (option) * update readme
This commit is contained in:
parent
b504881be4
commit
74ca42f829
@ -22,7 +22,7 @@
|
|||||||
#include "flash_utils.h"
|
#include "flash_utils.h"
|
||||||
#include "eboot_command.h"
|
#include "eboot_command.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "interrupts.h"
|
#include <interrupts.h>
|
||||||
#include "MD5Builder.h"
|
#include "MD5Builder.h"
|
||||||
#include "umm_malloc/umm_malloc.h"
|
#include "umm_malloc/umm_malloc.h"
|
||||||
#include "cont.h"
|
#include "cont.h"
|
||||||
@ -165,6 +165,7 @@ void EspClass::restart(void)
|
|||||||
uint16_t EspClass::getVcc(void)
|
uint16_t EspClass::getVcc(void)
|
||||||
{
|
{
|
||||||
InterruptLock lock;
|
InterruptLock lock;
|
||||||
|
(void)lock;
|
||||||
return system_get_vdd33();
|
return system_get_vdd33();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +62,7 @@ public:
|
|||||||
|
|
||||||
class FSImpl {
|
class FSImpl {
|
||||||
public:
|
public:
|
||||||
|
virtual ~FSImpl () { }
|
||||||
virtual bool begin() = 0;
|
virtual bool begin() = 0;
|
||||||
virtual void end() = 0;
|
virtual void end() = 0;
|
||||||
virtual bool format() = 0;
|
virtual bool format() = 0;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#include "Updater.h"
|
#include "Updater.h"
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
#include "eboot_command.h"
|
#include "eboot_command.h"
|
||||||
#include "interrupts.h"
|
#include <interrupts.h>
|
||||||
#include "esp8266_peri.h"
|
#include <esp8266_peri.h>
|
||||||
|
|
||||||
//#define DEBUG_UPDATER Serial
|
//#define DEBUG_UPDATER Serial
|
||||||
|
|
||||||
@ -84,21 +84,21 @@ bool UpdaterClass::begin(size_t size, int command, int ledPin, uint8_t ledOn) {
|
|||||||
|
|
||||||
wifi_set_sleep_type(NONE_SLEEP_T);
|
wifi_set_sleep_type(NONE_SLEEP_T);
|
||||||
|
|
||||||
uint32_t updateStartAddress = 0;
|
uintptr_t updateStartAddress = 0;
|
||||||
if (command == U_FLASH) {
|
if (command == U_FLASH) {
|
||||||
//size of current sketch rounded to a sector
|
//size of current sketch rounded to a sector
|
||||||
uint32_t currentSketchSize = (ESP.getSketchSize() + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1));
|
size_t currentSketchSize = (ESP.getSketchSize() + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1));
|
||||||
//address of the end of the space available for sketch and update
|
//address of the end of the space available for sketch and update
|
||||||
uint32_t updateEndAddress = (uint32_t)&_SPIFFS_start - 0x40200000;
|
uintptr_t updateEndAddress = (uintptr_t)&_SPIFFS_start - 0x40200000;
|
||||||
//size of the update rounded to a sector
|
//size of the update rounded to a sector
|
||||||
uint32_t roundedSize = (size + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1));
|
size_t roundedSize = (size + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1));
|
||||||
//address where we will start writing the update
|
//address where we will start writing the update
|
||||||
updateStartAddress = (updateEndAddress > roundedSize)? (updateEndAddress - roundedSize) : 0;
|
updateStartAddress = (updateEndAddress > roundedSize)? (updateEndAddress - roundedSize) : 0;
|
||||||
|
|
||||||
#ifdef DEBUG_UPDATER
|
#ifdef DEBUG_UPDATER
|
||||||
DEBUG_UPDATER.printf("[begin] roundedSize: 0x%08X (%d)\n", roundedSize, roundedSize);
|
DEBUG_UPDATER.printf("[begin] roundedSize: 0x%08zX (%zd)\n", roundedSize, roundedSize);
|
||||||
DEBUG_UPDATER.printf("[begin] updateEndAddress: 0x%08X (%d)\n", updateEndAddress, updateEndAddress);
|
DEBUG_UPDATER.printf("[begin] updateEndAddress: 0x%08zX (%zd)\n", updateEndAddress, updateEndAddress);
|
||||||
DEBUG_UPDATER.printf("[begin] currentSketchSize: 0x%08X (%d)\n", currentSketchSize, currentSketchSize);
|
DEBUG_UPDATER.printf("[begin] currentSketchSize: 0x%08zX (%zd)\n", currentSketchSize, currentSketchSize);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//make sure that the size of both sketches is less than the total space (updateEndAddress)
|
//make sure that the size of both sketches is less than the total space (updateEndAddress)
|
||||||
@ -108,7 +108,7 @@ bool UpdaterClass::begin(size_t size, int command, int ledPin, uint8_t ledOn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (command == U_SPIFFS) {
|
else if (command == U_SPIFFS) {
|
||||||
updateStartAddress = (uint32_t)&_SPIFFS_start - 0x40200000;
|
updateStartAddress = (uintptr_t)&_SPIFFS_start - 0x40200000;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// unknown command
|
// unknown command
|
||||||
@ -133,7 +133,7 @@ bool UpdaterClass::begin(size_t size, int command, int ledPin, uint8_t ledOn) {
|
|||||||
#ifdef DEBUG_UPDATER
|
#ifdef DEBUG_UPDATER
|
||||||
DEBUG_UPDATER.printf("[begin] _startAddress: 0x%08X (%d)\n", _startAddress, _startAddress);
|
DEBUG_UPDATER.printf("[begin] _startAddress: 0x%08X (%d)\n", _startAddress, _startAddress);
|
||||||
DEBUG_UPDATER.printf("[begin] _currentAddress: 0x%08X (%d)\n", _currentAddress, _currentAddress);
|
DEBUG_UPDATER.printf("[begin] _currentAddress: 0x%08X (%d)\n", _currentAddress, _currentAddress);
|
||||||
DEBUG_UPDATER.printf("[begin] _size: 0x%08X (%d)\n", _size, _size);
|
DEBUG_UPDATER.printf("[begin] _size: 0x%08zX (%zd)\n", _size, _size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_md5.begin();
|
_md5.begin();
|
||||||
@ -159,7 +159,7 @@ bool UpdaterClass::end(bool evenIfRemaining){
|
|||||||
|
|
||||||
if(hasError() || (!isFinished() && !evenIfRemaining)){
|
if(hasError() || (!isFinished() && !evenIfRemaining)){
|
||||||
#ifdef DEBUG_UPDATER
|
#ifdef DEBUG_UPDATER
|
||||||
DEBUG_UPDATER.printf("premature end: res:%u, pos:%u/%u\n", getError(), progress(), _size);
|
DEBUG_UPDATER.printf("premature end: res:%u, pos:%zu/%zu\n", getError(), progress(), _size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_reset();
|
_reset();
|
||||||
@ -199,10 +199,10 @@ bool UpdaterClass::end(bool evenIfRemaining){
|
|||||||
eboot_command_write(&ebcmd);
|
eboot_command_write(&ebcmd);
|
||||||
|
|
||||||
#ifdef DEBUG_UPDATER
|
#ifdef DEBUG_UPDATER
|
||||||
DEBUG_UPDATER.printf("Staged: address:0x%08X, size:0x%08X\n", _startAddress, _size);
|
DEBUG_UPDATER.printf("Staged: address:0x%08X, size:0x%08zX\n", _startAddress, _size);
|
||||||
}
|
}
|
||||||
else if (_command == U_SPIFFS) {
|
else if (_command == U_SPIFFS) {
|
||||||
DEBUG_UPDATER.printf("SPIFFS: address:0x%08X, size:0x%08X\n", _startAddress, _size);
|
DEBUG_UPDATER.printf("SPIFFS: address:0x%08X, size:0x%08zX\n", _startAddress, _size);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,6 +109,7 @@ bool isSpiffsFilenameValid(const char* name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// these symbols should be defined in the linker script for each flash layout
|
// these symbols should be defined in the linker script for each flash layout
|
||||||
|
#ifndef CORE_MOCK
|
||||||
#ifdef ARDUINO
|
#ifdef ARDUINO
|
||||||
extern "C" uint32_t _SPIFFS_start;
|
extern "C" uint32_t _SPIFFS_start;
|
||||||
extern "C" uint32_t _SPIFFS_end;
|
extern "C" uint32_t _SPIFFS_end;
|
||||||
@ -131,6 +132,7 @@ FS SPIFFS = FS(FSImplPtr(new SPIFFSImpl(
|
|||||||
SPIFFS_PHYS_PAGE,
|
SPIFFS_PHYS_PAGE,
|
||||||
SPIFFS_PHYS_BLOCK,
|
SPIFFS_PHYS_BLOCK,
|
||||||
SPIFFS_MAX_OPEN_FILES)));
|
SPIFFS_MAX_OPEN_FILES)));
|
||||||
#endif
|
#endif // ARDUINO
|
||||||
|
#endif // !CORE_MOCK
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -220,7 +220,7 @@ protected:
|
|||||||
size_t cacheBufSize = SPIFFS_buffer_bytes_for_cache(&_fs, _maxOpenFds);
|
size_t cacheBufSize = SPIFFS_buffer_bytes_for_cache(&_fs, _maxOpenFds);
|
||||||
|
|
||||||
if (!_workBuf) {
|
if (!_workBuf) {
|
||||||
DEBUGV("SPIFFSImpl: allocating %d+%d+%d=%d bytes\r\n",
|
DEBUGV("SPIFFSImpl: allocating %zd+%zd+%zd=%zd bytes\r\n",
|
||||||
workBufSize, fdsBufSize, cacheBufSize,
|
workBufSize, fdsBufSize, cacheBufSize,
|
||||||
workBufSize + fdsBufSize + cacheBufSize);
|
workBufSize + fdsBufSize + cacheBufSize);
|
||||||
_workBuf.reset(new uint8_t[workBufSize]);
|
_workBuf.reset(new uint8_t[workBufSize]);
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
DNSServer::DNSServer()
|
DNSServer::DNSServer()
|
||||||
{
|
{
|
||||||
_ttl = htonl(60);
|
_ttl = lwip_htonl(60);
|
||||||
_errorReplyCode = DNSReplyCode::NonExistentDomain;
|
_errorReplyCode = DNSReplyCode::NonExistentDomain;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ void DNSServer::setErrorReplyCode(const DNSReplyCode &replyCode)
|
|||||||
|
|
||||||
void DNSServer::setTTL(const uint32_t &ttl)
|
void DNSServer::setTTL(const uint32_t &ttl)
|
||||||
{
|
{
|
||||||
_ttl = htonl(ttl);
|
_ttl = lwip_htonl(ttl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DNSServer::stop()
|
void DNSServer::stop()
|
||||||
@ -81,7 +81,7 @@ void DNSServer::processNextRequest()
|
|||||||
|
|
||||||
bool DNSServer::requestIncludesOnlyOneQuestion(const DNSHeader* dnsHeader)
|
bool DNSServer::requestIncludesOnlyOneQuestion(const DNSHeader* dnsHeader)
|
||||||
{
|
{
|
||||||
return ntohs(dnsHeader->QDCount) == 1 &&
|
return lwip_ntohs(dnsHeader->QDCount) == 1 &&
|
||||||
dnsHeader->ANCount == 0 &&
|
dnsHeader->ANCount == 0 &&
|
||||||
dnsHeader->NSCount == 0 &&
|
dnsHeader->NSCount == 0 &&
|
||||||
dnsHeader->ARCount == 0;
|
dnsHeader->ARCount == 0;
|
||||||
|
@ -734,7 +734,7 @@ int HTTPClient::sendRequest(const char * type, Stream * stream, size_t size)
|
|||||||
free(buff);
|
free(buff);
|
||||||
|
|
||||||
if(size && (int) size != bytesWritten) {
|
if(size && (int) size != bytesWritten) {
|
||||||
DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] Stream payload bytesWritten %d and size %d mismatch!.\n", bytesWritten, size);
|
DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] Stream payload bytesWritten %d and size %zd mismatch!.\n", bytesWritten, size);
|
||||||
DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] ERROR SEND PAYLOAD FAILED!");
|
DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] ERROR SEND PAYLOAD FAILED!");
|
||||||
return returnError(HTTPC_ERROR_SEND_PAYLOAD_FAILED);
|
return returnError(HTTPC_ERROR_SEND_PAYLOAD_FAILED);
|
||||||
} else {
|
} else {
|
||||||
|
@ -438,12 +438,9 @@ void ESP8266WebServer::sendContent(const String& content) {
|
|||||||
const char * footer = "\r\n";
|
const char * footer = "\r\n";
|
||||||
size_t len = content.length();
|
size_t len = content.length();
|
||||||
if(_chunked) {
|
if(_chunked) {
|
||||||
char * chunkSize = (char *)malloc(11);
|
char chunkSize[11];
|
||||||
if(chunkSize){
|
sprintf(chunkSize, "%zx\r\n", len);
|
||||||
sprintf(chunkSize, "%x%s", len, footer);
|
_currentClientWrite(chunkSize, strlen(chunkSize));
|
||||||
_currentClientWrite(chunkSize, strlen(chunkSize));
|
|
||||||
free(chunkSize);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_currentClientWrite(content.c_str(), len);
|
_currentClientWrite(content.c_str(), len);
|
||||||
if(_chunked){
|
if(_chunked){
|
||||||
@ -461,12 +458,9 @@ void ESP8266WebServer::sendContent_P(PGM_P content) {
|
|||||||
void ESP8266WebServer::sendContent_P(PGM_P content, size_t size) {
|
void ESP8266WebServer::sendContent_P(PGM_P content, size_t size) {
|
||||||
const char * footer = "\r\n";
|
const char * footer = "\r\n";
|
||||||
if(_chunked) {
|
if(_chunked) {
|
||||||
char * chunkSize = (char *)malloc(11);
|
char chunkSize[11];
|
||||||
if(chunkSize){
|
sprintf(chunkSize, "%zx\r\n", size);
|
||||||
sprintf(chunkSize, "%x%s", size, footer);
|
_currentClientWrite(chunkSize, strlen(chunkSize));
|
||||||
_currentClientWrite(chunkSize, strlen(chunkSize));
|
|
||||||
free(chunkSize);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_currentClientWrite_P(content, size);
|
_currentClientWrite_P(content, size);
|
||||||
if(_chunked){
|
if(_chunked){
|
||||||
|
80
libraries/ESP8266WiFi/examples/udp/udp.ino
Normal file
80
libraries/ESP8266WiFi/examples/udp/udp.ino
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
UDPSendReceive.pde:
|
||||||
|
This sketch receives UDP message strings, prints them to the serial port
|
||||||
|
and sends an "acknowledge" string back to the sender
|
||||||
|
|
||||||
|
A Processing sketch is included at the end of file that can be used to send
|
||||||
|
and received messages for testing with a computer.
|
||||||
|
|
||||||
|
created 21 Aug 2010
|
||||||
|
by Michael Margolis
|
||||||
|
|
||||||
|
This code is in the public domain.
|
||||||
|
|
||||||
|
adapted from Ethernet library examples
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#include <WiFiUdp.h>
|
||||||
|
|
||||||
|
#define SSID "ssid"
|
||||||
|
#define PSK "psk"
|
||||||
|
|
||||||
|
unsigned int localPort = 8888; // local port to listen on
|
||||||
|
|
||||||
|
// buffers for receiving and sending data
|
||||||
|
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet,
|
||||||
|
char ReplyBuffer[] = "acknowledged\r\n"; // a string to send back
|
||||||
|
|
||||||
|
WiFiUDP Udp;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
WiFi.mode(WIFI_STA);
|
||||||
|
WiFi.begin(SSID, PSK);
|
||||||
|
while (WiFi.status() != WL_CONNECTED) {
|
||||||
|
Serial.print('.');
|
||||||
|
delay(500);
|
||||||
|
}
|
||||||
|
Serial.print("Connected! IP address: ");
|
||||||
|
Serial.println(WiFi.localIP());
|
||||||
|
Serial.printf("UDP server on port %d\n", localPort);
|
||||||
|
Udp.begin(localPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// if there's data available, read a packet
|
||||||
|
int packetSize = Udp.parsePacket();
|
||||||
|
if (packetSize) {
|
||||||
|
Serial.print("Received packet of size ");
|
||||||
|
Serial.println(packetSize);
|
||||||
|
Serial.print("From ");
|
||||||
|
IPAddress remote = Udp.remoteIP();
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
Serial.print(remote[i], DEC);
|
||||||
|
if (i < 3) {
|
||||||
|
Serial.print(".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Serial.print(", port ");
|
||||||
|
Serial.println(Udp.remotePort());
|
||||||
|
|
||||||
|
// read the packet into packetBufffer
|
||||||
|
Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
|
||||||
|
Serial.println("Contents:");
|
||||||
|
Serial.println(packetBuffer);
|
||||||
|
|
||||||
|
// send a reply, to the IP address and port that sent us the packet we received
|
||||||
|
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
|
||||||
|
Udp.write(ReplyBuffer);
|
||||||
|
Udp.endPacket();
|
||||||
|
}
|
||||||
|
delay(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
test (shell/netcat):
|
||||||
|
---------------
|
||||||
|
nc -u 192.168.esp.address 8888
|
||||||
|
*/
|
@ -826,6 +826,8 @@ bool X509List::append(const uint8_t *derCert, size_t derLen) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !CORE_MOCK
|
||||||
|
|
||||||
// Second stack thunked helpers
|
// Second stack thunked helpers
|
||||||
make_stack_thunk(br_ssl_engine_recvapp_ack);
|
make_stack_thunk(br_ssl_engine_recvapp_ack);
|
||||||
make_stack_thunk(br_ssl_engine_recvapp_buf);
|
make_stack_thunk(br_ssl_engine_recvapp_buf);
|
||||||
@ -836,4 +838,6 @@ make_stack_thunk(br_ssl_engine_sendapp_buf);
|
|||||||
make_stack_thunk(br_ssl_engine_sendrec_ack);
|
make_stack_thunk(br_ssl_engine_sendrec_ack);
|
||||||
make_stack_thunk(br_ssl_engine_sendrec_buf);
|
make_stack_thunk(br_ssl_engine_sendrec_buf);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
};
|
};
|
@ -38,7 +38,7 @@ extern "C"
|
|||||||
#include "lwip/tcp.h"
|
#include "lwip/tcp.h"
|
||||||
#include "lwip/inet.h"
|
#include "lwip/inet.h"
|
||||||
#include "lwip/netif.h"
|
#include "lwip/netif.h"
|
||||||
#include "include/ClientContext.h"
|
#include <include/ClientContext.h>
|
||||||
#include "c_types.h"
|
#include "c_types.h"
|
||||||
|
|
||||||
uint16_t WiFiClient::_localPort = 0;
|
uint16_t WiFiClient::_localPort = 0;
|
||||||
|
@ -40,10 +40,12 @@ extern "C" {
|
|||||||
#include "lwip/tcp.h"
|
#include "lwip/tcp.h"
|
||||||
#include "lwip/inet.h"
|
#include "lwip/inet.h"
|
||||||
#include "lwip/netif.h"
|
#include "lwip/netif.h"
|
||||||
#include "include/ClientContext.h"
|
#include <include/ClientContext.h>
|
||||||
#include "c_types.h"
|
#include "c_types.h"
|
||||||
#include "coredecls.h"
|
#include "coredecls.h"
|
||||||
|
|
||||||
|
#if !CORE_MOCK
|
||||||
|
|
||||||
// The BearSSL thunks in use for now
|
// The BearSSL thunks in use for now
|
||||||
#define br_ssl_engine_recvapp_ack thunk_br_ssl_engine_recvapp_ack
|
#define br_ssl_engine_recvapp_ack thunk_br_ssl_engine_recvapp_ack
|
||||||
#define br_ssl_engine_recvapp_buf thunk_br_ssl_engine_recvapp_buf
|
#define br_ssl_engine_recvapp_buf thunk_br_ssl_engine_recvapp_buf
|
||||||
@ -54,6 +56,8 @@ extern "C" {
|
|||||||
#define br_ssl_engine_sendrec_ack thunk_br_ssl_engine_sendrec_ack
|
#define br_ssl_engine_sendrec_ack thunk_br_ssl_engine_sendrec_ack
|
||||||
#define br_ssl_engine_sendrec_buf thunk_br_ssl_engine_sendrec_buf
|
#define br_ssl_engine_sendrec_buf thunk_br_ssl_engine_sendrec_buf
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace BearSSL {
|
namespace BearSSL {
|
||||||
|
|
||||||
void WiFiClientSecure::_clear() {
|
void WiFiClientSecure::_clear() {
|
||||||
@ -1377,6 +1381,21 @@ bool WiFiClientSecure::loadPrivateKey(Stream& stream, size_t size) {
|
|||||||
// SSL debugging which should focus on the WiFiClientBearSSL objects.
|
// SSL debugging which should focus on the WiFiClientBearSSL objects.
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
|
#if CORE_MOCK
|
||||||
|
|
||||||
|
void br_esp8266_stack_proxy_init(uint8_t *space, uint16_t size) {
|
||||||
|
(void)space;
|
||||||
|
(void)size;
|
||||||
|
}
|
||||||
|
void _BearSSLCheckStack(const char *fcn, const char *file, int line) {
|
||||||
|
(void)fcn;
|
||||||
|
(void)file;
|
||||||
|
(void)line;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // !CORE_MOCK
|
||||||
|
|
||||||
extern size_t br_esp8266_stack_proxy_usage();
|
extern size_t br_esp8266_stack_proxy_usage();
|
||||||
|
|
||||||
void _BearSSLCheckStack(const char *fcn, const char *file, int line) {
|
void _BearSSLCheckStack(const char *fcn, const char *file, int line) {
|
||||||
@ -1386,7 +1405,7 @@ extern "C" {
|
|||||||
int freeheap = ESP.getFreeHeap();
|
int freeheap = ESP.getFreeHeap();
|
||||||
static int laststack, lastheap, laststack2;
|
static int laststack, lastheap, laststack2;
|
||||||
if ((laststack != freestack) || (lastheap != freeheap) || (laststack2 != (int)br_esp8266_stack_proxy_usage())) {
|
if ((laststack != freestack) || (lastheap != freeheap) || (laststack2 != (int)br_esp8266_stack_proxy_usage())) {
|
||||||
Serial.printf("%s:%s(%d): FREESTACK=%d, STACK2USAGE=%d, FREEHEAP=%d\n", file, fcn, line, freestack, br_esp8266_stack_proxy_usage(), freeheap);
|
Serial.printf("%s:%s(%d): FREESTACK=%d, STACK2USAGE=%zd, FREEHEAP=%d\n", file, fcn, line, freestack, br_esp8266_stack_proxy_usage(), freeheap);
|
||||||
if (freestack < 256) {
|
if (freestack < 256) {
|
||||||
Serial.printf("!!! Out of main stack space\n");
|
Serial.printf("!!! Out of main stack space\n");
|
||||||
}
|
}
|
||||||
@ -1405,6 +1424,8 @@ extern "C" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // !CORE_MOCK
|
||||||
|
|
||||||
void _BearSSLSerialPrint(const char *str) {
|
void _BearSSLSerialPrint(const char *str) {
|
||||||
static int cnt = 0;
|
static int cnt = 0;
|
||||||
Serial.printf("%s", str);
|
Serial.printf("%s", str);
|
||||||
|
@ -35,7 +35,7 @@ extern "C" {
|
|||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
#include "lwip/tcp.h"
|
#include "lwip/tcp.h"
|
||||||
#include "lwip/inet.h"
|
#include "lwip/inet.h"
|
||||||
#include "include/ClientContext.h"
|
#include <include/ClientContext.h>
|
||||||
|
|
||||||
WiFiServer::WiFiServer(IPAddress addr, uint16_t port)
|
WiFiServer::WiFiServer(IPAddress addr, uint16_t port)
|
||||||
: _port(port)
|
: _port(port)
|
||||||
|
@ -34,7 +34,7 @@ extern "C" {
|
|||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
#include "lwip/tcp.h"
|
#include "lwip/tcp.h"
|
||||||
#include "lwip/inet.h"
|
#include "lwip/inet.h"
|
||||||
#include "include/ClientContext.h"
|
#include <include/ClientContext.h>
|
||||||
#include "WiFiServerSecureBearSSL.h"
|
#include "WiFiServerSecureBearSSL.h"
|
||||||
|
|
||||||
namespace BearSSL {
|
namespace BearSSL {
|
||||||
|
@ -38,7 +38,7 @@ extern "C"
|
|||||||
#include "lwip/inet.h"
|
#include "lwip/inet.h"
|
||||||
#include "lwip/igmp.h"
|
#include "lwip/igmp.h"
|
||||||
#include "lwip/mem.h"
|
#include "lwip/mem.h"
|
||||||
#include "include/UdpContext.h"
|
#include <include/UdpContext.h>
|
||||||
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
@ -106,7 +106,9 @@ uint8_t WiFiUDP::beginMulticast(IPAddress interfaceAddr, IPAddress multicast, ui
|
|||||||
|
|
||||||
_ctx = new UdpContext;
|
_ctx = new UdpContext;
|
||||||
_ctx->ref();
|
_ctx->ref();
|
||||||
if (!_ctx->listen(*IP_ADDR_ANY, port)) {
|
ip_addr_t addr;
|
||||||
|
addr.addr = INADDR_ANY;
|
||||||
|
if (!_ctx->listen(addr, port)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,7 +286,7 @@ uint16_t WiFiUDP::localPort()
|
|||||||
void WiFiUDP::stopAll()
|
void WiFiUDP::stopAll()
|
||||||
{
|
{
|
||||||
for (WiFiUDP* it = _s_first; it; it = it->_next) {
|
for (WiFiUDP* it = _s_first; it; it = it->_next) {
|
||||||
DEBUGV("%s %08x %08x\n", __func__, (uint32_t) it, (uint32_t) _s_first);
|
DEBUGV("%s %p %p\n", __func__, it, _s_first);
|
||||||
it->stop();
|
it->stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -292,7 +294,7 @@ void WiFiUDP::stopAll()
|
|||||||
void WiFiUDP::stopAllExcept(WiFiUDP * exC) {
|
void WiFiUDP::stopAllExcept(WiFiUDP * exC) {
|
||||||
for (WiFiUDP* it = _s_first; it; it = it->_next) {
|
for (WiFiUDP* it = _s_first; it; it = it->_next) {
|
||||||
if (it->_ctx != exC->_ctx) {
|
if (it->_ctx != exC->_ctx) {
|
||||||
DEBUGV("%s %08x %08x\n", __func__, (uint32_t) it, (uint32_t) _s_first);
|
DEBUGV("%s %p %p\n", __func__, it, _s_first);
|
||||||
it->stop();
|
it->stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ extern "C"
|
|||||||
#include "lwip/tcp.h"
|
#include "lwip/tcp.h"
|
||||||
#include "lwip/inet.h"
|
#include "lwip/inet.h"
|
||||||
#include "lwip/netif.h"
|
#include "lwip/netif.h"
|
||||||
#include "include/ClientContext.h"
|
#include <include/ClientContext.h>
|
||||||
#include "c_types.h"
|
#include "c_types.h"
|
||||||
|
|
||||||
namespace axTLS {
|
namespace axTLS {
|
||||||
|
@ -174,7 +174,7 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
udp_hdr* udphdr = GET_UDP_HDR(_rx_buf);
|
udp_hdr* udphdr = GET_UDP_HDR(_rx_buf);
|
||||||
return ntohs(udphdr->src);
|
return lwip_ntohs(udphdr->src);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t getDestAddress()
|
uint32_t getDestAddress()
|
||||||
@ -252,6 +252,7 @@ public:
|
|||||||
|
|
||||||
void flush()
|
void flush()
|
||||||
{
|
{
|
||||||
|
//XXX this does not follow Arduino's flush definition
|
||||||
if (!_rx_buf)
|
if (!_rx_buf)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -431,11 +431,11 @@ MDNSTxt * MDNSResponder::_getServiceTxt(char *name, char *proto){
|
|||||||
for (servicePtr = _services; servicePtr; servicePtr = servicePtr->_next) {
|
for (servicePtr = _services; servicePtr; servicePtr = servicePtr->_next) {
|
||||||
if(servicePtr->_port > 0 && strcmp(servicePtr->_name, name) == 0 && strcmp(servicePtr->_proto, proto) == 0){
|
if(servicePtr->_port > 0 && strcmp(servicePtr->_name, name) == 0 && strcmp(servicePtr->_proto, proto) == 0){
|
||||||
if (servicePtr->_txts == 0)
|
if (servicePtr->_txts == 0)
|
||||||
return false;
|
return nullptr;
|
||||||
return servicePtr->_txts;
|
return servicePtr->_txts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t MDNSResponder::_getServiceTxtLen(char *name, char *proto){
|
uint16_t MDNSResponder::_getServiceTxtLen(char *name, char *proto){
|
||||||
|
@ -134,7 +134,7 @@ function build_docs()
|
|||||||
function run_host_tests()
|
function run_host_tests()
|
||||||
{
|
{
|
||||||
pushd host
|
pushd host
|
||||||
make
|
make FORCE32=0 OPTZ=-O0 CI
|
||||||
make clean-objects
|
make clean-objects
|
||||||
popd
|
popd
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
BINARY_DIRECTORY := bin
|
BINDIR := bin
|
||||||
LCOV_DIRECTORY := lcov
|
LCOV_DIRECTORY := lcov
|
||||||
OUTPUT_BINARY := $(BINARY_DIRECTORY)/host_tests
|
OUTPUT_BINARY := $(BINDIR)/host_tests
|
||||||
CORE_PATH := ../../cores/esp8266
|
CORE_PATH := ../../cores/esp8266
|
||||||
|
FORCE32 ?= 1
|
||||||
|
OPTZ ?= -Os
|
||||||
|
V ?= 0
|
||||||
|
|
||||||
|
MAKEFILE = $(word 1, $(MAKEFILE_LIST))
|
||||||
|
|
||||||
# I wasn't able to build with clang when -coverage flag is enabled, forcing GCC on OS X
|
# I wasn't able to build with clang when -coverage flag is enabled, forcing GCC on OS X
|
||||||
ifeq ($(shell uname -s),Darwin)
|
ifeq ($(shell uname -s),Darwin)
|
||||||
@ -13,6 +18,36 @@ VALGRIND ?= valgrind
|
|||||||
LCOV ?= lcov
|
LCOV ?= lcov
|
||||||
GENHTML ?= genhtml
|
GENHTML ?= genhtml
|
||||||
|
|
||||||
|
ifeq ($(FORCE32),1)
|
||||||
|
ABILITY32 = $(shell echo 'int main(){return sizeof(long);}'|$(CXX) -m32 -x c++ - -o sizeoflong 2>/dev/null && ./sizeoflong; echo $$?; rm -f sizeoflong;)
|
||||||
|
ifneq ($(ABILITY32),4)
|
||||||
|
$(warning Cannot compile in 32 bit mode, switching to native mode)
|
||||||
|
else
|
||||||
|
N32 = 32
|
||||||
|
M32 = -m32
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(N32),32)
|
||||||
|
$(warning compiling in 32 bits mode)
|
||||||
|
else
|
||||||
|
$(warning compiling in native mode)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(V), 0)
|
||||||
|
VERBC = @echo "C $@";
|
||||||
|
VERBCXX = @echo "C++ $@";
|
||||||
|
VERBLD = @echo "LD $@";
|
||||||
|
VERBAR = @echo "AR $@";
|
||||||
|
else
|
||||||
|
VERBC =
|
||||||
|
VERBCXX =
|
||||||
|
VERBLD =
|
||||||
|
VERBAR =
|
||||||
|
endif
|
||||||
|
|
||||||
|
$(shell mkdir -p $(BINDIR))
|
||||||
|
|
||||||
CORE_CPP_FILES := $(addprefix $(CORE_PATH)/,\
|
CORE_CPP_FILES := $(addprefix $(CORE_PATH)/,\
|
||||||
StreamString.cpp \
|
StreamString.cpp \
|
||||||
Stream.cpp \
|
Stream.cpp \
|
||||||
@ -31,12 +66,24 @@ CORE_C_FILES := $(addprefix $(CORE_PATH)/,\
|
|||||||
spiffs/spiffs_gc.c \
|
spiffs/spiffs_gc.c \
|
||||||
spiffs/spiffs_hydrogen.c \
|
spiffs/spiffs_hydrogen.c \
|
||||||
spiffs/spiffs_nucleus.c \
|
spiffs/spiffs_nucleus.c \
|
||||||
|
libb64/cencode.c \
|
||||||
)
|
)
|
||||||
|
|
||||||
MOCK_CPP_FILES := $(addprefix common/,\
|
MOCK_CPP_FILES_COMMON := $(addprefix common/,\
|
||||||
Arduino.cpp \
|
Arduino.cpp \
|
||||||
spiffs_mock.cpp \
|
spiffs_mock.cpp \
|
||||||
WMath.cpp \
|
WMath.cpp \
|
||||||
|
MockSerial.cpp \
|
||||||
|
MockTools.cpp \
|
||||||
|
)
|
||||||
|
|
||||||
|
MOCK_CPP_FILES := $(MOCK_CPP_FILES_COMMON) $(addprefix common/,\
|
||||||
|
ArduinoCatch.cpp \
|
||||||
|
)
|
||||||
|
|
||||||
|
MOCK_CPP_FILES_EMU := $(MOCK_CPP_FILES_COMMON) $(addprefix common/,\
|
||||||
|
ArduinoMain.cpp \
|
||||||
|
user_interface.cpp \
|
||||||
)
|
)
|
||||||
|
|
||||||
MOCK_C_FILES := $(addprefix common/,\
|
MOCK_C_FILES := $(addprefix common/,\
|
||||||
@ -44,21 +91,40 @@ MOCK_C_FILES := $(addprefix common/,\
|
|||||||
noniso.c \
|
noniso.c \
|
||||||
)
|
)
|
||||||
|
|
||||||
INC_PATHS += $(addprefix -I, \
|
INC_PATHS := $(addprefix -I,\
|
||||||
common \
|
common \
|
||||||
$(CORE_PATH) \
|
$(CORE_PATH) \
|
||||||
)
|
)
|
||||||
|
|
||||||
|
INC_PATHS += $(addprefix -I,\
|
||||||
|
$(shell echo ../../libraries/*/src) \
|
||||||
|
$(shell echo ../../libraries/*) \
|
||||||
|
../../tools/sdk/include \
|
||||||
|
../../tools/sdk/lwip2/include \
|
||||||
|
)
|
||||||
|
|
||||||
TEST_CPP_FILES := \
|
TEST_CPP_FILES := \
|
||||||
fs/test_fs.cpp \
|
fs/test_fs.cpp \
|
||||||
core/test_pgmspace.cpp \
|
core/test_pgmspace.cpp \
|
||||||
core/test_md5builder.cpp \
|
core/test_md5builder.cpp \
|
||||||
core/test_string.cpp
|
core/test_string.cpp
|
||||||
|
|
||||||
CXXFLAGS += -std=c++11 -Wall -Werror -coverage -O0 -fno-common -g
|
PREINCLUDES := \
|
||||||
CFLAGS += -std=c99 -Wall -Werror -coverage -O0 -fno-common -g
|
-include common/mock.h \
|
||||||
LDFLAGS += -coverage -O0
|
-include common/c_types.h \
|
||||||
|
|
||||||
|
ifneq ($(D),)
|
||||||
|
OPTZ=-O0
|
||||||
|
DEBUG += -DDEBUG_ESP_PORT=Serial
|
||||||
|
DEBUG += -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_MDNS
|
||||||
|
endif
|
||||||
|
|
||||||
|
CXXFLAGS += $(DEBUG) -std=c++11 -Wall -Werror -coverage $(OPTZ) -fno-common -g $(M32)
|
||||||
|
CFLAGS += -std=c99 -Wall -Werror -coverage $(OPTZ) -fno-common -g $(M32)
|
||||||
|
LDFLAGS += -coverage $(OPTZ) -g $(M32)
|
||||||
VALGRINDFLAGS += --leak-check=full --track-origins=yes --error-limit=no --show-leak-kinds=all --error-exitcode=999
|
VALGRINDFLAGS += --leak-check=full --track-origins=yes --error-limit=no --show-leak-kinds=all --error-exitcode=999
|
||||||
|
CXXFLAGS += -Wno-error=format-security # cores/esp8266/Print.cpp:42:24: error: format not a string literal and no format arguments [-Werror=format-security] -- (os_printf_plus(not_the_best_way))
|
||||||
|
#CXXFLAGS += -Wno-format-security # cores/esp8266/Print.cpp:42:40: warning: format not a string literal and no format arguments [-Wformat-security] -- (os_printf_plus(not_the_best_way))
|
||||||
|
|
||||||
remduplicates = $(strip $(if $1,$(firstword $1) $(call remduplicates,$(filter-out $(firstword $1),$1))))
|
remduplicates = $(strip $(if $1,$(firstword $1) $(call remduplicates,$(filter-out $(firstword $1),$1))))
|
||||||
|
|
||||||
@ -74,21 +140,23 @@ CPP_OBJECTS = $(CPP_OBJECTS_CORE) $(CPP_OBJECTS_TESTS)
|
|||||||
OBJECTS = $(C_OBJECTS) $(CPP_OBJECTS)
|
OBJECTS = $(C_OBJECTS) $(CPP_OBJECTS)
|
||||||
COVERAGE_FILES = $(OBJECTS:.o=.gc*)
|
COVERAGE_FILES = $(OBJECTS:.o=.gc*)
|
||||||
|
|
||||||
all: build-info $(OUTPUT_BINARY) valgrind test gcov
|
all: help
|
||||||
|
|
||||||
test: $(OUTPUT_BINARY)
|
CI: build-info $(OUTPUT_BINARY) valgrind test gcov # run CI
|
||||||
|
|
||||||
|
test: $(OUTPUT_BINARY) # run host test for CI
|
||||||
$(OUTPUT_BINARY)
|
$(OUTPUT_BINARY)
|
||||||
|
|
||||||
clean: clean-objects clean-coverage
|
clean: clean-objects clean-coverage # clean everything
|
||||||
rm -rf $(BINARY_DIRECTORY)
|
rm -rf $(BINDIR)
|
||||||
|
|
||||||
clean-objects:
|
clean-objects:
|
||||||
rm -rf $(OBJECTS)
|
rm -rf $(C_OBJECTS) $(CPP_OBJECTS_CORE) $(CPP_OBJECTS_CORE_EMU) $(CPP_OBJECTS_TESTS)
|
||||||
|
|
||||||
clean-coverage:
|
clean-coverage:
|
||||||
rm -rf $(COVERAGE_FILES) $(LCOV_DIRECTORY) *.gcov
|
rm -rf $(COVERAGE_FILES) $(LCOV_DIRECTORY) *.gcov
|
||||||
|
|
||||||
gcov: test
|
gcov: test # run coverage for CI
|
||||||
find $(CORE_PATH) -name "*.gcno" -exec $(GCOV) -r -pb {} +
|
find $(CORE_PATH) -name "*.gcno" -exec $(GCOV) -r -pb {} +
|
||||||
|
|
||||||
valgrind: $(OUTPUT_BINARY)
|
valgrind: $(OUTPUT_BINARY)
|
||||||
@ -98,7 +166,7 @@ valgrind: $(OUTPUT_BINARY)
|
|||||||
$(LCOV) --directory $(CORE_PATH) --capture --output-file $(LCOV_DIRECTORY)/app.info
|
$(LCOV) --directory $(CORE_PATH) --capture --output-file $(LCOV_DIRECTORY)/app.info
|
||||||
$(GENHTML) $(LCOV_DIRECTORY)/app.info -o $(LCOV_DIRECTORY)
|
$(GENHTML) $(LCOV_DIRECTORY)/app.info -o $(LCOV_DIRECTORY)
|
||||||
|
|
||||||
build-info:
|
build-info: # show toolchain version
|
||||||
@echo "-------- build tools info --------"
|
@echo "-------- build tools info --------"
|
||||||
@echo "CC: " $(CC)
|
@echo "CC: " $(CC)
|
||||||
$(CC) -v
|
$(CC) -v
|
||||||
@ -108,18 +176,147 @@ build-info:
|
|||||||
$(GCOV) -v
|
$(GCOV) -v
|
||||||
@echo "----------------------------------"
|
@echo "----------------------------------"
|
||||||
|
|
||||||
$(BINARY_DIRECTORY):
|
-include $(BINDIR)/.*.d
|
||||||
mkdir -p $@
|
.SUFFIXES:
|
||||||
|
|
||||||
$(C_OBJECTS): %.c.o: %.c
|
%.c.o: %.c
|
||||||
$(CC) $(CFLAGS) $(INC_PATHS) -c -o $@ $<
|
$(VERBC) $(CC) $(PREINCLUDES) $(CFLAGS) $(INC_PATHS) -MD -MF $(BINDIR)/.$(notdir $<).d -c -o $@ $<
|
||||||
|
|
||||||
$(CPP_OBJECTS): %.cpp.o: %.cpp
|
.PRECIOUS: %.cpp.o
|
||||||
$(CXX) $(CXXFLAGS) $(INC_PATHS) -c -o $@ $<
|
%.cpp.o: %.cpp
|
||||||
|
$(VERBCXX) $(CXX) $(PREINCLUDES) $(CXXFLAGS) $(INC_PATHS) -MD -MF $(BINDIR)/.$(notdir $<).d -c -o $@ $<
|
||||||
|
|
||||||
$(BINARY_DIRECTORY)/core.a: $(C_OBJECTS) $(CPP_OBJECTS_CORE)
|
$(BINDIR)/core.a: $(C_OBJECTS) $(CPP_OBJECTS_CORE)
|
||||||
ar -rcu $@ $(C_OBJECTS) $(CPP_OBJECTS_CORE)
|
ar -rcu $@ $^
|
||||||
ranlib -c $@
|
ranlib -c $@
|
||||||
|
|
||||||
$(OUTPUT_BINARY): $(BINARY_DIRECTORY) $(CPP_OBJECTS_TESTS) $(BINARY_DIRECTORY)/core.a
|
$(OUTPUT_BINARY): $(CPP_OBJECTS_TESTS) $(BINDIR)/core.a
|
||||||
$(CXX) $(LDFLAGS) $(CPP_OBJECTS_TESTS) $(BINARY_DIRECTORY)/core.a $(LIBS) -o $(OUTPUT_BINARY)
|
$(VERBLD) $(CXX) $(LDFLAGS) $^ -o $@
|
||||||
|
|
||||||
|
#################################################
|
||||||
|
# building ino sources
|
||||||
|
|
||||||
|
ARDUINO_LIBS := \
|
||||||
|
$(addprefix $(CORE_PATH)/,\
|
||||||
|
IPAddress.cpp \
|
||||||
|
Updater.cpp \
|
||||||
|
) \
|
||||||
|
$(addprefix ../../libraries/,\
|
||||||
|
$(addprefix ESP8266WiFi/src/,\
|
||||||
|
ESP8266WiFi.cpp \
|
||||||
|
ESP8266WiFiAP.cpp \
|
||||||
|
ESP8266WiFiGeneric.cpp \
|
||||||
|
ESP8266WiFiMulti.cpp \
|
||||||
|
ESP8266WiFiSTA-WPS.cpp \
|
||||||
|
ESP8266WiFiSTA.cpp \
|
||||||
|
ESP8266WiFiScan.cpp \
|
||||||
|
WiFiClient.cpp \
|
||||||
|
WiFiUdp.cpp \
|
||||||
|
WiFiClientSecureBearSSL.cpp \
|
||||||
|
WiFiServerSecureBearSSL.cpp \
|
||||||
|
BearSSLHelpers.cpp \
|
||||||
|
CertStoreBearSSL.cpp \
|
||||||
|
) \
|
||||||
|
$(addprefix ESP8266WebServer/src/,\
|
||||||
|
ESP8266WebServer.cpp \
|
||||||
|
Parsing.cpp \
|
||||||
|
detail/mimetable.cpp \
|
||||||
|
) \
|
||||||
|
ESP8266mDNS/ESP8266mDNS.cpp \
|
||||||
|
ArduinoOTA/ArduinoOTA.cpp \
|
||||||
|
DNSServer/src/DNSServer.cpp \
|
||||||
|
ESP8266AVRISP/src/ESP8266AVRISP.cpp \
|
||||||
|
ESP8266HTTPClient/src/ESP8266HTTPClient.cpp \
|
||||||
|
) \
|
||||||
|
|
||||||
|
MOCK_ARDUINO_LIBS := \
|
||||||
|
common/ClientContextSocket.cpp \
|
||||||
|
common/ClientContextTools.cpp \
|
||||||
|
common/MockWiFiServerSocket.cpp \
|
||||||
|
common/MockWiFiServer.cpp \
|
||||||
|
common/UdpContextSocket.cpp \
|
||||||
|
common/HostWiring.cpp \
|
||||||
|
common/MockEsp.cpp \
|
||||||
|
common/MockEEPROM.cpp \
|
||||||
|
common/MockSPI.cpp \
|
||||||
|
|
||||||
|
CPP_SOURCES_CORE_EMU = \
|
||||||
|
$(MOCK_CPP_FILES_EMU) \
|
||||||
|
$(CORE_CPP_FILES) \
|
||||||
|
$(MOCK_ARDUINO_LIBS) \
|
||||||
|
$(ARDUINO_LIBS) \
|
||||||
|
|
||||||
|
|
||||||
|
LIBSSLFILE = ../../tools/sdk/ssl/bearssl/build$(N32)/libbearssl.a
|
||||||
|
ifeq (,$(wildcard $(LIBSSLFILE)))
|
||||||
|
LIBSSL =
|
||||||
|
else
|
||||||
|
LIBSSL = $(LIBSSLFILE)
|
||||||
|
endif
|
||||||
|
ssl: # download source and build BearSSL
|
||||||
|
cd ../../tools/sdk/ssl && make native$(N32)
|
||||||
|
|
||||||
|
ULIBPATHS = $(shell echo $(ULIBDIRS) | sed 's,:, ,g')
|
||||||
|
USERLIBDIRS = $(shell test -z "$(ULIBPATHS)" || for d in $(ULIBPATHS); do for dd in $$d $$d/src; do test -d $$dd && { echo -I$$dd; echo "userlib: using directory '$$dd'" 1>&2; } done; done)
|
||||||
|
USERLIBSRCS = $(shell test -z "$(ULIBPATHS)" || for d in $(ULIBPATHS); do for ss in $$d/*.cpp $$d/src/*.cpp; do test -r $$ss && echo $$ss; done; done)
|
||||||
|
INC_PATHS += $(USERLIBDIRS)
|
||||||
|
CPP_OBJECTS_CORE_EMU = $(CPP_SOURCES_CORE_EMU:.cpp=.cpp.o) $(USERLIBSRCS:.cpp=.cpp.o)
|
||||||
|
|
||||||
|
bin/fullcore.a: $(C_OBJECTS) $(CPP_OBJECTS_CORE_EMU)
|
||||||
|
$(VERBAR) ar -rcu $@ $^
|
||||||
|
$(VERBAR) ranlib -c $@
|
||||||
|
|
||||||
|
%: %.ino.cpp.o bin/fullcore.a
|
||||||
|
$(VERBLD) $(CXX) $(LDFLAGS) $< bin/fullcore.a $(LIBSSL) -o $@
|
||||||
|
@echo "----> $@ <----"
|
||||||
|
|
||||||
|
#################################################
|
||||||
|
# are we in primary make call ?
|
||||||
|
ifeq ($(INO),)
|
||||||
|
|
||||||
|
%: %.ino
|
||||||
|
@# recursive 'make' with paths
|
||||||
|
$(MAKE) -f $(MAKEFILE) INODIR=$(dir $@) INO=$(notdir $@) $(BINDIR)/$(notdir $@)/$(notdir $@)
|
||||||
|
@# see below the new build rule with fixed output path outside from core location
|
||||||
|
|
||||||
|
#####################
|
||||||
|
# recursive call on ino targer
|
||||||
|
else
|
||||||
|
|
||||||
|
$(BINDIR)/$(INO)/$(INO).ino.cpp:
|
||||||
|
@# arduino builder would come around here (.ino -> .ino.cpp)
|
||||||
|
@mkdir -p $(BINDIR)/$(INO); \
|
||||||
|
( \
|
||||||
|
echo "#include \"$(INODIR)/$(INO).ino\""; \
|
||||||
|
for i in $(INODIR)/*.ino; do \
|
||||||
|
test "$$i" = $(INODIR)/$(INO).ino || echo "#include \"$$i\""; \
|
||||||
|
done; \
|
||||||
|
) > $(BINDIR)/$(INO)/$(INO).ino.cpp
|
||||||
|
|
||||||
|
endif # recursive
|
||||||
|
#####################
|
||||||
|
|
||||||
|
#################################################
|
||||||
|
|
||||||
|
.PHONY: list
|
||||||
|
list: # show core example list
|
||||||
|
@for dir in ../../libraries/*/examples; do \
|
||||||
|
exampledir=$${dir%/*}; \
|
||||||
|
exampledirname=$${exampledir##*/}; \
|
||||||
|
for subdir in $$dir/*; do \
|
||||||
|
exname=$${subdir##*/}; \
|
||||||
|
echo "$$subdir/$$exname"; \
|
||||||
|
done; \
|
||||||
|
done; \
|
||||||
|
|
||||||
|
#################################################
|
||||||
|
# help
|
||||||
|
|
||||||
|
.PHONY: help
|
||||||
|
help:
|
||||||
|
@cat README.txt
|
||||||
|
@echo ""
|
||||||
|
@echo "Make rules:"
|
||||||
|
@echo ""
|
||||||
|
@sed -rne 's,([^: \t]*):[^=#]*#[\t ]*(.*),\1 - \2,p' $(MAKEFILE)
|
||||||
|
@echo ""
|
||||||
|
96
tests/host/README.txt
Normal file
96
tests/host/README.txt
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
|
||||||
|
Host Tests for Continuous Integration
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
make FORCE32=0 OPTZ=-O0 CI
|
||||||
|
|
||||||
|
(FORCE32=0: https://bugs.launchpad.net/ubuntu/+source/valgrind/+bug/948004)
|
||||||
|
|
||||||
|
Sketch emulation on host
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
This environment let compile esp8266/Arduino sketches into native
|
||||||
|
environment. Network (tcp, udp, including ssl and multicast) is linked to
|
||||||
|
local host interfaces. WiFi is trivialy emulated and reported as "just"
|
||||||
|
already connected and usable.
|
||||||
|
|
||||||
|
Currently network emulation is a complete rewrite of
|
||||||
|
WiFiClient+WiFiServer/ClientContext and WifiUdp/UdpContext using socket
|
||||||
|
posix API. Further work will optionally propose native lwIP library
|
||||||
|
instead.
|
||||||
|
|
||||||
|
How to compile and run a sketch
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
All results are stored in ./bin/ .
|
||||||
|
|
||||||
|
Show the core example list:
|
||||||
|
make list
|
||||||
|
|
||||||
|
|
||||||
|
Build one example
|
||||||
|
make D=1 ../../libraries/esp8266/examples/Blink/Blink
|
||||||
|
run it:
|
||||||
|
./bin/Blink/Blink -h
|
||||||
|
|
||||||
|
|
||||||
|
Optional 'V=1' enables makefile verbosity
|
||||||
|
Optional 'D=1' enables core debug (same as IDE's tools menu)
|
||||||
|
Optional 'OPTZ=-O2' will update gcc -O option (default is -Os, D=1 implies -O0)
|
||||||
|
Optional 'FORCE32=0' will use native/default gcc (default is FORCE32=1 unless gcc-multilib is not detected)
|
||||||
|
|
||||||
|
|
||||||
|
Non exhaustive list of working examples:
|
||||||
|
make D=1 ../../libraries/ESP8266WiFi/examples/udp/udp
|
||||||
|
make D=1 ../../libraries/ESP8266WiFi/examples/WiFiClient/WiFiClient
|
||||||
|
make D=1 ../../libraries/ESP8266WebServer/examples/HelloServer/HelloServer
|
||||||
|
make D=1 ../../libraries/ESP8266WebServer/examples/AdvancedWebServer/AdvancedWebServer
|
||||||
|
make D=1 ../../libraries/ESP8266mDNS/examples/mDNS_Web_Server/mDNS_Web_Server
|
||||||
|
make D=1 ../../libraries/ESP8266WiFi/examples/BearSSL_Validation/BearSSL_Validation
|
||||||
|
|
||||||
|
Compile other sketches:
|
||||||
|
- library paths are specified using ULIBDIRS variable, separated by ':'
|
||||||
|
- call 'make path-to-the-sketch-file' to build (without its '.ino' extension):
|
||||||
|
- CAVEAT: functions must be declared *before* being called (arduino builder is not around)
|
||||||
|
|
||||||
|
make D=1 ULIBDIRS=/path/to/your/arduino/libraries/lib1:/path/to/another/place/lib2 /path/to/your/sketchdir/sketch/sketch
|
||||||
|
or:
|
||||||
|
ULIBDIRS=/path/to/your/arduino/libraries/lib1:/path/to/another/place/lib2 make D=1 /path/to/your/sketchdir/sketch/sketch
|
||||||
|
|
||||||
|
or (preferred):
|
||||||
|
export ULIBDIRS=/path/to/your/arduino/libraries/lib1:/path/to/another/place/lib2
|
||||||
|
export D=1
|
||||||
|
export OPTZ=-O2
|
||||||
|
make clean
|
||||||
|
make /path/to/your/sketchdir/sketch/sketch
|
||||||
|
./bin/sketch/sketch
|
||||||
|
|
||||||
|
|
||||||
|
Executable location is always in bin/. Once a sketch is compiled, just run it:
|
||||||
|
bin/sketch/sketch
|
||||||
|
|
||||||
|
Options are available:
|
||||||
|
-h
|
||||||
|
-i eth0 bind servers to this interface (WIP)
|
||||||
|
-l bind Multicast to the above interface (WIP)
|
||||||
|
-f no throttle (possibly 100%CPU)
|
||||||
|
|
||||||
|
TODO
|
||||||
|
----
|
||||||
|
A lot.
|
||||||
|
Make fun, propose PRs.
|
||||||
|
|
||||||
|
- replace some "fprintf(stderr" with redirectable log functions
|
||||||
|
- spiffs in a file (done, need to initialize and check)
|
||||||
|
- EEPROM in a file (partly done)
|
||||||
|
- SDCARD on Host filesystem ? or in an image ?
|
||||||
|
- nice curses interface to display/change gpios ?
|
||||||
|
- display device emulation (like ssd1306)
|
||||||
|
- optionaly use arduino-builder ?
|
||||||
|
- store sketch objects and binaries outside from the source directories (done for sketches)
|
||||||
|
- compile and use lwIP on host
|
||||||
|
- easily debug HTTP classes
|
||||||
|
- https://github.com/esp8266/Arduino/issues/1715
|
||||||
|
- gpio, currently:
|
||||||
|
read as 0(digital) or 512(analog).
|
||||||
|
output is printed on console.
|
@ -13,11 +13,10 @@
|
|||||||
all copies or substantial portions of the Software.
|
all copies or substantial portions of the Software.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define CATCH_CONFIG_MAIN
|
|
||||||
#include <catch.hpp>
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
extern "C" unsigned long millis()
|
extern "C" unsigned long millis()
|
||||||
{
|
{
|
||||||
@ -26,11 +25,22 @@ extern "C" unsigned long millis()
|
|||||||
return (time.tv_sec * 1000) + (time.tv_usec / 1000);
|
return (time.tv_sec * 1000) + (time.tv_usec / 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" unsigned long micros()
|
||||||
|
{
|
||||||
|
timeval time;
|
||||||
|
gettimeofday(&time, NULL);
|
||||||
|
return (time.tv_sec * 1000000) + time.tv_usec;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
extern "C" void yield()
|
extern "C" void yield()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" void esp_yield()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
extern "C" void __panic_func(const char* file, int line, const char* func) {
|
extern "C" void __panic_func(const char* file, int line, const char* func) {
|
||||||
abort();
|
abort();
|
||||||
@ -38,4 +48,10 @@ extern "C" void __panic_func(const char* file, int line, const char* func) {
|
|||||||
|
|
||||||
extern "C" void delay(unsigned long ms)
|
extern "C" void delay(unsigned long ms)
|
||||||
{
|
{
|
||||||
|
usleep(ms * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void delayMicroseconds(unsigned int us)
|
||||||
|
{
|
||||||
|
usleep(us);
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
#ifndef Arduino_h
|
#ifndef Arduino_h
|
||||||
#define Arduino_h
|
#define Arduino_h
|
||||||
|
|
||||||
|
#define MOCK "mock: "
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
20
tests/host/common/ArduinoCatch.cpp
Normal file
20
tests/host/common/ArduinoCatch.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
Arduino.cpp - Mocks for common Arduino APIs
|
||||||
|
Copyright © 2016 Ivan Grokhotkov
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define CATCH_CONFIG_MAIN
|
||||||
|
#include <catch.hpp>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include "Arduino.h"
|
||||||
|
|
143
tests/host/common/ArduinoMain.cpp
Normal file
143
tests/host/common/ArduinoMain.cpp
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
Arduino emulator main loop
|
||||||
|
Copyright (c) 2018 david gauchard. 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 with 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:
|
||||||
|
|
||||||
|
- Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers.
|
||||||
|
|
||||||
|
- Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
- The names of its contributors may not be used to endorse or promote
|
||||||
|
products derived from this Software without specific prior written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
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 CONTRIBUTORS 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 WITH THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <user_interface.h> // wifi_get_ip_info()
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include "lwip/opt.h"
|
||||||
|
#include "lwip/udp.h"
|
||||||
|
#include "lwip/inet.h"
|
||||||
|
#include "lwip/igmp.h"
|
||||||
|
#include "lwip/mem.h"
|
||||||
|
#include <include/UdpContext.h>
|
||||||
|
#include <poll.h>
|
||||||
|
|
||||||
|
#include <unistd.h> // usleep
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#include "../common/spiffs_mock.h"
|
||||||
|
#include <spiffs/spiffs.h>
|
||||||
|
SPIFFS_MOCK_DECLARE(/*size_kb*/1024, /(blovk_kb*/8, /*page_b*/512);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::map<int,UdpContext*> udps;
|
||||||
|
|
||||||
|
void register_udp (int sock, UdpContext* udp)
|
||||||
|
{
|
||||||
|
if (udp)
|
||||||
|
udps[sock] = udp;
|
||||||
|
else
|
||||||
|
udps.erase(sock);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* host_interface = nullptr;
|
||||||
|
|
||||||
|
void help (const char* argv0, int exitcode)
|
||||||
|
{
|
||||||
|
printf(
|
||||||
|
"%s - compiled with esp8266/arduino emulator\n"
|
||||||
|
"options:\n"
|
||||||
|
" -h\n"
|
||||||
|
" -i <interface> - use this interface for IP address\n"
|
||||||
|
" -l - bind tcp/udp servers to interface only (not 0.0.0.0)\n"
|
||||||
|
" -f - no throttle (possibly 100%%CPU)\n"
|
||||||
|
, argv0);
|
||||||
|
exit(exitcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct option options[] =
|
||||||
|
{
|
||||||
|
{ "help", no_argument, NULL, 'h' },
|
||||||
|
{ "fast", no_argument, NULL, 'f' },
|
||||||
|
{ "local", no_argument, NULL, 'l' },
|
||||||
|
{ "interface", required_argument, NULL, 'i' },
|
||||||
|
};
|
||||||
|
|
||||||
|
int main (int argc, char* const argv [])
|
||||||
|
{
|
||||||
|
bool fast = false;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
int n = getopt_long(argc, argv, "hlfi:", options, NULL);
|
||||||
|
if (n < 0)
|
||||||
|
break;
|
||||||
|
switch (n)
|
||||||
|
{
|
||||||
|
case 'h':
|
||||||
|
help(argv[0], EXIT_SUCCESS);
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
host_interface = optarg;
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
global_ipv4_netfmt = NO_GLOBAL_BINDING;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
fast = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, MOCK "bad option '%c'\n", n);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup global global_ipv4_netfmt
|
||||||
|
wifi_get_ip_info(0, nullptr);
|
||||||
|
|
||||||
|
setup();
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (!fast)
|
||||||
|
usleep(10000); // not 100% cpu
|
||||||
|
|
||||||
|
loop();
|
||||||
|
|
||||||
|
// check incoming udp
|
||||||
|
for (auto& udp: udps)
|
||||||
|
{
|
||||||
|
pollfd p;
|
||||||
|
p.fd = udp.first;
|
||||||
|
p.events = POLLIN;
|
||||||
|
if (poll(&p, 1, 0) && p.revents == POLLIN)
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "UDP poll(%d) -> cb\r", p.fd);
|
||||||
|
udp.second->mock_cb();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
151
tests/host/common/ClientContextSocket.cpp
Normal file
151
tests/host/common/ClientContextSocket.cpp
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
Arduino emulation - socket part of ClientContext
|
||||||
|
Copyright (c) 2018 david gauchard. 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 with 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:
|
||||||
|
|
||||||
|
- Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers.
|
||||||
|
|
||||||
|
- Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
- The names of its contributors may not be used to endorse or promote
|
||||||
|
products derived from this Software without specific prior written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
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 CONTRIBUTORS 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 WITH THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
// separated from lwIP to avoid type conflicts
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
int mockConnect (uint32_t ipv4, int& sock, int port)
|
||||||
|
{
|
||||||
|
struct sockaddr_in server;
|
||||||
|
if ((sock = ::socket(AF_INET, SOCK_STREAM, 0)) == -1)
|
||||||
|
{
|
||||||
|
perror(MOCK "ClientContext:connect: ::socket()");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
server.sin_family = AF_INET;
|
||||||
|
server.sin_port = htons(port);
|
||||||
|
memcpy(&server.sin_addr, &ipv4, 4);
|
||||||
|
if (::connect(sock, (struct sockaddr*)&server, sizeof(server)) == -1)
|
||||||
|
{
|
||||||
|
perror(MOCK "ClientContext::connect: ::connect()");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "ClientContext::connect: fcntl(O_NONBLOCK): %s\n", strerror(errno));
|
||||||
|
close(sock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t mockFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize)
|
||||||
|
{
|
||||||
|
size_t maxread = CCBUFSIZE - ccinbufsize;
|
||||||
|
ssize_t ret = ::read(sock, ccinbuf + ccinbufsize, maxread);
|
||||||
|
if (ret == -1)
|
||||||
|
{
|
||||||
|
if (errno != EAGAIN)
|
||||||
|
fprintf(stderr, MOCK "ClientContext::(read/peek): filling buffer for %zd bytes: %s\n", maxread, strerror(errno));
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
return ccinbufsize += ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t mockPeekBytes (int sock, char* dst, size_t usersize, int timeout_ms, char* ccinbuf, size_t& ccinbufsize)
|
||||||
|
{
|
||||||
|
if (usersize > CCBUFSIZE)
|
||||||
|
fprintf(stderr, MOCK "CCBUFSIZE(%d) should be increased by %zd bytes (-> %zd)\n", CCBUFSIZE, usersize - CCBUFSIZE, usersize);
|
||||||
|
|
||||||
|
struct pollfd p;
|
||||||
|
size_t retsize = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (usersize <= ccinbufsize)
|
||||||
|
{
|
||||||
|
// data already buffered
|
||||||
|
retsize = usersize;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check incoming data data
|
||||||
|
mockFillInBuf(sock, ccinbuf, ccinbufsize);
|
||||||
|
if (usersize <= ccinbufsize)
|
||||||
|
{
|
||||||
|
// data just received
|
||||||
|
retsize = usersize;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for more data until timeout
|
||||||
|
p.fd = sock;
|
||||||
|
p.events = POLLIN;
|
||||||
|
} while (poll(&p, 1, timeout_ms) == 1);
|
||||||
|
|
||||||
|
memcpy(dst, ccinbuf, retsize);
|
||||||
|
return retsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t mockRead (int sock, char* dst, size_t size, int timeout_ms, char* ccinbuf, size_t& ccinbufsize)
|
||||||
|
{
|
||||||
|
size_t copied = mockPeekBytes(sock, dst, size, timeout_ms, ccinbuf, ccinbufsize);
|
||||||
|
// swallow (XXX use a circular buffer)
|
||||||
|
memmove(ccinbuf, ccinbuf + copied, ccinbufsize - copied);
|
||||||
|
ccinbufsize -= copied;
|
||||||
|
return copied;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t mockWrite (int sock, const uint8_t* data, size_t size, int timeout_ms)
|
||||||
|
{
|
||||||
|
struct pollfd p;
|
||||||
|
p.fd = sock;
|
||||||
|
p.events = POLLOUT;
|
||||||
|
int ret = poll(&p, 1, timeout_ms);
|
||||||
|
if (ret == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "ClientContext::write: poll(%d): %s\n", sock, strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
ret = ::write(sock, data, size);
|
||||||
|
if (ret == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "ClientContext::read: write(%d): %s\n", sock, strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (ret != (int)size)
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "ClientContext::write: short write (%d < %zd) (TODO)\n", ret, size);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
57
tests/host/common/ClientContextTools.cpp
Normal file
57
tests/host/common/ClientContextTools.cpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
Arduino emulation - part of ClientContext
|
||||||
|
Copyright (c) 2018 david gauchard. 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 with 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:
|
||||||
|
|
||||||
|
- Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers.
|
||||||
|
|
||||||
|
- Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
- The names of its contributors may not be used to endorse or promote
|
||||||
|
products derived from this Software without specific prior written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
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 CONTRIBUTORS 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 WITH THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <lwip/def.h>
|
||||||
|
#include <lwip/tcp.h>
|
||||||
|
#include <lwip/dns.h>
|
||||||
|
#include <WiFiClient.h>
|
||||||
|
#include <include/ClientContext.h>
|
||||||
|
|
||||||
|
#include <netdb.h> // gethostbyname
|
||||||
|
|
||||||
|
err_t dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found, void *callback_arg)
|
||||||
|
{
|
||||||
|
(void)callback_arg;
|
||||||
|
(void)found;
|
||||||
|
struct hostent* hbn = gethostbyname(hostname);
|
||||||
|
if (!hbn)
|
||||||
|
return ERR_TIMEOUT;
|
||||||
|
addr->addr = *(uint32_t*)hbn->h_addr_list[0];
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct tcp_pcb mock_tcp_pcb;
|
||||||
|
tcp_pcb* tcp_new (void)
|
||||||
|
{
|
||||||
|
// this is useless
|
||||||
|
// ClientContext is setting the source port and we don't care here
|
||||||
|
return &mock_tcp_pcb;
|
||||||
|
}
|
81
tests/host/common/EEPROM.h
Normal file
81
tests/host/common/EEPROM.h
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
Arduino EEPROM emulation
|
||||||
|
Copyright (c) 2018 david gauchard. 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 with 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:
|
||||||
|
|
||||||
|
- Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers.
|
||||||
|
|
||||||
|
- Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
- The names of its contributors may not be used to endorse or promote
|
||||||
|
products derived from this Software without specific prior written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
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 CONTRIBUTORS 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 WITH THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EEPROM_MOCK
|
||||||
|
#define EEPROM_MOCK
|
||||||
|
|
||||||
|
class EEPROMClass {
|
||||||
|
public:
|
||||||
|
EEPROMClass(uint32_t sector);
|
||||||
|
EEPROMClass(void);
|
||||||
|
~EEPROMClass();
|
||||||
|
|
||||||
|
void begin(size_t size);
|
||||||
|
uint8_t read(int address);
|
||||||
|
void write(int address, uint8_t val);
|
||||||
|
bool commit();
|
||||||
|
void end();
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T& get(int const address, T& t)
|
||||||
|
{
|
||||||
|
if (address < 0 || address + sizeof(T) > _size)
|
||||||
|
return t;
|
||||||
|
for (size_t i = 0; i < sizeof(T); i++)
|
||||||
|
((uint8_t*)&t)[i] = read(i);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
const T& put(int const address, const T& t)
|
||||||
|
{
|
||||||
|
if (address < 0 || address + sizeof(T) > _size)
|
||||||
|
return t;
|
||||||
|
for (size_t i = 0; i < sizeof(T); i++)
|
||||||
|
write(i, ((uint8_t*)&t)[i]);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t length() { return _size; }
|
||||||
|
|
||||||
|
//uint8_t& operator[](int const address) { return read(address); }
|
||||||
|
uint8_t operator[] (int address) { return read(address); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
size_t _size = 0;
|
||||||
|
int _fd = -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_EEPROM)
|
||||||
|
extern EEPROMClass EEPROM;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
71
tests/host/common/HostWiring.cpp
Normal file
71
tests/host/common/HostWiring.cpp
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
Arduino: wire emulation
|
||||||
|
Copyright (c) 2018 david gauchard. 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 with 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:
|
||||||
|
|
||||||
|
- Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers.
|
||||||
|
|
||||||
|
- Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
- The names of its contributors may not be used to endorse or promote
|
||||||
|
products derived from this Software without specific prior written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
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 CONTRIBUTORS 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 WITH THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
void pinMode (uint8_t pin, uint8_t mode)
|
||||||
|
{
|
||||||
|
#define xxx(mode) case mode: m=STRHELPER(mode); break
|
||||||
|
const char* m;
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case INPUT: m="INPUT"; break;
|
||||||
|
case OUTPUT: m="OUTPUT"; break;
|
||||||
|
case INPUT_PULLUP: m="INPUT_PULLUP"; break;
|
||||||
|
case OUTPUT_OPEN_DRAIN: m="OUTPUT_OPEN_DRAIN"; break;
|
||||||
|
case INPUT_PULLDOWN_16: m="INPUT_PULLDOWN_16"; break;
|
||||||
|
case WAKEUP_PULLUP: m="WAKEUP_PULLUP"; break;
|
||||||
|
case WAKEUP_PULLDOWN: m="WAKEUP_PULLDOWN"; break;
|
||||||
|
default: m="(special)";
|
||||||
|
}
|
||||||
|
fprintf(stderr, MOCK "gpio%d: mode='%s'\n", pin, m);
|
||||||
|
}
|
||||||
|
|
||||||
|
void digitalWrite(uint8_t pin, uint8_t val)
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "digitalWrite(pin=%d val=%d)\n", pin, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void analogWrite(uint8_t pin, int val)
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "analogWrite(pin=%d, val=%d\n", pin, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
int analogRead(uint8_t pin)
|
||||||
|
{
|
||||||
|
(void)pin;
|
||||||
|
return 512;
|
||||||
|
}
|
||||||
|
|
||||||
|
void analogWriteRange(uint32_t range)
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "analogWriteRange(range=%d)\n", range);
|
||||||
|
}
|
97
tests/host/common/MockEEPROM.cpp
Normal file
97
tests/host/common/MockEEPROM.cpp
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
Arduino emulation - EEPROM
|
||||||
|
Copyright (c) 2018 david gauchard. 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 with 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:
|
||||||
|
|
||||||
|
- Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers.
|
||||||
|
|
||||||
|
- Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
- The names of its contributors may not be used to endorse or promote
|
||||||
|
products derived from this Software without specific prior written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
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 CONTRIBUTORS 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 WITH THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __EEPROM_H
|
||||||
|
#define __EEPROM_H
|
||||||
|
|
||||||
|
#include <EEPROM.h>
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#define EEPROM_FILE_NAME "eeprom"
|
||||||
|
|
||||||
|
EEPROMClass::EEPROMClass ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
EEPROMClass::~EEPROMClass ()
|
||||||
|
{
|
||||||
|
if (_fd >= 0)
|
||||||
|
close(_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EEPROMClass::begin(size_t size)
|
||||||
|
{
|
||||||
|
_size = size;
|
||||||
|
if ( (_fd = open(EEPROM_FILE_NAME, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1
|
||||||
|
|| ftruncate(_fd, size) == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "EEPROM: cannot open/create '%s' for r/w: %s\n\r", EEPROM_FILE_NAME, strerror(errno));
|
||||||
|
_fd = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EEPROMClass::end()
|
||||||
|
{
|
||||||
|
if (_fd != -1)
|
||||||
|
close(_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EEPROMClass::commit()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t EEPROMClass::read (int x)
|
||||||
|
{
|
||||||
|
char c = 0;
|
||||||
|
if (pread(_fd, &c, 1, x) != 1)
|
||||||
|
fprintf(stderr, MOCK "eeprom: %s\n\r", strerror(errno));
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EEPROMClass::write (int x, uint8_t c)
|
||||||
|
{
|
||||||
|
if (x > (int)_size)
|
||||||
|
fprintf(stderr, MOCK "### eeprom beyond\r\n");
|
||||||
|
else if (pwrite(_fd, &c, 1, x) != 1)
|
||||||
|
fprintf(stderr, MOCK "eeprom: %s\n\r", strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_EEPROM)
|
||||||
|
EEPROMClass EEPROM;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
183
tests/host/common/MockEsp.cpp
Normal file
183
tests/host/common/MockEsp.cpp
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
/*
|
||||||
|
Arduino emulation - esp8266's core
|
||||||
|
Copyright (c) 2018 david gauchard. 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 with 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:
|
||||||
|
|
||||||
|
- Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers.
|
||||||
|
|
||||||
|
- Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
- The names of its contributors may not be used to endorse or promote
|
||||||
|
products derived from this Software without specific prior written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
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 CONTRIBUTORS 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 WITH THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Esp.h>
|
||||||
|
#include <eboot_command.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
unsigned long long operator"" _kHz(unsigned long long x) {
|
||||||
|
return x * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long long operator"" _MHz(unsigned long long x) {
|
||||||
|
return x * 1000 * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long long operator"" _GHz(unsigned long long x) {
|
||||||
|
return x * 1000 * 1000 * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long long operator"" _kBit(unsigned long long x) {
|
||||||
|
return x * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long long operator"" _MBit(unsigned long long x) {
|
||||||
|
return x * 1024 * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long long operator"" _GBit(unsigned long long x) {
|
||||||
|
return x * 1024 * 1024 * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long long operator"" _kB(unsigned long long x) {
|
||||||
|
return x * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long long operator"" _MB(unsigned long long x) {
|
||||||
|
return x * 1024 * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long long operator"" _GB(unsigned long long x) {
|
||||||
|
return x * 1024 * 1024 * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t _SPIFFS_start;
|
||||||
|
|
||||||
|
void eboot_command_write (struct eboot_command* cmd)
|
||||||
|
{
|
||||||
|
(void)cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
EspClass ESP;
|
||||||
|
|
||||||
|
void EspClass::restart ()
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "Esp.restart(): exiting\n");
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t EspClass::getChipId()
|
||||||
|
{
|
||||||
|
return 0xee1337;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EspClass::checkFlashConfig(bool needsEquals)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t EspClass::getSketchSize()
|
||||||
|
{
|
||||||
|
return 400000;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t EspClass::getFreeHeap()
|
||||||
|
{
|
||||||
|
return 30000;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EspClass::flashEraseSector(uint32_t sector)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
FlashMode_t EspClass::getFlashChipMode()
|
||||||
|
{
|
||||||
|
return FM_DOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
FlashMode_t EspClass::magicFlashChipMode(uint8_t byte)
|
||||||
|
{
|
||||||
|
return FM_DOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EspClass::flashWrite(uint32_t offset, uint32_t *data, size_t size)
|
||||||
|
{
|
||||||
|
(void)offset;
|
||||||
|
(void)data;
|
||||||
|
(void)size;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EspClass::flashRead(uint32_t offset, uint32_t *data, size_t size)
|
||||||
|
{
|
||||||
|
(void)offset;
|
||||||
|
(void)data;
|
||||||
|
(void)size;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t EspClass::magicFlashChipSize(uint8_t byte) {
|
||||||
|
switch(byte & 0x0F) {
|
||||||
|
case 0x0: // 4 Mbit (512KB)
|
||||||
|
return (512_kB);
|
||||||
|
case 0x1: // 2 MBit (256KB)
|
||||||
|
return (256_kB);
|
||||||
|
case 0x2: // 8 MBit (1MB)
|
||||||
|
return (1_MB);
|
||||||
|
case 0x3: // 16 MBit (2MB)
|
||||||
|
return (2_MB);
|
||||||
|
case 0x4: // 32 MBit (4MB)
|
||||||
|
return (4_MB);
|
||||||
|
case 0x8: // 64 MBit (8MB)
|
||||||
|
return (8_MB);
|
||||||
|
case 0x9: // 128 MBit (16MB)
|
||||||
|
return (16_MB);
|
||||||
|
default: // fail?
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t EspClass::getFlashChipRealSize(void)
|
||||||
|
{
|
||||||
|
return magicFlashChipSize(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t EspClass::getFlashChipSize(void)
|
||||||
|
{
|
||||||
|
return magicFlashChipSize(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
String EspClass::getFullVersion ()
|
||||||
|
{
|
||||||
|
return "host-emulation";
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t EspClass::getFreeContStack()
|
||||||
|
{
|
||||||
|
return 4000;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EspClass::resetFreeContStack()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
63
tests/host/common/MockSPI.cpp
Normal file
63
tests/host/common/MockSPI.cpp
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
Arduino emulation - spi
|
||||||
|
Copyright (c) 2018 david gauchard. 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 with 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:
|
||||||
|
|
||||||
|
- Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers.
|
||||||
|
|
||||||
|
- Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
- The names of its contributors may not be used to endorse or promote
|
||||||
|
products derived from this Software without specific prior written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
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 CONTRIBUTORS 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 WITH THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <SPI.h>
|
||||||
|
|
||||||
|
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SPI)
|
||||||
|
SPIClass SPI;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SPIClass::SPIClass ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t SPIClass::transfer(uint8_t data)
|
||||||
|
{
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPIClass::begin()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPIClass::end()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPIClass::setFrequency(uint32_t freq)
|
||||||
|
{
|
||||||
|
(void)freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPIClass::setHwCs(bool use)
|
||||||
|
{
|
||||||
|
(void)use;
|
||||||
|
}
|
112
tests/host/common/MockSerial.cpp
Normal file
112
tests/host/common/MockSerial.cpp
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
Arduino Hardware Serial emulation
|
||||||
|
Copyright (c) 2018 david gauchard. 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 with 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:
|
||||||
|
|
||||||
|
- Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers.
|
||||||
|
|
||||||
|
- Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
- The names of its contributors may not be used to endorse or promote
|
||||||
|
products derived from this Software without specific prior written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
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 CONTRIBUTORS 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 WITH THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#include <unistd.h> // write
|
||||||
|
|
||||||
|
HardwareSerial Serial(UART0);
|
||||||
|
|
||||||
|
HardwareSerial::HardwareSerial (int uart_nr)
|
||||||
|
{
|
||||||
|
if (uart_nr != 0)
|
||||||
|
fprintf(stderr, MOCK "FIXME HardwareSerial::HardwareSerial(%d)\n", uart_nr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HardwareSerial::begin (unsigned long baud, SerialConfig config, SerialMode mode, uint8_t tx_pin)
|
||||||
|
{
|
||||||
|
if (config != SERIAL_8N1 || mode != SERIAL_FULL || tx_pin != 1)
|
||||||
|
fprintf(stderr, MOCK "FIXME HardwareSerial::begin(baud=%ld config=0x%x mode=0x%x)\n", baud, (int)config, (int)mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HardwareSerial::setDebugOutput (bool on)
|
||||||
|
{
|
||||||
|
(void)on;
|
||||||
|
}
|
||||||
|
|
||||||
|
int HardwareSerial::available (void)
|
||||||
|
{
|
||||||
|
printf(MOCK "TODO HardwareSerial::available\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HardwareSerial::flush ()
|
||||||
|
{
|
||||||
|
//XXXTODO
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// uart.c
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
|
||||||
|
size_t uart_write_char (uart_t* uart, char c)
|
||||||
|
{
|
||||||
|
//XXXTODO
|
||||||
|
(void)uart;
|
||||||
|
return write(1, &c, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int uart_peek_char (uart_t* uart)
|
||||||
|
{
|
||||||
|
///XXXTODO
|
||||||
|
static bool notimpl = false;
|
||||||
|
if (!notimpl)
|
||||||
|
{
|
||||||
|
notimpl = true;
|
||||||
|
fprintf(stderr, MOCK "FIXME uart_peek_char\n");
|
||||||
|
}
|
||||||
|
(void)uart;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int uart_read_char (uart_t* uart)
|
||||||
|
{
|
||||||
|
///XXXTODO
|
||||||
|
static bool notimpl = false;
|
||||||
|
if (!notimpl)
|
||||||
|
{
|
||||||
|
notimpl = true;
|
||||||
|
fprintf(stderr, MOCK "FIXME uart_read_char\n");
|
||||||
|
}
|
||||||
|
(void)uart;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t uart_write (uart_t* uart, const char* buf, size_t size)
|
||||||
|
{
|
||||||
|
///XXXTODO
|
||||||
|
(void)uart;
|
||||||
|
return write(1, buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // extern "C"
|
79
tests/host/common/MockTools.cpp
Normal file
79
tests/host/common/MockTools.cpp
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
Arduino emulation - tools
|
||||||
|
Copyright (c) 2018 david gauchard. 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 with 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:
|
||||||
|
|
||||||
|
- Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers.
|
||||||
|
|
||||||
|
- Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
- The names of its contributors may not be used to endorse or promote
|
||||||
|
products derived from this Software without specific prior written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
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 CONTRIBUTORS 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 WITH THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
|
||||||
|
uint32_t lwip_htonl (uint32_t hostlong) { return htonl(hostlong); }
|
||||||
|
uint16_t lwip_htons (uint16_t hostshort) { return htons(hostshort); }
|
||||||
|
uint32_t lwip_ntohl (uint32_t netlong) { return ntohl(netlong); }
|
||||||
|
uint16_t lwip_ntohs (uint16_t netshort) { return ntohs(netshort); }
|
||||||
|
|
||||||
|
char* ets_strcpy (char* d, const char* s) { return strcpy(d, s); }
|
||||||
|
size_t ets_strlen (const char* s) { return strlen(s); }
|
||||||
|
|
||||||
|
int ets_printf (const char* fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
int len = vprintf(fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void configTime(long timezone, int daylightOffset_sec,
|
||||||
|
const char* server1, const char* server2, const char* server3)
|
||||||
|
{
|
||||||
|
(void)server1;
|
||||||
|
(void)server2;
|
||||||
|
(void)server3;
|
||||||
|
|
||||||
|
fprintf(stderr, MOCK "configTime: TODO (tz=%ldH offset=%dS) (time will be host's)\n", timezone, daylightOffset_sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void stack_thunk_add_ref() { }
|
||||||
|
void stack_thunk_del_ref() { }
|
||||||
|
void stack_thunk_repaint() { }
|
||||||
|
|
||||||
|
uint32_t stack_thunk_get_refcnt() { return 0; }
|
||||||
|
uint32_t stack_thunk_get_stack_top() { return 0; }
|
||||||
|
uint32_t stack_thunk_get_stack_bot() { return 0; }
|
||||||
|
uint32_t stack_thunk_get_cont_sp() { return 0; }
|
||||||
|
uint32_t stack_thunk_get_max_usage() { return 0; }
|
||||||
|
void stack_thunk_dump_stack() { }
|
||||||
|
|
||||||
|
// Thunking macro
|
||||||
|
#define make_stack_thunk(fcnToThunk)
|
||||||
|
|
||||||
|
};
|
82
tests/host/common/MockWiFiServer.cpp
Normal file
82
tests/host/common/MockWiFiServer.cpp
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
Arduino emulation - WiFiServer
|
||||||
|
Copyright (c) 2018 david gauchard. 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 with 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:
|
||||||
|
|
||||||
|
- Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers.
|
||||||
|
|
||||||
|
- Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
- The names of its contributors may not be used to endorse or promote
|
||||||
|
products derived from this Software without specific prior written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
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 CONTRIBUTORS 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 WITH THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <WiFiClient.h>
|
||||||
|
#include <WiFiServer.h>
|
||||||
|
|
||||||
|
#include <lwip/err.h>
|
||||||
|
#include <lwip/ip_addr.h>
|
||||||
|
|
||||||
|
#include <include/ClientContext.h>
|
||||||
|
|
||||||
|
extern "C" const ip_addr_t ip_addr_any = IPADDR4_INIT(IPADDR_ANY);
|
||||||
|
|
||||||
|
#define int2pcb(x) ((tcp_pcb*)(intptr_t)(x))
|
||||||
|
#define pcb2int(x) ((int)(intptr_t)(x))
|
||||||
|
|
||||||
|
// lwIP API side of WiFiServer
|
||||||
|
|
||||||
|
WiFiServer::WiFiServer (IPAddress addr, uint16_t port)
|
||||||
|
{
|
||||||
|
(void)addr;
|
||||||
|
if (port < 1024)
|
||||||
|
{
|
||||||
|
int newport = port + 9000;
|
||||||
|
fprintf(stderr, MOCK "WiFiServer port: %d -> %d\n", port, newport);
|
||||||
|
port = newport;
|
||||||
|
}
|
||||||
|
_port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
WiFiServer::WiFiServer (uint16_t port)
|
||||||
|
{
|
||||||
|
if (port < 1024)
|
||||||
|
{
|
||||||
|
int newport = port + 9000;
|
||||||
|
fprintf(stderr, MOCK "WiFiServer port: %d -> %d\n", port, newport);
|
||||||
|
port = newport;
|
||||||
|
}
|
||||||
|
_port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
WiFiClient WiFiServer::available (uint8_t* status)
|
||||||
|
{
|
||||||
|
(void)status;
|
||||||
|
if (hasClient())
|
||||||
|
return WiFiClient(new ClientContext(serverAccept(pcb2int(_pcb))));
|
||||||
|
return WiFiClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
// static declaration
|
||||||
|
|
||||||
|
#include <include/UdpContext.h>
|
||||||
|
uint32_t UdpContext::staticMCastAddr = 0;
|
||||||
|
|
127
tests/host/common/MockWiFiServerSocket.cpp
Normal file
127
tests/host/common/MockWiFiServerSocket.cpp
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
Arduino emulation - WiFiServer socket side
|
||||||
|
Copyright (c) 2018 david gauchard. 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 with 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:
|
||||||
|
|
||||||
|
- Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers.
|
||||||
|
|
||||||
|
- Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
- The names of its contributors may not be used to endorse or promote
|
||||||
|
products derived from this Software without specific prior written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
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 CONTRIBUTORS 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 WITH THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <WiFiServer.h>
|
||||||
|
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define int2pcb(x) ((tcp_pcb*)(intptr_t)(x))
|
||||||
|
#define pcb2int(x) ((int)(intptr_t)(x))
|
||||||
|
|
||||||
|
// host socket internal side of WiFiServer
|
||||||
|
|
||||||
|
int serverAccept (int srvsock)
|
||||||
|
{
|
||||||
|
int clisock;
|
||||||
|
socklen_t n;
|
||||||
|
struct sockaddr_in client;
|
||||||
|
n = sizeof(client);
|
||||||
|
if ((clisock = accept(srvsock, (struct sockaddr*)&client, &n)) == -1)
|
||||||
|
{
|
||||||
|
perror("accept()");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
return clisock;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WiFiServer::begin (uint16_t port)
|
||||||
|
{
|
||||||
|
_port = port;
|
||||||
|
return begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WiFiServer::begin ()
|
||||||
|
{
|
||||||
|
int sock;
|
||||||
|
struct sockaddr_in server;
|
||||||
|
|
||||||
|
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
|
||||||
|
{
|
||||||
|
perror(MOCK "socket()");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int optval = 1;
|
||||||
|
if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)) == -1)
|
||||||
|
{
|
||||||
|
perror(MOCK "reuseport");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
server.sin_family = AF_INET;
|
||||||
|
server.sin_port = htons(_port);
|
||||||
|
server.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
if (bind(sock, (struct sockaddr*)&server, sizeof(server)) == -1)
|
||||||
|
{
|
||||||
|
perror(MOCK "bind()");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listen(sock, 1) == -1)
|
||||||
|
{
|
||||||
|
perror(MOCK "listen()");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// store int into pointer
|
||||||
|
_pcb = int2pcb(sock);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WiFiServer::hasClient ()
|
||||||
|
{
|
||||||
|
struct pollfd p;
|
||||||
|
p.fd = pcb2int(_pcb);
|
||||||
|
p.events = POLLIN;
|
||||||
|
return poll(&p, 1, 0) && p.revents == POLLIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t WiFiServer::write (uint8_t c)
|
||||||
|
{
|
||||||
|
return write(&c, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t WiFiServer::write (const uint8_t *buf, size_t size)
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "todo: WiFiServer::write(%p, %zd)\n", buf, size);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WiFiServer::close ()
|
||||||
|
{
|
||||||
|
if (pcb2int(_pcb) >= 0)
|
||||||
|
::close(pcb2int(_pcb));
|
||||||
|
_pcb = int2pcb(-1);
|
||||||
|
}
|
182
tests/host/common/UdpContextSocket.cpp
Normal file
182
tests/host/common/UdpContextSocket.cpp
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
/*
|
||||||
|
Arduino emulation - UdpContext emulation - socket part
|
||||||
|
Copyright (c) 2018 david gauchard. 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 with 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:
|
||||||
|
|
||||||
|
- Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers.
|
||||||
|
|
||||||
|
- Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
- The names of its contributors may not be used to endorse or promote
|
||||||
|
products derived from this Software without specific prior written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
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 CONTRIBUTORS 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 WITH THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
int mockUDPSocket ()
|
||||||
|
{
|
||||||
|
int s;
|
||||||
|
if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1 || fcntl(s, F_SETFL, O_NONBLOCK) == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "UDP socket: %s", strerror(errno));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mockUDPListen (int sock, uint32_t dstaddr, uint16_t port, uint32_t mcast)
|
||||||
|
{
|
||||||
|
int optval = 1;
|
||||||
|
if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)) == -1)
|
||||||
|
fprintf(stderr, MOCK "SO_REUSEPORT failed\n");
|
||||||
|
optval = 1;
|
||||||
|
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1)
|
||||||
|
fprintf(stderr, MOCK "SO_REUSEADDR failed\n");
|
||||||
|
|
||||||
|
struct sockaddr_in servaddr;
|
||||||
|
memset(&servaddr, 0, sizeof(servaddr));
|
||||||
|
|
||||||
|
// Filling server information
|
||||||
|
servaddr.sin_family = AF_INET;
|
||||||
|
//servaddr.sin_addr.s_addr = global_ipv4_netfmt?: dstaddr;
|
||||||
|
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
servaddr.sin_port = htons(port);
|
||||||
|
|
||||||
|
// Bind the socket with the server address
|
||||||
|
if (bind(sock, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "UDP bind on port %d failed: %s\n", port, strerror(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fprintf(stderr, MOCK "UDP server on port %d (sock=%d)\n", (int)port, sock);
|
||||||
|
|
||||||
|
if (mcast)
|
||||||
|
{
|
||||||
|
// https://web.cs.wpi.edu/~claypool/courses/4514-B99/samples/multicast.c
|
||||||
|
// https://stackoverflow.com/questions/12681097/c-choose-interface-for-udp-multicast-socket
|
||||||
|
|
||||||
|
struct ip_mreq mreq;
|
||||||
|
mreq.imr_multiaddr.s_addr = mcast;
|
||||||
|
//mreq.imr_interface.s_addr = global_ipv4_netfmt?: htonl(INADDR_ANY);
|
||||||
|
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
|
||||||
|
if (global_ipv4_netfmt)
|
||||||
|
{
|
||||||
|
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, host_interface, strlen(host_interface)) == -1)
|
||||||
|
fprintf(stderr, MOCK "UDP multicast: can't setup bind/output on interface %s: %s\n", host_interface, strerror(errno));
|
||||||
|
if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, &mreq.imr_interface, sizeof(struct in_addr)) == -1)
|
||||||
|
fprintf(stderr, MOCK "UDP multicast: can't setup bind/input on interface %s: %s\n", host_interface, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "can't join multicast group addr %08x\n", (int)mcast);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t mockUDPFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize, uint8_t& addrsize, uint8_t addr[16], uint16_t& port)
|
||||||
|
{
|
||||||
|
struct sockaddr_storage addrbuf;
|
||||||
|
socklen_t addrbufsize = std::min((socklen_t)sizeof(addrbuf), (socklen_t)16);
|
||||||
|
|
||||||
|
size_t maxread = CCBUFSIZE - ccinbufsize;
|
||||||
|
ssize_t ret = ::recvfrom(sock, ccinbuf + ccinbufsize, maxread, 0/*flags*/, (sockaddr*)&addrbuf, &addrbufsize);
|
||||||
|
if (ret == -1)
|
||||||
|
{
|
||||||
|
if (errno != EAGAIN)
|
||||||
|
fprintf(stderr, MOCK "UDPContext::(read/peek): filling buffer for %zd bytes: %s\n", maxread, strerror(errno));
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret > 0)
|
||||||
|
{
|
||||||
|
port = ntohs(((sockaddr_in*)&addrbuf)->sin_port);
|
||||||
|
if (addrbuf.ss_family == AF_INET)
|
||||||
|
memcpy(&addr[0], &(((sockaddr_in*)&addrbuf)->sin_addr.s_addr), addrsize = 4);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "TODO UDP+IPv6\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ccinbufsize += ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t mockUDPPeekBytes (int sock, char* dst, size_t usersize, int timeout_ms, char* ccinbuf, size_t& ccinbufsize)
|
||||||
|
{
|
||||||
|
if (usersize > CCBUFSIZE)
|
||||||
|
fprintf(stderr, MOCK "CCBUFSIZE(%d) should be increased by %zd bytes (-> %zd)\n", CCBUFSIZE, usersize - CCBUFSIZE, usersize);
|
||||||
|
|
||||||
|
size_t retsize = 0;
|
||||||
|
if (ccinbufsize)
|
||||||
|
{
|
||||||
|
// data already buffered
|
||||||
|
retsize = usersize;
|
||||||
|
if (retsize > ccinbufsize)
|
||||||
|
retsize = ccinbufsize;
|
||||||
|
}
|
||||||
|
memcpy(dst, ccinbuf, retsize);
|
||||||
|
return retsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t mockUDPRead (int sock, char* dst, size_t size, int timeout_ms, char* ccinbuf, size_t& ccinbufsize)
|
||||||
|
{
|
||||||
|
size_t copied = mockUDPPeekBytes(sock, dst, size, timeout_ms, ccinbuf, ccinbufsize);
|
||||||
|
// swallow (XXX use a circular buffer?)
|
||||||
|
memmove(ccinbuf, ccinbuf + copied, ccinbufsize - copied);
|
||||||
|
ccinbufsize -= copied;
|
||||||
|
return copied;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t mockUDPWrite (int sock, const uint8_t* data, size_t size, int timeout_ms, uint32_t ipv4, uint16_t port)
|
||||||
|
{
|
||||||
|
// Filling server information
|
||||||
|
struct sockaddr_in peer;
|
||||||
|
peer.sin_family = AF_INET;
|
||||||
|
peer.sin_addr.s_addr = ipv4; //XXFIXME should use lwip_htonl?
|
||||||
|
peer.sin_port = htons(port);
|
||||||
|
int ret = ::sendto(sock, data, size, 0/*flags*/, (const sockaddr*)&peer, sizeof(peer));
|
||||||
|
if (ret == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "UDPContext::write: write(%d): %s\n", sock, strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (ret != (int)size)
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "UDPContext::write: short write (%d < %zd) (TODO)\n", ret, size);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
void randomSeed(unsigned long seed) {
|
void randomSeed(unsigned long seed) {
|
||||||
@ -52,10 +53,10 @@ long map(long x, long in_min, long in_max, long out_min, long out_max) {
|
|||||||
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int makeWord(unsigned int w) {
|
uint16_t makeWord(unsigned int w) {
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int makeWord(unsigned char h, unsigned char l) {
|
uint16_t makeWord(unsigned char h, unsigned char l) {
|
||||||
return (h << 8) | l;
|
return (h << 8) | l;
|
||||||
}
|
}
|
||||||
|
115
tests/host/common/c_types.h
Normal file
115
tests/host/common/c_types.h
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
|
||||||
|
// This is a copy of SDK's "c_type.h"
|
||||||
|
// with conflicting declarations commented out
|
||||||
|
// (search CONFLICT in this file)
|
||||||
|
|
||||||
|
// diff -u common/c_types.h ../../tools/sdk/include/c_types.h
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ESPRESSIF MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case,
|
||||||
|
* it is 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 _C_TYPES_H_
|
||||||
|
#define _C_TYPES_H_
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
typedef signed char sint8_t;
|
||||||
|
typedef signed short sint16_t;
|
||||||
|
typedef signed long sint32_t;
|
||||||
|
typedef signed long long sint64_t;
|
||||||
|
// CONFLICT typedef unsigned long long u_int64_t;
|
||||||
|
typedef float real32_t;
|
||||||
|
typedef double real64_t;
|
||||||
|
|
||||||
|
typedef unsigned char uint8;
|
||||||
|
typedef unsigned char u8;
|
||||||
|
typedef signed char sint8;
|
||||||
|
typedef signed char int8;
|
||||||
|
typedef signed char s8;
|
||||||
|
typedef unsigned short uint16;
|
||||||
|
typedef unsigned short u16;
|
||||||
|
typedef signed short sint16;
|
||||||
|
typedef signed short s16;
|
||||||
|
typedef unsigned int uint32;
|
||||||
|
typedef unsigned int u_int;
|
||||||
|
typedef unsigned int u32;
|
||||||
|
typedef signed int sint32;
|
||||||
|
typedef signed int s32;
|
||||||
|
typedef int int32;
|
||||||
|
typedef signed long long sint64;
|
||||||
|
typedef unsigned long long uint64;
|
||||||
|
typedef unsigned long long u64;
|
||||||
|
typedef float real32;
|
||||||
|
typedef double real64;
|
||||||
|
|
||||||
|
#define __le16 u16
|
||||||
|
|
||||||
|
#define LOCAL static
|
||||||
|
|
||||||
|
#ifndef NULL
|
||||||
|
#define NULL (void *)0
|
||||||
|
#endif /* NULL */
|
||||||
|
|
||||||
|
/* probably should not put STATUS here */
|
||||||
|
typedef enum {
|
||||||
|
OK = 0,
|
||||||
|
FAIL,
|
||||||
|
PENDING,
|
||||||
|
BUSY,
|
||||||
|
CANCEL,
|
||||||
|
} STATUS;
|
||||||
|
|
||||||
|
#define BIT(nr) (1UL << (nr))
|
||||||
|
|
||||||
|
#define REG_SET_BIT(_r, _b) (*(volatile uint32_t*)(_r) |= (_b))
|
||||||
|
#define REG_CLR_BIT(_r, _b) (*(volatile uint32_t*)(_r) &= ~(_b))
|
||||||
|
|
||||||
|
#define DMEM_ATTR __attribute__((section(".bss")))
|
||||||
|
#define SHMEM_ATTR
|
||||||
|
|
||||||
|
#ifdef ICACHE_FLASH
|
||||||
|
#define __ICACHE_STRINGIZE_NX(A) #A
|
||||||
|
#define __ICACHE_STRINGIZE(A) __ICACHE_STRINGIZE_NX(A)
|
||||||
|
#define ICACHE_FLASH_ATTR __attribute__((section("\".irom0.text." __FILE__ "." __ICACHE_STRINGIZE(__LINE__) "." __ICACHE_STRINGIZE(__COUNTER__) "\"")))
|
||||||
|
#define ICACHE_RAM_ATTR __attribute__((section("\".iram.text." __FILE__ "." __ICACHE_STRINGIZE(__LINE__) "." __ICACHE_STRINGIZE(__COUNTER__) "\"")))
|
||||||
|
#define ICACHE_RODATA_ATTR __attribute__((section("\".irom.text." __FILE__ "." __ICACHE_STRINGIZE(__LINE__) "." __ICACHE_STRINGIZE(__COUNTER__) "\"")))
|
||||||
|
#else
|
||||||
|
#define ICACHE_FLASH_ATTR
|
||||||
|
#define ICACHE_RAM_ATTR
|
||||||
|
#define ICACHE_RODATA_ATTR
|
||||||
|
#endif /* ICACHE_FLASH */
|
||||||
|
|
||||||
|
#define STORE_ATTR __attribute__((aligned(4)))
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#define BOOL bool
|
||||||
|
#define TRUE true
|
||||||
|
#define FALSE false
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* !__cplusplus */
|
||||||
|
|
||||||
|
#endif /* _C_TYPES_H_ */
|
7
tests/host/common/esp8266_peri.h
Normal file
7
tests/host/common/esp8266_peri.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
#ifndef FAKE_ESP8266_PERI_H
|
||||||
|
#define FAKE_ESP8266_PERI_H
|
||||||
|
|
||||||
|
const int GPI = 0;
|
||||||
|
|
||||||
|
#endif
|
286
tests/host/common/include/ClientContext.h
Normal file
286
tests/host/common/include/ClientContext.h
Normal file
@ -0,0 +1,286 @@
|
|||||||
|
/*
|
||||||
|
ClientContext.h - emulation of TCP connection handling on top of lwIP
|
||||||
|
|
||||||
|
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
|
||||||
|
This file is part of the esp8266 core for Arduino environment.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#ifndef CLIENTCONTEXT_H
|
||||||
|
#define CLIENTCONTEXT_H
|
||||||
|
|
||||||
|
class ClientContext;
|
||||||
|
class WiFiClient;
|
||||||
|
|
||||||
|
extern "C" void esp_yield();
|
||||||
|
extern "C" void esp_schedule();
|
||||||
|
|
||||||
|
#include <include/DataSource.h>
|
||||||
|
|
||||||
|
bool getDefaultPrivateGlobalSyncValue ();
|
||||||
|
|
||||||
|
typedef void (*discard_cb_t)(void*, ClientContext*);
|
||||||
|
|
||||||
|
class ClientContext
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ClientContext(tcp_pcb* pcb, discard_cb_t discard_cb, void* discard_cb_arg) :
|
||||||
|
_discard_cb(discard_cb), _discard_cb_arg(discard_cb_arg), _refcnt(0), _next(0),
|
||||||
|
_sync(::getDefaultPrivateGlobalSyncValue()), _sock(-1)
|
||||||
|
{
|
||||||
|
(void)pcb;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientContext (int sock) :
|
||||||
|
_discard_cb(nullptr), _discard_cb_arg(nullptr), _refcnt(0), _next(nullptr),
|
||||||
|
_sync(::getDefaultPrivateGlobalSyncValue()), _sock(sock)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
err_t abort()
|
||||||
|
{
|
||||||
|
if (_sock >= 0)
|
||||||
|
::close(_sock);
|
||||||
|
_sock = -1;
|
||||||
|
return ERR_ABRT;
|
||||||
|
}
|
||||||
|
|
||||||
|
err_t close()
|
||||||
|
{
|
||||||
|
abort();
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
~ClientContext()
|
||||||
|
{
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientContext* next() const
|
||||||
|
{
|
||||||
|
return _next;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientContext* next(ClientContext* new_next)
|
||||||
|
{
|
||||||
|
_next = new_next;
|
||||||
|
return _next;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ref()
|
||||||
|
{
|
||||||
|
++_refcnt;
|
||||||
|
DEBUGV(":ref %d\r\n", _refcnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void unref()
|
||||||
|
{
|
||||||
|
DEBUGV(":ur %d\r\n", _refcnt);
|
||||||
|
if(--_refcnt == 0) {
|
||||||
|
discard_received();
|
||||||
|
close();
|
||||||
|
if (_discard_cb)
|
||||||
|
_discard_cb(_discard_cb_arg, this);
|
||||||
|
DEBUGV(":del\r\n");
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int connect(ip_addr_t* addr, uint16_t port)
|
||||||
|
{
|
||||||
|
return mockConnect(addr->addr, _sock, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t availableForWrite()
|
||||||
|
{
|
||||||
|
// XXXFIXME be smarter
|
||||||
|
return 512;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setNoDelay(bool nodelay)
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "TODO setNoDelay(%d)\n", (int)nodelay);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getNoDelay() const
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "TODO getNoDelay()\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setTimeout(int timeout_ms)
|
||||||
|
{
|
||||||
|
_timeout_ms = timeout_ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getTimeout() const
|
||||||
|
{
|
||||||
|
return _timeout_ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t getRemoteAddress() const
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "TODO getRemoteAddress()\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t getRemotePort() const
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "TODO getRemotePort()\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t getLocalAddress() const
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "TODO getLocalAddress()\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t getLocalPort() const
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "TODO getLocalPort()\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getSize()
|
||||||
|
{
|
||||||
|
return _inbufsize?: mockFillInBuf(_sock, _inbuf, _inbufsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
int read()
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
return read(&c, 1)? c: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t read (char* dst, size_t size)
|
||||||
|
{
|
||||||
|
return mockRead(_sock, dst, size, 0, _inbuf, _inbufsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
int peek()
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
return peekBytes(&c, 1)? c: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t peekBytes(char *dst, size_t size)
|
||||||
|
{
|
||||||
|
return mockPeekBytes(_sock, dst, size, _timeout_ms, _inbuf, _inbufsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void discard_received()
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "TODO: ClientContext::discard_received()\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wait_until_sent(int max_wait_ms = WIFICLIENT_MAX_FLUSH_WAIT_MS)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t state() const
|
||||||
|
{
|
||||||
|
return _sock >= 0? ESTABLISHED: CLOSED;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t write(const uint8_t* data, size_t size)
|
||||||
|
{
|
||||||
|
return mockWrite(_sock, data, size, _timeout_ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t write(Stream& stream)
|
||||||
|
{
|
||||||
|
size_t avail = stream.available();
|
||||||
|
uint8_t buf [avail];
|
||||||
|
avail = stream.readBytes(buf, avail);
|
||||||
|
size_t totwrote = 0;
|
||||||
|
uint8_t* w = buf;
|
||||||
|
while (avail)
|
||||||
|
{
|
||||||
|
size_t wrote = write(w, avail);
|
||||||
|
w += wrote;
|
||||||
|
avail -= wrote;
|
||||||
|
totwrote += wrote;
|
||||||
|
}
|
||||||
|
return totwrote;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t write_P(PGM_P buf, size_t size)
|
||||||
|
{
|
||||||
|
return write((const uint8_t*)buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void keepAlive (uint16_t idle_sec = TCP_DEFAULT_KEEPALIVE_IDLE_SEC, uint16_t intv_sec = TCP_DEFAULT_KEEPALIVE_INTERVAL_SEC, uint8_t count = TCP_DEFAULT_KEEPALIVE_COUNT)
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "TODO ClientContext::keepAlive()\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isKeepAliveEnabled () const
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "TODO ClientContext::isKeepAliveEnabled()\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t getKeepAliveIdle () const
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "TODO ClientContext::getKeepAliveIdle()\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t getKeepAliveInterval () const
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "TODO ClientContext::getKeepAliveInternal()\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t getKeepAliveCount () const
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "TODO ClientContext::getKeepAliveCount()\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getSync () const
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "TODO ClientContext::getSync()\n");
|
||||||
|
return _sync;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSync (bool sync)
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "TODO ClientContext::setSync()\n");
|
||||||
|
_sync = sync;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
discard_cb_t _discard_cb = nullptr;
|
||||||
|
void* _discard_cb_arg = nullptr;
|
||||||
|
|
||||||
|
int8_t _refcnt;
|
||||||
|
ClientContext* _next;
|
||||||
|
|
||||||
|
bool _sync;
|
||||||
|
|
||||||
|
// MOCK
|
||||||
|
|
||||||
|
int _sock = -1;
|
||||||
|
int _timeout_ms = 5000;
|
||||||
|
|
||||||
|
char _inbuf [CCBUFSIZE];
|
||||||
|
size_t _inbufsize = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //CLIENTCONTEXT_H
|
254
tests/host/common/include/UdpContext.h
Normal file
254
tests/host/common/include/UdpContext.h
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
/*
|
||||||
|
UdpContext.h - emulation of UDP connection handling on top of lwIP
|
||||||
|
|
||||||
|
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
|
||||||
|
This file is part of the esp8266 core for Arduino environment.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#ifndef UDPCONTEXT_H
|
||||||
|
#define UDPCONTEXT_H
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
class UdpContext;
|
||||||
|
|
||||||
|
#define GET_IP_HDR(pb) reinterpret_cast<ip_hdr*>(((uint8_t*)((pb)->payload)) - UDP_HLEN - IP_HLEN);
|
||||||
|
#define GET_UDP_HDR(pb) reinterpret_cast<udp_hdr*>(((uint8_t*)((pb)->payload)) - UDP_HLEN);
|
||||||
|
|
||||||
|
class UdpContext
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef std::function<void(void)> rxhandler_t;
|
||||||
|
|
||||||
|
UdpContext(): _on_rx(nullptr), _refcnt(0)
|
||||||
|
{
|
||||||
|
_sock = mockUDPSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
~UdpContext()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ref()
|
||||||
|
{
|
||||||
|
++_refcnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void unref()
|
||||||
|
{
|
||||||
|
if(--_refcnt == 0) {
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool connect (ip_addr_t addr, uint16_t port)
|
||||||
|
{
|
||||||
|
_dst = addr;
|
||||||
|
_dstport = port;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool listen(ip_addr_t addr, uint16_t port)
|
||||||
|
{
|
||||||
|
bool ret = mockUDPListen(_sock, addr.addr, port, staticMCastAddr);
|
||||||
|
register_udp(_sock, this);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void disconnect()
|
||||||
|
{
|
||||||
|
if (_sock >= 0)
|
||||||
|
{
|
||||||
|
close(_sock);
|
||||||
|
register_udp(_sock, nullptr);
|
||||||
|
}
|
||||||
|
_sock = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setMulticastInterface(const ip_addr_t& addr)
|
||||||
|
{
|
||||||
|
// user multicast, and this is how it works with posix: send to multicast address:
|
||||||
|
_dst.addr = staticMCastAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setMulticastTTL(int ttl)
|
||||||
|
{
|
||||||
|
//fprintf(stderr, MOCK "TODO: UdpContext::setMulticastTTL\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// warning: handler is called from tcp stack context
|
||||||
|
// esp_yield and non-reentrant functions which depend on it will fail
|
||||||
|
void onRx(rxhandler_t handler) {
|
||||||
|
_on_rx = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getSize()
|
||||||
|
{
|
||||||
|
return _inbufsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t tell() const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void seek(const size_t pos)
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "TODO: implement UDP offset\n");
|
||||||
|
if (!isValidOffset(pos))
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "UDPContext::seek too far (%zd >= %zd)\n", pos, _inbufsize);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isValidOffset(const size_t pos) const {
|
||||||
|
return pos <= _inbufsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t getRemoteAddress()
|
||||||
|
{
|
||||||
|
return _dst.addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t getRemotePort()
|
||||||
|
{
|
||||||
|
return _dstport;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t getDestAddress()
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "TODO: implement UDP getDestAddress\n");
|
||||||
|
return 0; //ip_hdr* iphdr = GET_IP_HDR(_rx_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t getLocalPort()
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "TODO: implement UDP getLocalPort\n");
|
||||||
|
return 0; //
|
||||||
|
}
|
||||||
|
|
||||||
|
bool next()
|
||||||
|
{
|
||||||
|
_inbufsize = 0;
|
||||||
|
mockUDPFillInBuf(_sock, _inbuf, _inbufsize, addrsize, addr, _dstport);
|
||||||
|
if (_inbufsize > 0)
|
||||||
|
{
|
||||||
|
translate_addr();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int read()
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
return read(&c, 1)? c: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t read(char* dst, size_t size)
|
||||||
|
{
|
||||||
|
return mockUDPRead(_sock, dst, size, _timeout_ms, _inbuf, _inbufsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
int peek()
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
return mockUDPPeekBytes(_sock, &c, 1, _timeout_ms, _inbuf, _inbufsize)?: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void flush()
|
||||||
|
{
|
||||||
|
//fprintf(stderr, MOCK "UdpContext::flush() does not follow arduino's flush concept\n");
|
||||||
|
//exit(EXIT_FAILURE);
|
||||||
|
// would be:
|
||||||
|
_inbufsize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t append (const char* data, size_t size)
|
||||||
|
{
|
||||||
|
if (size + _outbufsize > sizeof _outbuf)
|
||||||
|
{
|
||||||
|
fprintf(stderr, MOCK "UdpContext::append: increase CCBUFSIZE (%d -> %zd)\n", CCBUFSIZE, (size + _outbufsize));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(_outbuf + _outbufsize, data, size);
|
||||||
|
_outbufsize += size;
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool send (ip_addr_t* addr = 0, uint16_t port = 0)
|
||||||
|
{
|
||||||
|
uint32_t dst = addr? addr->addr: _dst.addr;
|
||||||
|
uint16_t dstport = port?: _dstport;
|
||||||
|
size_t ret = mockUDPWrite(_sock, (const uint8_t*)_outbuf, _outbufsize, _timeout_ms, dst, dstport);
|
||||||
|
_outbufsize = 0;
|
||||||
|
return ret > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mock_cb (void)
|
||||||
|
{
|
||||||
|
if (_on_rx) _on_rx();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
static uint32_t staticMCastAddr;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void translate_addr ()
|
||||||
|
{
|
||||||
|
if (addrsize == 4)
|
||||||
|
{
|
||||||
|
uint32_t ipv4;
|
||||||
|
memcpy(&ipv4, addr, 4);
|
||||||
|
ip4_addr_set_u32(&ip_2_ip4(_dst), ipv4);
|
||||||
|
// ^ this is a workaround for "type-punned pointer" with "*(uint32*)addr"
|
||||||
|
//ip4_addr_set_u32(&ip_2_ip4(_dst), *(uint32_t*)addr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fprintf(stderr, MOCK "TODO unhandled udp address of size %d\n", (int)addrsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _sock = -1;
|
||||||
|
rxhandler_t _on_rx;
|
||||||
|
int _refcnt = 0;
|
||||||
|
|
||||||
|
ip_addr_t _dst;
|
||||||
|
uint16_t _dstport;
|
||||||
|
|
||||||
|
char _inbuf [CCBUFSIZE];
|
||||||
|
size_t _inbufsize = 0;
|
||||||
|
char _outbuf [CCBUFSIZE];
|
||||||
|
size_t _outbufsize = 0;
|
||||||
|
|
||||||
|
int _timeout_ms = 0;
|
||||||
|
|
||||||
|
uint8_t addrsize;
|
||||||
|
uint8_t addr[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
inline err_t igmp_joingroup (const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr)
|
||||||
|
{
|
||||||
|
(void)ifaddr;
|
||||||
|
UdpContext::staticMCastAddr = groupaddr->addr;
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif//UDPCONTEXT_H
|
0
tests/host/common/interrupts.h
Normal file
0
tests/host/common/interrupts.h
Normal file
1
tests/host/common/machine/ansi.h
Normal file
1
tests/host/common/machine/ansi.h
Normal file
@ -0,0 +1 @@
|
|||||||
|
/* dummy header file to support BSD compiler */
|
121
tests/host/common/mock.h
Normal file
121
tests/host/common/mock.h
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
Arduino emulation - common to all emulated code
|
||||||
|
Copyright (c) 2018 david gauchard. 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 with 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:
|
||||||
|
|
||||||
|
- Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers.
|
||||||
|
|
||||||
|
- Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
- The names of its contributors may not be used to endorse or promote
|
||||||
|
products derived from this Software without specific prior written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
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 CONTRIBUTORS 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 WITH THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// include host's STL before any other include file
|
||||||
|
// because core definition like max() is in the way
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#include <vector>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// exotic typedefs used in the sdk
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
typedef uint8_t uint8;
|
||||||
|
typedef uint32_t uint32;
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#define RANDOM_REG32 ((uint32_t)random())
|
||||||
|
|
||||||
|
// net tweak
|
||||||
|
|
||||||
|
// htontoh code in common/MockTools.cpp
|
||||||
|
#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS
|
||||||
|
#undef INADDR_NONE
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
int ets_printf (const char* fmt, ...) __attribute__ ((format (printf, 1, 2)));
|
||||||
|
#define os_printf_plus printf
|
||||||
|
|
||||||
|
extern const char* host_interface; // cmdline parameter
|
||||||
|
|
||||||
|
#define NO_GLOBAL_BINDING 0xffffffff
|
||||||
|
extern uint32_t global_ipv4_netfmt; // selected interface addresse to bind to
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
#ifndef CCBUFSIZE
|
||||||
|
#define CCBUFSIZE 8192
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// tcp
|
||||||
|
int mockConnect (uint32_t addr, int& sock, int port);
|
||||||
|
size_t mockFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize);
|
||||||
|
size_t mockPeekBytes (int sock, char* dst, size_t size, int timeout_ms, char* buf, size_t& bufsize);
|
||||||
|
size_t mockRead (int sock, char* dst, size_t size, int timeout_ms, char* buf, size_t& bufsize);
|
||||||
|
size_t mockWrite (int sock, const uint8_t* data, size_t size, int timeout_ms);
|
||||||
|
int serverAccept (int sock);
|
||||||
|
|
||||||
|
// udp
|
||||||
|
int mockUDPSocket ();
|
||||||
|
bool mockUDPListen (int sock, uint32_t dstaddr, uint16_t port, uint32_t mcast = 0);
|
||||||
|
size_t mockUDPFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize, uint8_t& addrsize, uint8_t addr[16], uint16_t& port);
|
||||||
|
size_t mockUDPPeekBytes (int sock, char* dst, size_t usersize, int timeout_ms, char* ccinbuf, size_t& ccinbufsize);
|
||||||
|
size_t mockUDPRead (int sock, char* dst, size_t size, int timeout_ms, char* ccinbuf, size_t& ccinbufsize);
|
||||||
|
size_t mockUDPWrite (int sock, const uint8_t* data, size_t size, int timeout_ms, uint32_t ipv4, uint16_t port);
|
||||||
|
|
||||||
|
class UdpContext;
|
||||||
|
void register_udp (int sock, UdpContext* udp = nullptr);
|
||||||
|
|
||||||
|
class InterruptLock { };
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
#define CORE_MOCK 1
|
||||||
|
|
||||||
|
#define ARDUINO 267
|
||||||
|
#define ESP8266 1
|
||||||
|
#define A0 0
|
||||||
|
#define LED_BUILTIN 0
|
||||||
|
#define F_CPU 80000000
|
||||||
|
#define LWIP_OPEN_SRC
|
||||||
|
#define TCP_MSS 536
|
||||||
|
#define LWIP_FEATURES 1
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
#endif // __cplusplus
|
471
tests/host/common/queue.h
Normal file
471
tests/host/common/queue.h
Normal file
@ -0,0 +1,471 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 1991, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
|
||||||
|
*
|
||||||
|
* @(#)queue.h 8.5 (Berkeley) 8/20/94
|
||||||
|
* $FreeBSD: src/sys/sys/queue.h,v 1.48 2002/04/17 14:00:37 tmm Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SYS_QUEUE_H_
|
||||||
|
#define _SYS_QUEUE_H_
|
||||||
|
|
||||||
|
#include <machine/ansi.h> /* for __offsetof */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file defines four types of data structures: singly-linked lists,
|
||||||
|
* singly-linked tail queues, lists and tail queues.
|
||||||
|
*
|
||||||
|
* A singly-linked list is headed by a single forward pointer. The elements
|
||||||
|
* are singly linked for minimum space and pointer manipulation overhead at
|
||||||
|
* the expense of O(n) removal for arbitrary elements. New elements can be
|
||||||
|
* added to the list after an existing element or at the head of the list.
|
||||||
|
* Elements being removed from the head of the list should use the explicit
|
||||||
|
* macro for this purpose for optimum efficiency. A singly-linked list may
|
||||||
|
* only be traversed in the forward direction. Singly-linked lists are ideal
|
||||||
|
* for applications with large datasets and few or no removals or for
|
||||||
|
* implementing a LIFO queue.
|
||||||
|
*
|
||||||
|
* A singly-linked tail queue is headed by a pair of pointers, one to the
|
||||||
|
* head of the list and the other to the tail of the list. The elements are
|
||||||
|
* singly linked for minimum space and pointer manipulation overhead at the
|
||||||
|
* expense of O(n) removal for arbitrary elements. New elements can be added
|
||||||
|
* to the list after an existing element, at the head of the list, or at the
|
||||||
|
* end of the list. Elements being removed from the head of the tail queue
|
||||||
|
* should use the explicit macro for this purpose for optimum efficiency.
|
||||||
|
* A singly-linked tail queue may only be traversed in the forward direction.
|
||||||
|
* Singly-linked tail queues are ideal for applications with large datasets
|
||||||
|
* and few or no removals or for implementing a FIFO queue.
|
||||||
|
*
|
||||||
|
* A list is headed by a single forward pointer (or an array of forward
|
||||||
|
* pointers for a hash table header). The elements are doubly linked
|
||||||
|
* so that an arbitrary element can be removed without a need to
|
||||||
|
* traverse the list. New elements can be added to the list before
|
||||||
|
* or after an existing element or at the head of the list. A list
|
||||||
|
* may only be traversed in the forward direction.
|
||||||
|
*
|
||||||
|
* A tail queue is headed by a pair of pointers, one to the head of the
|
||||||
|
* list and the other to the tail of the list. The elements are doubly
|
||||||
|
* linked so that an arbitrary element can be removed without a need to
|
||||||
|
* traverse the list. New elements can be added to the list before or
|
||||||
|
* after an existing element, at the head of the list, or at the end of
|
||||||
|
* the list. A tail queue may be traversed in either direction.
|
||||||
|
*
|
||||||
|
* For details on the use of these macros, see the queue(3) manual page.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* SLIST LIST STAILQ TAILQ
|
||||||
|
* _HEAD + + + +
|
||||||
|
* _HEAD_INITIALIZER + + + +
|
||||||
|
* _ENTRY + + + +
|
||||||
|
* _INIT + + + +
|
||||||
|
* _EMPTY + + + +
|
||||||
|
* _FIRST + + + +
|
||||||
|
* _NEXT + + + +
|
||||||
|
* _PREV - - - +
|
||||||
|
* _LAST - - + +
|
||||||
|
* _FOREACH + + + +
|
||||||
|
* _FOREACH_REVERSE - - - +
|
||||||
|
* _INSERT_HEAD + + + +
|
||||||
|
* _INSERT_BEFORE - + - +
|
||||||
|
* _INSERT_AFTER + + + +
|
||||||
|
* _INSERT_TAIL - - + +
|
||||||
|
* _CONCAT - - + +
|
||||||
|
* _REMOVE_HEAD + - + -
|
||||||
|
* _REMOVE + + + +
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Singly-linked List declarations.
|
||||||
|
*/
|
||||||
|
#define SLIST_HEAD(name, type) \
|
||||||
|
struct name { \
|
||||||
|
struct type *slh_first; /* first element */ \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SLIST_HEAD_INITIALIZER(head) \
|
||||||
|
{ NULL }
|
||||||
|
|
||||||
|
#define SLIST_ENTRY(type) \
|
||||||
|
struct { \
|
||||||
|
struct type *sle_next; /* next element */ \
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Singly-linked List functions.
|
||||||
|
*/
|
||||||
|
#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
|
||||||
|
|
||||||
|
#define SLIST_FIRST(head) ((head)->slh_first)
|
||||||
|
|
||||||
|
#define SLIST_FOREACH(var, head, field) \
|
||||||
|
for ((var) = SLIST_FIRST((head)); \
|
||||||
|
(var); \
|
||||||
|
(var) = SLIST_NEXT((var), field))
|
||||||
|
|
||||||
|
#define SLIST_INIT(head) do { \
|
||||||
|
SLIST_FIRST((head)) = NULL; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
|
||||||
|
SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
|
||||||
|
SLIST_NEXT((slistelm), field) = (elm); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define SLIST_INSERT_HEAD(head, elm, field) do { \
|
||||||
|
SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
|
||||||
|
SLIST_FIRST((head)) = (elm); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
|
||||||
|
|
||||||
|
#define SLIST_REMOVE(head, elm, type, field) do { \
|
||||||
|
if (SLIST_FIRST((head)) == (elm)) { \
|
||||||
|
SLIST_REMOVE_HEAD((head), field); \
|
||||||
|
} \
|
||||||
|
else { \
|
||||||
|
struct type *curelm = SLIST_FIRST((head)); \
|
||||||
|
while (SLIST_NEXT(curelm, field) != (elm)) \
|
||||||
|
curelm = SLIST_NEXT(curelm, field); \
|
||||||
|
SLIST_NEXT(curelm, field) = \
|
||||||
|
SLIST_NEXT(SLIST_NEXT(curelm, field), field); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define SLIST_REMOVE_HEAD(head, field) do { \
|
||||||
|
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Singly-linked Tail queue declarations.
|
||||||
|
*/
|
||||||
|
#define STAILQ_HEAD(name, type) \
|
||||||
|
struct name { \
|
||||||
|
struct type *stqh_first;/* first element */ \
|
||||||
|
struct type **stqh_last;/* addr of last next element */ \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define STAILQ_HEAD_INITIALIZER(head) \
|
||||||
|
{ NULL, &(head).stqh_first }
|
||||||
|
|
||||||
|
#define STAILQ_ENTRY(type) \
|
||||||
|
struct { \
|
||||||
|
struct type *stqe_next; /* next element */ \
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Singly-linked Tail queue functions.
|
||||||
|
*/
|
||||||
|
#define STAILQ_CONCAT(head1, head2) do { \
|
||||||
|
if (!STAILQ_EMPTY((head2))) { \
|
||||||
|
*(head1)->stqh_last = (head2)->stqh_first; \
|
||||||
|
(head1)->stqh_last = (head2)->stqh_last; \
|
||||||
|
STAILQ_INIT((head2)); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
|
||||||
|
|
||||||
|
#define STAILQ_FIRST(head) ((head)->stqh_first)
|
||||||
|
|
||||||
|
#define STAILQ_FOREACH(var, head, field) \
|
||||||
|
for((var) = STAILQ_FIRST((head)); \
|
||||||
|
(var); \
|
||||||
|
(var) = STAILQ_NEXT((var), field))
|
||||||
|
|
||||||
|
#define STAILQ_INIT(head) do { \
|
||||||
|
STAILQ_FIRST((head)) = NULL; \
|
||||||
|
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
|
||||||
|
if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
|
||||||
|
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||||
|
STAILQ_NEXT((tqelm), field) = (elm); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define STAILQ_INSERT_HEAD(head, elm, field) do { \
|
||||||
|
if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
|
||||||
|
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||||
|
STAILQ_FIRST((head)) = (elm); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define STAILQ_INSERT_TAIL(head, elm, field) do { \
|
||||||
|
STAILQ_NEXT((elm), field) = NULL; \
|
||||||
|
*(head)->stqh_last = (elm); \
|
||||||
|
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define STAILQ_LAST(head, type, field) \
|
||||||
|
(STAILQ_EMPTY((head)) ? \
|
||||||
|
NULL : \
|
||||||
|
((struct type *) \
|
||||||
|
((char *)((head)->stqh_last) - __offsetof(struct type, field))))
|
||||||
|
|
||||||
|
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
|
||||||
|
|
||||||
|
#define STAILQ_REMOVE(head, elm, type, field) do { \
|
||||||
|
if (STAILQ_FIRST((head)) == (elm)) { \
|
||||||
|
STAILQ_REMOVE_HEAD((head), field); \
|
||||||
|
} \
|
||||||
|
else { \
|
||||||
|
struct type *curelm = STAILQ_FIRST((head)); \
|
||||||
|
while (STAILQ_NEXT(curelm, field) != (elm)) \
|
||||||
|
curelm = STAILQ_NEXT(curelm, field); \
|
||||||
|
if ((STAILQ_NEXT(curelm, field) = \
|
||||||
|
STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
|
||||||
|
(head)->stqh_last = &STAILQ_NEXT((curelm), field);\
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define STAILQ_REMOVE_HEAD(head, field) do { \
|
||||||
|
if ((STAILQ_FIRST((head)) = \
|
||||||
|
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
|
||||||
|
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \
|
||||||
|
if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \
|
||||||
|
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List declarations.
|
||||||
|
*/
|
||||||
|
#define LIST_HEAD(name, type) \
|
||||||
|
struct name { \
|
||||||
|
struct type *lh_first; /* first element */ \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LIST_HEAD_INITIALIZER(head) \
|
||||||
|
{ NULL }
|
||||||
|
|
||||||
|
#define LIST_ENTRY(type) \
|
||||||
|
struct { \
|
||||||
|
struct type *le_next; /* next element */ \
|
||||||
|
struct type **le_prev; /* address of previous next element */ \
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LIST_EMPTY(head) ((head)->lh_first == NULL)
|
||||||
|
|
||||||
|
#define LIST_FIRST(head) ((head)->lh_first)
|
||||||
|
|
||||||
|
#define LIST_FOREACH(var, head, field) \
|
||||||
|
for ((var) = LIST_FIRST((head)); \
|
||||||
|
(var); \
|
||||||
|
(var) = LIST_NEXT((var), field))
|
||||||
|
|
||||||
|
#define LIST_INIT(head) do { \
|
||||||
|
LIST_FIRST((head)) = NULL; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
|
||||||
|
if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
|
||||||
|
LIST_NEXT((listelm), field)->field.le_prev = \
|
||||||
|
&LIST_NEXT((elm), field); \
|
||||||
|
LIST_NEXT((listelm), field) = (elm); \
|
||||||
|
(elm)->field.le_prev = &LIST_NEXT((listelm), field); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
|
||||||
|
(elm)->field.le_prev = (listelm)->field.le_prev; \
|
||||||
|
LIST_NEXT((elm), field) = (listelm); \
|
||||||
|
*(listelm)->field.le_prev = (elm); \
|
||||||
|
(listelm)->field.le_prev = &LIST_NEXT((elm), field); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LIST_INSERT_HEAD(head, elm, field) do { \
|
||||||
|
if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
|
||||||
|
LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
|
||||||
|
LIST_FIRST((head)) = (elm); \
|
||||||
|
(elm)->field.le_prev = &LIST_FIRST((head)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
|
||||||
|
|
||||||
|
#define LIST_REMOVE(elm, field) do { \
|
||||||
|
if (LIST_NEXT((elm), field) != NULL) \
|
||||||
|
LIST_NEXT((elm), field)->field.le_prev = \
|
||||||
|
(elm)->field.le_prev; \
|
||||||
|
*(elm)->field.le_prev = LIST_NEXT((elm), field); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tail queue declarations.
|
||||||
|
*/
|
||||||
|
#define TAILQ_HEAD(name, type) \
|
||||||
|
struct name { \
|
||||||
|
struct type *tqh_first; /* first element */ \
|
||||||
|
struct type **tqh_last; /* addr of last next element */ \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TAILQ_HEAD_INITIALIZER(head) \
|
||||||
|
{ NULL, &(head).tqh_first }
|
||||||
|
|
||||||
|
#define TAILQ_ENTRY(type) \
|
||||||
|
struct { \
|
||||||
|
struct type *tqe_next; /* next element */ \
|
||||||
|
struct type **tqe_prev; /* address of previous next element */ \
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tail queue functions.
|
||||||
|
*/
|
||||||
|
#define TAILQ_CONCAT(head1, head2, field) do { \
|
||||||
|
if (!TAILQ_EMPTY(head2)) { \
|
||||||
|
*(head1)->tqh_last = (head2)->tqh_first; \
|
||||||
|
(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
|
||||||
|
(head1)->tqh_last = (head2)->tqh_last; \
|
||||||
|
TAILQ_INIT((head2)); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
|
||||||
|
|
||||||
|
#define TAILQ_FIRST(head) ((head)->tqh_first)
|
||||||
|
|
||||||
|
#define TAILQ_FOREACH(var, head, field) \
|
||||||
|
for ((var) = TAILQ_FIRST((head)); \
|
||||||
|
(var); \
|
||||||
|
(var) = TAILQ_NEXT((var), field))
|
||||||
|
|
||||||
|
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
|
||||||
|
for ((var) = TAILQ_LAST((head), headname); \
|
||||||
|
(var); \
|
||||||
|
(var) = TAILQ_PREV((var), headname, field))
|
||||||
|
|
||||||
|
#define TAILQ_INIT(head) do { \
|
||||||
|
TAILQ_FIRST((head)) = NULL; \
|
||||||
|
(head)->tqh_last = &TAILQ_FIRST((head)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||||
|
if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
|
||||||
|
TAILQ_NEXT((elm), field)->field.tqe_prev = \
|
||||||
|
&TAILQ_NEXT((elm), field); \
|
||||||
|
else \
|
||||||
|
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
|
||||||
|
TAILQ_NEXT((listelm), field) = (elm); \
|
||||||
|
(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
|
||||||
|
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
|
||||||
|
TAILQ_NEXT((elm), field) = (listelm); \
|
||||||
|
*(listelm)->field.tqe_prev = (elm); \
|
||||||
|
(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
|
||||||
|
if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
|
||||||
|
TAILQ_FIRST((head))->field.tqe_prev = \
|
||||||
|
&TAILQ_NEXT((elm), field); \
|
||||||
|
else \
|
||||||
|
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
|
||||||
|
TAILQ_FIRST((head)) = (elm); \
|
||||||
|
(elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
|
||||||
|
TAILQ_NEXT((elm), field) = NULL; \
|
||||||
|
(elm)->field.tqe_prev = (head)->tqh_last; \
|
||||||
|
*(head)->tqh_last = (elm); \
|
||||||
|
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define TAILQ_LAST(head, headname) \
|
||||||
|
(*(((struct headname *)((head)->tqh_last))->tqh_last))
|
||||||
|
|
||||||
|
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
|
||||||
|
|
||||||
|
#define TAILQ_PREV(elm, headname, field) \
|
||||||
|
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
|
||||||
|
|
||||||
|
#define TAILQ_REMOVE(head, elm, field) do { \
|
||||||
|
if ((TAILQ_NEXT((elm), field)) != NULL) \
|
||||||
|
TAILQ_NEXT((elm), field)->field.tqe_prev = \
|
||||||
|
(elm)->field.tqe_prev; \
|
||||||
|
else \
|
||||||
|
(head)->tqh_last = (elm)->field.tqe_prev; \
|
||||||
|
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _KERNEL
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX insque() and remque() are an old way of handling certain queues.
|
||||||
|
* They bogusly assumes that all queue heads look alike.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct quehead {
|
||||||
|
struct quehead *qh_link;
|
||||||
|
struct quehead *qh_rlink;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
|
||||||
|
static __inline void
|
||||||
|
insque(void *a, void *b)
|
||||||
|
{
|
||||||
|
struct quehead *element = (struct quehead *)a,
|
||||||
|
*head = (struct quehead *)b;
|
||||||
|
|
||||||
|
element->qh_link = head->qh_link;
|
||||||
|
element->qh_rlink = head;
|
||||||
|
head->qh_link = element;
|
||||||
|
element->qh_link->qh_rlink = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline void
|
||||||
|
remque(void *a)
|
||||||
|
{
|
||||||
|
struct quehead *element = (struct quehead *)a;
|
||||||
|
|
||||||
|
element->qh_link->qh_rlink = element->qh_rlink;
|
||||||
|
element->qh_rlink->qh_link = element->qh_link;
|
||||||
|
element->qh_rlink = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* !__GNUC__ */
|
||||||
|
|
||||||
|
void insque(void *a, void *b);
|
||||||
|
void remque(void *a);
|
||||||
|
|
||||||
|
#endif /* __GNUC__ */
|
||||||
|
|
||||||
|
#endif /* _KERNEL */
|
||||||
|
|
||||||
|
#endif /* !_SYS_QUEUE_H_ */
|
@ -22,6 +22,13 @@
|
|||||||
|
|
||||||
#include <spiffs_api.h>
|
#include <spiffs_api.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define SPIFFS_FILE_NAME "spiffs.bin"
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
static uint32_t s_phys_addr = 0;
|
static uint32_t s_phys_addr = 0;
|
||||||
@ -33,32 +40,89 @@ extern "C"
|
|||||||
|
|
||||||
FS SPIFFS(nullptr);
|
FS SPIFFS(nullptr);
|
||||||
|
|
||||||
SpiffsMock::SpiffsMock(size_t fs_size, size_t fs_block, size_t fs_page)
|
SpiffsMock::SpiffsMock(size_t fs_size, size_t fs_block, size_t fs_page, bool storage)
|
||||||
{
|
{
|
||||||
m_fs.resize(fs_size, 0xff);
|
fprintf(stderr, "SPIFFS: %zd bytes\n", fs_size);
|
||||||
|
|
||||||
|
m_storage = storage;
|
||||||
|
m_fs = new uint8_t[m_fs_size = fs_size];
|
||||||
|
memset(&m_fs[0], 0xff, m_fs_size);
|
||||||
|
|
||||||
s_phys_addr = 0;
|
s_phys_addr = 0;
|
||||||
s_phys_size = static_cast<uint32_t>(fs_size);
|
s_phys_size = static_cast<uint32_t>(fs_size);
|
||||||
s_phys_page = static_cast<uint32_t>(fs_page);
|
s_phys_page = static_cast<uint32_t>(fs_page);
|
||||||
s_phys_block = static_cast<uint32_t>(fs_block);
|
s_phys_block = static_cast<uint32_t>(fs_block);
|
||||||
s_phys_data = m_fs.data();
|
s_phys_data = &m_fs[0];
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpiffsMock::reset()
|
void SpiffsMock::reset()
|
||||||
{
|
{
|
||||||
SPIFFS = FS(FSImplPtr(new SPIFFSImpl(0, s_phys_size, s_phys_page, s_phys_block, 5)));
|
SPIFFS = FS(FSImplPtr(new SPIFFSImpl(0, s_phys_size, s_phys_page, s_phys_block, 5)));
|
||||||
|
if (m_storage)
|
||||||
|
load();
|
||||||
}
|
}
|
||||||
|
|
||||||
SpiffsMock::~SpiffsMock()
|
SpiffsMock::~SpiffsMock()
|
||||||
{
|
{
|
||||||
|
if (m_storage)
|
||||||
|
save();
|
||||||
s_phys_addr = 0;
|
s_phys_addr = 0;
|
||||||
s_phys_size = 0;
|
s_phys_size = 0;
|
||||||
s_phys_page = 0;
|
s_phys_page = 0;
|
||||||
s_phys_block = 0;
|
s_phys_block = 0;
|
||||||
s_phys_data = nullptr;
|
s_phys_data = nullptr;
|
||||||
|
delete [] m_fs;
|
||||||
|
m_fs = nullptr;
|
||||||
|
m_fs_size = 0;
|
||||||
SPIFFS = FS(FSImplPtr(nullptr));
|
SPIFFS = FS(FSImplPtr(nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SpiffsMock::load ()
|
||||||
|
{
|
||||||
|
if (!m_fs_size)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const char* fname = getenv("SPIFFS_PATH");
|
||||||
|
if (!fname)
|
||||||
|
fname = DEFAULT_SPIFFS_FILE_NAME;
|
||||||
|
int fs = ::open(SPIFFS_FILE_NAME, O_RDONLY);
|
||||||
|
if (fs == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "SPIFFS: loading '%s': %s\n", fname, strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "SPIFFS: loading %zi bytes from '%s'\n", m_fs_size, fname);
|
||||||
|
if (::read(fs, &m_fs[0], m_fs_size) != (ssize_t)m_fs_size)
|
||||||
|
fprintf(stderr, "SPIFFS: reading %zi bytes: %s\n", m_fs_size, strerror(errno));
|
||||||
|
::close(fs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpiffsMock::save ()
|
||||||
|
{
|
||||||
|
if (!m_fs_size)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const char* fname = getenv("SPIFFS_PATH");
|
||||||
|
if (!fname)
|
||||||
|
fname = DEFAULT_SPIFFS_FILE_NAME;
|
||||||
|
int fs = ::open(SPIFFS_FILE_NAME, O_CREAT | O_TRUNC | O_WRONLY, 0644);
|
||||||
|
if (fs == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "SPIFFS: saving '%s': %s\n", fname, strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "SPIFFS: saving %zi bytes to '%s'\n", m_fs_size, fname);
|
||||||
|
|
||||||
|
// this can be a valgrind error, I don't understand how it happens
|
||||||
|
//for (size_t i = 0; i < m_fs_size; i++) printf("\r%zd:%d ", i, (int)m_fs[i]);
|
||||||
|
|
||||||
|
if (::write(fs, &m_fs[0], m_fs_size) != (ssize_t)m_fs_size)
|
||||||
|
fprintf(stderr, "SPIFFS: writing %zi bytes: %s\n", m_fs_size, strerror(errno));
|
||||||
|
if (::close(fs) == -1)
|
||||||
|
fprintf(stderr, "SPIFFS: closing %s: %s\n", fname, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
int32_t spiffs_hal_read(uint32_t addr, uint32_t size, uint8_t *dst) {
|
int32_t spiffs_hal_read(uint32_t addr, uint32_t size, uint8_t *dst) {
|
||||||
memcpy(dst, s_phys_data + addr, size);
|
memcpy(dst, s_phys_data + addr, size);
|
||||||
return SPIFFS_OK;
|
return SPIFFS_OK;
|
||||||
|
@ -21,17 +21,32 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <FS.h>
|
#include <FS.h>
|
||||||
|
|
||||||
|
#define DEFAULT_SPIFFS_FILE_NAME "spiffs.bin"
|
||||||
|
|
||||||
class SpiffsMock {
|
class SpiffsMock {
|
||||||
public:
|
public:
|
||||||
SpiffsMock(size_t fs_size, size_t fs_block, size_t fs_page);
|
SpiffsMock(size_t fs_size, size_t fs_block, size_t fs_page, bool storage = true);
|
||||||
void reset();
|
void reset();
|
||||||
~SpiffsMock();
|
~SpiffsMock();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<uint8_t> m_fs;
|
void load ();
|
||||||
|
void save ();
|
||||||
|
|
||||||
|
// it was a vector, but CI tests & valgrind complain with:
|
||||||
|
// Syscall param write(buf) points to uninitialised byte(s)
|
||||||
|
// by 0x43E9FF: SpiffsMock::save() (spiffs_mock.cpp:116)
|
||||||
|
// = if (::write(fs, &m_fs[0], m_fs_size) != (ssize_t)m_fs_size)
|
||||||
|
// so switched to a regular array
|
||||||
|
// and that bug is still here
|
||||||
|
// XXXWIPTODO
|
||||||
|
|
||||||
|
uint8_t* m_fs;
|
||||||
|
size_t m_fs_size;
|
||||||
|
bool m_storage;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SPIFFS_MOCK_DECLARE(size_kb, block_kb, page_b) SpiffsMock spiffs_mock(size_kb * 1024, block_kb * 1024, page_b)
|
#define SPIFFS_MOCK_DECLARE(size_kb, block_kb, page_b, storage) SpiffsMock spiffs_mock(size_kb * 1024, block_kb * 1024, page_b, storage)
|
||||||
#define SPIFFS_MOCK_RESET() spiffs_mock.reset()
|
#define SPIFFS_MOCK_RESET() spiffs_mock.reset()
|
||||||
|
|
||||||
|
|
||||||
|
458
tests/host/common/user_interface.cpp
Normal file
458
tests/host/common/user_interface.cpp
Normal file
@ -0,0 +1,458 @@
|
|||||||
|
/*
|
||||||
|
Arduino emulation - espressif sdk host implementation
|
||||||
|
Copyright (c) 2018 david gauchard. 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 with 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:
|
||||||
|
|
||||||
|
- Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers.
|
||||||
|
|
||||||
|
- Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimers in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
- The names of its contributors may not be used to endorse or promote
|
||||||
|
products derived from this Software without specific prior written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
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 CONTRIBUTORS 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 WITH THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <lwip/def.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <ifaddrs.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
|
||||||
|
#include <user_interface.h>
|
||||||
|
|
||||||
|
uint8 wifi_get_opmode(void)
|
||||||
|
{
|
||||||
|
return STATION_MODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
phy_mode_t wifi_get_phy_mode(void)
|
||||||
|
{
|
||||||
|
return PHY_MODE_11N;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 wifi_get_channel (void)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 wifi_station_get_current_ap_id (void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
station_status_t wifi_station_get_connect_status (void)
|
||||||
|
{
|
||||||
|
return STATION_GOT_IP;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 wifi_station_get_auto_connect (void)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_station_get_config (struct station_config *config)
|
||||||
|
{
|
||||||
|
strcpy((char*)config->ssid, "emulated-ssid");
|
||||||
|
strcpy((char*)config->password, "emulated-ssid-password");
|
||||||
|
config->bssid_set = 0;
|
||||||
|
for (int i = 0; i < 6; i++)
|
||||||
|
config->bssid[i] = i;
|
||||||
|
config->threshold.rssi = 1;
|
||||||
|
config->threshold.authmode = AUTH_WPA_PSK;
|
||||||
|
config->open_and_wep_mode_disable = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wifi_fpm_close(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
sint8 wifi_fpm_do_sleep (uint32 sleep_time_in_us)
|
||||||
|
{
|
||||||
|
usleep(sleep_time_in_us);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wifi_fpm_do_wakeup (void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void wifi_fpm_open (void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void wifi_fpm_set_sleep_type (sleep_type_t type)
|
||||||
|
{
|
||||||
|
(void)type;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t global_ipv4_netfmt = 0; // global binding
|
||||||
|
|
||||||
|
bool wifi_get_ip_info (uint8 if_index, struct ip_info *info)
|
||||||
|
{
|
||||||
|
struct ifaddrs * ifAddrStruct = NULL, * ifa = NULL;
|
||||||
|
uint32_t ipv4 = lwip_htonl(0x7f000001);
|
||||||
|
uint32_t mask = lwip_htonl(0xff000000);
|
||||||
|
|
||||||
|
if (getifaddrs(&ifAddrStruct) != 0)
|
||||||
|
{
|
||||||
|
perror("getifaddrs");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next)
|
||||||
|
{
|
||||||
|
if ( ifa->ifa_addr
|
||||||
|
&& ifa->ifa_addr->sa_family == AF_INET // ip_info is IPv4 only
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (lwip_ntohl(*(uint32_t*)&((struct sockaddr_in*) ifa->ifa_netmask)->sin_addr) != 0xff000000)
|
||||||
|
{
|
||||||
|
if (ipv4 == lwip_htonl(0x7f000001))
|
||||||
|
{
|
||||||
|
// take the first by default
|
||||||
|
ipv4 = *(uint32_t*)&((struct sockaddr_in*)ifa->ifa_addr)->sin_addr;
|
||||||
|
mask = *(uint32_t*)&((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr;
|
||||||
|
}
|
||||||
|
if (host_interface && strcmp(ifa->ifa_name, host_interface) == 0)
|
||||||
|
{
|
||||||
|
// .. or the one specified by user on cmdline
|
||||||
|
ipv4 = *(uint32_t*)&((struct sockaddr_in*)ifa->ifa_addr)->sin_addr;
|
||||||
|
mask = *(uint32_t*)&((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ifAddrStruct != NULL)
|
||||||
|
freeifaddrs(ifAddrStruct);
|
||||||
|
|
||||||
|
(void)if_index;
|
||||||
|
//if (if_index != STATION_IF)
|
||||||
|
// fprintf(stderr, "we are not AP");
|
||||||
|
|
||||||
|
if (global_ipv4_netfmt == NO_GLOBAL_BINDING)
|
||||||
|
global_ipv4_netfmt = ipv4;
|
||||||
|
|
||||||
|
if (info)
|
||||||
|
{
|
||||||
|
info->ip.addr = ipv4;
|
||||||
|
info->netmask.addr = mask;
|
||||||
|
info->gw.addr = ipv4;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 wifi_get_listen_interval (void)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_get_macaddr(uint8 if_index, uint8 *macaddr)
|
||||||
|
{
|
||||||
|
macaddr[0] = 0xde;
|
||||||
|
macaddr[1] = 0xba;
|
||||||
|
macaddr[2] = 0x7a;
|
||||||
|
macaddr[3] = 0xb1;
|
||||||
|
macaddr[4] = 0xe0;
|
||||||
|
macaddr[5] = 0x42;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 wifi_get_opmode_default (void)
|
||||||
|
{
|
||||||
|
return STATION_MODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep_level_t wifi_get_sleep_level (void)
|
||||||
|
{
|
||||||
|
return MIN_SLEEP_T;
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep_type_t wifi_get_sleep_type (void)
|
||||||
|
{
|
||||||
|
return NONE_SLEEP_T;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_set_channel (uint8 channel)
|
||||||
|
{
|
||||||
|
(void)channel;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
wifi_event_handler_cb_t wifi_event_handler_cb_emu = nullptr;
|
||||||
|
void wifi_set_event_handler_cb (wifi_event_handler_cb_t cb)
|
||||||
|
{
|
||||||
|
wifi_event_handler_cb_emu = cb;
|
||||||
|
fprintf(stderr, MOCK "TODO: wifi_set_event_handler_cb set\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_set_ip_info (uint8 if_index, struct ip_info *info)
|
||||||
|
{
|
||||||
|
(void)if_index;
|
||||||
|
(void)info;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_set_listen_interval (uint8 interval)
|
||||||
|
{
|
||||||
|
(void)interval;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_set_opmode (uint8 opmode)
|
||||||
|
{
|
||||||
|
return opmode == STATION_MODE || opmode == STATIONAP_MODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_set_opmode_current (uint8 opmode)
|
||||||
|
{
|
||||||
|
return opmode == STATION_MODE || opmode == STATIONAP_MODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_set_phy_mode (phy_mode_t mode)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_set_sleep_level (sleep_level_t level)
|
||||||
|
{
|
||||||
|
(void)level;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_set_sleep_type (sleep_type_t type)
|
||||||
|
{
|
||||||
|
(void)type;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_station_connect (void)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_station_dhcpc_start (void)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_station_dhcpc_stop (void)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_station_disconnect (void)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_station_get_config_default (struct station_config *config)
|
||||||
|
{
|
||||||
|
return wifi_station_get_config(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
char wifi_station_get_hostname_str [128];
|
||||||
|
char* wifi_station_get_hostname (void)
|
||||||
|
{
|
||||||
|
return strcpy(wifi_station_get_hostname_str, "esposix");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_station_get_reconnect_policy ()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
sint8 wifi_station_get_rssi (void)
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_station_set_auto_connect (uint8 set)
|
||||||
|
{
|
||||||
|
return set != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_station_set_config (struct station_config *config)
|
||||||
|
{
|
||||||
|
(void)config;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_station_set_config_current (struct station_config *config)
|
||||||
|
{
|
||||||
|
(void)config;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_station_set_hostname (char *name)
|
||||||
|
{
|
||||||
|
(void)name;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_station_set_reconnect_policy (bool set)
|
||||||
|
{
|
||||||
|
(void)set;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void system_phy_set_max_tpw (uint8 max_tpw)
|
||||||
|
{
|
||||||
|
(void)max_tpw;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_softap_dhcps_start(void)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum dhcp_status wifi_softap_dhcps_status(void)
|
||||||
|
{
|
||||||
|
return DHCP_STARTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_softap_dhcps_stop(void)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_softap_get_config(struct softap_config *config)
|
||||||
|
{
|
||||||
|
strcpy((char*)config->ssid, "apssid");
|
||||||
|
strcpy((char*)config->password, "appasswd");
|
||||||
|
config->ssid_len = strlen("appasswd");
|
||||||
|
config->channel = 1;
|
||||||
|
config->authmode = AUTH_WPA2_PSK;
|
||||||
|
config->ssid_hidden = 0;
|
||||||
|
config->max_connection = 4;
|
||||||
|
config->beacon_interval = 100;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_softap_get_config_default(struct softap_config *config)
|
||||||
|
{
|
||||||
|
return wifi_softap_get_config(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 wifi_softap_get_station_num(void)
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_softap_set_config(struct softap_config *config)
|
||||||
|
{
|
||||||
|
(void)config;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_softap_set_config_current(struct softap_config *config)
|
||||||
|
{
|
||||||
|
(void)config;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_softap_set_dhcps_lease(struct dhcps_lease *please)
|
||||||
|
{
|
||||||
|
(void)please;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_softap_set_dhcps_lease_time(uint32 minute)
|
||||||
|
{
|
||||||
|
(void)minute;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_softap_set_dhcps_offer_option(uint8 level, void* optarg)
|
||||||
|
{
|
||||||
|
(void)level;
|
||||||
|
(void)optarg;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_station_scan(struct scan_config *config, scan_done_cb_t cb)
|
||||||
|
{
|
||||||
|
cb(nullptr, FAIL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t core_version = 1;
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
// not user_interface
|
||||||
|
|
||||||
|
void ets_isr_mask (int intr)
|
||||||
|
{
|
||||||
|
(void)intr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ets_isr_unmask (int intr)
|
||||||
|
{
|
||||||
|
(void)intr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_schedule (void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void optimistic_yield (uint32_t ms)
|
||||||
|
{
|
||||||
|
usleep(ms * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dns_setserver (u8_t numdns, ip_addr_t *dnsserver)
|
||||||
|
{
|
||||||
|
(void)numdns;
|
||||||
|
(void)dnsserver;
|
||||||
|
}
|
||||||
|
|
||||||
|
ip_addr_t dns_getserver (u8_t numdns)
|
||||||
|
{
|
||||||
|
ip_addr_t addr = { 0x7f000001 };
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#include <smartconfig.h>
|
||||||
|
bool smartconfig_start (sc_callback_t cb, ...)
|
||||||
|
{
|
||||||
|
//XXXFIXME ... -> ptr
|
||||||
|
cb(SC_STATUS_LINK, NULL);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool smartconfig_stop (void)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} // extern "C"
|
@ -50,25 +50,25 @@ static std::set<String> listDir (const char* path)
|
|||||||
|
|
||||||
TEST_CASE("FS can begin","[fs]")
|
TEST_CASE("FS can begin","[fs]")
|
||||||
{
|
{
|
||||||
SPIFFS_MOCK_DECLARE(64, 8, 512);
|
SPIFFS_MOCK_DECLARE(64, 8, 512, false);
|
||||||
REQUIRE(SPIFFS.begin());
|
REQUIRE(SPIFFS.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("FS can't begin with zero size","[fs]")
|
TEST_CASE("FS can't begin with zero size","[fs]")
|
||||||
{
|
{
|
||||||
SPIFFS_MOCK_DECLARE(0, 8, 512);
|
SPIFFS_MOCK_DECLARE(0, 8, 512, false);
|
||||||
REQUIRE_FALSE(SPIFFS.begin());
|
REQUIRE_FALSE(SPIFFS.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Before begin is called, open will fail","[fs]")
|
TEST_CASE("Before begin is called, open will fail","[fs]")
|
||||||
{
|
{
|
||||||
SPIFFS_MOCK_DECLARE(64, 8, 512);
|
SPIFFS_MOCK_DECLARE(64, 8, 512, false);
|
||||||
REQUIRE_FALSE(SPIFFS.open("/foo", "w"));
|
REQUIRE_FALSE(SPIFFS.open("/foo", "w"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("FS can create file","[fs]")
|
TEST_CASE("FS can create file","[fs]")
|
||||||
{
|
{
|
||||||
SPIFFS_MOCK_DECLARE(64, 8, 512);
|
SPIFFS_MOCK_DECLARE(64, 8, 512, false);
|
||||||
REQUIRE(SPIFFS.begin());
|
REQUIRE(SPIFFS.begin());
|
||||||
createFile("/test", "");
|
createFile("/test", "");
|
||||||
REQUIRE(SPIFFS.exists("/test"));
|
REQUIRE(SPIFFS.exists("/test"));
|
||||||
@ -76,7 +76,7 @@ TEST_CASE("FS can create file","[fs]")
|
|||||||
|
|
||||||
TEST_CASE("Files can be written and appended to","[fs]")
|
TEST_CASE("Files can be written and appended to","[fs]")
|
||||||
{
|
{
|
||||||
SPIFFS_MOCK_DECLARE(64, 8, 512);
|
SPIFFS_MOCK_DECLARE(64, 8, 512, false);
|
||||||
REQUIRE(SPIFFS.begin());
|
REQUIRE(SPIFFS.begin());
|
||||||
{
|
{
|
||||||
File f = SPIFFS.open("config1.txt", "w");
|
File f = SPIFFS.open("config1.txt", "w");
|
||||||
@ -100,7 +100,7 @@ TEST_CASE("Files can be written and appended to","[fs]")
|
|||||||
|
|
||||||
TEST_CASE("Files persist after reset", "[fs]")
|
TEST_CASE("Files persist after reset", "[fs]")
|
||||||
{
|
{
|
||||||
SPIFFS_MOCK_DECLARE(64, 8, 512);
|
SPIFFS_MOCK_DECLARE(64, 8, 512, false);
|
||||||
REQUIRE(SPIFFS.begin());
|
REQUIRE(SPIFFS.begin());
|
||||||
createFile("config1.txt", "file 1");
|
createFile("config1.txt", "file 1");
|
||||||
|
|
||||||
@ -112,7 +112,7 @@ TEST_CASE("Files persist after reset", "[fs]")
|
|||||||
|
|
||||||
TEST_CASE("Filesystem is empty after format", "[fs]")
|
TEST_CASE("Filesystem is empty after format", "[fs]")
|
||||||
{
|
{
|
||||||
SPIFFS_MOCK_DECLARE(64, 8, 512);
|
SPIFFS_MOCK_DECLARE(64, 8, 512, false);
|
||||||
REQUIRE(SPIFFS.format());
|
REQUIRE(SPIFFS.format());
|
||||||
REQUIRE(SPIFFS.begin());
|
REQUIRE(SPIFFS.begin());
|
||||||
createFile("/1", "first");
|
createFile("/1", "first");
|
||||||
@ -128,7 +128,7 @@ TEST_CASE("Filesystem is empty after format", "[fs]")
|
|||||||
|
|
||||||
TEST_CASE("Dir lists all files", "[fs]")
|
TEST_CASE("Dir lists all files", "[fs]")
|
||||||
{
|
{
|
||||||
SPIFFS_MOCK_DECLARE(64, 8, 512);
|
SPIFFS_MOCK_DECLARE(64, 8, 512, false);
|
||||||
REQUIRE(SPIFFS.begin());
|
REQUIRE(SPIFFS.begin());
|
||||||
createFile("/empty", "");
|
createFile("/empty", "");
|
||||||
createFile("/not_empty", "some text");
|
createFile("/not_empty", "some text");
|
||||||
@ -146,7 +146,7 @@ TEST_CASE("Dir lists all files", "[fs]")
|
|||||||
|
|
||||||
TEST_CASE("File names which are too long are rejected", "[fs]")
|
TEST_CASE("File names which are too long are rejected", "[fs]")
|
||||||
{
|
{
|
||||||
SPIFFS_MOCK_DECLARE(64, 8, 512);
|
SPIFFS_MOCK_DECLARE(64, 8, 512, false);
|
||||||
REQUIRE(SPIFFS.begin());
|
REQUIRE(SPIFFS.begin());
|
||||||
const char* emptyName = "";
|
const char* emptyName = "";
|
||||||
const char* longName_31 = "/234567890123456789012345678901";
|
const char* longName_31 = "/234567890123456789012345678901";
|
||||||
@ -164,7 +164,7 @@ TEST_CASE("File names which are too long are rejected", "[fs]")
|
|||||||
|
|
||||||
TEST_CASE("#1685 Duplicate files", "[fs][bugreport]")
|
TEST_CASE("#1685 Duplicate files", "[fs][bugreport]")
|
||||||
{
|
{
|
||||||
SPIFFS_MOCK_DECLARE(64, 8, 512);
|
SPIFFS_MOCK_DECLARE(64, 8, 512, false);
|
||||||
REQUIRE(SPIFFS.begin());
|
REQUIRE(SPIFFS.begin());
|
||||||
createFile("/config", "some text");
|
createFile("/config", "some text");
|
||||||
createFile("/data", "");
|
createFile("/data", "");
|
||||||
@ -175,7 +175,7 @@ TEST_CASE("#1685 Duplicate files", "[fs][bugreport]")
|
|||||||
|
|
||||||
TEST_CASE("#1819 Can list all files with openDir(\"\")", "[fs][bugreport]")
|
TEST_CASE("#1819 Can list all files with openDir(\"\")", "[fs][bugreport]")
|
||||||
{
|
{
|
||||||
SPIFFS_MOCK_DECLARE(64, 8, 512);
|
SPIFFS_MOCK_DECLARE(64, 8, 512, false);
|
||||||
REQUIRE(SPIFFS.begin());
|
REQUIRE(SPIFFS.begin());
|
||||||
createFile("/file1", "some text");
|
createFile("/file1", "some text");
|
||||||
createFile("/file2", "other text");
|
createFile("/file2", "other text");
|
||||||
|
@ -11,7 +11,7 @@ install: all version-header
|
|||||||
|
|
||||||
bearssl/README.txt:
|
bearssl/README.txt:
|
||||||
git submodule update --init --recursive bearssl
|
git submodule update --init --recursive bearssl
|
||||||
cd bearssl && git remote add bearssl https://www.bearssl.org/git/BearSSL
|
cd bearssl && (git remote add bearssl https://www.bearssl.org/git/BearSSL || true)
|
||||||
|
|
||||||
merge-upstream:
|
merge-upstream:
|
||||||
cd bearssl && git pull bearssl master
|
cd bearssl && git pull bearssl master
|
||||||
@ -20,3 +20,9 @@ version-header:
|
|||||||
echo "// Do not edit -- Automatically generated by tools/sdk/ssl/bearssl/Makefile" > $(VER_H)
|
echo "// Do not edit -- Automatically generated by tools/sdk/ssl/bearssl/Makefile" > $(VER_H)
|
||||||
echo -n "#define BEARSSL_GIT " >> $(VER_H)
|
echo -n "#define BEARSSL_GIT " >> $(VER_H)
|
||||||
cd bearssl && git rev-parse --short HEAD >> ../$(VER_H)
|
cd bearssl && git rev-parse --short HEAD >> ../$(VER_H)
|
||||||
|
|
||||||
|
native: bearssl/README.txt
|
||||||
|
cd bearssl && make
|
||||||
|
|
||||||
|
native32: bearssl/README.txt
|
||||||
|
cd bearssl && make CONF=Unix32
|
||||||
|
Loading…
x
Reference in New Issue
Block a user