mirror of
https://github.com/esp8266/Arduino.git
synced 2025-07-30 16:24:09 +03:00
Migrate from astyle to clang-format (#8464)
This commit is contained in:
committed by
Max Prokhorov
parent
46190b61f1
commit
19b7a29720
@ -1,14 +1,14 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
@ -41,7 +41,6 @@ extern "C" unsigned long micros()
|
||||
return ((time.tv_sec - gtod0.tv_sec) * 1000000) + time.tv_usec - gtod0.tv_usec;
|
||||
}
|
||||
|
||||
|
||||
extern "C" void yield()
|
||||
{
|
||||
run_scheduled_recurrent_functions();
|
||||
@ -58,38 +57,35 @@ extern "C" bool can_yield()
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" void optimistic_yield (uint32_t interval_us)
|
||||
extern "C" void optimistic_yield(uint32_t interval_us)
|
||||
{
|
||||
(void)interval_us;
|
||||
}
|
||||
|
||||
extern "C" void esp_suspend()
|
||||
{
|
||||
}
|
||||
extern "C" void esp_suspend() { }
|
||||
|
||||
extern "C" void esp_schedule()
|
||||
{
|
||||
}
|
||||
extern "C" void esp_schedule() { }
|
||||
|
||||
extern "C" void esp_yield()
|
||||
{
|
||||
}
|
||||
extern "C" void esp_yield() { }
|
||||
|
||||
extern "C" void esp_delay (unsigned long ms)
|
||||
extern "C" void esp_delay(unsigned long ms)
|
||||
{
|
||||
usleep(ms * 1000);
|
||||
}
|
||||
|
||||
bool esp_try_delay(const uint32_t start_ms, const uint32_t timeout_ms, const uint32_t intvl_ms) {
|
||||
bool esp_try_delay(const uint32_t start_ms, const uint32_t timeout_ms, const uint32_t intvl_ms)
|
||||
{
|
||||
uint32_t expired = millis() - start_ms;
|
||||
if (expired >= timeout_ms) {
|
||||
if (expired >= timeout_ms)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
esp_delay(std::min((timeout_ms - expired), intvl_ms));
|
||||
return false;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
(void)file;
|
||||
(void)line;
|
||||
(void)func;
|
||||
@ -107,15 +103,14 @@ extern "C" void delayMicroseconds(unsigned int us)
|
||||
}
|
||||
|
||||
#include "cont.h"
|
||||
cont_t* g_pcont = NULL;
|
||||
extern "C" void cont_suspend(cont_t*)
|
||||
{
|
||||
}
|
||||
cont_t* g_pcont = NULL;
|
||||
extern "C" void cont_suspend(cont_t*) { }
|
||||
|
||||
extern "C" int __mockverbose (const char* fmt, ...)
|
||||
extern "C" int __mockverbose(const char* fmt, ...)
|
||||
{
|
||||
(void)fmt;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mockverbose (const char* fmt, ...) __attribute__ ((weak, alias("__mockverbose"), format (printf, 1, 2)));
|
||||
int mockverbose(const char* fmt, ...)
|
||||
__attribute__((weak, alias("__mockverbose"), format(printf, 1, 2)));
|
||||
|
@ -1,14 +1,14 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
@ -17,4 +17,3 @@
|
||||
#include <catch.hpp>
|
||||
#include <sys/time.h>
|
||||
#include "Arduino.h"
|
||||
|
||||
|
@ -30,7 +30,7 @@
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <user_interface.h> // wifi_get_ip_info()
|
||||
#include <user_interface.h> // wifi_get_ip_info()
|
||||
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
@ -41,280 +41,280 @@
|
||||
|
||||
#define MOCK_PORT_SHIFTER 9000
|
||||
|
||||
bool user_exit = false;
|
||||
bool run_once = false;
|
||||
const char* host_interface = nullptr;
|
||||
size_t spiffs_kb = 1024;
|
||||
size_t littlefs_kb = 1024;
|
||||
bool ignore_sigint = false;
|
||||
bool restore_tty = false;
|
||||
bool mockdebug = false;
|
||||
int mock_port_shifter = MOCK_PORT_SHIFTER;
|
||||
const char* fspath = nullptr;
|
||||
bool user_exit = false;
|
||||
bool run_once = false;
|
||||
const char* host_interface = nullptr;
|
||||
size_t spiffs_kb = 1024;
|
||||
size_t littlefs_kb = 1024;
|
||||
bool ignore_sigint = false;
|
||||
bool restore_tty = false;
|
||||
bool mockdebug = false;
|
||||
int mock_port_shifter = MOCK_PORT_SHIFTER;
|
||||
const char* fspath = nullptr;
|
||||
|
||||
#define STDIN STDIN_FILENO
|
||||
|
||||
static struct termios initial_settings;
|
||||
|
||||
int mockverbose (const char* fmt, ...)
|
||||
int mockverbose(const char* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
if (mockdebug)
|
||||
return fprintf(stderr, MOCK) + vfprintf(stderr, fmt, ap);
|
||||
return 0;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
if (mockdebug)
|
||||
return fprintf(stderr, MOCK) + vfprintf(stderr, fmt, ap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mock_start_uart(void)
|
||||
{
|
||||
struct termios settings;
|
||||
struct termios settings;
|
||||
|
||||
if (!isatty(STDIN))
|
||||
{
|
||||
perror("setting tty in raw mode: isatty(STDIN)");
|
||||
return -1;
|
||||
}
|
||||
if (tcgetattr(STDIN, &initial_settings) < 0)
|
||||
{
|
||||
perror("setting tty in raw mode: tcgetattr(STDIN)");
|
||||
return -1;
|
||||
}
|
||||
settings = initial_settings;
|
||||
settings.c_lflag &= ~(ignore_sigint ? ISIG : 0);
|
||||
settings.c_lflag &= ~(ECHO | ICANON);
|
||||
settings.c_iflag &= ~(ICRNL | INLCR | ISTRIP | IXON);
|
||||
settings.c_oflag |= (ONLCR);
|
||||
settings.c_cc[VMIN] = 0;
|
||||
settings.c_cc[VTIME] = 0;
|
||||
if (tcsetattr(STDIN, TCSANOW, &settings) < 0)
|
||||
{
|
||||
perror("setting tty in raw mode: tcsetattr(STDIN)");
|
||||
return -1;
|
||||
}
|
||||
restore_tty = true;
|
||||
return 0;
|
||||
if (!isatty(STDIN))
|
||||
{
|
||||
perror("setting tty in raw mode: isatty(STDIN)");
|
||||
return -1;
|
||||
}
|
||||
if (tcgetattr(STDIN, &initial_settings) < 0)
|
||||
{
|
||||
perror("setting tty in raw mode: tcgetattr(STDIN)");
|
||||
return -1;
|
||||
}
|
||||
settings = initial_settings;
|
||||
settings.c_lflag &= ~(ignore_sigint ? ISIG : 0);
|
||||
settings.c_lflag &= ~(ECHO | ICANON);
|
||||
settings.c_iflag &= ~(ICRNL | INLCR | ISTRIP | IXON);
|
||||
settings.c_oflag |= (ONLCR);
|
||||
settings.c_cc[VMIN] = 0;
|
||||
settings.c_cc[VTIME] = 0;
|
||||
if (tcsetattr(STDIN, TCSANOW, &settings) < 0)
|
||||
{
|
||||
perror("setting tty in raw mode: tcsetattr(STDIN)");
|
||||
return -1;
|
||||
}
|
||||
restore_tty = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mock_stop_uart(void)
|
||||
{
|
||||
if (!restore_tty) return 0;
|
||||
if (!isatty(STDIN)) {
|
||||
perror("restoring tty: isatty(STDIN)");
|
||||
return -1;
|
||||
}
|
||||
if (tcsetattr(STDIN, TCSANOW, &initial_settings) < 0)
|
||||
{
|
||||
perror("restoring tty: tcsetattr(STDIN)");
|
||||
return -1;
|
||||
}
|
||||
printf("\e[?25h"); // show cursor
|
||||
return (0);
|
||||
if (!restore_tty)
|
||||
return 0;
|
||||
if (!isatty(STDIN))
|
||||
{
|
||||
perror("restoring tty: isatty(STDIN)");
|
||||
return -1;
|
||||
}
|
||||
if (tcsetattr(STDIN, TCSANOW, &initial_settings) < 0)
|
||||
{
|
||||
perror("restoring tty: tcsetattr(STDIN)");
|
||||
return -1;
|
||||
}
|
||||
printf("\e[?25h"); // show cursor
|
||||
return (0);
|
||||
}
|
||||
|
||||
static uint8_t mock_read_uart(void)
|
||||
{
|
||||
uint8_t ch = 0;
|
||||
return (read(STDIN, &ch, 1) == 1) ? ch : 0;
|
||||
uint8_t ch = 0;
|
||||
return (read(STDIN, &ch, 1) == 1) ? ch : 0;
|
||||
}
|
||||
|
||||
void help (const char* argv0, int exitcode)
|
||||
void help(const char* argv0, int exitcode)
|
||||
{
|
||||
printf(
|
||||
"%s - compiled with esp8266/arduino emulator\n"
|
||||
"options:\n"
|
||||
"\t-h\n"
|
||||
"\tnetwork:\n"
|
||||
"\t-i <interface> - use this interface for IP address\n"
|
||||
"\t-l - bind tcp/udp servers to interface only (not 0.0.0.0)\n"
|
||||
"\t-s - port shifter (default: %d, when root: 0)\n"
|
||||
"\tterminal:\n"
|
||||
"\t-b - blocking tty/mocked-uart (default: not blocking tty)\n"
|
||||
"\t-T - show timestamp on output\n"
|
||||
"\tFS:\n"
|
||||
"\t-P - path for fs-persistent files (default: %s-)\n"
|
||||
"\t-S - spiffs size in KBytes (default: %zd)\n"
|
||||
"\t-L - littlefs size in KBytes (default: %zd)\n"
|
||||
"\t (spiffs, littlefs: negative value will force mismatched size)\n"
|
||||
"\tgeneral:\n"
|
||||
"\t-c - ignore CTRL-C (send it via Serial)\n"
|
||||
"\t-f - no throttle (possibly 100%%CPU)\n"
|
||||
"\t-1 - run loop once then exit (for host testing)\n"
|
||||
"\t-v - verbose\n"
|
||||
, argv0, MOCK_PORT_SHIFTER, argv0, spiffs_kb, littlefs_kb);
|
||||
exit(exitcode);
|
||||
printf("%s - compiled with esp8266/arduino emulator\n"
|
||||
"options:\n"
|
||||
"\t-h\n"
|
||||
"\tnetwork:\n"
|
||||
"\t-i <interface> - use this interface for IP address\n"
|
||||
"\t-l - bind tcp/udp servers to interface only (not 0.0.0.0)\n"
|
||||
"\t-s - port shifter (default: %d, when root: 0)\n"
|
||||
"\tterminal:\n"
|
||||
"\t-b - blocking tty/mocked-uart (default: not blocking tty)\n"
|
||||
"\t-T - show timestamp on output\n"
|
||||
"\tFS:\n"
|
||||
"\t-P - path for fs-persistent files (default: %s-)\n"
|
||||
"\t-S - spiffs size in KBytes (default: %zd)\n"
|
||||
"\t-L - littlefs size in KBytes (default: %zd)\n"
|
||||
"\t (spiffs, littlefs: negative value will force mismatched size)\n"
|
||||
"\tgeneral:\n"
|
||||
"\t-c - ignore CTRL-C (send it via Serial)\n"
|
||||
"\t-f - no throttle (possibly 100%%CPU)\n"
|
||||
"\t-1 - run loop once then exit (for host testing)\n"
|
||||
"\t-v - verbose\n",
|
||||
argv0, MOCK_PORT_SHIFTER, argv0, spiffs_kb, littlefs_kb);
|
||||
exit(exitcode);
|
||||
}
|
||||
|
||||
static struct option options[] =
|
||||
{
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "fast", no_argument, NULL, 'f' },
|
||||
{ "local", no_argument, NULL, 'l' },
|
||||
{ "sigint", no_argument, NULL, 'c' },
|
||||
{ "blockinguart", no_argument, NULL, 'b' },
|
||||
{ "verbose", no_argument, NULL, 'v' },
|
||||
{ "timestamp", no_argument, NULL, 'T' },
|
||||
{ "interface", required_argument, NULL, 'i' },
|
||||
{ "fspath", required_argument, NULL, 'P' },
|
||||
{ "spiffskb", required_argument, NULL, 'S' },
|
||||
{ "littlefskb", required_argument, NULL, 'L' },
|
||||
{ "portshifter", required_argument, NULL, 's' },
|
||||
{ "once", no_argument, NULL, '1' },
|
||||
static struct option options[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "fast", no_argument, NULL, 'f' },
|
||||
{ "local", no_argument, NULL, 'l' },
|
||||
{ "sigint", no_argument, NULL, 'c' },
|
||||
{ "blockinguart", no_argument, NULL, 'b' },
|
||||
{ "verbose", no_argument, NULL, 'v' },
|
||||
{ "timestamp", no_argument, NULL, 'T' },
|
||||
{ "interface", required_argument, NULL, 'i' },
|
||||
{ "fspath", required_argument, NULL, 'P' },
|
||||
{ "spiffskb", required_argument, NULL, 'S' },
|
||||
{ "littlefskb", required_argument, NULL, 'L' },
|
||||
{ "portshifter", required_argument, NULL, 's' },
|
||||
{ "once", no_argument, NULL, '1' },
|
||||
};
|
||||
|
||||
void cleanup ()
|
||||
void cleanup()
|
||||
{
|
||||
mock_stop_spiffs();
|
||||
mock_stop_littlefs();
|
||||
mock_stop_uart();
|
||||
mock_stop_spiffs();
|
||||
mock_stop_littlefs();
|
||||
mock_stop_uart();
|
||||
}
|
||||
|
||||
void make_fs_filename (String& name, const char* fspath, const char* argv0)
|
||||
void make_fs_filename(String& name, const char* fspath, const char* argv0)
|
||||
{
|
||||
name.clear();
|
||||
if (fspath)
|
||||
{
|
||||
int lastSlash = -1;
|
||||
for (int i = 0; argv0[i]; i++)
|
||||
if (argv0[i] == '/')
|
||||
lastSlash = i;
|
||||
name = fspath;
|
||||
name += '/';
|
||||
name += &argv0[lastSlash + 1];
|
||||
}
|
||||
else
|
||||
name = argv0;
|
||||
name.clear();
|
||||
if (fspath)
|
||||
{
|
||||
int lastSlash = -1;
|
||||
for (int i = 0; argv0[i]; i++)
|
||||
if (argv0[i] == '/')
|
||||
lastSlash = i;
|
||||
name = fspath;
|
||||
name += '/';
|
||||
name += &argv0[lastSlash + 1];
|
||||
}
|
||||
else
|
||||
name = argv0;
|
||||
}
|
||||
|
||||
void control_c (int sig)
|
||||
void control_c(int sig)
|
||||
{
|
||||
(void)sig;
|
||||
(void)sig;
|
||||
|
||||
if (user_exit)
|
||||
{
|
||||
fprintf(stderr, MOCK "stuck, killing\n");
|
||||
cleanup();
|
||||
exit(1);
|
||||
}
|
||||
user_exit = true;
|
||||
if (user_exit)
|
||||
{
|
||||
fprintf(stderr, MOCK "stuck, killing\n");
|
||||
cleanup();
|
||||
exit(1);
|
||||
}
|
||||
user_exit = true;
|
||||
}
|
||||
|
||||
int main (int argc, char* const argv [])
|
||||
int main(int argc, char* const argv[])
|
||||
{
|
||||
bool fast = false;
|
||||
blocking_uart = false; // global
|
||||
bool fast = false;
|
||||
blocking_uart = false; // global
|
||||
|
||||
signal(SIGINT, control_c);
|
||||
signal(SIGTERM, control_c);
|
||||
if (geteuid() == 0)
|
||||
mock_port_shifter = 0;
|
||||
else
|
||||
mock_port_shifter = MOCK_PORT_SHIFTER;
|
||||
signal(SIGINT, control_c);
|
||||
signal(SIGTERM, control_c);
|
||||
if (geteuid() == 0)
|
||||
mock_port_shifter = 0;
|
||||
else
|
||||
mock_port_shifter = MOCK_PORT_SHIFTER;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int n = getopt_long(argc, argv, "hlcfbvTi:S:s:L:P:1", 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 's':
|
||||
mock_port_shifter = atoi(optarg);
|
||||
break;
|
||||
case 'c':
|
||||
ignore_sigint = true;
|
||||
break;
|
||||
case 'f':
|
||||
fast = true;
|
||||
break;
|
||||
case 'S':
|
||||
spiffs_kb = atoi(optarg);
|
||||
break;
|
||||
case 'L':
|
||||
littlefs_kb = atoi(optarg);
|
||||
break;
|
||||
case 'P':
|
||||
fspath = optarg;
|
||||
break;
|
||||
case 'b':
|
||||
blocking_uart = true;
|
||||
break;
|
||||
case 'v':
|
||||
mockdebug = true;
|
||||
break;
|
||||
case 'T':
|
||||
serial_timestamp = true;
|
||||
break;
|
||||
case '1':
|
||||
run_once = true;
|
||||
break;
|
||||
default:
|
||||
help(argv[0], EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
for (;;)
|
||||
{
|
||||
int n = getopt_long(argc, argv, "hlcfbvTi:S:s:L:P:1", 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 's':
|
||||
mock_port_shifter = atoi(optarg);
|
||||
break;
|
||||
case 'c':
|
||||
ignore_sigint = true;
|
||||
break;
|
||||
case 'f':
|
||||
fast = true;
|
||||
break;
|
||||
case 'S':
|
||||
spiffs_kb = atoi(optarg);
|
||||
break;
|
||||
case 'L':
|
||||
littlefs_kb = atoi(optarg);
|
||||
break;
|
||||
case 'P':
|
||||
fspath = optarg;
|
||||
break;
|
||||
case 'b':
|
||||
blocking_uart = true;
|
||||
break;
|
||||
case 'v':
|
||||
mockdebug = true;
|
||||
break;
|
||||
case 'T':
|
||||
serial_timestamp = true;
|
||||
break;
|
||||
case '1':
|
||||
run_once = true;
|
||||
break;
|
||||
default:
|
||||
help(argv[0], EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
mockverbose("server port shifter: %d\n", mock_port_shifter);
|
||||
mockverbose("server port shifter: %d\n", mock_port_shifter);
|
||||
|
||||
if (spiffs_kb)
|
||||
{
|
||||
String name;
|
||||
make_fs_filename(name, fspath, argv[0]);
|
||||
name += "-spiffs";
|
||||
name += String(spiffs_kb > 0? spiffs_kb: -spiffs_kb, DEC);
|
||||
name += "KB";
|
||||
mock_start_spiffs(name, spiffs_kb);
|
||||
}
|
||||
if (spiffs_kb)
|
||||
{
|
||||
String name;
|
||||
make_fs_filename(name, fspath, argv[0]);
|
||||
name += "-spiffs";
|
||||
name += String(spiffs_kb > 0 ? spiffs_kb : -spiffs_kb, DEC);
|
||||
name += "KB";
|
||||
mock_start_spiffs(name, spiffs_kb);
|
||||
}
|
||||
|
||||
if (littlefs_kb)
|
||||
{
|
||||
String name;
|
||||
make_fs_filename(name, fspath, argv[0]);
|
||||
name += "-littlefs";
|
||||
name += String(littlefs_kb > 0? littlefs_kb: -littlefs_kb, DEC);
|
||||
name += "KB";
|
||||
mock_start_littlefs(name, littlefs_kb);
|
||||
}
|
||||
if (littlefs_kb)
|
||||
{
|
||||
String name;
|
||||
make_fs_filename(name, fspath, argv[0]);
|
||||
name += "-littlefs";
|
||||
name += String(littlefs_kb > 0 ? littlefs_kb : -littlefs_kb, DEC);
|
||||
name += "KB";
|
||||
mock_start_littlefs(name, littlefs_kb);
|
||||
}
|
||||
|
||||
// setup global global_ipv4_netfmt
|
||||
wifi_get_ip_info(0, nullptr);
|
||||
// setup global global_ipv4_netfmt
|
||||
wifi_get_ip_info(0, nullptr);
|
||||
|
||||
if (!blocking_uart)
|
||||
{
|
||||
// set stdin to non blocking mode
|
||||
mock_start_uart();
|
||||
}
|
||||
if (!blocking_uart)
|
||||
{
|
||||
// set stdin to non blocking mode
|
||||
mock_start_uart();
|
||||
}
|
||||
|
||||
// install exit handler in case Esp.restart() is called
|
||||
atexit(cleanup);
|
||||
// install exit handler in case Esp.restart() is called
|
||||
atexit(cleanup);
|
||||
|
||||
// first call to millis(): now is millis() and micros() beginning
|
||||
millis();
|
||||
// first call to millis(): now is millis() and micros() beginning
|
||||
millis();
|
||||
|
||||
setup();
|
||||
while (!user_exit)
|
||||
{
|
||||
uint8_t data = mock_read_uart();
|
||||
setup();
|
||||
while (!user_exit)
|
||||
{
|
||||
uint8_t data = mock_read_uart();
|
||||
|
||||
if (data)
|
||||
uart_new_data(UART0, data);
|
||||
if (!fast)
|
||||
usleep(1000); // not 100% cpu, ~1000 loops per second
|
||||
loop();
|
||||
loop_end();
|
||||
check_incoming_udp();
|
||||
if (data)
|
||||
uart_new_data(UART0, data);
|
||||
if (!fast)
|
||||
usleep(1000); // not 100% cpu, ~1000 loops per second
|
||||
loop();
|
||||
loop_end();
|
||||
check_incoming_udp();
|
||||
|
||||
if (run_once)
|
||||
user_exit = true;
|
||||
}
|
||||
cleanup();
|
||||
if (run_once)
|
||||
user_exit = true;
|
||||
}
|
||||
cleanup();
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
@ -3,15 +3,14 @@
|
||||
|
||||
LittleFSMock* littlefs_mock = nullptr;
|
||||
|
||||
void mock_start_littlefs (const String& fname, size_t size_kb, size_t block_kb, size_t page_b)
|
||||
void mock_start_littlefs(const String& fname, size_t size_kb, size_t block_kb, size_t page_b)
|
||||
{
|
||||
littlefs_mock = new LittleFSMock(size_kb * 1024, block_kb * 1024, page_b, fname);
|
||||
littlefs_mock = new LittleFSMock(size_kb * 1024, block_kb * 1024, page_b, fname);
|
||||
}
|
||||
|
||||
void mock_stop_littlefs ()
|
||||
void mock_stop_littlefs()
|
||||
{
|
||||
if (littlefs_mock)
|
||||
delete littlefs_mock;
|
||||
littlefs_mock = nullptr;
|
||||
if (littlefs_mock)
|
||||
delete littlefs_mock;
|
||||
littlefs_mock = nullptr;
|
||||
}
|
||||
|
||||
|
@ -3,15 +3,14 @@
|
||||
|
||||
SpiffsMock* spiffs_mock = nullptr;
|
||||
|
||||
void mock_start_spiffs (const String& fname, size_t size_kb, size_t block_kb, size_t page_b)
|
||||
void mock_start_spiffs(const String& fname, size_t size_kb, size_t block_kb, size_t page_b)
|
||||
{
|
||||
spiffs_mock = new SpiffsMock(size_kb * 1024, block_kb * 1024, page_b, fname);
|
||||
spiffs_mock = new SpiffsMock(size_kb * 1024, block_kb * 1024, page_b, fname);
|
||||
}
|
||||
|
||||
void mock_stop_spiffs ()
|
||||
void mock_stop_spiffs()
|
||||
{
|
||||
if (spiffs_mock)
|
||||
delete spiffs_mock;
|
||||
spiffs_mock = nullptr;
|
||||
if (spiffs_mock)
|
||||
delete spiffs_mock;
|
||||
spiffs_mock = nullptr;
|
||||
}
|
||||
|
||||
|
@ -33,28 +33,28 @@
|
||||
#include <poll.h>
|
||||
#include <map>
|
||||
|
||||
std::map<int,UdpContext*> udps;
|
||||
std::map<int, UdpContext*> udps;
|
||||
|
||||
void register_udp (int sock, UdpContext* udp)
|
||||
void register_udp(int sock, UdpContext* udp)
|
||||
{
|
||||
if (udp)
|
||||
udps[sock] = udp;
|
||||
else
|
||||
udps.erase(sock);
|
||||
if (udp)
|
||||
udps[sock] = udp;
|
||||
else
|
||||
udps.erase(sock);
|
||||
}
|
||||
|
||||
void check_incoming_udp ()
|
||||
void check_incoming_udp()
|
||||
{
|
||||
// check incoming udp
|
||||
for (auto& udp: udps)
|
||||
{
|
||||
pollfd p;
|
||||
p.fd = udp.first;
|
||||
p.events = POLLIN;
|
||||
if (poll(&p, 1, 0) && p.revents == POLLIN)
|
||||
{
|
||||
mockverbose("UDP poll(%d) -> cb\r", p.fd);
|
||||
udp.second->mock_cb();
|
||||
}
|
||||
}
|
||||
// check incoming udp
|
||||
for (auto& udp : udps)
|
||||
{
|
||||
pollfd p;
|
||||
p.fd = udp.first;
|
||||
p.events = POLLIN;
|
||||
if (poll(&p, 1, 0) && p.revents == POLLIN)
|
||||
{
|
||||
mockverbose("UDP poll(%d) -> cb\r", p.fd);
|
||||
udp.second->mock_cb();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,168 +39,173 @@
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
int mockSockSetup (int sock)
|
||||
int mockSockSetup(int sock)
|
||||
{
|
||||
if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
|
||||
{
|
||||
perror("socket fcntl(O_NONBLOCK)");
|
||||
close(sock);
|
||||
return -1;
|
||||
}
|
||||
if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
|
||||
{
|
||||
perror("socket fcntl(O_NONBLOCK)");
|
||||
close(sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifndef MSG_NOSIGNAL
|
||||
int i = 1;
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, &i, sizeof i) == -1)
|
||||
{
|
||||
perror("sockopt(SO_NOSIGPIPE)(macOS)");
|
||||
close(sock);
|
||||
return -1;
|
||||
}
|
||||
int i = 1;
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, &i, sizeof i) == -1)
|
||||
{
|
||||
perror("sockopt(SO_NOSIGPIPE)(macOS)");
|
||||
close(sock);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return sock;
|
||||
return sock;
|
||||
}
|
||||
|
||||
int mockConnect (uint32_t ipv4, int& sock, int port)
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
return mockSockSetup(sock) == -1? 0: 1;
|
||||
return mockSockSetup(sock) == -1 ? 0 : 1;
|
||||
}
|
||||
|
||||
ssize_t mockFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize)
|
||||
ssize_t mockFillInBuf(int sock, char* ccinbuf, size_t& ccinbufsize)
|
||||
{
|
||||
size_t maxread = CCBUFSIZE - ccinbufsize;
|
||||
ssize_t ret = ::read(sock, ccinbuf + ccinbufsize, maxread);
|
||||
size_t maxread = CCBUFSIZE - ccinbufsize;
|
||||
ssize_t ret = ::read(sock, ccinbuf + ccinbufsize, maxread);
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
// connection closed
|
||||
// nothing is read
|
||||
return 0;
|
||||
}
|
||||
if (ret == 0)
|
||||
{
|
||||
// connection closed
|
||||
// nothing is read
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ret == -1)
|
||||
{
|
||||
if (errno != EAGAIN)
|
||||
{
|
||||
fprintf(stderr, MOCK "ClientContext::(read/peek fd=%i): filling buffer for %zd bytes: %s\n", sock, maxread, strerror(errno));
|
||||
if (ret == -1)
|
||||
{
|
||||
if (errno != EAGAIN)
|
||||
{
|
||||
fprintf(stderr,
|
||||
MOCK "ClientContext::(read/peek fd=%i): filling buffer for %zd bytes: %s\n",
|
||||
sock, maxread, strerror(errno));
|
||||
// error
|
||||
return -1;
|
||||
}
|
||||
ret = 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
ccinbufsize += ret;
|
||||
return ret;
|
||||
ccinbufsize += ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t mockPeekBytes (int sock, char* dst, size_t usersize, int timeout_ms, char* ccinbuf, size_t& ccinbufsize)
|
||||
ssize_t mockPeekBytes(int sock, char* dst, size_t usersize, int timeout_ms, char* ccinbuf,
|
||||
size_t& ccinbufsize)
|
||||
{
|
||||
// usersize==0: peekAvailable()
|
||||
|
||||
if (usersize > CCBUFSIZE)
|
||||
mockverbose("CCBUFSIZE(%d) should be increased by %zd bytes (-> %zd)\n", CCBUFSIZE, usersize - CCBUFSIZE, usersize);
|
||||
if (usersize > CCBUFSIZE)
|
||||
mockverbose("CCBUFSIZE(%d) should be increased by %zd bytes (-> %zd)\n", CCBUFSIZE,
|
||||
usersize - CCBUFSIZE, usersize);
|
||||
|
||||
struct pollfd p;
|
||||
size_t retsize = 0;
|
||||
do
|
||||
{
|
||||
if (usersize && usersize <= ccinbufsize)
|
||||
{
|
||||
// data already buffered
|
||||
retsize = usersize;
|
||||
break;
|
||||
}
|
||||
|
||||
// check incoming data data
|
||||
if (mockFillInBuf(sock, ccinbuf, ccinbufsize) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
struct pollfd p;
|
||||
size_t retsize = 0;
|
||||
do
|
||||
{
|
||||
if (usersize && usersize <= ccinbufsize)
|
||||
{
|
||||
// data already buffered
|
||||
retsize = usersize;
|
||||
break;
|
||||
}
|
||||
|
||||
// check incoming data data
|
||||
if (mockFillInBuf(sock, ccinbuf, ccinbufsize) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (usersize == 0 && ccinbufsize)
|
||||
// peekAvailable
|
||||
return 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);
|
||||
|
||||
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);
|
||||
|
||||
if (dst)
|
||||
{
|
||||
memcpy(dst, ccinbuf, retsize);
|
||||
}
|
||||
|
||||
return retsize;
|
||||
return retsize;
|
||||
}
|
||||
|
||||
ssize_t mockRead (int sock, char* dst, size_t size, int timeout_ms, char* ccinbuf, size_t& ccinbufsize)
|
||||
ssize_t mockRead(int sock, char* dst, size_t size, int timeout_ms, char* ccinbuf,
|
||||
size_t& ccinbufsize)
|
||||
{
|
||||
ssize_t copied = mockPeekBytes(sock, dst, size, timeout_ms, ccinbuf, ccinbufsize);
|
||||
if (copied < 0)
|
||||
return -1;
|
||||
// swallow (XXX use a circular buffer)
|
||||
memmove(ccinbuf, ccinbuf + copied, ccinbufsize - copied);
|
||||
ccinbufsize -= copied;
|
||||
return copied;
|
||||
ssize_t copied = mockPeekBytes(sock, dst, size, timeout_ms, ccinbuf, ccinbufsize);
|
||||
if (copied < 0)
|
||||
return -1;
|
||||
// swallow (XXX use a circular buffer)
|
||||
memmove(ccinbuf, ccinbuf + copied, ccinbufsize - copied);
|
||||
ccinbufsize -= copied;
|
||||
return copied;
|
||||
}
|
||||
|
||||
ssize_t mockWrite (int sock, const uint8_t* data, size_t size, int timeout_ms)
|
||||
{
|
||||
size_t sent = 0;
|
||||
while (sent < size)
|
||||
{
|
||||
|
||||
struct pollfd p;
|
||||
p.fd = sock;
|
||||
p.events = POLLOUT;
|
||||
int ret = poll(&p, 1, timeout_ms);
|
||||
if (ret == -1)
|
||||
{
|
||||
fprintf(stderr, MOCK "ClientContext::write(%d): %s\n", sock, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (ret)
|
||||
{
|
||||
ssize_t mockWrite(int sock, const uint8_t* data, size_t size, int timeout_ms)
|
||||
{
|
||||
size_t sent = 0;
|
||||
while (sent < size)
|
||||
{
|
||||
struct pollfd p;
|
||||
p.fd = sock;
|
||||
p.events = POLLOUT;
|
||||
int ret = poll(&p, 1, timeout_ms);
|
||||
if (ret == -1)
|
||||
{
|
||||
fprintf(stderr, MOCK "ClientContext::write(%d): %s\n", sock, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (ret)
|
||||
{
|
||||
#ifndef MSG_NOSIGNAL
|
||||
ret = ::write(sock, data + sent, size - sent);
|
||||
ret = ::write(sock, data + sent, size - sent);
|
||||
#else
|
||||
ret = ::send(sock, data + sent, size - sent, MSG_NOSIGNAL);
|
||||
ret = ::send(sock, data + sent, size - sent, MSG_NOSIGNAL);
|
||||
#endif
|
||||
if (ret == -1)
|
||||
{
|
||||
fprintf(stderr, MOCK "ClientContext::write/send(%d): %s\n", sock, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
sent += ret;
|
||||
if (sent < size)
|
||||
fprintf(stderr, MOCK "ClientContext::write: sent %d bytes (%zd / %zd)\n", ret, sent, size);
|
||||
}
|
||||
}
|
||||
if (ret == -1)
|
||||
{
|
||||
fprintf(stderr, MOCK "ClientContext::write/send(%d): %s\n", sock, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
sent += ret;
|
||||
if (sent < size)
|
||||
fprintf(stderr, MOCK "ClientContext::write: sent %d bytes (%zd / %zd)\n", ret, sent,
|
||||
size);
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_ESP_WIFI
|
||||
mockverbose(MOCK "ClientContext::write: total sent %zd bytes\n", sent);
|
||||
#endif
|
||||
return sent;
|
||||
return sent;
|
||||
}
|
||||
|
@ -35,23 +35,24 @@
|
||||
#include <WiFiClient.h>
|
||||
#include <include/ClientContext.h>
|
||||
|
||||
#include <netdb.h> // gethostbyname
|
||||
#include <netdb.h> // gethostbyname
|
||||
|
||||
err_t dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found, void *callback_arg)
|
||||
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;
|
||||
(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)
|
||||
tcp_pcb* tcp_new(void)
|
||||
{
|
||||
// this is useless
|
||||
// ClientContext is setting the source port and we don't care here
|
||||
return &mock_tcp_pcb;
|
||||
// this is useless
|
||||
// ClientContext is setting the source port and we don't care here
|
||||
return &mock_tcp_pcb;
|
||||
}
|
||||
|
@ -32,46 +32,53 @@
|
||||
#ifndef EEPROM_MOCK
|
||||
#define EEPROM_MOCK
|
||||
|
||||
class EEPROMClass {
|
||||
class EEPROMClass
|
||||
{
|
||||
public:
|
||||
EEPROMClass(uint32_t sector);
|
||||
EEPROMClass(void);
|
||||
~EEPROMClass();
|
||||
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();
|
||||
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>
|
||||
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;
|
||||
}
|
||||
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; }
|
||||
size_t length()
|
||||
{
|
||||
return _size;
|
||||
}
|
||||
|
||||
//uint8_t& operator[](int const address) { return read(address); }
|
||||
uint8_t operator[] (int address) { return read(address); }
|
||||
// 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;
|
||||
size_t _size = 0;
|
||||
int _fd = -1;
|
||||
};
|
||||
|
||||
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_EEPROM)
|
||||
|
@ -42,60 +42,82 @@
|
||||
static uint8_t _mode[GPIONUM];
|
||||
static uint8_t _gpio[GPIONUM];
|
||||
|
||||
void pinMode (uint8_t pin, uint8_t mode)
|
||||
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)";
|
||||
}
|
||||
VERBOSE("gpio%d: mode='%s'\n", pin, m);
|
||||
#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)";
|
||||
}
|
||||
VERBOSE("gpio%d: mode='%s'\n", pin, m);
|
||||
|
||||
if (pin < GPIONUM)
|
||||
{
|
||||
_mode[pin] = mode;
|
||||
_mode[pin] = mode;
|
||||
}
|
||||
}
|
||||
|
||||
void digitalWrite(uint8_t pin, uint8_t val)
|
||||
{
|
||||
VERBOSE("digitalWrite(pin=%d val=%d)\n", pin, val);
|
||||
if (pin < GPIONUM) {
|
||||
VERBOSE("digitalWrite(pin=%d val=%d)\n", pin, val);
|
||||
if (pin < GPIONUM)
|
||||
{
|
||||
_gpio[pin] = val;
|
||||
}
|
||||
}
|
||||
|
||||
void analogWrite(uint8_t pin, int val)
|
||||
{
|
||||
VERBOSE("analogWrite(pin=%d, val=%d\n", pin, val);
|
||||
VERBOSE("analogWrite(pin=%d, val=%d\n", pin, val);
|
||||
}
|
||||
|
||||
int analogRead(uint8_t pin)
|
||||
{
|
||||
(void)pin;
|
||||
return 512;
|
||||
(void)pin;
|
||||
return 512;
|
||||
}
|
||||
|
||||
void analogWriteRange(uint32_t range)
|
||||
{
|
||||
VERBOSE("analogWriteRange(range=%d)\n", range);
|
||||
VERBOSE("analogWriteRange(range=%d)\n", range);
|
||||
}
|
||||
|
||||
int digitalRead(uint8_t pin)
|
||||
{
|
||||
VERBOSE("digitalRead(%d)\n", pin);
|
||||
VERBOSE("digitalRead(%d)\n", pin);
|
||||
|
||||
if (pin < GPIONUM) {
|
||||
return _gpio[pin] != 0;
|
||||
} else {
|
||||
return 0;
|
||||
if (pin < GPIONUM)
|
||||
{
|
||||
return _gpio[pin] != 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -42,52 +42,52 @@
|
||||
|
||||
#define EEPROM_FILE_NAME "eeprom"
|
||||
|
||||
EEPROMClass::EEPROMClass ()
|
||||
{
|
||||
}
|
||||
EEPROMClass::EEPROMClass() { }
|
||||
|
||||
EEPROMClass::~EEPROMClass ()
|
||||
EEPROMClass::~EEPROMClass()
|
||||
{
|
||||
if (_fd >= 0)
|
||||
close(_fd);
|
||||
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;
|
||||
}
|
||||
_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);
|
||||
if (_fd != -1)
|
||||
close(_fd);
|
||||
}
|
||||
|
||||
bool EEPROMClass::commit()
|
||||
{
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t EEPROMClass::read (int x)
|
||||
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;
|
||||
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)
|
||||
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 (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)
|
||||
|
@ -36,204 +36,223 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
unsigned long long operator"" _kHz(unsigned long long x) {
|
||||
unsigned long long operator"" _kHz(unsigned long long x)
|
||||
{
|
||||
return x * 1000;
|
||||
}
|
||||
|
||||
unsigned long long operator"" _MHz(unsigned long long x) {
|
||||
unsigned long long operator"" _MHz(unsigned long long x)
|
||||
{
|
||||
return x * 1000 * 1000;
|
||||
}
|
||||
|
||||
unsigned long long operator"" _GHz(unsigned long long x) {
|
||||
unsigned long long operator"" _GHz(unsigned long long x)
|
||||
{
|
||||
return x * 1000 * 1000 * 1000;
|
||||
}
|
||||
|
||||
unsigned long long operator"" _kBit(unsigned long long x) {
|
||||
unsigned long long operator"" _kBit(unsigned long long x)
|
||||
{
|
||||
return x * 1024;
|
||||
}
|
||||
|
||||
unsigned long long operator"" _MBit(unsigned long long x) {
|
||||
unsigned long long operator"" _MBit(unsigned long long x)
|
||||
{
|
||||
return x * 1024 * 1024;
|
||||
}
|
||||
|
||||
unsigned long long operator"" _GBit(unsigned long long x) {
|
||||
unsigned long long operator"" _GBit(unsigned long long x)
|
||||
{
|
||||
return x * 1024 * 1024 * 1024;
|
||||
}
|
||||
|
||||
unsigned long long operator"" _kB(unsigned long long x) {
|
||||
unsigned long long operator"" _kB(unsigned long long x)
|
||||
{
|
||||
return x * 1024;
|
||||
}
|
||||
|
||||
unsigned long long operator"" _MB(unsigned long long x) {
|
||||
unsigned long long operator"" _MB(unsigned long long x)
|
||||
{
|
||||
return x * 1024 * 1024;
|
||||
}
|
||||
|
||||
unsigned long long operator"" _GB(unsigned long long x) {
|
||||
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 eboot_command_write(struct eboot_command* cmd)
|
||||
{
|
||||
(void)cmd;
|
||||
(void)cmd;
|
||||
}
|
||||
|
||||
EspClass ESP;
|
||||
|
||||
void EspClass::restart ()
|
||||
void EspClass::restart()
|
||||
{
|
||||
mockverbose("Esp.restart(): exiting\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
mockverbose("Esp.restart(): exiting\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
uint32_t EspClass::getChipId()
|
||||
{
|
||||
return 0xee1337;
|
||||
return 0xee1337;
|
||||
}
|
||||
|
||||
bool EspClass::checkFlashConfig(bool needsEquals)
|
||||
{
|
||||
(void) needsEquals;
|
||||
return true;
|
||||
(void)needsEquals;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t EspClass::getSketchSize()
|
||||
{
|
||||
return 400000;
|
||||
return 400000;
|
||||
}
|
||||
|
||||
uint32_t EspClass::getFreeHeap()
|
||||
{
|
||||
return 30000;
|
||||
return 30000;
|
||||
}
|
||||
|
||||
uint32_t EspClass::getMaxFreeBlockSize()
|
||||
{
|
||||
return 20000;
|
||||
return 20000;
|
||||
}
|
||||
|
||||
String EspClass::getResetReason()
|
||||
{
|
||||
return "Power on";
|
||||
return "Power on";
|
||||
}
|
||||
|
||||
uint32_t EspClass::getFreeSketchSpace()
|
||||
{
|
||||
return 4 * 1024 * 1024;
|
||||
return 4 * 1024 * 1024;
|
||||
}
|
||||
|
||||
const char *EspClass::getSdkVersion()
|
||||
const char* EspClass::getSdkVersion()
|
||||
{
|
||||
return "2.5.0";
|
||||
return "2.5.0";
|
||||
}
|
||||
|
||||
uint32_t EspClass::getFlashChipSpeed()
|
||||
{
|
||||
return 40;
|
||||
return 40;
|
||||
}
|
||||
|
||||
void EspClass::getHeapStats(uint32_t* hfree, uint16_t* hmax, uint8_t* hfrag) {
|
||||
uint32_t hf = 10 * 1024;
|
||||
float hm = 1 * 1024;
|
||||
void EspClass::getHeapStats(uint32_t* hfree, uint16_t* hmax, uint8_t* hfrag)
|
||||
{
|
||||
uint32_t hf = 10 * 1024;
|
||||
float hm = 1 * 1024;
|
||||
|
||||
if (hfree) *hfree = hf;
|
||||
if (hmax) *hmax = hm;
|
||||
if (hfrag) *hfrag = 100 - (sqrt(hm) * 100) / hf;
|
||||
if (hfree)
|
||||
*hfree = hf;
|
||||
if (hmax)
|
||||
*hmax = hm;
|
||||
if (hfrag)
|
||||
*hfrag = 100 - (sqrt(hm) * 100) / hf;
|
||||
}
|
||||
|
||||
void EspClass::getHeapStats(uint32_t* hfree, uint32_t* hmax, uint8_t* hfrag) {
|
||||
uint32_t hf = 10 * 1024;
|
||||
float hm = 1 * 1024;
|
||||
void EspClass::getHeapStats(uint32_t* hfree, uint32_t* hmax, uint8_t* hfrag)
|
||||
{
|
||||
uint32_t hf = 10 * 1024;
|
||||
float hm = 1 * 1024;
|
||||
|
||||
if (hfree) *hfree = hf;
|
||||
if (hmax) *hmax = hm;
|
||||
if (hfrag) *hfrag = 100 - (sqrt(hm) * 100) / hf;
|
||||
if (hfree)
|
||||
*hfree = hf;
|
||||
if (hmax)
|
||||
*hmax = hm;
|
||||
if (hfrag)
|
||||
*hfrag = 100 - (sqrt(hm) * 100) / hf;
|
||||
}
|
||||
|
||||
bool EspClass::flashEraseSector(uint32_t sector)
|
||||
{
|
||||
(void) sector;
|
||||
return true;
|
||||
(void)sector;
|
||||
return true;
|
||||
}
|
||||
|
||||
FlashMode_t EspClass::getFlashChipMode()
|
||||
{
|
||||
return FM_DOUT;
|
||||
return FM_DOUT;
|
||||
}
|
||||
|
||||
FlashMode_t EspClass::magicFlashChipMode(uint8_t byte)
|
||||
{
|
||||
(void) byte;
|
||||
return FM_DOUT;
|
||||
(void)byte;
|
||||
return FM_DOUT;
|
||||
}
|
||||
|
||||
bool EspClass::flashWrite(uint32_t offset, const uint32_t *data, size_t size)
|
||||
bool EspClass::flashWrite(uint32_t offset, const uint32_t* data, size_t size)
|
||||
{
|
||||
(void)offset;
|
||||
(void)data;
|
||||
(void)size;
|
||||
return true;
|
||||
(void)offset;
|
||||
(void)data;
|
||||
(void)size;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EspClass::flashWrite(uint32_t offset, const uint8_t *data, size_t size)
|
||||
bool EspClass::flashWrite(uint32_t offset, const uint8_t* data, size_t size)
|
||||
{
|
||||
(void)offset;
|
||||
(void)data;
|
||||
(void)size;
|
||||
return true;
|
||||
(void)offset;
|
||||
(void)data;
|
||||
(void)size;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EspClass::flashRead(uint32_t offset, uint32_t *data, size_t size)
|
||||
bool EspClass::flashRead(uint32_t offset, uint32_t* data, size_t size)
|
||||
{
|
||||
(void)offset;
|
||||
(void)data;
|
||||
(void)size;
|
||||
return true;
|
||||
(void)offset;
|
||||
(void)data;
|
||||
(void)size;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EspClass::flashRead(uint32_t offset, uint8_t *data, size_t size)
|
||||
bool EspClass::flashRead(uint32_t offset, uint8_t* data, size_t size)
|
||||
{
|
||||
(void)offset;
|
||||
(void)data;
|
||||
(void)size;
|
||||
return true;
|
||||
(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::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);
|
||||
return magicFlashChipSize(4);
|
||||
}
|
||||
|
||||
uint32_t EspClass::getFlashChipSize(void)
|
||||
{
|
||||
return magicFlashChipSize(4);
|
||||
return magicFlashChipSize(4);
|
||||
}
|
||||
|
||||
String EspClass::getFullVersion ()
|
||||
String EspClass::getFullVersion()
|
||||
{
|
||||
return "emulation-on-host";
|
||||
return "emulation-on-host";
|
||||
}
|
||||
|
||||
uint32_t EspClass::getFreeContStack()
|
||||
@ -241,9 +260,7 @@ uint32_t EspClass::getFreeContStack()
|
||||
return 4000;
|
||||
}
|
||||
|
||||
void EspClass::resetFreeContStack()
|
||||
{
|
||||
}
|
||||
void EspClass::resetFreeContStack() { }
|
||||
|
||||
uint32_t EspClass::getCycleCount()
|
||||
{
|
||||
@ -257,23 +274,15 @@ uint32_t esp_get_cycle_count()
|
||||
return (((uint64_t)t.tv_sec) * 1000000 + t.tv_usec) * (F_CPU / 1000000);
|
||||
}
|
||||
|
||||
void EspClass::setDramHeap()
|
||||
{
|
||||
}
|
||||
void EspClass::setDramHeap() { }
|
||||
|
||||
void EspClass::setIramHeap()
|
||||
{
|
||||
}
|
||||
void EspClass::setIramHeap() { }
|
||||
|
||||
void EspClass::setExternalHeap()
|
||||
{
|
||||
}
|
||||
void EspClass::setExternalHeap() { }
|
||||
|
||||
void EspClass::resetHeap()
|
||||
{
|
||||
}
|
||||
void EspClass::resetHeap() { }
|
||||
|
||||
void EspClass::reset ()
|
||||
void EspClass::reset()
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
@ -35,29 +35,23 @@
|
||||
SPIClass SPI;
|
||||
#endif
|
||||
|
||||
SPIClass::SPIClass ()
|
||||
{
|
||||
}
|
||||
SPIClass::SPIClass() { }
|
||||
|
||||
uint8_t SPIClass::transfer(uint8_t data)
|
||||
{
|
||||
return data;
|
||||
return data;
|
||||
}
|
||||
|
||||
void SPIClass::begin()
|
||||
{
|
||||
}
|
||||
void SPIClass::begin() { }
|
||||
|
||||
void SPIClass::end()
|
||||
{
|
||||
}
|
||||
void SPIClass::end() { }
|
||||
|
||||
void SPIClass::setFrequency(uint32_t freq)
|
||||
{
|
||||
(void)freq;
|
||||
(void)freq;
|
||||
}
|
||||
|
||||
void SPIClass::setHwCs(bool use)
|
||||
{
|
||||
(void)use;
|
||||
(void)use;
|
||||
}
|
||||
|
@ -34,56 +34,91 @@
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
char* ets_strncpy(char* d, const char* s, size_t n)
|
||||
{
|
||||
return strncpy(d, s, n);
|
||||
}
|
||||
size_t ets_strlen(const char* s)
|
||||
{
|
||||
return strlen(s);
|
||||
}
|
||||
|
||||
char* ets_strcpy (char* d, const char* s) { return strcpy(d, s); }
|
||||
char* ets_strncpy (char* d, const char* s, size_t n) { return strncpy(d, s, n); }
|
||||
size_t ets_strlen (const char* s) { return strlen(s); }
|
||||
|
||||
int ets_printf (const char* fmt, ...)
|
||||
{
|
||||
int ets_printf(const char* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
int len = vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
return len;
|
||||
}
|
||||
int len = vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
return len;
|
||||
}
|
||||
|
||||
void stack_thunk_add_ref() { }
|
||||
void stack_thunk_del_ref() { }
|
||||
void stack_thunk_repaint() { }
|
||||
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() { }
|
||||
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)
|
||||
|
||||
};
|
||||
|
||||
void configTime(int timezone, int daylightOffset_sec,
|
||||
const char* server1, const char* server2, const char* server3)
|
||||
void configTime(int timezone, int daylightOffset_sec, const char* server1, const char* server2,
|
||||
const char* server3)
|
||||
{
|
||||
(void)server1;
|
||||
(void)server2;
|
||||
(void)server3;
|
||||
(void)server1;
|
||||
(void)server2;
|
||||
(void)server3;
|
||||
|
||||
mockverbose("configTime: TODO (tz=%dH offset=%dS) (time will be host's)\n", timezone, daylightOffset_sec);
|
||||
mockverbose("configTime: TODO (tz=%dH offset=%dS) (time will be host's)\n", timezone,
|
||||
daylightOffset_sec);
|
||||
}
|
||||
|
||||
void configTime(const char* tz, const char* server1, const char* server2, const char* server3)
|
||||
{
|
||||
(void)server1;
|
||||
(void)server2;
|
||||
(void)server3;
|
||||
(void)server1;
|
||||
(void)server2;
|
||||
(void)server3;
|
||||
|
||||
mockverbose("configTime: TODO (tz='%s') (time will be host's)\n", tz);
|
||||
mockverbose("configTime: TODO (tz='%s') (time will be host's)\n", tz);
|
||||
}
|
||||
|
@ -28,475 +28,455 @@
|
||||
is responsible for feeding the RX FIFO new data by calling uart_new_data().
|
||||
*/
|
||||
|
||||
#include <unistd.h> // write
|
||||
#include <sys/time.h> // gettimeofday
|
||||
#include <time.h> // localtime
|
||||
#include <unistd.h> // write
|
||||
#include <sys/time.h> // gettimeofday
|
||||
#include <time.h> // localtime
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "uart.h"
|
||||
|
||||
//#define UART_DISCARD_NEWEST
|
||||
|
||||
extern "C" {
|
||||
|
||||
bool blocking_uart = true; // system default
|
||||
|
||||
static int s_uart_debug_nr = UART1;
|
||||
|
||||
static uart_t *UART[2] = { NULL, NULL };
|
||||
|
||||
struct uart_rx_buffer_
|
||||
extern "C"
|
||||
{
|
||||
size_t size;
|
||||
size_t rpos;
|
||||
size_t wpos;
|
||||
uint8_t * buffer;
|
||||
};
|
||||
bool blocking_uart = true; // system default
|
||||
|
||||
struct uart_
|
||||
{
|
||||
int uart_nr;
|
||||
int baud_rate;
|
||||
bool rx_enabled;
|
||||
bool tx_enabled;
|
||||
bool rx_overrun;
|
||||
struct uart_rx_buffer_ * rx_buffer;
|
||||
};
|
||||
static int s_uart_debug_nr = UART1;
|
||||
|
||||
bool serial_timestamp = false;
|
||||
static uart_t* UART[2] = { NULL, NULL };
|
||||
|
||||
// write one byte to the emulated UART
|
||||
static void
|
||||
uart_do_write_char(const int uart_nr, char c)
|
||||
{
|
||||
static bool w = false;
|
||||
struct uart_rx_buffer_
|
||||
{
|
||||
size_t size;
|
||||
size_t rpos;
|
||||
size_t wpos;
|
||||
uint8_t* buffer;
|
||||
};
|
||||
|
||||
if (uart_nr >= UART0 && uart_nr <= UART1)
|
||||
{
|
||||
if (serial_timestamp && (c == '\n' || c == '\r'))
|
||||
{
|
||||
if (w)
|
||||
{
|
||||
FILE* out = uart_nr == UART0? stdout: stderr;
|
||||
timeval tv;
|
||||
gettimeofday(&tv, nullptr);
|
||||
const tm* tm = localtime(&tv.tv_sec);
|
||||
fprintf(out, "\r\n%d:%02d:%02d.%06d: ", tm->tm_hour, tm->tm_min, tm->tm_sec, (int)tv.tv_usec);
|
||||
fflush(out);
|
||||
w = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
struct uart_
|
||||
{
|
||||
int uart_nr;
|
||||
int baud_rate;
|
||||
bool rx_enabled;
|
||||
bool tx_enabled;
|
||||
bool rx_overrun;
|
||||
struct uart_rx_buffer_* rx_buffer;
|
||||
};
|
||||
|
||||
bool serial_timestamp = false;
|
||||
|
||||
// write one byte to the emulated UART
|
||||
static void uart_do_write_char(const int uart_nr, char c)
|
||||
{
|
||||
static bool w = false;
|
||||
|
||||
if (uart_nr >= UART0 && uart_nr <= UART1)
|
||||
{
|
||||
if (serial_timestamp && (c == '\n' || c == '\r'))
|
||||
{
|
||||
if (w)
|
||||
{
|
||||
FILE* out = uart_nr == UART0 ? stdout : stderr;
|
||||
timeval tv;
|
||||
gettimeofday(&tv, nullptr);
|
||||
const tm* tm = localtime(&tv.tv_sec);
|
||||
fprintf(out, "\r\n%d:%02d:%02d.%06d: ", tm->tm_hour, tm->tm_min, tm->tm_sec,
|
||||
(int)tv.tv_usec);
|
||||
fflush(out);
|
||||
w = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-result"
|
||||
write(uart_nr + 1, &c, 1);
|
||||
write(uart_nr + 1, &c, 1);
|
||||
#pragma GCC diagnostic pop
|
||||
w = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// write a new byte into the RX FIFO buffer
|
||||
static void
|
||||
uart_handle_data(uart_t* uart, uint8_t data)
|
||||
{
|
||||
struct uart_rx_buffer_ *rx_buffer = uart->rx_buffer;
|
||||
|
||||
size_t nextPos = (rx_buffer->wpos + 1) % rx_buffer->size;
|
||||
if(nextPos == rx_buffer->rpos)
|
||||
{
|
||||
uart->rx_overrun = true;
|
||||
#ifdef UART_DISCARD_NEWEST
|
||||
return;
|
||||
#else
|
||||
if (++rx_buffer->rpos == rx_buffer->size)
|
||||
rx_buffer->rpos = 0;
|
||||
#endif
|
||||
}
|
||||
rx_buffer->buffer[rx_buffer->wpos] = data;
|
||||
rx_buffer->wpos = nextPos;
|
||||
}
|
||||
|
||||
// insert a new byte into the RX FIFO nuffer
|
||||
void
|
||||
uart_new_data(const int uart_nr, uint8_t data)
|
||||
{
|
||||
uart_t* uart = UART[uart_nr];
|
||||
|
||||
if(uart == NULL || !uart->rx_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
uart_handle_data(uart, data);
|
||||
}
|
||||
|
||||
static size_t
|
||||
uart_rx_available_unsafe(const struct uart_rx_buffer_ * rx_buffer)
|
||||
{
|
||||
size_t ret = rx_buffer->wpos - rx_buffer->rpos;
|
||||
|
||||
if(rx_buffer->wpos < rx_buffer->rpos)
|
||||
ret = (rx_buffer->wpos + rx_buffer->size) - rx_buffer->rpos;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// taking data straight from fifo, only needed in uart_resize_rx_buffer()
|
||||
static int
|
||||
uart_read_char_unsafe(uart_t* uart)
|
||||
{
|
||||
if (uart_rx_available_unsafe(uart->rx_buffer))
|
||||
{
|
||||
// take oldest sw data
|
||||
int ret = uart->rx_buffer->buffer[uart->rx_buffer->rpos];
|
||||
uart->rx_buffer->rpos = (uart->rx_buffer->rpos + 1) % uart->rx_buffer->size;
|
||||
return ret;
|
||||
}
|
||||
// unavailable
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**********************************************************/
|
||||
/************ UART API FUNCTIONS **************************/
|
||||
/**********************************************************/
|
||||
|
||||
size_t
|
||||
uart_rx_available(uart_t* uart)
|
||||
{
|
||||
if(uart == NULL || !uart->rx_enabled)
|
||||
return 0;
|
||||
|
||||
return uart_rx_available_unsafe(uart->rx_buffer);
|
||||
}
|
||||
|
||||
int
|
||||
uart_peek_char(uart_t* uart)
|
||||
{
|
||||
if(uart == NULL || !uart->rx_enabled)
|
||||
return -1;
|
||||
|
||||
if (!uart_rx_available_unsafe(uart->rx_buffer))
|
||||
return -1;
|
||||
|
||||
return uart->rx_buffer->buffer[uart->rx_buffer->rpos];
|
||||
}
|
||||
|
||||
int
|
||||
uart_read_char(uart_t* uart)
|
||||
{
|
||||
uint8_t ret;
|
||||
return uart_read(uart, (char*)&ret, 1) ? ret : -1;
|
||||
}
|
||||
|
||||
size_t
|
||||
uart_read(uart_t* uart, char* userbuffer, size_t usersize)
|
||||
{
|
||||
if(uart == NULL || !uart->rx_enabled)
|
||||
return 0;
|
||||
|
||||
if (!blocking_uart)
|
||||
{
|
||||
char c;
|
||||
if (read(0, &c, 1) == 1)
|
||||
uart_new_data(0, c);
|
||||
w = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t ret = 0;
|
||||
while (ret < usersize && uart_rx_available_unsafe(uart->rx_buffer))
|
||||
{
|
||||
// pour sw buffer to user's buffer
|
||||
// get largest linear length from sw buffer
|
||||
size_t chunk = uart->rx_buffer->rpos < uart->rx_buffer->wpos ?
|
||||
uart->rx_buffer->wpos - uart->rx_buffer->rpos :
|
||||
uart->rx_buffer->size - uart->rx_buffer->rpos;
|
||||
if (ret + chunk > usersize)
|
||||
chunk = usersize - ret;
|
||||
memcpy(userbuffer + ret, uart->rx_buffer->buffer + uart->rx_buffer->rpos, chunk);
|
||||
uart->rx_buffer->rpos = (uart->rx_buffer->rpos + chunk) % uart->rx_buffer->size;
|
||||
ret += chunk;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
// write a new byte into the RX FIFO buffer
|
||||
static void uart_handle_data(uart_t* uart, uint8_t data)
|
||||
{
|
||||
struct uart_rx_buffer_* rx_buffer = uart->rx_buffer;
|
||||
|
||||
size_t
|
||||
uart_resize_rx_buffer(uart_t* uart, size_t new_size)
|
||||
{
|
||||
if(uart == NULL || !uart->rx_enabled)
|
||||
return 0;
|
||||
size_t nextPos = (rx_buffer->wpos + 1) % rx_buffer->size;
|
||||
if (nextPos == rx_buffer->rpos)
|
||||
{
|
||||
uart->rx_overrun = true;
|
||||
#ifdef UART_DISCARD_NEWEST
|
||||
return;
|
||||
#else
|
||||
if (++rx_buffer->rpos == rx_buffer->size)
|
||||
rx_buffer->rpos = 0;
|
||||
#endif
|
||||
}
|
||||
rx_buffer->buffer[rx_buffer->wpos] = data;
|
||||
rx_buffer->wpos = nextPos;
|
||||
}
|
||||
|
||||
if(uart->rx_buffer->size == new_size)
|
||||
return uart->rx_buffer->size;
|
||||
// insert a new byte into the RX FIFO nuffer
|
||||
void uart_new_data(const int uart_nr, uint8_t data)
|
||||
{
|
||||
uart_t* uart = UART[uart_nr];
|
||||
|
||||
uint8_t * new_buf = (uint8_t*)malloc(new_size);
|
||||
if(!new_buf)
|
||||
return uart->rx_buffer->size;
|
||||
if (uart == NULL || !uart->rx_enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
size_t new_wpos = 0;
|
||||
// if uart_rx_available_unsafe() returns non-0, uart_read_char_unsafe() can't return -1
|
||||
while(uart_rx_available_unsafe(uart->rx_buffer) && new_wpos < new_size)
|
||||
new_buf[new_wpos++] = uart_read_char_unsafe(uart);
|
||||
if (new_wpos == new_size)
|
||||
new_wpos = 0;
|
||||
uart_handle_data(uart, data);
|
||||
}
|
||||
|
||||
uint8_t * old_buf = uart->rx_buffer->buffer;
|
||||
uart->rx_buffer->rpos = 0;
|
||||
uart->rx_buffer->wpos = new_wpos;
|
||||
uart->rx_buffer->size = new_size;
|
||||
uart->rx_buffer->buffer = new_buf;
|
||||
free(old_buf);
|
||||
return uart->rx_buffer->size;
|
||||
}
|
||||
static size_t uart_rx_available_unsafe(const struct uart_rx_buffer_* rx_buffer)
|
||||
{
|
||||
size_t ret = rx_buffer->wpos - rx_buffer->rpos;
|
||||
|
||||
size_t
|
||||
uart_get_rx_buffer_size(uart_t* uart)
|
||||
{
|
||||
return uart && uart->rx_enabled ? uart->rx_buffer->size : 0;
|
||||
}
|
||||
if (rx_buffer->wpos < rx_buffer->rpos)
|
||||
ret = (rx_buffer->wpos + rx_buffer->size) - rx_buffer->rpos;
|
||||
|
||||
size_t
|
||||
uart_write_char(uart_t* uart, char c)
|
||||
{
|
||||
if(uart == NULL || !uart->tx_enabled)
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
uart_do_write_char(uart->uart_nr, c);
|
||||
// taking data straight from fifo, only needed in uart_resize_rx_buffer()
|
||||
static int uart_read_char_unsafe(uart_t* uart)
|
||||
{
|
||||
if (uart_rx_available_unsafe(uart->rx_buffer))
|
||||
{
|
||||
// take oldest sw data
|
||||
int ret = uart->rx_buffer->buffer[uart->rx_buffer->rpos];
|
||||
uart->rx_buffer->rpos = (uart->rx_buffer->rpos + 1) % uart->rx_buffer->size;
|
||||
return ret;
|
||||
}
|
||||
// unavailable
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
/**********************************************************/
|
||||
/************ UART API FUNCTIONS **************************/
|
||||
/**********************************************************/
|
||||
|
||||
size_t
|
||||
uart_write(uart_t* uart, const char* buf, size_t size)
|
||||
{
|
||||
if(uart == NULL || !uart->tx_enabled)
|
||||
return 0;
|
||||
size_t uart_rx_available(uart_t* uart)
|
||||
{
|
||||
if (uart == NULL || !uart->rx_enabled)
|
||||
return 0;
|
||||
|
||||
size_t ret = size;
|
||||
const int uart_nr = uart->uart_nr;
|
||||
while (size--)
|
||||
uart_do_write_char(uart_nr, *buf++);
|
||||
return uart_rx_available_unsafe(uart->rx_buffer);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
int uart_peek_char(uart_t* uart)
|
||||
{
|
||||
if (uart == NULL || !uart->rx_enabled)
|
||||
return -1;
|
||||
|
||||
size_t
|
||||
uart_tx_free(uart_t* uart)
|
||||
{
|
||||
if(uart == NULL || !uart->tx_enabled)
|
||||
return 0;
|
||||
if (!uart_rx_available_unsafe(uart->rx_buffer))
|
||||
return -1;
|
||||
|
||||
return UART_TX_FIFO_SIZE;
|
||||
}
|
||||
return uart->rx_buffer->buffer[uart->rx_buffer->rpos];
|
||||
}
|
||||
|
||||
void
|
||||
uart_wait_tx_empty(uart_t* uart)
|
||||
{
|
||||
(void) uart;
|
||||
}
|
||||
int uart_read_char(uart_t* uart)
|
||||
{
|
||||
uint8_t ret;
|
||||
return uart_read(uart, (char*)&ret, 1) ? ret : -1;
|
||||
}
|
||||
|
||||
void
|
||||
uart_flush(uart_t* uart)
|
||||
{
|
||||
if(uart == NULL)
|
||||
return;
|
||||
size_t uart_read(uart_t* uart, char* userbuffer, size_t usersize)
|
||||
{
|
||||
if (uart == NULL || !uart->rx_enabled)
|
||||
return 0;
|
||||
|
||||
if(uart->rx_enabled)
|
||||
{
|
||||
uart->rx_buffer->rpos = 0;
|
||||
uart->rx_buffer->wpos = 0;
|
||||
}
|
||||
}
|
||||
if (!blocking_uart)
|
||||
{
|
||||
char c;
|
||||
if (read(0, &c, 1) == 1)
|
||||
uart_new_data(0, c);
|
||||
}
|
||||
|
||||
void
|
||||
uart_set_baudrate(uart_t* uart, int baud_rate)
|
||||
{
|
||||
if(uart == NULL)
|
||||
return;
|
||||
size_t ret = 0;
|
||||
while (ret < usersize && uart_rx_available_unsafe(uart->rx_buffer))
|
||||
{
|
||||
// pour sw buffer to user's buffer
|
||||
// get largest linear length from sw buffer
|
||||
size_t chunk = uart->rx_buffer->rpos < uart->rx_buffer->wpos
|
||||
? uart->rx_buffer->wpos - uart->rx_buffer->rpos
|
||||
: uart->rx_buffer->size - uart->rx_buffer->rpos;
|
||||
if (ret + chunk > usersize)
|
||||
chunk = usersize - ret;
|
||||
memcpy(userbuffer + ret, uart->rx_buffer->buffer + uart->rx_buffer->rpos, chunk);
|
||||
uart->rx_buffer->rpos = (uart->rx_buffer->rpos + chunk) % uart->rx_buffer->size;
|
||||
ret += chunk;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uart->baud_rate = baud_rate;
|
||||
}
|
||||
size_t uart_resize_rx_buffer(uart_t* uart, size_t new_size)
|
||||
{
|
||||
if (uart == NULL || !uart->rx_enabled)
|
||||
return 0;
|
||||
|
||||
int
|
||||
uart_get_baudrate(uart_t* uart)
|
||||
{
|
||||
if(uart == NULL)
|
||||
return 0;
|
||||
if (uart->rx_buffer->size == new_size)
|
||||
return uart->rx_buffer->size;
|
||||
|
||||
return uart->baud_rate;
|
||||
}
|
||||
uint8_t* new_buf = (uint8_t*)malloc(new_size);
|
||||
if (!new_buf)
|
||||
return uart->rx_buffer->size;
|
||||
|
||||
uint8_t
|
||||
uart_get_bit_length(const int uart_nr)
|
||||
{
|
||||
uint8_t width = ((uart_nr % 16) >> 2) + 5;
|
||||
uint8_t parity = (uart_nr >> 5) + 1;
|
||||
uint8_t stop = uart_nr % 4;
|
||||
return (width + parity + stop + 1);
|
||||
}
|
||||
size_t new_wpos = 0;
|
||||
// if uart_rx_available_unsafe() returns non-0, uart_read_char_unsafe() can't return -1
|
||||
while (uart_rx_available_unsafe(uart->rx_buffer) && new_wpos < new_size)
|
||||
new_buf[new_wpos++] = uart_read_char_unsafe(uart);
|
||||
if (new_wpos == new_size)
|
||||
new_wpos = 0;
|
||||
|
||||
uart_t*
|
||||
uart_init(int uart_nr, int baudrate, int config, int mode, int tx_pin, size_t rx_size, bool invert)
|
||||
{
|
||||
(void) config;
|
||||
(void) tx_pin;
|
||||
(void) invert;
|
||||
uart_t* uart = (uart_t*) malloc(sizeof(uart_t));
|
||||
if(uart == NULL)
|
||||
return NULL;
|
||||
uint8_t* old_buf = uart->rx_buffer->buffer;
|
||||
uart->rx_buffer->rpos = 0;
|
||||
uart->rx_buffer->wpos = new_wpos;
|
||||
uart->rx_buffer->size = new_size;
|
||||
uart->rx_buffer->buffer = new_buf;
|
||||
free(old_buf);
|
||||
return uart->rx_buffer->size;
|
||||
}
|
||||
|
||||
uart->uart_nr = uart_nr;
|
||||
uart->rx_overrun = false;
|
||||
size_t uart_get_rx_buffer_size(uart_t* uart)
|
||||
{
|
||||
return uart && uart->rx_enabled ? uart->rx_buffer->size : 0;
|
||||
}
|
||||
|
||||
switch(uart->uart_nr)
|
||||
{
|
||||
case UART0:
|
||||
uart->rx_enabled = (mode != UART_TX_ONLY);
|
||||
uart->tx_enabled = (mode != UART_RX_ONLY);
|
||||
if(uart->rx_enabled)
|
||||
{
|
||||
struct uart_rx_buffer_ * rx_buffer = (struct uart_rx_buffer_ *)malloc(sizeof(struct uart_rx_buffer_));
|
||||
if(rx_buffer == NULL)
|
||||
{
|
||||
free(uart);
|
||||
return NULL;
|
||||
}
|
||||
rx_buffer->size = rx_size;//var this
|
||||
rx_buffer->rpos = 0;
|
||||
rx_buffer->wpos = 0;
|
||||
rx_buffer->buffer = (uint8_t *)malloc(rx_buffer->size);
|
||||
if(rx_buffer->buffer == NULL)
|
||||
{
|
||||
free(rx_buffer);
|
||||
free(uart);
|
||||
return NULL;
|
||||
}
|
||||
uart->rx_buffer = rx_buffer;
|
||||
}
|
||||
break;
|
||||
size_t uart_write_char(uart_t* uart, char c)
|
||||
{
|
||||
if (uart == NULL || !uart->tx_enabled)
|
||||
return 0;
|
||||
|
||||
case UART1:
|
||||
// Note: uart_interrupt_handler does not support RX on UART 1.
|
||||
uart->rx_enabled = false;
|
||||
uart->tx_enabled = (mode != UART_RX_ONLY);
|
||||
break;
|
||||
uart_do_write_char(uart->uart_nr, c);
|
||||
|
||||
case UART_NO:
|
||||
default:
|
||||
// big fail!
|
||||
free(uart);
|
||||
return NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
uart_set_baudrate(uart, baudrate);
|
||||
size_t uart_write(uart_t* uart, const char* buf, size_t size)
|
||||
{
|
||||
if (uart == NULL || !uart->tx_enabled)
|
||||
return 0;
|
||||
|
||||
UART[uart_nr] = uart;
|
||||
size_t ret = size;
|
||||
const int uart_nr = uart->uart_nr;
|
||||
while (size--)
|
||||
uart_do_write_char(uart_nr, *buf++);
|
||||
|
||||
return uart;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
uart_uninit(uart_t* uart)
|
||||
{
|
||||
if(uart == NULL)
|
||||
return;
|
||||
size_t uart_tx_free(uart_t* uart)
|
||||
{
|
||||
if (uart == NULL || !uart->tx_enabled)
|
||||
return 0;
|
||||
|
||||
if(uart->rx_enabled) {
|
||||
free(uart->rx_buffer->buffer);
|
||||
free(uart->rx_buffer);
|
||||
}
|
||||
free(uart);
|
||||
}
|
||||
return UART_TX_FIFO_SIZE;
|
||||
}
|
||||
|
||||
bool
|
||||
uart_swap(uart_t* uart, int tx_pin)
|
||||
{
|
||||
(void) uart;
|
||||
(void) tx_pin;
|
||||
return true;
|
||||
}
|
||||
void uart_wait_tx_empty(uart_t* uart)
|
||||
{
|
||||
(void)uart;
|
||||
}
|
||||
|
||||
bool
|
||||
uart_set_tx(uart_t* uart, int tx_pin)
|
||||
{
|
||||
(void) uart;
|
||||
(void) tx_pin;
|
||||
return true;
|
||||
}
|
||||
void uart_flush(uart_t* uart)
|
||||
{
|
||||
if (uart == NULL)
|
||||
return;
|
||||
|
||||
bool
|
||||
uart_set_pins(uart_t* uart, int tx, int rx)
|
||||
{
|
||||
(void) uart;
|
||||
(void) tx;
|
||||
(void) rx;
|
||||
return true;
|
||||
}
|
||||
if (uart->rx_enabled)
|
||||
{
|
||||
uart->rx_buffer->rpos = 0;
|
||||
uart->rx_buffer->wpos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
uart_tx_enabled(uart_t* uart)
|
||||
{
|
||||
if(uart == NULL)
|
||||
return false;
|
||||
void uart_set_baudrate(uart_t* uart, int baud_rate)
|
||||
{
|
||||
if (uart == NULL)
|
||||
return;
|
||||
|
||||
return uart->tx_enabled;
|
||||
}
|
||||
uart->baud_rate = baud_rate;
|
||||
}
|
||||
|
||||
bool
|
||||
uart_rx_enabled(uart_t* uart)
|
||||
{
|
||||
if(uart == NULL)
|
||||
return false;
|
||||
int uart_get_baudrate(uart_t* uart)
|
||||
{
|
||||
if (uart == NULL)
|
||||
return 0;
|
||||
|
||||
return uart->rx_enabled;
|
||||
}
|
||||
return uart->baud_rate;
|
||||
}
|
||||
|
||||
bool
|
||||
uart_has_overrun(uart_t* uart)
|
||||
{
|
||||
if(uart == NULL || !uart->rx_overrun)
|
||||
return false;
|
||||
uint8_t uart_get_bit_length(const int uart_nr)
|
||||
{
|
||||
uint8_t width = ((uart_nr % 16) >> 2) + 5;
|
||||
uint8_t parity = (uart_nr >> 5) + 1;
|
||||
uint8_t stop = uart_nr % 4;
|
||||
return (width + parity + stop + 1);
|
||||
}
|
||||
|
||||
// clear flag
|
||||
uart->rx_overrun = false;
|
||||
return true;
|
||||
}
|
||||
uart_t* uart_init(int uart_nr, int baudrate, int config, int mode, int tx_pin, size_t rx_size,
|
||||
bool invert)
|
||||
{
|
||||
(void)config;
|
||||
(void)tx_pin;
|
||||
(void)invert;
|
||||
uart_t* uart = (uart_t*)malloc(sizeof(uart_t));
|
||||
if (uart == NULL)
|
||||
return NULL;
|
||||
|
||||
bool
|
||||
uart_has_rx_error(uart_t* uart)
|
||||
{
|
||||
(void) uart;
|
||||
return false;
|
||||
}
|
||||
uart->uart_nr = uart_nr;
|
||||
uart->rx_overrun = false;
|
||||
|
||||
void
|
||||
uart_set_debug(int uart_nr)
|
||||
{
|
||||
(void)uart_nr;
|
||||
}
|
||||
switch (uart->uart_nr)
|
||||
{
|
||||
case UART0:
|
||||
uart->rx_enabled = (mode != UART_TX_ONLY);
|
||||
uart->tx_enabled = (mode != UART_RX_ONLY);
|
||||
if (uart->rx_enabled)
|
||||
{
|
||||
struct uart_rx_buffer_* rx_buffer
|
||||
= (struct uart_rx_buffer_*)malloc(sizeof(struct uart_rx_buffer_));
|
||||
if (rx_buffer == NULL)
|
||||
{
|
||||
free(uart);
|
||||
return NULL;
|
||||
}
|
||||
rx_buffer->size = rx_size; // var this
|
||||
rx_buffer->rpos = 0;
|
||||
rx_buffer->wpos = 0;
|
||||
rx_buffer->buffer = (uint8_t*)malloc(rx_buffer->size);
|
||||
if (rx_buffer->buffer == NULL)
|
||||
{
|
||||
free(rx_buffer);
|
||||
free(uart);
|
||||
return NULL;
|
||||
}
|
||||
uart->rx_buffer = rx_buffer;
|
||||
}
|
||||
break;
|
||||
|
||||
int
|
||||
uart_get_debug()
|
||||
{
|
||||
return s_uart_debug_nr;
|
||||
}
|
||||
case UART1:
|
||||
// Note: uart_interrupt_handler does not support RX on UART 1.
|
||||
uart->rx_enabled = false;
|
||||
uart->tx_enabled = (mode != UART_RX_ONLY);
|
||||
break;
|
||||
|
||||
void
|
||||
uart_start_detect_baudrate(int uart_nr)
|
||||
{
|
||||
(void) uart_nr;
|
||||
}
|
||||
case UART_NO:
|
||||
default:
|
||||
// big fail!
|
||||
free(uart);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
uart_detect_baudrate(int uart_nr)
|
||||
{
|
||||
(void) uart_nr;
|
||||
return 115200;
|
||||
}
|
||||
uart_set_baudrate(uart, baudrate);
|
||||
|
||||
UART[uart_nr] = uart;
|
||||
|
||||
return uart;
|
||||
}
|
||||
|
||||
void uart_uninit(uart_t* uart)
|
||||
{
|
||||
if (uart == NULL)
|
||||
return;
|
||||
|
||||
if (uart->rx_enabled)
|
||||
{
|
||||
free(uart->rx_buffer->buffer);
|
||||
free(uart->rx_buffer);
|
||||
}
|
||||
free(uart);
|
||||
}
|
||||
|
||||
bool uart_swap(uart_t* uart, int tx_pin)
|
||||
{
|
||||
(void)uart;
|
||||
(void)tx_pin;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool uart_set_tx(uart_t* uart, int tx_pin)
|
||||
{
|
||||
(void)uart;
|
||||
(void)tx_pin;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool uart_set_pins(uart_t* uart, int tx, int rx)
|
||||
{
|
||||
(void)uart;
|
||||
(void)tx;
|
||||
(void)rx;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool uart_tx_enabled(uart_t* uart)
|
||||
{
|
||||
if (uart == NULL)
|
||||
return false;
|
||||
|
||||
return uart->tx_enabled;
|
||||
}
|
||||
|
||||
bool uart_rx_enabled(uart_t* uart)
|
||||
{
|
||||
if (uart == NULL)
|
||||
return false;
|
||||
|
||||
return uart->rx_enabled;
|
||||
}
|
||||
|
||||
bool uart_has_overrun(uart_t* uart)
|
||||
{
|
||||
if (uart == NULL || !uart->rx_overrun)
|
||||
return false;
|
||||
|
||||
// clear flag
|
||||
uart->rx_overrun = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool uart_has_rx_error(uart_t* uart)
|
||||
{
|
||||
(void)uart;
|
||||
return false;
|
||||
}
|
||||
|
||||
void uart_set_debug(int uart_nr)
|
||||
{
|
||||
(void)uart_nr;
|
||||
}
|
||||
|
||||
int uart_get_debug()
|
||||
{
|
||||
return s_uart_debug_nr;
|
||||
}
|
||||
|
||||
void uart_start_detect_baudrate(int uart_nr)
|
||||
{
|
||||
(void)uart_nr;
|
||||
}
|
||||
|
||||
int uart_detect_baudrate(int uart_nr)
|
||||
{
|
||||
(void)uart_nr;
|
||||
return 115200;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
size_t uart_peek_available (uart_t* uart) { return 0; }
|
||||
const char* uart_peek_buffer (uart_t* uart) { return nullptr; }
|
||||
void uart_peek_consume (uart_t* uart, size_t consume) { (void)uart; (void)consume; }
|
||||
|
||||
size_t uart_peek_available(uart_t* uart)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
const char* uart_peek_buffer(uart_t* uart)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
void uart_peek_consume(uart_t* uart, size_t consume)
|
||||
{
|
||||
(void)uart;
|
||||
(void)consume;
|
||||
}
|
||||
|
@ -44,32 +44,31 @@ extern "C" const ip_addr_t ip_addr_any = IPADDR4_INIT(IPADDR_ANY);
|
||||
|
||||
// lwIP API side of WiFiServer
|
||||
|
||||
WiFiServer::WiFiServer (const IPAddress& addr, uint16_t port)
|
||||
WiFiServer::WiFiServer(const IPAddress& addr, uint16_t port)
|
||||
{
|
||||
(void)addr;
|
||||
_port = port;
|
||||
(void)addr;
|
||||
_port = port;
|
||||
}
|
||||
|
||||
WiFiServer::WiFiServer (uint16_t port)
|
||||
WiFiServer::WiFiServer(uint16_t port)
|
||||
{
|
||||
_port = port;
|
||||
_port = port;
|
||||
}
|
||||
|
||||
WiFiClient WiFiServer::available (uint8_t* status)
|
||||
WiFiClient WiFiServer::available(uint8_t* status)
|
||||
{
|
||||
(void)status;
|
||||
return accept();
|
||||
(void)status;
|
||||
return accept();
|
||||
}
|
||||
|
||||
WiFiClient WiFiServer::accept ()
|
||||
WiFiClient WiFiServer::accept()
|
||||
{
|
||||
if (hasClient())
|
||||
return WiFiClient(new ClientContext(serverAccept(pcb2int(_listen_pcb))));
|
||||
return WiFiClient();
|
||||
if (hasClient())
|
||||
return WiFiClient(new ClientContext(serverAccept(pcb2int(_listen_pcb))));
|
||||
return WiFiClient();
|
||||
}
|
||||
|
||||
// static declaration
|
||||
|
||||
#include <include/UdpContext.h>
|
||||
uint32_t UdpContext::staticMCastAddr = 0;
|
||||
|
||||
|
@ -44,26 +44,26 @@
|
||||
|
||||
// host socket internal side of WiFiServer
|
||||
|
||||
int serverAccept (int srvsock)
|
||||
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(MOCK "accept()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return mockSockSetup(clisock);
|
||||
int clisock;
|
||||
socklen_t n;
|
||||
struct sockaddr_in client;
|
||||
n = sizeof(client);
|
||||
if ((clisock = accept(srvsock, (struct sockaddr*)&client, &n)) == -1)
|
||||
{
|
||||
perror(MOCK "accept()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return mockSockSetup(clisock);
|
||||
}
|
||||
|
||||
void WiFiServer::begin (uint16_t port)
|
||||
void WiFiServer::begin(uint16_t port)
|
||||
{
|
||||
return begin(port, !0);
|
||||
}
|
||||
|
||||
void WiFiServer::begin (uint16_t port, uint8_t backlog)
|
||||
void WiFiServer::begin(uint16_t port, uint8_t backlog)
|
||||
{
|
||||
if (!backlog)
|
||||
return;
|
||||
@ -71,85 +71,86 @@ void WiFiServer::begin (uint16_t port, uint8_t backlog)
|
||||
return begin();
|
||||
}
|
||||
|
||||
void WiFiServer::begin ()
|
||||
void WiFiServer::begin()
|
||||
{
|
||||
int sock;
|
||||
int mockport;
|
||||
struct sockaddr_in server;
|
||||
int sock;
|
||||
int mockport;
|
||||
struct sockaddr_in server;
|
||||
|
||||
mockport = _port;
|
||||
if (mockport < 1024 && mock_port_shifter)
|
||||
{
|
||||
mockport += mock_port_shifter;
|
||||
fprintf(stderr, MOCK "=====> WiFiServer port: %d shifted to %d (use option -s) <=====\n", _port, mockport);
|
||||
}
|
||||
else
|
||||
fprintf(stderr, MOCK "=====> WiFiServer port: %d <=====\n", mockport);
|
||||
mockport = _port;
|
||||
if (mockport < 1024 && mock_port_shifter)
|
||||
{
|
||||
mockport += mock_port_shifter;
|
||||
fprintf(stderr, MOCK "=====> WiFiServer port: %d shifted to %d (use option -s) <=====\n",
|
||||
_port, mockport);
|
||||
}
|
||||
else
|
||||
fprintf(stderr, MOCK "=====> WiFiServer port: %d <=====\n", mockport);
|
||||
|
||||
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
|
||||
{
|
||||
perror(MOCK "socket()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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(mockport);
|
||||
server.sin_addr.s_addr = htonl(global_source_address);
|
||||
if (bind(sock, (struct sockaddr*)&server, sizeof(server)) == -1)
|
||||
{
|
||||
perror(MOCK "bind()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_port = htons(mockport);
|
||||
server.sin_addr.s_addr = htonl(global_source_address);
|
||||
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);
|
||||
}
|
||||
if (listen(sock, 1) == -1)
|
||||
{
|
||||
perror(MOCK "listen()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
// store int into pointer
|
||||
_listen_pcb = int2pcb(sock);
|
||||
// store int into pointer
|
||||
_listen_pcb = int2pcb(sock);
|
||||
}
|
||||
|
||||
bool WiFiServer::hasClient ()
|
||||
bool WiFiServer::hasClient()
|
||||
{
|
||||
struct pollfd p;
|
||||
p.fd = pcb2int(_listen_pcb);
|
||||
p.events = POLLIN;
|
||||
return poll(&p, 1, 0) && p.revents == POLLIN;
|
||||
struct pollfd p;
|
||||
p.fd = pcb2int(_listen_pcb);
|
||||
p.events = POLLIN;
|
||||
return poll(&p, 1, 0) && p.revents == POLLIN;
|
||||
}
|
||||
|
||||
void WiFiServer::close ()
|
||||
void WiFiServer::close()
|
||||
{
|
||||
if (pcb2int(_listen_pcb) >= 0)
|
||||
::close(pcb2int(_listen_pcb));
|
||||
_listen_pcb = int2pcb(-1);
|
||||
if (pcb2int(_listen_pcb) >= 0)
|
||||
::close(pcb2int(_listen_pcb));
|
||||
_listen_pcb = int2pcb(-1);
|
||||
}
|
||||
|
||||
void WiFiServer::stop ()
|
||||
void WiFiServer::stop()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
size_t WiFiServer::hasClientData ()
|
||||
size_t WiFiServer::hasClientData()
|
||||
{
|
||||
// Trivial Mocking:
|
||||
// There is no waiting list of clients in this trivial mocking code,
|
||||
// so the code has to act as if the tcp backlog list is full,
|
||||
// and nothing is known about potential further clients.
|
||||
// It could be implemented by accepting new clients and store their data until the current one is closed.
|
||||
// It could be implemented by accepting new clients and store their data until the current one
|
||||
// is closed.
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool WiFiServer::hasMaxPendingClients ()
|
||||
bool WiFiServer::hasMaxPendingClients()
|
||||
{
|
||||
// Mocking code does not consider the waiting client list,
|
||||
// so it will return ::hasClient() here meaning:
|
||||
|
@ -7,58 +7,54 @@ esp8266::AddressListImplementation::AddressList addrList;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
extern netif netif0;
|
||||
|
||||
extern netif netif0;
|
||||
netif* netif_list = &netif0;
|
||||
|
||||
netif* netif_list = &netif0;
|
||||
err_t dhcp_renew(struct netif* netif)
|
||||
{
|
||||
(void)netif;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
err_t dhcp_renew(struct netif *netif)
|
||||
{
|
||||
(void)netif;
|
||||
return ERR_OK;
|
||||
}
|
||||
void sntp_setserver(u8_t, const ip_addr_t) { }
|
||||
|
||||
void sntp_setserver(u8_t, const ip_addr_t)
|
||||
{
|
||||
}
|
||||
const ip_addr_t* sntp_getserver(u8_t)
|
||||
{
|
||||
return IP_ADDR_ANY;
|
||||
}
|
||||
|
||||
const ip_addr_t* sntp_getserver(u8_t)
|
||||
{
|
||||
return IP_ADDR_ANY;
|
||||
}
|
||||
err_t etharp_request(struct netif* netif, const ip4_addr_t* ipaddr)
|
||||
{
|
||||
(void)netif;
|
||||
(void)ipaddr;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
err_t etharp_request(struct netif *netif, const ip4_addr_t *ipaddr)
|
||||
{
|
||||
(void)netif;
|
||||
(void)ipaddr;
|
||||
return ERR_OK;
|
||||
}
|
||||
err_t igmp_start(struct netif* netif)
|
||||
{
|
||||
(void)netif;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
err_t igmp_start(struct netif* netif)
|
||||
{
|
||||
(void)netif;
|
||||
return ERR_OK;
|
||||
}
|
||||
err_t igmp_joingroup_netif(struct netif* netif, const ip4_addr_t* groupaddr)
|
||||
{
|
||||
(void)netif;
|
||||
(void)groupaddr;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
err_t igmp_joingroup_netif(struct netif *netif, const ip4_addr_t *groupaddr)
|
||||
{
|
||||
(void)netif;
|
||||
(void)groupaddr;
|
||||
return ERR_OK;
|
||||
}
|
||||
err_t igmp_leavegroup_netif(struct netif* netif, const ip4_addr_t* groupaddr)
|
||||
{
|
||||
(void)netif;
|
||||
(void)groupaddr;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
err_t igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr)
|
||||
{
|
||||
(void)netif;
|
||||
(void)groupaddr;
|
||||
return ERR_OK;
|
||||
}
|
||||
struct netif* netif_get_by_index(u8_t idx)
|
||||
{
|
||||
(void)idx;
|
||||
return &netif0;
|
||||
}
|
||||
|
||||
struct netif* netif_get_by_index(u8_t idx)
|
||||
{
|
||||
(void)idx;
|
||||
return &netif0;
|
||||
}
|
||||
|
||||
|
||||
} // extern "C"
|
||||
} // extern "C"
|
||||
|
@ -4,12 +4,11 @@
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
#include <user_interface.h>
|
||||
#include <lwip/netif.h>
|
||||
|
||||
extern netif netif0;
|
||||
extern netif netif0;
|
||||
|
||||
} // extern "C"
|
||||
} // extern "C"
|
||||
|
||||
#endif // __MOCKLWIP_H
|
||||
#endif // __MOCKLWIP_H
|
||||
|
@ -39,176 +39,189 @@
|
||||
#include <assert.h>
|
||||
#include <net/if.h>
|
||||
|
||||
int mockUDPSocket ()
|
||||
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;
|
||||
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)
|
||||
bool mockUDPListen(int sock, uint32_t dstaddr, uint16_t port, uint32_t mcast)
|
||||
{
|
||||
int optval;
|
||||
int mockport;
|
||||
int optval;
|
||||
int mockport;
|
||||
|
||||
mockport = port;
|
||||
if (mockport < 1024 && mock_port_shifter)
|
||||
{
|
||||
mockport += mock_port_shifter;
|
||||
fprintf(stderr, MOCK "=====> UdpServer port: %d shifted to %d (use option -s) <=====\n", port, mockport);
|
||||
}
|
||||
else
|
||||
fprintf(stderr, MOCK "=====> UdpServer port: %d <=====\n", mockport);
|
||||
mockport = port;
|
||||
if (mockport < 1024 && mock_port_shifter)
|
||||
{
|
||||
mockport += mock_port_shifter;
|
||||
fprintf(stderr, MOCK "=====> UdpServer port: %d shifted to %d (use option -s) <=====\n",
|
||||
port, mockport);
|
||||
}
|
||||
else
|
||||
fprintf(stderr, MOCK "=====> UdpServer port: %d <=====\n", mockport);
|
||||
|
||||
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");
|
||||
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));
|
||||
struct sockaddr_in servaddr;
|
||||
memset(&servaddr, 0, sizeof(servaddr));
|
||||
|
||||
// Filling server information
|
||||
servaddr.sin_family = AF_INET;
|
||||
(void) dstaddr;
|
||||
//servaddr.sin_addr.s_addr = htonl(global_source_address);
|
||||
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
servaddr.sin_port = htons(mockport);
|
||||
// Filling server information
|
||||
servaddr.sin_family = AF_INET;
|
||||
(void)dstaddr;
|
||||
// servaddr.sin_addr.s_addr = htonl(global_source_address);
|
||||
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
servaddr.sin_port = htons(mockport);
|
||||
|
||||
// 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", mockport, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
else
|
||||
mockverbose("UDP server on port %d (sock=%d)\n", mockport, sock);
|
||||
// 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", mockport, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
else
|
||||
mockverbose("UDP server on port %d (sock=%d)\n", mockport, sock);
|
||||
|
||||
if (!mcast)
|
||||
mcast = inet_addr("224.0.0.1"); // all hosts group
|
||||
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
|
||||
if (!mcast)
|
||||
mcast = inet_addr("224.0.0.1"); // all hosts group
|
||||
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 = htonl(global_source_address);
|
||||
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
|
||||
struct ip_mreq mreq;
|
||||
mreq.imr_multiaddr.s_addr = mcast;
|
||||
// mreq.imr_interface.s_addr = htonl(global_source_address);
|
||||
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
if (host_interface)
|
||||
{
|
||||
if (host_interface)
|
||||
{
|
||||
#if __APPLE__
|
||||
int idx = if_nametoindex(host_interface);
|
||||
if (setsockopt(sock, IPPROTO_TCP, IP_BOUND_IF, &idx, sizeof(idx)) == -1)
|
||||
int idx = if_nametoindex(host_interface);
|
||||
if (setsockopt(sock, IPPROTO_TCP, IP_BOUND_IF, &idx, sizeof(idx)) == -1)
|
||||
#else
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, host_interface, strlen(host_interface)) == -1)
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, host_interface,
|
||||
strlen(host_interface))
|
||||
== -1)
|
||||
#endif
|
||||
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));
|
||||
}
|
||||
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;
|
||||
}
|
||||
else
|
||||
mockverbose("joined multicast group addr %08lx\n", (long)ntohl(mcast));
|
||||
}
|
||||
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;
|
||||
}
|
||||
else
|
||||
mockverbose("joined multicast group addr %08lx\n", (long)ntohl(mcast));
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
size_t mockUDPFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize, uint8_t& addrsize, uint8_t addr[16], uint16_t& port)
|
||||
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);
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
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;
|
||||
return ccinbufsize += ret;
|
||||
}
|
||||
|
||||
size_t mockUDPPeekBytes (int sock, char* dst, size_t usersize, int timeout_ms, char* ccinbuf, size_t& ccinbufsize)
|
||||
size_t mockUDPPeekBytes(int sock, char* dst, size_t usersize, int timeout_ms, char* ccinbuf,
|
||||
size_t& ccinbufsize)
|
||||
{
|
||||
(void) sock;
|
||||
(void) timeout_ms;
|
||||
if (usersize > CCBUFSIZE)
|
||||
fprintf(stderr, MOCK "CCBUFSIZE(%d) should be increased by %zd bytes (-> %zd)\n", CCBUFSIZE, usersize - CCBUFSIZE, usersize);
|
||||
(void)sock;
|
||||
(void)timeout_ms;
|
||||
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 retsize = 0;
|
||||
if (ccinbufsize)
|
||||
{
|
||||
// data already buffered
|
||||
retsize = usersize;
|
||||
if (retsize > ccinbufsize)
|
||||
retsize = ccinbufsize;
|
||||
}
|
||||
memcpy(dst, ccinbuf, retsize);
|
||||
return retsize;
|
||||
}
|
||||
|
||||
void mockUDPSwallow (size_t copied, char* ccinbuf, size_t& ccinbufsize)
|
||||
void mockUDPSwallow(size_t copied, char* ccinbuf, size_t& ccinbufsize)
|
||||
{
|
||||
// poor man buffer
|
||||
memmove(ccinbuf, ccinbuf + copied, ccinbufsize - copied);
|
||||
ccinbufsize -= copied;
|
||||
// poor man buffer
|
||||
memmove(ccinbuf, ccinbuf + copied, ccinbufsize - copied);
|
||||
ccinbufsize -= copied;
|
||||
}
|
||||
|
||||
size_t mockUDPRead (int sock, char* dst, size_t size, 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 copied = mockUDPPeekBytes(sock, dst, size, timeout_ms, ccinbuf, ccinbufsize);
|
||||
mockUDPSwallow(copied, ccinbuf, ccinbufsize);
|
||||
return copied;
|
||||
size_t copied = mockUDPPeekBytes(sock, dst, size, timeout_ms, ccinbuf, ccinbufsize);
|
||||
mockUDPSwallow(copied, ccinbuf, ccinbufsize);
|
||||
return copied;
|
||||
}
|
||||
|
||||
size_t mockUDPWrite (int sock, const uint8_t* data, size_t size, int timeout_ms, uint32_t ipv4, uint16_t port)
|
||||
size_t mockUDPWrite(int sock, const uint8_t* data, size_t size, int timeout_ms, uint32_t ipv4,
|
||||
uint16_t port)
|
||||
{
|
||||
(void) timeout_ms;
|
||||
// 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);
|
||||
}
|
||||
(void)timeout_ms;
|
||||
// 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;
|
||||
return ret;
|
||||
}
|
||||
|
@ -4,59 +4,69 @@
|
||||
Part of the Wiring project - http://wiring.org.co
|
||||
Copyright (c) 2004-06 Hernando Barragan
|
||||
Modified 13 August 2006, David A. Mellis for Arduino - http://www.arduino.cc/
|
||||
|
||||
|
||||
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., 59 Temple Place, Suite 330,
|
||||
Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
$Id$
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
extern "C"
|
||||
{
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
}
|
||||
|
||||
void randomSeed(unsigned long seed) {
|
||||
if(seed != 0) {
|
||||
void randomSeed(unsigned long seed)
|
||||
{
|
||||
if (seed != 0)
|
||||
{
|
||||
srand(seed);
|
||||
}
|
||||
}
|
||||
|
||||
long random(long howbig) {
|
||||
if(howbig == 0) {
|
||||
long random(long howbig)
|
||||
{
|
||||
if (howbig == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return (rand()) % howbig;
|
||||
}
|
||||
|
||||
long random(long howsmall, long howbig) {
|
||||
if(howsmall >= howbig) {
|
||||
long random(long howsmall, long howbig)
|
||||
{
|
||||
if (howsmall >= howbig)
|
||||
{
|
||||
return howsmall;
|
||||
}
|
||||
long diff = howbig - howsmall;
|
||||
return random(diff) + howsmall;
|
||||
}
|
||||
|
||||
long map(long x, long in_min, long in_max, long out_min, long out_max) {
|
||||
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;
|
||||
}
|
||||
|
||||
uint16_t makeWord(unsigned int w) {
|
||||
uint16_t makeWord(unsigned int w)
|
||||
{
|
||||
return w;
|
||||
}
|
||||
|
||||
uint16_t makeWord(unsigned char h, unsigned char l) {
|
||||
uint16_t makeWord(unsigned char h, unsigned char l)
|
||||
{
|
||||
return (h << 8) | l;
|
||||
}
|
||||
|
@ -36,45 +36,46 @@
|
||||
#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;
|
||||
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 float real32_t;
|
||||
typedef double real64_t;
|
||||
|
||||
// CONFLICT 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 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;
|
||||
// CONFLICT 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;
|
||||
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 __le16 u16
|
||||
|
||||
#define LOCAL static
|
||||
#define LOCAL static
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL (void *)0
|
||||
#define NULL (void*)0
|
||||
#endif /* NULL */
|
||||
|
||||
/* probably should not put STATUS here */
|
||||
typedef enum {
|
||||
typedef enum
|
||||
{
|
||||
OK = 0,
|
||||
FAIL,
|
||||
PENDING,
|
||||
@ -82,10 +83,10 @@ typedef enum {
|
||||
CANCEL,
|
||||
} STATUS;
|
||||
|
||||
#define BIT(nr) (1UL << (nr))
|
||||
#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 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
|
||||
@ -93,9 +94,15 @@ typedef enum {
|
||||
#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 IRAM_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__) "\"")))
|
||||
#define ICACHE_FLASH_ATTR \
|
||||
__attribute__((section("\".irom0.text." __FILE__ "." __ICACHE_STRINGIZE( \
|
||||
__LINE__) "." __ICACHE_STRINGIZE(__COUNTER__) "\"")))
|
||||
#define IRAM_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 IRAM_ATTR
|
||||
@ -108,10 +115,9 @@ typedef enum {
|
||||
#define STORE_ATTR __attribute__((aligned(4)))
|
||||
|
||||
#ifndef __cplusplus
|
||||
#define BOOL bool
|
||||
#define TRUE true
|
||||
#define FALSE false
|
||||
|
||||
#define BOOL bool
|
||||
#define TRUE true
|
||||
#define FALSE false
|
||||
|
||||
#endif /* !__cplusplus */
|
||||
|
||||
|
@ -2,8 +2,8 @@
|
||||
#ifndef FAKE_ESP8266_PERI_H
|
||||
#define FAKE_ESP8266_PERI_H
|
||||
|
||||
const int GPI = 0;
|
||||
const int GPO = 0;
|
||||
const int GPI = 0;
|
||||
const int GPO = 0;
|
||||
const int GP16I = 0;
|
||||
|
||||
#endif
|
||||
|
@ -11,17 +11,15 @@
|
||||
|
||||
extern "C"
|
||||
{
|
||||
extern uint32_t s_phys_addr;
|
||||
extern uint32_t s_phys_size;
|
||||
extern uint32_t s_phys_page;
|
||||
extern uint32_t s_phys_block;
|
||||
extern uint8_t* s_phys_data;
|
||||
|
||||
extern uint32_t s_phys_addr;
|
||||
extern uint32_t s_phys_size;
|
||||
extern uint32_t s_phys_page;
|
||||
extern uint32_t s_phys_block;
|
||||
extern uint8_t* s_phys_data;
|
||||
|
||||
extern int32_t flash_hal_read(uint32_t addr, uint32_t size, uint8_t *dst);
|
||||
extern int32_t flash_hal_write(uint32_t addr, uint32_t size, const uint8_t *src);
|
||||
extern int32_t flash_hal_erase(uint32_t addr, uint32_t size);
|
||||
|
||||
extern int32_t flash_hal_read(uint32_t addr, uint32_t size, uint8_t* dst);
|
||||
extern int32_t flash_hal_write(uint32_t addr, uint32_t size, const uint8_t* src);
|
||||
extern int32_t flash_hal_erase(uint32_t addr, uint32_t size);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -7,31 +7,35 @@
|
||||
|
||||
extern "C"
|
||||
{
|
||||
uint32_t s_phys_addr = 0;
|
||||
uint32_t s_phys_size = 0;
|
||||
uint32_t s_phys_page = 0;
|
||||
uint32_t s_phys_addr = 0;
|
||||
uint32_t s_phys_size = 0;
|
||||
uint32_t s_phys_page = 0;
|
||||
uint32_t s_phys_block = 0;
|
||||
uint8_t* s_phys_data = nullptr;
|
||||
uint8_t* s_phys_data = nullptr;
|
||||
}
|
||||
|
||||
int32_t flash_hal_read(uint32_t addr, uint32_t size, uint8_t *dst) {
|
||||
int32_t flash_hal_read(uint32_t addr, uint32_t size, uint8_t* dst)
|
||||
{
|
||||
memcpy(dst, s_phys_data + addr, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t flash_hal_write(uint32_t addr, uint32_t size, const uint8_t *src) {
|
||||
int32_t flash_hal_write(uint32_t addr, uint32_t size, const uint8_t* src)
|
||||
{
|
||||
memcpy(s_phys_data + addr, src, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t flash_hal_erase(uint32_t addr, uint32_t size) {
|
||||
if ((size & (FLASH_SECTOR_SIZE - 1)) != 0 ||
|
||||
(addr & (FLASH_SECTOR_SIZE - 1)) != 0) {
|
||||
int32_t flash_hal_erase(uint32_t addr, uint32_t size)
|
||||
{
|
||||
if ((size & (FLASH_SECTOR_SIZE - 1)) != 0 || (addr & (FLASH_SECTOR_SIZE - 1)) != 0)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
const uint32_t sector = addr / FLASH_SECTOR_SIZE;
|
||||
const uint32_t sector = addr / FLASH_SECTOR_SIZE;
|
||||
const uint32_t sectorCount = size / FLASH_SECTOR_SIZE;
|
||||
for (uint32_t i = 0; i < sectorCount; ++i) {
|
||||
for (uint32_t i = 0; i < sectorCount; ++i)
|
||||
{
|
||||
memset(s_phys_data + (sector + i) * FLASH_SECTOR_SIZE, 0xff, FLASH_SECTOR_SIZE);
|
||||
}
|
||||
return 0;
|
||||
|
@ -26,7 +26,7 @@ class WiFiClient;
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
bool getDefaultPrivateGlobalSyncValue ();
|
||||
bool getDefaultPrivateGlobalSyncValue();
|
||||
|
||||
typedef void (*discard_cb_t)(void*, ClientContext*);
|
||||
|
||||
@ -39,19 +39,19 @@ public:
|
||||
{
|
||||
(void)pcb;
|
||||
}
|
||||
|
||||
ClientContext (int sock) :
|
||||
|
||||
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);
|
||||
mockverbose("socket %d closed\n", _sock);
|
||||
mockverbose("socket %d closed\n", _sock);
|
||||
}
|
||||
_sock = -1;
|
||||
return ERR_ABRT;
|
||||
@ -88,11 +88,12 @@ public:
|
||||
void unref()
|
||||
{
|
||||
DEBUGV(":ur %d\r\n", _refcnt);
|
||||
if(--_refcnt == 0) {
|
||||
if (--_refcnt == 0)
|
||||
{
|
||||
discard_received();
|
||||
close();
|
||||
if (_discard_cb)
|
||||
_discard_cb(_discard_cb_arg, this);
|
||||
_discard_cb(_discard_cb_arg, this);
|
||||
DEBUGV(":del\r\n");
|
||||
delete this;
|
||||
}
|
||||
@ -172,10 +173,10 @@ public:
|
||||
int read()
|
||||
{
|
||||
char c;
|
||||
return read(&c, 1)? (unsigned char)c: -1;
|
||||
return read(&c, 1) ? (unsigned char)c : -1;
|
||||
}
|
||||
|
||||
size_t read (char* dst, size_t size)
|
||||
size_t read(char* dst, size_t size)
|
||||
{
|
||||
ssize_t ret = mockRead(_sock, dst, size, 0, _inbuf, _inbufsize);
|
||||
if (ret < 0)
|
||||
@ -189,10 +190,10 @@ public:
|
||||
int peek()
|
||||
{
|
||||
char c;
|
||||
return peekBytes(&c, 1)? c: -1;
|
||||
return peekBytes(&c, 1) ? c : -1;
|
||||
}
|
||||
|
||||
size_t peekBytes(char *dst, size_t size)
|
||||
size_t peekBytes(char* dst, size_t size)
|
||||
{
|
||||
ssize_t ret = mockPeekBytes(_sock, dst, size, _timeout_ms, _inbuf, _inbufsize);
|
||||
if (ret < 0)
|
||||
@ -216,60 +217,62 @@ public:
|
||||
|
||||
uint8_t state()
|
||||
{
|
||||
(void)getSize(); // read on socket to force detect closed peer
|
||||
return _sock >= 0? ESTABLISHED: CLOSED;
|
||||
(void)getSize(); // read on socket to force detect closed peer
|
||||
return _sock >= 0 ? ESTABLISHED : CLOSED;
|
||||
}
|
||||
|
||||
size_t write(const char* data, size_t size)
|
||||
{
|
||||
ssize_t ret = mockWrite(_sock, (const uint8_t*)data, size, _timeout_ms);
|
||||
if (ret < 0)
|
||||
{
|
||||
abort();
|
||||
return 0;
|
||||
}
|
||||
return ret;
|
||||
ssize_t ret = mockWrite(_sock, (const uint8_t*)data, size, _timeout_ms);
|
||||
if (ret < 0)
|
||||
{
|
||||
abort();
|
||||
return 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
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)
|
||||
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)
|
||||
{
|
||||
(void) idle_sec;
|
||||
(void) intv_sec;
|
||||
(void) count;
|
||||
(void)idle_sec;
|
||||
(void)intv_sec;
|
||||
(void)count;
|
||||
mockverbose("TODO ClientContext::keepAlive()\n");
|
||||
}
|
||||
|
||||
bool isKeepAliveEnabled () const
|
||||
bool isKeepAliveEnabled() const
|
||||
{
|
||||
mockverbose("TODO ClientContext::isKeepAliveEnabled()\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t getKeepAliveIdle () const
|
||||
uint16_t getKeepAliveIdle() const
|
||||
{
|
||||
mockverbose("TODO ClientContext::getKeepAliveIdle()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t getKeepAliveInterval () const
|
||||
uint16_t getKeepAliveInterval() const
|
||||
{
|
||||
mockverbose("TODO ClientContext::getKeepAliveInternal()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t getKeepAliveCount () const
|
||||
uint8_t getKeepAliveCount() const
|
||||
{
|
||||
mockverbose("TODO ClientContext::getKeepAliveCount()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool getSync () const
|
||||
bool getSync() const
|
||||
{
|
||||
mockverbose("TODO ClientContext::getSync()\n");
|
||||
return _sync;
|
||||
}
|
||||
|
||||
void setSync (bool sync)
|
||||
void setSync(bool sync)
|
||||
{
|
||||
mockverbose("TODO ClientContext::setSync()\n");
|
||||
_sync = sync;
|
||||
@ -277,13 +280,13 @@ public:
|
||||
|
||||
// return a pointer to available data buffer (size = peekAvailable())
|
||||
// semantic forbids any kind of read() before calling peekConsume()
|
||||
const char* peekBuffer ()
|
||||
const char* peekBuffer()
|
||||
{
|
||||
return _inbuf;
|
||||
}
|
||||
|
||||
// return number of byte accessible by peekBuffer()
|
||||
size_t peekAvailable ()
|
||||
size_t peekAvailable()
|
||||
{
|
||||
ssize_t ret = mockPeekBytes(_sock, nullptr, 0, 0, _inbuf, _inbufsize);
|
||||
if (ret < 0)
|
||||
@ -295,7 +298,7 @@ public:
|
||||
}
|
||||
|
||||
// consume bytes after use (see peekBuffer)
|
||||
void peekConsume (size_t consume)
|
||||
void peekConsume(size_t consume)
|
||||
{
|
||||
assert(consume <= _inbufsize);
|
||||
memmove(_inbuf, _inbuf + consume, _inbufsize - consume);
|
||||
@ -303,22 +306,21 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
discard_cb_t _discard_cb = nullptr;
|
||||
void* _discard_cb_arg = nullptr;
|
||||
|
||||
discard_cb_t _discard_cb = nullptr;
|
||||
void* _discard_cb_arg = nullptr;
|
||||
|
||||
int8_t _refcnt;
|
||||
int8_t _refcnt;
|
||||
ClientContext* _next;
|
||||
|
||||
|
||||
bool _sync;
|
||||
|
||||
|
||||
// MOCK
|
||||
|
||||
int _sock = -1;
|
||||
|
||||
int _sock = -1;
|
||||
int _timeout_ms = 5000;
|
||||
|
||||
char _inbuf [CCBUFSIZE];
|
||||
char _inbuf[CCBUFSIZE];
|
||||
size_t _inbufsize = 0;
|
||||
};
|
||||
|
||||
#endif //CLIENTCONTEXT_H
|
||||
#endif // CLIENTCONTEXT_H
|
||||
|
@ -37,17 +37,14 @@ extern netif netif0;
|
||||
class UdpContext
|
||||
{
|
||||
public:
|
||||
|
||||
typedef std::function<void(void)> rxhandler_t;
|
||||
|
||||
UdpContext(): _on_rx(nullptr), _refcnt(0)
|
||||
UdpContext() : _on_rx(nullptr), _refcnt(0)
|
||||
{
|
||||
_sock = mockUDPSocket();
|
||||
}
|
||||
|
||||
~UdpContext()
|
||||
{
|
||||
}
|
||||
~UdpContext() { }
|
||||
|
||||
void ref()
|
||||
{
|
||||
@ -64,7 +61,7 @@ public:
|
||||
|
||||
bool connect(const ip_addr_t* addr, uint16_t port)
|
||||
{
|
||||
_dst = *addr;
|
||||
_dst = *addr;
|
||||
_dstport = port;
|
||||
return true;
|
||||
}
|
||||
@ -103,7 +100,7 @@ public:
|
||||
void setMulticastTTL(int ttl)
|
||||
{
|
||||
(void)ttl;
|
||||
//mockverbose("TODO: UdpContext::setMulticastTTL\n");
|
||||
// mockverbose("TODO: UdpContext::setMulticastTTL\n");
|
||||
}
|
||||
|
||||
netif* getInputNetif() const
|
||||
@ -156,13 +153,13 @@ public:
|
||||
IPAddress getDestAddress()
|
||||
{
|
||||
mockverbose("TODO: implement UDP getDestAddress\n");
|
||||
return 0; //ip_hdr* iphdr = GET_IP_HDR(_rx_buf);
|
||||
return 0; // ip_hdr* iphdr = GET_IP_HDR(_rx_buf);
|
||||
}
|
||||
|
||||
uint16_t getLocalPort()
|
||||
{
|
||||
mockverbose("TODO: implement UDP getLocalPort\n");
|
||||
return 0; //
|
||||
return 0; //
|
||||
}
|
||||
|
||||
bool next()
|
||||
@ -191,14 +188,14 @@ public:
|
||||
int peek()
|
||||
{
|
||||
char c;
|
||||
return mockUDPPeekBytes(_sock, &c, 1, _timeout_ms, _inbuf, _inbufsize) ? : -1;
|
||||
return mockUDPPeekBytes(_sock, &c, 1, _timeout_ms, _inbuf, _inbufsize) ?: -1;
|
||||
}
|
||||
|
||||
void flush()
|
||||
{
|
||||
//mockverbose("UdpContext::flush() does not follow arduino's flush concept\n");
|
||||
//exit(EXIT_FAILURE);
|
||||
// would be:
|
||||
// mockverbose("UdpContext::flush() does not follow arduino's flush concept\n");
|
||||
// exit(EXIT_FAILURE);
|
||||
// would be:
|
||||
_inbufsize = 0;
|
||||
}
|
||||
|
||||
@ -206,7 +203,8 @@ public:
|
||||
{
|
||||
if (size + _outbufsize > sizeof _outbuf)
|
||||
{
|
||||
mockverbose("UdpContext::append: increase CCBUFSIZE (%d -> %zd)\n", CCBUFSIZE, (size + _outbufsize));
|
||||
mockverbose("UdpContext::append: increase CCBUFSIZE (%d -> %zd)\n", CCBUFSIZE,
|
||||
(size + _outbufsize));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
@ -217,9 +215,10 @@ public:
|
||||
|
||||
err_t trySend(ip_addr_t* addr = 0, uint16_t port = 0, bool keepBuffer = true)
|
||||
{
|
||||
uint32_t dst = addr ? addr->addr : _dst.addr;
|
||||
uint16_t dstport = port ? : _dstport;
|
||||
size_t wrt = mockUDPWrite(_sock, (const uint8_t*)_outbuf, _outbufsize, _timeout_ms, dst, dstport);
|
||||
uint32_t dst = addr ? addr->addr : _dst.addr;
|
||||
uint16_t dstport = port ?: _dstport;
|
||||
size_t wrt
|
||||
= mockUDPWrite(_sock, (const uint8_t*)_outbuf, _outbufsize, _timeout_ms, dst, dstport);
|
||||
err_t ret = _outbufsize ? ERR_OK : ERR_ABRT;
|
||||
if (!keepBuffer || wrt == _outbufsize)
|
||||
cancelBuffer();
|
||||
@ -239,7 +238,7 @@ public:
|
||||
bool sendTimeout(ip_addr_t* addr, uint16_t port,
|
||||
esp8266::polledTimeout::oneShotFastMs::timeType timeoutMs)
|
||||
{
|
||||
err_t err;
|
||||
err_t err;
|
||||
esp8266::polledTimeout::oneShotFastMs timeout(timeoutMs);
|
||||
while (((err = trySend(addr, port)) != ERR_OK) && !timeout)
|
||||
delay(0);
|
||||
@ -250,15 +249,14 @@ public:
|
||||
|
||||
void mock_cb(void)
|
||||
{
|
||||
if (_on_rx) _on_rx();
|
||||
if (_on_rx)
|
||||
_on_rx();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
static uint32_t staticMCastAddr;
|
||||
|
||||
private:
|
||||
|
||||
void translate_addr()
|
||||
{
|
||||
if (addrsize == 4)
|
||||
@ -267,22 +265,22 @@ private:
|
||||
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);
|
||||
// ip4_addr_set_u32(&ip_2_ip4(_dst), *(uint32_t*)addr);
|
||||
}
|
||||
else
|
||||
mockverbose("TODO unhandled udp address of size %d\n", (int)addrsize);
|
||||
}
|
||||
|
||||
int _sock = -1;
|
||||
int _sock = -1;
|
||||
rxhandler_t _on_rx;
|
||||
int _refcnt = 0;
|
||||
int _refcnt = 0;
|
||||
|
||||
ip_addr_t _dst;
|
||||
uint16_t _dstport;
|
||||
uint16_t _dstport;
|
||||
|
||||
char _inbuf [CCBUFSIZE];
|
||||
char _inbuf[CCBUFSIZE];
|
||||
size_t _inbufsize = 0;
|
||||
char _outbuf [CCBUFSIZE];
|
||||
char _outbuf[CCBUFSIZE];
|
||||
size_t _outbufsize = 0;
|
||||
|
||||
int _timeout_ms = 0;
|
||||
@ -291,11 +289,11 @@ private:
|
||||
uint8_t addr[16];
|
||||
};
|
||||
|
||||
extern "C" inline err_t igmp_joingroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr)
|
||||
extern "C" 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
|
||||
#endif // UDPCONTEXT_H
|
||||
|
@ -16,7 +16,6 @@
|
||||
all copies or substantial portions of the Software.
|
||||
*/
|
||||
|
||||
|
||||
#include "littlefs_mock.h"
|
||||
#include "spiffs_mock.h"
|
||||
#include "spiffs/spiffs.h"
|
||||
@ -56,7 +55,8 @@ LittleFSMock::LittleFSMock(ssize_t fs_size, size_t fs_block, size_t fs_page, con
|
||||
|
||||
void LittleFSMock::reset()
|
||||
{
|
||||
LittleFS = FS(FSImplPtr(new littlefs_impl::LittleFSImpl(0, s_phys_size, s_phys_page, s_phys_block, 5)));
|
||||
LittleFS = FS(
|
||||
FSImplPtr(new littlefs_impl::LittleFSImpl(0, s_phys_size, s_phys_page, s_phys_block, 5)));
|
||||
load();
|
||||
}
|
||||
|
||||
@ -72,47 +72,52 @@ LittleFSMock::~LittleFSMock()
|
||||
LittleFS = FS(FSImplPtr(nullptr));
|
||||
}
|
||||
|
||||
void LittleFSMock::load ()
|
||||
void LittleFSMock::load()
|
||||
{
|
||||
if (!m_fs.size() || !m_storage.length())
|
||||
return;
|
||||
|
||||
|
||||
int fs = ::open(m_storage.c_str(), O_RDONLY);
|
||||
if (fs == -1)
|
||||
{
|
||||
fprintf(stderr, "LittleFS: loading '%s': %s\n", m_storage.c_str(), strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
off_t flen = lseek(fs, 0, SEEK_END);
|
||||
if (flen == (off_t)-1)
|
||||
{
|
||||
fprintf(stderr, "LittleFS: checking size of '%s': %s\n", m_storage.c_str(), strerror(errno));
|
||||
fprintf(stderr, "LittleFS: checking size of '%s': %s\n", m_storage.c_str(),
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
lseek(fs, 0, SEEK_SET);
|
||||
|
||||
|
||||
if (flen != (off_t)m_fs.size())
|
||||
{
|
||||
fprintf(stderr, "LittleFS: size of '%s': %d does not match requested size %zd\n", m_storage.c_str(), (int)flen, m_fs.size());
|
||||
fprintf(stderr, "LittleFS: size of '%s': %d does not match requested size %zd\n",
|
||||
m_storage.c_str(), (int)flen, m_fs.size());
|
||||
if (!m_overwrite && flen > 0)
|
||||
{
|
||||
fprintf(stderr, "LittleFS: aborting at user request\n");
|
||||
exit(1);
|
||||
}
|
||||
fprintf(stderr, "LittleFS: continuing without loading at user request, '%s' will be overwritten\n", m_storage.c_str());
|
||||
fprintf(stderr,
|
||||
"LittleFS: continuing without loading at user request, '%s' will be overwritten\n",
|
||||
m_storage.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "LittleFS: loading %zi bytes from '%s'\n", m_fs.size(), m_storage.c_str());
|
||||
ssize_t r = ::read(fs, m_fs.data(), m_fs.size());
|
||||
if (r != (ssize_t)m_fs.size())
|
||||
fprintf(stderr, "LittleFS: reading %zi bytes: returned %zd: %s\n", m_fs.size(), r, strerror(errno));
|
||||
fprintf(stderr, "LittleFS: reading %zi bytes: returned %zd: %s\n", m_fs.size(), r,
|
||||
strerror(errno));
|
||||
}
|
||||
::close(fs);
|
||||
}
|
||||
|
||||
void LittleFSMock::save ()
|
||||
void LittleFSMock::save()
|
||||
{
|
||||
if (!m_fs.size() || !m_storage.length())
|
||||
return;
|
||||
|
@ -4,14 +4,14 @@
|
||||
|
||||
Based on spiffs_mock:
|
||||
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.
|
||||
*/
|
||||
@ -27,22 +27,25 @@
|
||||
|
||||
#define DEFAULT_LITTLEFS_FILE_NAME "littlefs.bin"
|
||||
|
||||
class LittleFSMock {
|
||||
class LittleFSMock
|
||||
{
|
||||
public:
|
||||
LittleFSMock(ssize_t fs_size, size_t fs_block, size_t fs_page, const String& storage = emptyString);
|
||||
LittleFSMock(ssize_t fs_size, size_t fs_block, size_t fs_page,
|
||||
const String& storage = emptyString);
|
||||
void reset();
|
||||
~LittleFSMock();
|
||||
|
||||
|
||||
protected:
|
||||
void load ();
|
||||
void save ();
|
||||
void load();
|
||||
void save();
|
||||
|
||||
std::vector<uint8_t> m_fs;
|
||||
String m_storage;
|
||||
bool m_overwrite;
|
||||
String m_storage;
|
||||
bool m_overwrite;
|
||||
};
|
||||
|
||||
#define LITTLEFS_MOCK_DECLARE(size_kb, block_kb, page_b, storage) LittleFSMock littlefs_mock(size_kb * 1024, block_kb * 1024, page_b, storage)
|
||||
#define LITTLEFS_MOCK_DECLARE(size_kb, block_kb, page_b, storage) \
|
||||
LittleFSMock littlefs_mock(size_kb * 1024, block_kb * 1024, page_b, storage)
|
||||
#define LITTLEFS_MOCK_RESET() littlefs_mock.reset()
|
||||
|
||||
#endif /* littlefs_mock_hpp */
|
||||
|
@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2007, Cameron Rich
|
||||
*
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* * Neither the name of the axTLS project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* * Neither the name of the axTLS project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
@ -39,16 +39,15 @@
|
||||
#define EXP_FUNC extern
|
||||
#define STDCALL
|
||||
|
||||
#define MD5_SIZE 16
|
||||
#define MD5_SIZE 16
|
||||
|
||||
typedef struct
|
||||
typedef struct
|
||||
{
|
||||
uint32_t state[4]; /* state (ABCD) */
|
||||
uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */
|
||||
uint8_t buffer[64]; /* input buffer */
|
||||
uint32_t state[4]; /* state (ABCD) */
|
||||
uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */
|
||||
uint8_t buffer[64]; /* input buffer */
|
||||
} MD5_CTX;
|
||||
|
||||
|
||||
/* Constants for MD5Transform routine.
|
||||
*/
|
||||
#define S11 7
|
||||
@ -70,15 +69,13 @@ typedef struct
|
||||
|
||||
/* ----- static functions ----- */
|
||||
static void MD5Transform(uint32_t state[4], const uint8_t block[64]);
|
||||
static void Encode(uint8_t *output, uint32_t *input, uint32_t len);
|
||||
static void Decode(uint32_t *output, const uint8_t *input, uint32_t len);
|
||||
static void Encode(uint8_t* output, uint32_t* input, uint32_t len);
|
||||
static void Decode(uint32_t* output, const uint8_t* input, uint32_t len);
|
||||
|
||||
static const uint8_t PADDING[64] =
|
||||
{
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
static const uint8_t PADDING[64]
|
||||
= { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
/* F, G, H and I are basic MD5 functions.
|
||||
*/
|
||||
@ -88,35 +85,39 @@ static const uint8_t PADDING[64] =
|
||||
#define I(x, y, z) ((y) ^ ((x) | (~z)))
|
||||
|
||||
/* ROTATE_LEFT rotates x left n bits. */
|
||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
|
||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
|
||||
|
||||
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
|
||||
Rotation is separate from addition to prevent recomputation. */
|
||||
#define FF(a, b, c, d, x, s, ac) { \
|
||||
(a) += F ((b), (c), (d)) + (x) + (uint32_t)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define GG(a, b, c, d, x, s, ac) { \
|
||||
(a) += G ((b), (c), (d)) + (x) + (uint32_t)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define HH(a, b, c, d, x, s, ac) { \
|
||||
(a) += H ((b), (c), (d)) + (x) + (uint32_t)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define II(a, b, c, d, x, s, ac) { \
|
||||
(a) += I ((b), (c), (d)) + (x) + (uint32_t)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define FF(a, b, c, d, x, s, ac) \
|
||||
{ \
|
||||
(a) += F((b), (c), (d)) + (x) + (uint32_t)(ac); \
|
||||
(a) = ROTATE_LEFT((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define GG(a, b, c, d, x, s, ac) \
|
||||
{ \
|
||||
(a) += G((b), (c), (d)) + (x) + (uint32_t)(ac); \
|
||||
(a) = ROTATE_LEFT((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define HH(a, b, c, d, x, s, ac) \
|
||||
{ \
|
||||
(a) += H((b), (c), (d)) + (x) + (uint32_t)(ac); \
|
||||
(a) = ROTATE_LEFT((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define II(a, b, c, d, x, s, ac) \
|
||||
{ \
|
||||
(a) += I((b), (c), (d)) + (x) + (uint32_t)(ac); \
|
||||
(a) = ROTATE_LEFT((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
|
||||
/**
|
||||
* MD5 initialization - begins an MD5 operation, writing a new ctx.
|
||||
*/
|
||||
EXP_FUNC void STDCALL MD5Init(MD5_CTX *ctx)
|
||||
EXP_FUNC void STDCALL MD5Init(MD5_CTX* ctx)
|
||||
{
|
||||
ctx->count[0] = ctx->count[1] = 0;
|
||||
|
||||
@ -131,10 +132,10 @@ EXP_FUNC void STDCALL MD5Init(MD5_CTX *ctx)
|
||||
/**
|
||||
* Accepts an array of octets as the next portion of the message.
|
||||
*/
|
||||
EXP_FUNC void STDCALL MD5Update(MD5_CTX *ctx, const uint8_t * msg, int len)
|
||||
EXP_FUNC void STDCALL MD5Update(MD5_CTX* ctx, const uint8_t* msg, int len)
|
||||
{
|
||||
uint32_t x;
|
||||
int i, partLen;
|
||||
int i, partLen;
|
||||
|
||||
/* Compute number of bytes mod 64 */
|
||||
x = (uint32_t)((ctx->count[0] >> 3) & 0x3F);
|
||||
@ -147,7 +148,7 @@ EXP_FUNC void STDCALL MD5Update(MD5_CTX *ctx, const uint8_t * msg, int len)
|
||||
partLen = 64 - x;
|
||||
|
||||
/* Transform as many times as possible. */
|
||||
if (len >= partLen)
|
||||
if (len >= partLen)
|
||||
{
|
||||
memcpy(&ctx->buffer[x], msg, partLen);
|
||||
MD5Transform(ctx->state, ctx->buffer);
|
||||
@ -161,15 +162,15 @@ EXP_FUNC void STDCALL MD5Update(MD5_CTX *ctx, const uint8_t * msg, int len)
|
||||
i = 0;
|
||||
|
||||
/* Buffer remaining input */
|
||||
memcpy(&ctx->buffer[x], &msg[i], len-i);
|
||||
memcpy(&ctx->buffer[x], &msg[i], len - i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the 128-bit message digest into the user's array
|
||||
*/
|
||||
EXP_FUNC void STDCALL MD5Final(uint8_t *digest, MD5_CTX *ctx)
|
||||
EXP_FUNC void STDCALL MD5Final(uint8_t* digest, MD5_CTX* ctx)
|
||||
{
|
||||
uint8_t bits[8];
|
||||
uint8_t bits[8];
|
||||
uint32_t x, padLen;
|
||||
|
||||
/* Save number of bits */
|
||||
@ -177,7 +178,7 @@ EXP_FUNC void STDCALL MD5Final(uint8_t *digest, MD5_CTX *ctx)
|
||||
|
||||
/* Pad out to 56 mod 64.
|
||||
*/
|
||||
x = (uint32_t)((ctx->count[0] >> 3) & 0x3f);
|
||||
x = (uint32_t)((ctx->count[0] >> 3) & 0x3f);
|
||||
padLen = (x < 56) ? (56 - x) : (120 - x);
|
||||
MD5Update(ctx, PADDING, padLen);
|
||||
|
||||
@ -193,82 +194,81 @@ EXP_FUNC void STDCALL MD5Final(uint8_t *digest, MD5_CTX *ctx)
|
||||
*/
|
||||
static void MD5Transform(uint32_t state[4], const uint8_t block[64])
|
||||
{
|
||||
uint32_t a = state[0], b = state[1], c = state[2],
|
||||
d = state[3], x[MD5_SIZE];
|
||||
uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[MD5_SIZE];
|
||||
|
||||
Decode(x, block, 64);
|
||||
|
||||
/* Round 1 */
|
||||
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
|
||||
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
|
||||
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
|
||||
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
|
||||
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
|
||||
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
|
||||
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
|
||||
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
|
||||
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
|
||||
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
|
||||
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
|
||||
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
|
||||
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
|
||||
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
|
||||
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
|
||||
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
|
||||
FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
|
||||
FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
|
||||
FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
|
||||
FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
|
||||
FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
|
||||
FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
|
||||
FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
|
||||
FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
|
||||
FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
|
||||
FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
|
||||
FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
|
||||
FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
|
||||
FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
|
||||
FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
|
||||
FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
|
||||
FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
|
||||
|
||||
/* Round 2 */
|
||||
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
|
||||
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
|
||||
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
|
||||
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
|
||||
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
|
||||
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
|
||||
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
|
||||
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
|
||||
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
|
||||
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
|
||||
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
|
||||
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
|
||||
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
|
||||
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
|
||||
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
|
||||
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
|
||||
GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
|
||||
GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
|
||||
GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
|
||||
GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
|
||||
GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
|
||||
GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
|
||||
GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
|
||||
GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
|
||||
GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
|
||||
GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
|
||||
GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
|
||||
GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
|
||||
GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
|
||||
GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
|
||||
GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
|
||||
GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
|
||||
|
||||
/* Round 3 */
|
||||
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
|
||||
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
|
||||
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
|
||||
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
|
||||
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
|
||||
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
|
||||
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
|
||||
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
|
||||
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
|
||||
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
|
||||
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
|
||||
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
|
||||
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
|
||||
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
|
||||
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
|
||||
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
|
||||
HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
|
||||
HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
|
||||
HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
|
||||
HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
|
||||
HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
|
||||
HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
|
||||
HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
|
||||
HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
|
||||
HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
|
||||
HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
|
||||
HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
|
||||
HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
|
||||
HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
|
||||
HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
|
||||
HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
|
||||
HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
|
||||
|
||||
/* Round 4 */
|
||||
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
|
||||
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
|
||||
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
|
||||
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
|
||||
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
|
||||
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
|
||||
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
|
||||
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
|
||||
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
|
||||
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
|
||||
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
|
||||
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
|
||||
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
|
||||
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
|
||||
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
|
||||
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
|
||||
II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
|
||||
II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
|
||||
II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
|
||||
II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
|
||||
II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
|
||||
II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
|
||||
II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
|
||||
II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
|
||||
II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
|
||||
II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
|
||||
II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
|
||||
II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
|
||||
II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
|
||||
II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
|
||||
II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
|
||||
II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
|
||||
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
@ -280,16 +280,16 @@ static void MD5Transform(uint32_t state[4], const uint8_t block[64])
|
||||
* Encodes input (uint32_t) into output (uint8_t). Assumes len is
|
||||
* a multiple of 4.
|
||||
*/
|
||||
static void Encode(uint8_t *output, uint32_t *input, uint32_t len)
|
||||
static void Encode(uint8_t* output, uint32_t* input, uint32_t len)
|
||||
{
|
||||
uint32_t i, j;
|
||||
|
||||
for (i = 0, j = 0; j < len; i++, j += 4)
|
||||
for (i = 0, j = 0; j < len; i++, j += 4)
|
||||
{
|
||||
output[j] = (uint8_t)(input[i] & 0xff);
|
||||
output[j+1] = (uint8_t)((input[i] >> 8) & 0xff);
|
||||
output[j+2] = (uint8_t)((input[i] >> 16) & 0xff);
|
||||
output[j+3] = (uint8_t)((input[i] >> 24) & 0xff);
|
||||
output[j] = (uint8_t)(input[i] & 0xff);
|
||||
output[j + 1] = (uint8_t)((input[i] >> 8) & 0xff);
|
||||
output[j + 2] = (uint8_t)((input[i] >> 16) & 0xff);
|
||||
output[j + 3] = (uint8_t)((input[i] >> 24) & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
@ -297,11 +297,11 @@ static void Encode(uint8_t *output, uint32_t *input, uint32_t len)
|
||||
* Decodes input (uint8_t) into output (uint32_t). Assumes len is
|
||||
* a multiple of 4.
|
||||
*/
|
||||
static void Decode(uint32_t *output, const uint8_t *input, uint32_t len)
|
||||
static void Decode(uint32_t* output, const uint8_t* input, uint32_t len)
|
||||
{
|
||||
uint32_t i, j;
|
||||
|
||||
for (i = 0, j = 0; j < len; i++, j += 4)
|
||||
output[i] = ((uint32_t)input[j]) | (((uint32_t)input[j+1]) << 8) |
|
||||
(((uint32_t)input[j+2]) << 16) | (((uint32_t)input[j+3]) << 24);
|
||||
output[i] = ((uint32_t)input[j]) | (((uint32_t)input[j + 1]) << 8)
|
||||
| (((uint32_t)input[j + 2]) << 16) | (((uint32_t)input[j + 3]) << 24);
|
||||
}
|
||||
|
@ -30,7 +30,8 @@
|
||||
*/
|
||||
|
||||
#define CORE_MOCK 1
|
||||
#define MOCK "(mock) " // TODO: provide common logging API instead of adding this string everywhere?
|
||||
#define MOCK \
|
||||
"(mock) " // TODO: provide common logging API instead of adding this string everywhere?
|
||||
|
||||
//
|
||||
|
||||
@ -57,15 +58,15 @@
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
// TODO: #include <stdlib_noniso.h> ?
|
||||
char* itoa (int val, char *s, int radix);
|
||||
char* ltoa (long val, char *s, int radix);
|
||||
// TODO: #include <stdlib_noniso.h> ?
|
||||
char* itoa(int val, char* s, int radix);
|
||||
char* ltoa(long val, char* s, int radix);
|
||||
|
||||
|
||||
size_t strlcat(char *dst, const char *src, size_t size);
|
||||
size_t strlcpy(char *dst, const char *src, size_t size);
|
||||
size_t strlcat(char* dst, const char* src, size_t size);
|
||||
size_t strlcpy(char* dst, const char* src, size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
@ -74,7 +75,7 @@ size_t strlcpy(char *dst, const char *src, size_t size);
|
||||
// exotic typedefs used in the sdk
|
||||
|
||||
#include <stdint.h>
|
||||
typedef uint8_t uint8;
|
||||
typedef uint8_t uint8;
|
||||
typedef uint32_t uint32;
|
||||
|
||||
//
|
||||
@ -97,26 +98,30 @@ uint32_t esp_get_cycle_count();
|
||||
//
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
#include <osapi.h>
|
||||
int ets_printf (const char* fmt, ...) __attribute__ ((format (printf, 1, 2)));
|
||||
int ets_printf(const char* fmt, ...) __attribute__((format(printf, 1, 2)));
|
||||
#define os_printf_plus printf
|
||||
#define ets_vsnprintf vsnprintf
|
||||
inline void ets_putc (char c) { putchar(c); }
|
||||
inline void ets_putc(char c)
|
||||
{
|
||||
putchar(c);
|
||||
}
|
||||
|
||||
int mockverbose (const char* fmt, ...) __attribute__ ((format (printf, 1, 2)));
|
||||
int mockverbose(const char* fmt, ...) __attribute__((format(printf, 1, 2)));
|
||||
|
||||
extern const char* host_interface; // cmdline parameter
|
||||
extern bool serial_timestamp;
|
||||
extern int mock_port_shifter;
|
||||
extern bool blocking_uart;
|
||||
extern uint32_t global_source_address; // 0 = INADDR_ANY by default
|
||||
extern const char* host_interface; // cmdline parameter
|
||||
extern bool serial_timestamp;
|
||||
extern int mock_port_shifter;
|
||||
extern bool blocking_uart;
|
||||
extern uint32_t global_source_address; // 0 = INADDR_ANY by default
|
||||
|
||||
#define NO_GLOBAL_BINDING 0xffffffff
|
||||
extern uint32_t global_ipv4_netfmt; // selected interface addresse to bind to
|
||||
extern uint32_t global_ipv4_netfmt; // selected interface addresse to bind to
|
||||
|
||||
void loop_end();
|
||||
void loop_end();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
@ -132,41 +137,48 @@ void loop_end();
|
||||
|
||||
// uart
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
void uart_new_data(const int uart_nr, uint8_t data);
|
||||
void uart_new_data(const int uart_nr, uint8_t data);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
// tcp
|
||||
int mockSockSetup (int sock);
|
||||
int mockConnect (uint32_t addr, int& sock, int port);
|
||||
ssize_t mockFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize);
|
||||
ssize_t mockPeekBytes (int sock, char* dst, size_t size, int timeout_ms, char* buf, size_t& bufsize);
|
||||
ssize_t mockRead (int sock, char* dst, size_t size, int timeout_ms, char* buf, size_t& bufsize);
|
||||
ssize_t mockWrite (int sock, const uint8_t* data, size_t size, int timeout_ms);
|
||||
int serverAccept (int sock);
|
||||
int mockSockSetup(int sock);
|
||||
int mockConnect(uint32_t addr, int& sock, int port);
|
||||
ssize_t mockFillInBuf(int sock, char* ccinbuf, size_t& ccinbufsize);
|
||||
ssize_t mockPeekBytes(int sock, char* dst, size_t size, int timeout_ms, char* buf, size_t& bufsize);
|
||||
ssize_t mockRead(int sock, char* dst, size_t size, int timeout_ms, char* buf, size_t& bufsize);
|
||||
ssize_t mockWrite(int sock, const uint8_t* data, size_t size, int timeout_ms);
|
||||
int serverAccept(int sock);
|
||||
|
||||
// udp
|
||||
void check_incoming_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);
|
||||
void mockUDPSwallow (size_t copied, char* ccinbuf, size_t& ccinbufsize);
|
||||
void check_incoming_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);
|
||||
void mockUDPSwallow(size_t copied, char* ccinbuf, size_t& ccinbufsize);
|
||||
|
||||
class UdpContext;
|
||||
void register_udp (int sock, UdpContext* udp = nullptr);
|
||||
void register_udp(int sock, UdpContext* udp = nullptr);
|
||||
|
||||
//
|
||||
|
||||
void mock_start_spiffs (const String& fname, size_t size_kb, size_t block_kb = 8, size_t page_b = 512);
|
||||
void mock_stop_spiffs ();
|
||||
void mock_start_littlefs (const String& fname, size_t size_kb, size_t block_kb = 8, size_t page_b = 512);
|
||||
void mock_stop_littlefs ();
|
||||
void mock_start_spiffs(const String& fname, size_t size_kb, size_t block_kb = 8,
|
||||
size_t page_b = 512);
|
||||
void mock_stop_spiffs();
|
||||
void mock_start_littlefs(const String& fname, size_t size_kb, size_t block_kb = 8,
|
||||
size_t page_b = 512);
|
||||
void mock_stop_littlefs();
|
||||
|
||||
//
|
||||
|
||||
@ -174,4 +186,4 @@ void mock_stop_littlefs ();
|
||||
|
||||
//
|
||||
|
||||
#endif // __cplusplus
|
||||
#endif // __cplusplus
|
||||
|
@ -1,19 +1,18 @@
|
||||
/*
|
||||
noniso.cpp - replacements for non-ISO functions used by Arduino core
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
@ -21,61 +20,69 @@
|
||||
#include <math.h>
|
||||
#include "stdlib_noniso.h"
|
||||
|
||||
|
||||
void reverse(char* begin, char* end) {
|
||||
char *is = begin;
|
||||
char *ie = end - 1;
|
||||
while(is < ie) {
|
||||
void reverse(char* begin, char* end)
|
||||
{
|
||||
char* is = begin;
|
||||
char* ie = end - 1;
|
||||
while (is < ie)
|
||||
{
|
||||
char tmp = *ie;
|
||||
*ie = *is;
|
||||
*is = tmp;
|
||||
*ie = *is;
|
||||
*is = tmp;
|
||||
++is;
|
||||
--ie;
|
||||
}
|
||||
}
|
||||
|
||||
char* utoa(unsigned value, char* result, int base) {
|
||||
if(base < 2 || base > 16) {
|
||||
char* utoa(unsigned value, char* result, int base)
|
||||
{
|
||||
if (base < 2 || base > 16)
|
||||
{
|
||||
*result = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
char* out = result;
|
||||
char* out = result;
|
||||
unsigned quotient = value;
|
||||
|
||||
do {
|
||||
do
|
||||
{
|
||||
const unsigned tmp = quotient / base;
|
||||
*out = "0123456789abcdef"[quotient - (tmp * base)];
|
||||
*out = "0123456789abcdef"[quotient - (tmp * base)];
|
||||
++out;
|
||||
quotient = tmp;
|
||||
} while(quotient);
|
||||
} while (quotient);
|
||||
|
||||
reverse(result, out);
|
||||
*out = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
char* itoa(int value, char* result, int base) {
|
||||
if(base < 2 || base > 16) {
|
||||
char* itoa(int value, char* result, int base)
|
||||
{
|
||||
if (base < 2 || base > 16)
|
||||
{
|
||||
*result = 0;
|
||||
return result;
|
||||
}
|
||||
if (base != 10) {
|
||||
return utoa((unsigned)value, result, base);
|
||||
}
|
||||
if (base != 10)
|
||||
{
|
||||
return utoa((unsigned)value, result, base);
|
||||
}
|
||||
|
||||
char* out = result;
|
||||
int quotient = abs(value);
|
||||
char* out = result;
|
||||
int quotient = abs(value);
|
||||
|
||||
do {
|
||||
do
|
||||
{
|
||||
const int tmp = quotient / base;
|
||||
*out = "0123456789abcdef"[quotient - (tmp * base)];
|
||||
*out = "0123456789abcdef"[quotient - (tmp * base)];
|
||||
++out;
|
||||
quotient = tmp;
|
||||
} while(quotient);
|
||||
} while (quotient);
|
||||
|
||||
// Apply negative sign
|
||||
if(value < 0)
|
||||
if (value < 0)
|
||||
*out++ = '-';
|
||||
|
||||
reverse(result, out);
|
||||
@ -83,17 +90,19 @@ char* itoa(int value, char* result, int base) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int atoi(const char* s) {
|
||||
return (int) atol(s);
|
||||
int atoi(const char* s)
|
||||
{
|
||||
return (int)atol(s);
|
||||
}
|
||||
|
||||
long atol(const char* s) {
|
||||
char * tmp;
|
||||
long atol(const char* s)
|
||||
{
|
||||
char* tmp;
|
||||
return strtol(s, &tmp, 10);
|
||||
}
|
||||
|
||||
double atof(const char* s) {
|
||||
char * tmp;
|
||||
double atof(const char* s)
|
||||
{
|
||||
char* tmp;
|
||||
return strtod(s, &tmp);
|
||||
}
|
||||
|
||||
|
@ -1,19 +1,18 @@
|
||||
/*
|
||||
pins_arduino.h
|
||||
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.
|
||||
*/
|
||||
#ifndef pins_arduino_h
|
||||
#define pins_arduino_h
|
||||
|
||||
|
||||
#endif /* pins_arduino_h */
|
||||
|
@ -35,9 +35,9 @@
|
||||
*/
|
||||
|
||||
#ifndef _SYS_QUEUE_H_
|
||||
#define _SYS_QUEUE_H_
|
||||
#define _SYS_QUEUE_H_
|
||||
|
||||
#include <machine/ansi.h> /* for __offsetof */
|
||||
#include <machine/ansi.h> /* for __offsetof */
|
||||
|
||||
/*
|
||||
* This file defines four types of data structures: singly-linked lists,
|
||||
@ -106,322 +106,373 @@
|
||||
/*
|
||||
* Singly-linked List declarations.
|
||||
*/
|
||||
#define SLIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *slh_first; /* first element */ \
|
||||
}
|
||||
#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 */ \
|
||||
}
|
||||
|
||||
#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_EMPTY(head) ((head)->slh_first == NULL)
|
||||
|
||||
#define SLIST_FIRST(head) ((head)->slh_first)
|
||||
#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_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_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_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_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_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, 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)
|
||||
#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(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_HEAD_INITIALIZER(head) \
|
||||
{ \
|
||||
NULL, &(head).stqh_first \
|
||||
}
|
||||
|
||||
#define STAILQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *stqe_next; /* next element */ \
|
||||
}
|
||||
#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_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_EMPTY(head) ((head)->stqh_first == NULL)
|
||||
|
||||
#define STAILQ_FIRST(head) ((head)->stqh_first)
|
||||
#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_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_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_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_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_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_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_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, 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(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)
|
||||
#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(name, type) \
|
||||
struct name \
|
||||
{ \
|
||||
struct type* lh_first; /* first element */ \
|
||||
}
|
||||
|
||||
#define LIST_HEAD_INITIALIZER(head) \
|
||||
{ NULL }
|
||||
#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 */ \
|
||||
}
|
||||
#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_EMPTY(head) ((head)->lh_first == NULL)
|
||||
|
||||
#define LIST_FIRST(head) ((head)->lh_first)
|
||||
#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_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_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_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_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_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_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)
|
||||
#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(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_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 */ \
|
||||
}
|
||||
#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_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_EMPTY(head) ((head)->tqh_first == NULL)
|
||||
|
||||
#define TAILQ_FIRST(head) ((head)->tqh_first)
|
||||
#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(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_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_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_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_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_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_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_LAST(head, headname) (*(((struct headname*)((head)->tqh_last))->tqh_last))
|
||||
|
||||
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
|
||||
#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)
|
||||
#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
|
||||
|
||||
@ -430,39 +481,37 @@ struct { \
|
||||
* They bogusly assumes that all queue heads look alike.
|
||||
*/
|
||||
|
||||
struct quehead {
|
||||
struct quehead *qh_link;
|
||||
struct quehead *qh_rlink;
|
||||
struct quehead
|
||||
{
|
||||
struct quehead* qh_link;
|
||||
struct quehead* qh_rlink;
|
||||
};
|
||||
|
||||
#ifdef __GNUC__
|
||||
#ifdef __GNUC__
|
||||
|
||||
static __inline void
|
||||
insque(void *a, void *b)
|
||||
static __inline void insque(void* a, void* b)
|
||||
{
|
||||
struct quehead *element = (struct quehead *)a,
|
||||
*head = (struct quehead *)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;
|
||||
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)
|
||||
static __inline void remque(void* a)
|
||||
{
|
||||
struct quehead *element = (struct quehead *)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;
|
||||
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);
|
||||
void insque(void* a, void* b);
|
||||
void remque(void* a);
|
||||
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
|
@ -18,4 +18,4 @@
|
||||
|
||||
#define SDSIZE 16LL
|
||||
uint64_t _sdCardSizeB = 0;
|
||||
uint8_t *_sdCard = nullptr;
|
||||
uint8_t* _sdCard = nullptr;
|
||||
|
@ -21,22 +21,32 @@
|
||||
#include <vector>
|
||||
#include <FS.h>
|
||||
|
||||
class SDFSMock {
|
||||
class SDFSMock
|
||||
{
|
||||
public:
|
||||
SDFSMock(ssize_t fs_size, size_t fs_block, size_t fs_page, const String& storage = emptyString) { (void)fs_size; (void)fs_block; (void)fs_page; (void)storage; }
|
||||
SDFSMock(ssize_t fs_size, size_t fs_block, size_t fs_page, const String& storage = emptyString)
|
||||
{
|
||||
(void)fs_size;
|
||||
(void)fs_block;
|
||||
(void)fs_page;
|
||||
(void)storage;
|
||||
}
|
||||
void reset() { }
|
||||
~SDFSMock() { }
|
||||
};
|
||||
|
||||
extern uint64_t _sdCardSizeB;
|
||||
extern uint8_t *_sdCard;
|
||||
extern uint8_t* _sdCard;
|
||||
|
||||
#define SDFS_MOCK_DECLARE(size_kb, block_kb, page_b, storage) \
|
||||
SDFS.end(); \
|
||||
SDFSMock sdfs_mock(size_kb * 1024, block_kb * 1024, page_b, storage); free(_sdCard); \
|
||||
_sdCardSizeB = size_kb ? 16 * 1024 * 1024 : 0; \
|
||||
if (_sdCardSizeB) _sdCard = (uint8_t*)calloc(_sdCardSizeB, 1); \
|
||||
else _sdCard = nullptr; \
|
||||
#define SDFS_MOCK_DECLARE(size_kb, block_kb, page_b, storage) \
|
||||
SDFS.end(); \
|
||||
SDFSMock sdfs_mock(size_kb * 1024, block_kb * 1024, page_b, storage); \
|
||||
free(_sdCard); \
|
||||
_sdCardSizeB = size_kb ? 16 * 1024 * 1024 : 0; \
|
||||
if (_sdCardSizeB) \
|
||||
_sdCard = (uint8_t*)calloc(_sdCardSizeB, 1); \
|
||||
else \
|
||||
_sdCard = nullptr; \
|
||||
SDFS.setConfig(SDFSConfig().setAutoFormat(true));
|
||||
#define SDFS_MOCK_RESET() sdfs_mock.reset()
|
||||
|
||||
|
@ -13,7 +13,6 @@
|
||||
all copies or substantial portions of the Software.
|
||||
*/
|
||||
|
||||
|
||||
#include "spiffs_mock.h"
|
||||
#include "spiffs/spiffs.h"
|
||||
#include "debug.h"
|
||||
@ -54,7 +53,8 @@ SpiffsMock::SpiffsMock(ssize_t fs_size, size_t fs_block, size_t fs_page, const S
|
||||
|
||||
void SpiffsMock::reset()
|
||||
{
|
||||
SPIFFS = FS(FSImplPtr(new spiffs_impl::SPIFFSImpl(0, s_phys_size, s_phys_page, s_phys_block, 5)));
|
||||
SPIFFS
|
||||
= FS(FSImplPtr(new spiffs_impl::SPIFFSImpl(0, s_phys_size, s_phys_page, s_phys_block, 5)));
|
||||
load();
|
||||
}
|
||||
|
||||
@ -70,18 +70,18 @@ SpiffsMock::~SpiffsMock()
|
||||
SPIFFS = FS(FSImplPtr(nullptr));
|
||||
}
|
||||
|
||||
void SpiffsMock::load ()
|
||||
void SpiffsMock::load()
|
||||
{
|
||||
if (!m_fs.size() || !m_storage.length())
|
||||
return;
|
||||
|
||||
|
||||
int fs = ::open(m_storage.c_str(), O_RDONLY);
|
||||
if (fs == -1)
|
||||
{
|
||||
fprintf(stderr, "SPIFFS: loading '%s': %s\n", m_storage.c_str(), strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
off_t flen = lseek(fs, 0, SEEK_END);
|
||||
if (flen == (off_t)-1)
|
||||
{
|
||||
@ -89,28 +89,32 @@ void SpiffsMock::load ()
|
||||
return;
|
||||
}
|
||||
lseek(fs, 0, SEEK_SET);
|
||||
|
||||
|
||||
if (flen != (off_t)m_fs.size())
|
||||
{
|
||||
fprintf(stderr, "SPIFFS: size of '%s': %d does not match requested size %zd\n", m_storage.c_str(), (int)flen, m_fs.size());
|
||||
fprintf(stderr, "SPIFFS: size of '%s': %d does not match requested size %zd\n",
|
||||
m_storage.c_str(), (int)flen, m_fs.size());
|
||||
if (!m_overwrite && flen > 0)
|
||||
{
|
||||
fprintf(stderr, "SPIFFS: aborting at user request\n");
|
||||
exit(1);
|
||||
}
|
||||
fprintf(stderr, "SPIFFS: continuing without loading at user request, '%s' will be overwritten\n", m_storage.c_str());
|
||||
fprintf(stderr,
|
||||
"SPIFFS: continuing without loading at user request, '%s' will be overwritten\n",
|
||||
m_storage.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "SPIFFS: loading %zi bytes from '%s'\n", m_fs.size(), m_storage.c_str());
|
||||
ssize_t r = ::read(fs, m_fs.data(), m_fs.size());
|
||||
if (r != (ssize_t)m_fs.size())
|
||||
fprintf(stderr, "SPIFFS: reading %zi bytes: returned %zd: %s\n", m_fs.size(), r, strerror(errno));
|
||||
fprintf(stderr, "SPIFFS: reading %zi bytes: returned %zd: %s\n", m_fs.size(), r,
|
||||
strerror(errno));
|
||||
}
|
||||
::close(fs);
|
||||
}
|
||||
|
||||
void SpiffsMock::save ()
|
||||
void SpiffsMock::save()
|
||||
{
|
||||
if (!m_fs.size() || !m_storage.length())
|
||||
return;
|
||||
@ -130,4 +134,3 @@ void SpiffsMock::save ()
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
|
@ -1,14 +1,14 @@
|
||||
/*
|
||||
spiffs_mock.h - SPIFFS HAL mock for host side testing
|
||||
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.
|
||||
*/
|
||||
@ -24,22 +24,25 @@
|
||||
|
||||
#define DEFAULT_SPIFFS_FILE_NAME "spiffs.bin"
|
||||
|
||||
class SpiffsMock {
|
||||
class SpiffsMock
|
||||
{
|
||||
public:
|
||||
SpiffsMock(ssize_t fs_size, size_t fs_block, size_t fs_page, const String& storage = emptyString);
|
||||
SpiffsMock(ssize_t fs_size, size_t fs_block, size_t fs_page,
|
||||
const String& storage = emptyString);
|
||||
void reset();
|
||||
~SpiffsMock();
|
||||
|
||||
|
||||
protected:
|
||||
void load ();
|
||||
void save ();
|
||||
void load();
|
||||
void save();
|
||||
|
||||
std::vector<uint8_t> m_fs;
|
||||
String m_storage;
|
||||
bool m_overwrite;
|
||||
String m_storage;
|
||||
bool m_overwrite;
|
||||
};
|
||||
|
||||
#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_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()
|
||||
|
||||
#endif /* spiffs_mock_hpp */
|
||||
|
@ -5,25 +5,24 @@
|
||||
'_cups_strlcat()' - Safely concatenate two strings.
|
||||
*/
|
||||
|
||||
size_t /* O - Length of string */
|
||||
strlcat(char *dst, /* O - Destination string */
|
||||
const char *src, /* I - Source string */
|
||||
size_t size) /* I - Size of destination string buffer */
|
||||
size_t /* O - Length of string */
|
||||
strlcat(char* dst, /* O - Destination string */
|
||||
const char* src, /* I - Source string */
|
||||
size_t size) /* I - Size of destination string buffer */
|
||||
{
|
||||
size_t srclen; /* Length of source string */
|
||||
size_t dstlen; /* Length of destination string */
|
||||
|
||||
size_t srclen; /* Length of source string */
|
||||
size_t dstlen; /* Length of destination string */
|
||||
|
||||
/*
|
||||
Figure out how much room is left...
|
||||
*/
|
||||
|
||||
dstlen = strlen(dst);
|
||||
size -= dstlen + 1;
|
||||
size -= dstlen + 1;
|
||||
|
||||
if (!size)
|
||||
{
|
||||
return (dstlen); /* No room, return immediately... */
|
||||
return (dstlen); /* No room, return immediately... */
|
||||
}
|
||||
|
||||
/*
|
||||
@ -53,19 +52,18 @@ strlcat(char *dst, /* O - Destination string */
|
||||
'_cups_strlcpy()' - Safely copy two strings.
|
||||
*/
|
||||
|
||||
size_t /* O - Length of string */
|
||||
strlcpy(char *dst, /* O - Destination string */
|
||||
const char *src, /* I - Source string */
|
||||
size_t /* O - Length of string */
|
||||
strlcpy(char* dst, /* O - Destination string */
|
||||
const char* src, /* I - Source string */
|
||||
size_t size) /* I - Size of destination string buffer */
|
||||
{
|
||||
size_t srclen; /* Length of source string */
|
||||
|
||||
size_t srclen; /* Length of source string */
|
||||
|
||||
/*
|
||||
Figure out how much room is needed...
|
||||
*/
|
||||
|
||||
size --;
|
||||
size--;
|
||||
|
||||
srclen = strlen(src);
|
||||
|
||||
|
@ -43,7 +43,7 @@
|
||||
|
||||
#include <LwipDhcpServer.h>
|
||||
|
||||
bool DhcpServer::set_dhcps_lease(struct dhcps_lease *please)
|
||||
bool DhcpServer::set_dhcps_lease(struct dhcps_lease* please)
|
||||
{
|
||||
(void)please;
|
||||
return false;
|
||||
@ -62,22 +62,20 @@ bool DhcpServer::set_dhcps_offer_option(uint8 level, void* optarg)
|
||||
return false;
|
||||
}
|
||||
|
||||
void DhcpServer::end ()
|
||||
{
|
||||
}
|
||||
void DhcpServer::end() { }
|
||||
|
||||
bool DhcpServer::begin (struct ip_info *info)
|
||||
bool DhcpServer::begin(struct ip_info* info)
|
||||
{
|
||||
(void)info;
|
||||
return false;
|
||||
}
|
||||
|
||||
DhcpServer::DhcpServer (netif* netif)
|
||||
DhcpServer::DhcpServer(netif* netif)
|
||||
{
|
||||
(void)netif;
|
||||
}
|
||||
|
||||
DhcpServer::~DhcpServer ()
|
||||
DhcpServer::~DhcpServer()
|
||||
{
|
||||
end();
|
||||
}
|
||||
@ -86,7 +84,6 @@ DhcpServer dhcpSoftAP(nullptr);
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
#include <user_interface.h>
|
||||
#include <lwip/netif.h>
|
||||
|
||||
@ -120,14 +117,14 @@ extern "C"
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool wifi_station_get_config(struct station_config *config)
|
||||
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.rssi = 1;
|
||||
config->threshold.authmode = AUTH_WPA_PSK;
|
||||
#ifdef NONOSDK3V0
|
||||
config->open_and_wep_mode_disable = true;
|
||||
@ -135,9 +132,7 @@ extern "C"
|
||||
return true;
|
||||
}
|
||||
|
||||
void wifi_fpm_close(void)
|
||||
{
|
||||
}
|
||||
void wifi_fpm_close(void) { }
|
||||
|
||||
sint8 wifi_fpm_do_sleep(uint32 sleep_time_in_us)
|
||||
{
|
||||
@ -145,34 +140,30 @@ extern "C"
|
||||
return 1;
|
||||
}
|
||||
|
||||
void wifi_fpm_do_wakeup(void)
|
||||
{
|
||||
}
|
||||
void wifi_fpm_do_wakeup(void) { }
|
||||
|
||||
void wifi_fpm_open(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
|
||||
uint32_t global_ipv4_netfmt = 0; // global binding
|
||||
|
||||
netif netif0;
|
||||
netif netif0;
|
||||
uint32_t global_source_address = INADDR_ANY;
|
||||
|
||||
bool wifi_get_ip_info(uint8 if_index, struct ip_info *info)
|
||||
bool wifi_get_ip_info(uint8 if_index, struct ip_info* info)
|
||||
{
|
||||
// emulate wifi_get_ip_info()
|
||||
// ignore if_index
|
||||
// use global option -i (host_interface) to select bound interface/address
|
||||
|
||||
struct ifaddrs * ifAddrStruct = NULL, * ifa = NULL;
|
||||
uint32_t ipv4 = lwip_htonl(0x7f000001);
|
||||
uint32_t mask = lwip_htonl(0xff000000);
|
||||
global_source_address = INADDR_ANY; // =0
|
||||
struct ifaddrs *ifAddrStruct = NULL, *ifa = NULL;
|
||||
uint32_t ipv4 = lwip_htonl(0x7f000001);
|
||||
uint32_t mask = lwip_htonl(0xff000000);
|
||||
global_source_address = INADDR_ANY; // =0
|
||||
|
||||
if (getifaddrs(&ifAddrStruct) != 0)
|
||||
{
|
||||
@ -186,22 +177,24 @@ extern "C"
|
||||
for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next)
|
||||
{
|
||||
mockverbose("host: interface: %s", ifa->ifa_name);
|
||||
if (ifa->ifa_addr
|
||||
&& ifa->ifa_addr->sa_family == AF_INET // ip_info is IPv4 only
|
||||
)
|
||||
if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET // ip_info is IPv4 only
|
||||
)
|
||||
{
|
||||
auto test_ipv4 = lwip_ntohl(*(uint32_t*) & ((struct sockaddr_in*)ifa->ifa_addr)->sin_addr);
|
||||
auto test_ipv4
|
||||
= lwip_ntohl(*(uint32_t*)&((struct sockaddr_in*)ifa->ifa_addr)->sin_addr);
|
||||
mockverbose(" IPV4 (0x%08lx)", test_ipv4);
|
||||
if ((test_ipv4 & 0xff000000) == 0x7f000000)
|
||||
// 127./8
|
||||
mockverbose(" (local, ignored)");
|
||||
else
|
||||
{
|
||||
if (!host_interface || (host_interface && strcmp(ifa->ifa_name, host_interface) == 0))
|
||||
if (!host_interface
|
||||
|| (host_interface && strcmp(ifa->ifa_name, host_interface) == 0))
|
||||
{
|
||||
// use the first non-local interface, or, if specified, the one selected 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;
|
||||
// use the first non-local interface, or, if specified, the one selected 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;
|
||||
mockverbose(" (selected)\n");
|
||||
if (host_interface)
|
||||
global_source_address = ntohl(ipv4);
|
||||
@ -216,7 +209,7 @@ extern "C"
|
||||
freeifaddrs(ifAddrStruct);
|
||||
|
||||
(void)if_index;
|
||||
//if (if_index != STATION_IF)
|
||||
// if (if_index != STATION_IF)
|
||||
// fprintf(stderr, "we are not AP");
|
||||
|
||||
if (global_ipv4_netfmt == NO_GLOBAL_BINDING)
|
||||
@ -224,15 +217,15 @@ extern "C"
|
||||
|
||||
if (info)
|
||||
{
|
||||
info->ip.addr = ipv4;
|
||||
info->ip.addr = ipv4;
|
||||
info->netmask.addr = mask;
|
||||
info->gw.addr = ipv4;
|
||||
info->gw.addr = ipv4;
|
||||
|
||||
netif0.ip_addr.addr = ipv4;
|
||||
netif0.netmask.addr = mask;
|
||||
netif0.gw.addr = ipv4;
|
||||
netif0.flags = NETIF_FLAG_IGMP | NETIF_FLAG_UP | NETIF_FLAG_LINK_UP;
|
||||
netif0.next = nullptr;
|
||||
netif0.gw.addr = ipv4;
|
||||
netif0.flags = NETIF_FLAG_IGMP | NETIF_FLAG_UP | NETIF_FLAG_LINK_UP;
|
||||
netif0.next = nullptr;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -243,7 +236,7 @@ extern "C"
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool wifi_get_macaddr(uint8 if_index, uint8 *macaddr)
|
||||
bool wifi_get_macaddr(uint8 if_index, uint8* macaddr)
|
||||
{
|
||||
(void)if_index;
|
||||
macaddr[0] = 0xde;
|
||||
@ -267,7 +260,7 @@ extern "C"
|
||||
return MIN_SLEEP_T;
|
||||
}
|
||||
|
||||
#endif // nonos-sdk-pre-3
|
||||
#endif // nonos-sdk-pre-3
|
||||
|
||||
sleep_type_t wifi_get_sleep_type(void)
|
||||
{
|
||||
@ -281,13 +274,13 @@ extern "C"
|
||||
}
|
||||
|
||||
wifi_event_handler_cb_t wifi_event_handler_cb_emu = nullptr;
|
||||
void wifi_set_event_handler_cb(wifi_event_handler_cb_t cb)
|
||||
void wifi_set_event_handler_cb(wifi_event_handler_cb_t cb)
|
||||
{
|
||||
wifi_event_handler_cb_emu = cb;
|
||||
mockverbose("TODO: wifi_set_event_handler_cb set\n");
|
||||
}
|
||||
|
||||
bool wifi_set_ip_info(uint8 if_index, struct ip_info *info)
|
||||
bool wifi_set_ip_info(uint8 if_index, struct ip_info* info)
|
||||
{
|
||||
(void)if_index;
|
||||
(void)info;
|
||||
@ -352,12 +345,12 @@ extern "C"
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wifi_station_get_config_default(struct station_config *config)
|
||||
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_str[128];
|
||||
const char* wifi_station_get_hostname(void)
|
||||
{
|
||||
return strcpy(wifi_station_get_hostname_str, "esposix");
|
||||
@ -378,19 +371,19 @@ extern "C"
|
||||
return set != 0;
|
||||
}
|
||||
|
||||
bool wifi_station_set_config(struct station_config *config)
|
||||
bool wifi_station_set_config(struct station_config* config)
|
||||
{
|
||||
(void)config;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wifi_station_set_config_current(struct station_config *config)
|
||||
bool wifi_station_set_config_current(struct station_config* config)
|
||||
{
|
||||
(void)config;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wifi_station_set_hostname(const char *name)
|
||||
bool wifi_station_set_hostname(const char* name)
|
||||
{
|
||||
(void)name;
|
||||
return true;
|
||||
@ -422,20 +415,20 @@ extern "C"
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wifi_softap_get_config(struct softap_config *config)
|
||||
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->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)
|
||||
bool wifi_softap_get_config_default(struct softap_config* config)
|
||||
{
|
||||
return wifi_softap_get_config(config);
|
||||
}
|
||||
@ -445,19 +438,19 @@ extern "C"
|
||||
return 2;
|
||||
}
|
||||
|
||||
bool wifi_softap_set_config(struct softap_config *config)
|
||||
bool wifi_softap_set_config(struct softap_config* config)
|
||||
{
|
||||
(void)config;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wifi_softap_set_config_current(struct softap_config *config)
|
||||
bool wifi_softap_set_config_current(struct softap_config* config)
|
||||
{
|
||||
(void)config;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wifi_softap_set_dhcps_lease(struct dhcps_lease *please)
|
||||
bool wifi_softap_set_dhcps_lease(struct dhcps_lease* please)
|
||||
{
|
||||
(void)please;
|
||||
return true;
|
||||
@ -476,7 +469,7 @@ extern "C"
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wifi_station_scan(struct scan_config *config, scan_done_cb_t cb)
|
||||
bool wifi_station_scan(struct scan_config* config, scan_done_cb_t cb)
|
||||
{
|
||||
(void)config;
|
||||
cb(nullptr, FAIL);
|
||||
@ -498,7 +491,7 @@ extern "C"
|
||||
(void)intr;
|
||||
}
|
||||
|
||||
void dns_setserver(u8_t numdns, ip_addr_t *dnsserver)
|
||||
void dns_setserver(u8_t numdns, ip_addr_t* dnsserver)
|
||||
{
|
||||
(void)numdns;
|
||||
(void)dnsserver;
|
||||
@ -511,11 +504,10 @@ extern "C"
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
#include <smartconfig.h>
|
||||
bool smartconfig_start(sc_callback_t cb, ...)
|
||||
{
|
||||
//XXXFIXME ... -> ptr
|
||||
// XXXFIXME ... -> ptr
|
||||
cb(SC_STATUS_LINK, NULL);
|
||||
return true;
|
||||
}
|
||||
@ -530,4 +522,4 @@ extern "C"
|
||||
return NONE_SLEEP_T;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
} // extern "C"
|
||||
|
@ -2,245 +2,239 @@
|
||||
#include "PolledTimeout.h"
|
||||
|
||||
#define mockverbose printf
|
||||
#include "common/MockEsp.cpp" // getCycleCount
|
||||
#include "common/MockEsp.cpp" // getCycleCount
|
||||
|
||||
//This won't work for
|
||||
// This won't work for
|
||||
template<typename argT>
|
||||
inline bool
|
||||
fuzzycomp(argT a, argT b)
|
||||
inline bool fuzzycomp(argT a, argT b)
|
||||
{
|
||||
const argT epsilon = 10;
|
||||
return (std::max(a,b) - std::min(a,b) <= epsilon);
|
||||
const argT epsilon = 10;
|
||||
return (std::max(a, b) - std::min(a, b) <= epsilon);
|
||||
}
|
||||
|
||||
TEST_CASE("OneShot Timeout 500000000ns (0.5s)", "[polledTimeout]")
|
||||
{
|
||||
using esp8266::polledTimeout::oneShotFastNs;
|
||||
using timeType = oneShotFastNs::timeType;
|
||||
timeType before, after, delta;
|
||||
using esp8266::polledTimeout::oneShotFastNs;
|
||||
using timeType = oneShotFastNs::timeType;
|
||||
timeType before, after, delta;
|
||||
|
||||
Serial.println("OneShot Timeout 500000000ns (0.5s)");
|
||||
Serial.println("OneShot Timeout 500000000ns (0.5s)");
|
||||
|
||||
oneShotFastNs timeout(500000000);
|
||||
before = micros();
|
||||
while(!timeout.expired())
|
||||
yield();
|
||||
after = micros();
|
||||
oneShotFastNs timeout(500000000);
|
||||
before = micros();
|
||||
while (!timeout.expired())
|
||||
yield();
|
||||
after = micros();
|
||||
|
||||
delta = after - before;
|
||||
Serial.printf("delta = %u\n", delta);
|
||||
delta = after - before;
|
||||
Serial.printf("delta = %u\n", delta);
|
||||
|
||||
REQUIRE(fuzzycomp(delta/1000, (timeType)500));
|
||||
REQUIRE(fuzzycomp(delta / 1000, (timeType)500));
|
||||
|
||||
Serial.print("reset\n");
|
||||
|
||||
Serial.print("reset\n");
|
||||
timeout.reset();
|
||||
before = micros();
|
||||
while (!timeout)
|
||||
yield();
|
||||
after = micros();
|
||||
|
||||
timeout.reset();
|
||||
before = micros();
|
||||
while(!timeout)
|
||||
yield();
|
||||
after = micros();
|
||||
delta = after - before;
|
||||
Serial.printf("delta = %u\n", delta);
|
||||
|
||||
delta = after - before;
|
||||
Serial.printf("delta = %u\n", delta);
|
||||
|
||||
REQUIRE(fuzzycomp(delta/1000, (timeType)500));
|
||||
REQUIRE(fuzzycomp(delta / 1000, (timeType)500));
|
||||
}
|
||||
|
||||
TEST_CASE("OneShot Timeout 3000000us", "[polledTimeout]")
|
||||
{
|
||||
using esp8266::polledTimeout::oneShotFastUs;
|
||||
using timeType = oneShotFastUs::timeType;
|
||||
timeType before, after, delta;
|
||||
using esp8266::polledTimeout::oneShotFastUs;
|
||||
using timeType = oneShotFastUs::timeType;
|
||||
timeType before, after, delta;
|
||||
|
||||
Serial.println("OneShot Timeout 3000000us");
|
||||
Serial.println("OneShot Timeout 3000000us");
|
||||
|
||||
oneShotFastUs timeout(3000000);
|
||||
before = micros();
|
||||
while(!timeout.expired())
|
||||
yield();
|
||||
after = micros();
|
||||
oneShotFastUs timeout(3000000);
|
||||
before = micros();
|
||||
while (!timeout.expired())
|
||||
yield();
|
||||
after = micros();
|
||||
|
||||
delta = after - before;
|
||||
Serial.printf("delta = %u\n", delta);
|
||||
delta = after - before;
|
||||
Serial.printf("delta = %u\n", delta);
|
||||
|
||||
REQUIRE(fuzzycomp(delta/1000, (timeType)3000));
|
||||
REQUIRE(fuzzycomp(delta / 1000, (timeType)3000));
|
||||
|
||||
Serial.print("reset\n");
|
||||
|
||||
Serial.print("reset\n");
|
||||
timeout.reset();
|
||||
before = micros();
|
||||
while (!timeout)
|
||||
yield();
|
||||
after = micros();
|
||||
|
||||
timeout.reset();
|
||||
before = micros();
|
||||
while(!timeout)
|
||||
yield();
|
||||
after = micros();
|
||||
delta = after - before;
|
||||
Serial.printf("delta = %u\n", delta);
|
||||
|
||||
delta = after - before;
|
||||
Serial.printf("delta = %u\n", delta);
|
||||
|
||||
REQUIRE(fuzzycomp(delta/1000, (timeType)3000));
|
||||
REQUIRE(fuzzycomp(delta / 1000, (timeType)3000));
|
||||
}
|
||||
|
||||
TEST_CASE("OneShot Timeout 3000ms", "[polledTimeout]")
|
||||
{
|
||||
using esp8266::polledTimeout::oneShotMs;
|
||||
using timeType = oneShotMs::timeType;
|
||||
timeType before, after, delta;
|
||||
using esp8266::polledTimeout::oneShotMs;
|
||||
using timeType = oneShotMs::timeType;
|
||||
timeType before, after, delta;
|
||||
|
||||
Serial.println("OneShot Timeout 3000ms");
|
||||
Serial.println("OneShot Timeout 3000ms");
|
||||
|
||||
oneShotMs timeout(3000);
|
||||
before = millis();
|
||||
while(!timeout.expired())
|
||||
yield();
|
||||
after = millis();
|
||||
oneShotMs timeout(3000);
|
||||
before = millis();
|
||||
while (!timeout.expired())
|
||||
yield();
|
||||
after = millis();
|
||||
|
||||
delta = after - before;
|
||||
Serial.printf("delta = %lu\n", delta);
|
||||
delta = after - before;
|
||||
Serial.printf("delta = %lu\n", delta);
|
||||
|
||||
REQUIRE(fuzzycomp(delta, (timeType)3000));
|
||||
REQUIRE(fuzzycomp(delta, (timeType)3000));
|
||||
|
||||
Serial.print("reset\n");
|
||||
|
||||
Serial.print("reset\n");
|
||||
timeout.reset();
|
||||
before = millis();
|
||||
while (!timeout)
|
||||
yield();
|
||||
after = millis();
|
||||
|
||||
timeout.reset();
|
||||
before = millis();
|
||||
while(!timeout)
|
||||
yield();
|
||||
after = millis();
|
||||
delta = after - before;
|
||||
Serial.printf("delta = %lu\n", delta);
|
||||
|
||||
delta = after - before;
|
||||
Serial.printf("delta = %lu\n", delta);
|
||||
|
||||
REQUIRE(fuzzycomp(delta, (timeType)3000));
|
||||
REQUIRE(fuzzycomp(delta, (timeType)3000));
|
||||
}
|
||||
|
||||
TEST_CASE("OneShot Timeout 3000ms reset to 1000ms", "[polledTimeout]")
|
||||
{
|
||||
using esp8266::polledTimeout::oneShotMs;
|
||||
using timeType = oneShotMs::timeType;
|
||||
timeType before, after, delta;
|
||||
using esp8266::polledTimeout::oneShotMs;
|
||||
using timeType = oneShotMs::timeType;
|
||||
timeType before, after, delta;
|
||||
|
||||
Serial.println("OneShot Timeout 3000ms");
|
||||
Serial.println("OneShot Timeout 3000ms");
|
||||
|
||||
oneShotMs timeout(3000);
|
||||
before = millis();
|
||||
while(!timeout.expired())
|
||||
yield();
|
||||
after = millis();
|
||||
oneShotMs timeout(3000);
|
||||
before = millis();
|
||||
while (!timeout.expired())
|
||||
yield();
|
||||
after = millis();
|
||||
|
||||
delta = after - before;
|
||||
Serial.printf("delta = %lu\n", delta);
|
||||
delta = after - before;
|
||||
Serial.printf("delta = %lu\n", delta);
|
||||
|
||||
REQUIRE(fuzzycomp(delta, (timeType)3000));
|
||||
REQUIRE(fuzzycomp(delta, (timeType)3000));
|
||||
|
||||
Serial.print("reset\n");
|
||||
|
||||
Serial.print("reset\n");
|
||||
timeout.reset(1000);
|
||||
before = millis();
|
||||
while (!timeout)
|
||||
yield();
|
||||
after = millis();
|
||||
|
||||
timeout.reset(1000);
|
||||
before = millis();
|
||||
while(!timeout)
|
||||
yield();
|
||||
after = millis();
|
||||
delta = after - before;
|
||||
Serial.printf("delta = %lu\n", delta);
|
||||
|
||||
delta = after - before;
|
||||
Serial.printf("delta = %lu\n", delta);
|
||||
|
||||
REQUIRE(fuzzycomp(delta, (timeType)1000));
|
||||
REQUIRE(fuzzycomp(delta, (timeType)1000));
|
||||
}
|
||||
|
||||
TEST_CASE("Periodic Timeout 1T 3000ms", "[polledTimeout]")
|
||||
{
|
||||
using esp8266::polledTimeout::periodicMs;
|
||||
using timeType = periodicMs::timeType;
|
||||
timeType before, after, delta;
|
||||
using esp8266::polledTimeout::periodicMs;
|
||||
using timeType = periodicMs::timeType;
|
||||
timeType before, after, delta;
|
||||
|
||||
Serial.println("Periodic Timeout 1T 3000ms");
|
||||
Serial.println("Periodic Timeout 1T 3000ms");
|
||||
|
||||
periodicMs timeout(3000);
|
||||
before = millis();
|
||||
while(!timeout)
|
||||
yield();
|
||||
after = millis();
|
||||
periodicMs timeout(3000);
|
||||
before = millis();
|
||||
while (!timeout)
|
||||
yield();
|
||||
after = millis();
|
||||
|
||||
delta = after - before;
|
||||
Serial.printf("delta = %lu\n", delta);
|
||||
delta = after - before;
|
||||
Serial.printf("delta = %lu\n", delta);
|
||||
|
||||
REQUIRE(fuzzycomp(delta, (timeType)3000));
|
||||
REQUIRE(fuzzycomp(delta, (timeType)3000));
|
||||
|
||||
Serial.print("no reset needed\n");
|
||||
Serial.print("no reset needed\n");
|
||||
|
||||
before = millis();
|
||||
while(!timeout)
|
||||
yield();
|
||||
after = millis();
|
||||
before = millis();
|
||||
while (!timeout)
|
||||
yield();
|
||||
after = millis();
|
||||
|
||||
delta = after - before;
|
||||
Serial.printf("delta = %lu\n", delta);
|
||||
delta = after - before;
|
||||
Serial.printf("delta = %lu\n", delta);
|
||||
|
||||
REQUIRE(fuzzycomp(delta, (timeType)3000));
|
||||
REQUIRE(fuzzycomp(delta, (timeType)3000));
|
||||
}
|
||||
|
||||
TEST_CASE("Periodic Timeout 10T 1000ms", "[polledTimeout]")
|
||||
{
|
||||
using esp8266::polledTimeout::periodicMs;
|
||||
using timeType = periodicMs::timeType;
|
||||
timeType before, after, delta;
|
||||
using esp8266::polledTimeout::periodicMs;
|
||||
using timeType = periodicMs::timeType;
|
||||
timeType before, after, delta;
|
||||
|
||||
Serial.println("Periodic 10T Timeout 1000ms");
|
||||
Serial.println("Periodic 10T Timeout 1000ms");
|
||||
|
||||
int counter = 10;
|
||||
int counter = 10;
|
||||
|
||||
periodicMs timeout(1000);
|
||||
before = millis();
|
||||
while(1)
|
||||
{
|
||||
if(timeout)
|
||||
periodicMs timeout(1000);
|
||||
before = millis();
|
||||
while (1)
|
||||
{
|
||||
Serial.print("*");
|
||||
if(!--counter)
|
||||
break;
|
||||
yield();
|
||||
if (timeout)
|
||||
{
|
||||
Serial.print("*");
|
||||
if (!--counter)
|
||||
break;
|
||||
yield();
|
||||
}
|
||||
}
|
||||
}
|
||||
after = millis();
|
||||
after = millis();
|
||||
|
||||
delta = after - before;
|
||||
Serial.printf("\ndelta = %lu\n", delta);
|
||||
REQUIRE(fuzzycomp(delta, (timeType)10000));
|
||||
delta = after - before;
|
||||
Serial.printf("\ndelta = %lu\n", delta);
|
||||
REQUIRE(fuzzycomp(delta, (timeType)10000));
|
||||
}
|
||||
|
||||
TEST_CASE("OneShot Timeout 3000ms reset to 1000ms custom yield", "[polledTimeout]")
|
||||
{
|
||||
using YieldOrSkipPolicy = esp8266::polledTimeout::YieldPolicy::YieldOrSkip;
|
||||
using oneShotMsYield = esp8266::polledTimeout::timeoutTemplate<false, YieldOrSkipPolicy>;
|
||||
using timeType = oneShotMsYield::timeType;
|
||||
timeType before, after, delta;
|
||||
using YieldOrSkipPolicy = esp8266::polledTimeout::YieldPolicy::YieldOrSkip;
|
||||
using oneShotMsYield = esp8266::polledTimeout::timeoutTemplate<false, YieldOrSkipPolicy>;
|
||||
using timeType = oneShotMsYield::timeType;
|
||||
timeType before, after, delta;
|
||||
|
||||
Serial.println("OneShot Timeout 3000ms");
|
||||
Serial.println("OneShot Timeout 3000ms");
|
||||
|
||||
oneShotMsYield timeout(3000);
|
||||
before = millis();
|
||||
while (!timeout.expired())
|
||||
;
|
||||
after = millis();
|
||||
|
||||
oneShotMsYield timeout(3000);
|
||||
before = millis();
|
||||
while(!timeout.expired());
|
||||
after = millis();
|
||||
delta = after - before;
|
||||
Serial.printf("delta = %lu\n", delta);
|
||||
|
||||
delta = after - before;
|
||||
Serial.printf("delta = %lu\n", delta);
|
||||
REQUIRE(fuzzycomp(delta, (timeType)3000));
|
||||
|
||||
REQUIRE(fuzzycomp(delta, (timeType)3000));
|
||||
Serial.print("reset\n");
|
||||
|
||||
timeout.reset(1000);
|
||||
before = millis();
|
||||
while (!timeout)
|
||||
;
|
||||
after = millis();
|
||||
|
||||
Serial.print("reset\n");
|
||||
delta = after - before;
|
||||
Serial.printf("delta = %lu\n", delta);
|
||||
|
||||
timeout.reset(1000);
|
||||
before = millis();
|
||||
while(!timeout);
|
||||
after = millis();
|
||||
|
||||
delta = after - before;
|
||||
Serial.printf("delta = %lu\n", delta);
|
||||
|
||||
REQUIRE(fuzzycomp(delta, (timeType)1000));
|
||||
REQUIRE(fuzzycomp(delta, (timeType)1000));
|
||||
}
|
||||
|
||||
|
@ -27,19 +27,19 @@ TEST_CASE("Print::write overrides all compile properly", "[core][Print]")
|
||||
REQUIRE(LittleFS.begin());
|
||||
auto p = LittleFS.open("test.bin", "w");
|
||||
REQUIRE(p);
|
||||
uint8_t uint8 = 1;
|
||||
uint16_t uint16 = 2;
|
||||
uint32_t uint32 = 3;
|
||||
size_t size = 4;
|
||||
int8_t int8 = 1;
|
||||
int16_t int16 = 2;
|
||||
int32_t int32 = 3;
|
||||
char c = 'h';
|
||||
int i = 10;
|
||||
long l = 11;
|
||||
unsigned char uc = 20;
|
||||
unsigned int ui = 21;
|
||||
unsigned long ul = 22;
|
||||
uint8_t uint8 = 1;
|
||||
uint16_t uint16 = 2;
|
||||
uint32_t uint32 = 3;
|
||||
size_t size = 4;
|
||||
int8_t int8 = 1;
|
||||
int16_t int16 = 2;
|
||||
int32_t int32 = 3;
|
||||
char c = 'h';
|
||||
int i = 10;
|
||||
long l = 11;
|
||||
unsigned char uc = 20;
|
||||
unsigned int ui = 21;
|
||||
unsigned long ul = 22;
|
||||
p.write(uint8);
|
||||
p.write(uint16);
|
||||
p.write(uint32);
|
||||
@ -60,7 +60,7 @@ TEST_CASE("Print::write overrides all compile properly", "[core][Print]")
|
||||
p = LittleFS.open("test.bin", "r");
|
||||
REQUIRE(p);
|
||||
uint8_t buff[16];
|
||||
int len = p.read(buff, 16);
|
||||
int len = p.read(buff, 16);
|
||||
p.close();
|
||||
REQUIRE(len == 15);
|
||||
REQUIRE(buff[0] == 1);
|
||||
|
@ -16,12 +16,11 @@
|
||||
#include <catch.hpp>
|
||||
#include <Updater.h>
|
||||
|
||||
|
||||
// Use a SPIFFS file because we can't instantiate a virtual class like Print
|
||||
TEST_CASE("Updater fails when writes overflow requested size", "[core][Updater]")
|
||||
{
|
||||
UpdaterClass *u;
|
||||
uint8_t buff[6000];
|
||||
UpdaterClass* u;
|
||||
uint8_t buff[6000];
|
||||
memset(buff, 0, sizeof(buff));
|
||||
u = new UpdaterClass();
|
||||
REQUIRE(u->begin(6000));
|
||||
|
@ -32,30 +32,35 @@ TEST_CASE("MD5Builder::add works as expected", "[core][MD5Builder]")
|
||||
REQUIRE(builder.toString() == "9edb67f2b22c604fab13e2fd1d6056d7");
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("MD5Builder::addHexString works as expected", "[core][MD5Builder]")
|
||||
{
|
||||
WHEN("A char array is parsed"){
|
||||
MD5Builder builder;
|
||||
builder.begin();
|
||||
const char * myPayload = "1234567890abcdeffedcba98765432106469676974616c7369676e61747572656170706c69636174696F6e73";
|
||||
builder.addHexString(myPayload);
|
||||
builder.calculate();
|
||||
REQUIRE(builder.toString() == "47b937a6f9f12a4c389fa5854e023efb");
|
||||
WHEN("A char array is parsed")
|
||||
{
|
||||
MD5Builder builder;
|
||||
builder.begin();
|
||||
const char* myPayload = "1234567890abcdeffedcba98765432106469676974616c7369676e617475726561"
|
||||
"70706c69636174696F6e73";
|
||||
builder.addHexString(myPayload);
|
||||
builder.calculate();
|
||||
REQUIRE(builder.toString() == "47b937a6f9f12a4c389fa5854e023efb");
|
||||
}
|
||||
|
||||
WHEN("A Arduino String is parsed"){
|
||||
MD5Builder builder;
|
||||
builder.begin();
|
||||
builder.addHexString(String("1234567890abcdeffedcba98765432106469676974616c7369676e61747572656170706c69636174696f6e73"));
|
||||
builder.calculate();
|
||||
REQUIRE(builder.toString() == "47b937a6f9f12a4c389fa5854e023efb");
|
||||
WHEN("A Arduino String is parsed")
|
||||
{
|
||||
MD5Builder builder;
|
||||
builder.begin();
|
||||
builder.addHexString(String("1234567890abcdeffedcba98765432106469676974616c7369676e61747572"
|
||||
"656170706c69636174696f6e73"));
|
||||
builder.calculate();
|
||||
REQUIRE(builder.toString() == "47b937a6f9f12a4c389fa5854e023efb");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("MD5Builder::addStream works", "[core][MD5Builder]"){
|
||||
MD5Builder builder;
|
||||
const char* str = "MD5Builder::addStream_works_longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong";
|
||||
TEST_CASE("MD5Builder::addStream works", "[core][MD5Builder]")
|
||||
{
|
||||
MD5Builder builder;
|
||||
const char* str = "MD5Builder::addStream_works_"
|
||||
"longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong";
|
||||
{
|
||||
StreamString stream;
|
||||
stream.print(str);
|
||||
|
@ -19,15 +19,16 @@
|
||||
|
||||
TEST_CASE("strstr_P works as strstr", "[core][pgmspace]")
|
||||
{
|
||||
auto t = [](const char* h, const char* n) {
|
||||
auto t = [](const char* h, const char* n)
|
||||
{
|
||||
const char* strstr_P_result = strstr_P(h, n);
|
||||
const char* strstr_result = strstr(h, n);
|
||||
const char* strstr_result = strstr(h, n);
|
||||
REQUIRE(strstr_P_result == strstr_result);
|
||||
};
|
||||
|
||||
// Test case data is from avr-libc, original copyright (c) 2007 Dmitry Xmelkov
|
||||
// See avr-libc/tests/simulate/pmstring/strstr_P.c
|
||||
t ("", "");
|
||||
t("", "");
|
||||
t("12345", "");
|
||||
t("ababac", "abac");
|
||||
t("", "a");
|
||||
|
@ -43,8 +43,8 @@ TEST_CASE("String::trim", "[core][String]")
|
||||
TEST_CASE("String::replace", "[core][String]")
|
||||
{
|
||||
String str;
|
||||
str = "The quick brown fox jumped over the lazy dog.";
|
||||
String find = "fox";
|
||||
str = "The quick brown fox jumped over the lazy dog.";
|
||||
String find = "fox";
|
||||
String replace = "vulpes vulpes";
|
||||
str.replace(find, replace);
|
||||
REQUIRE(str == "The quick brown vulpes vulpes jumped over the lazy dog.");
|
||||
@ -52,10 +52,10 @@ TEST_CASE("String::replace", "[core][String]")
|
||||
|
||||
TEST_CASE("String(value, base)", "[core][String]")
|
||||
{
|
||||
String strbase2(9999,2);
|
||||
String strbase8(9999,8);
|
||||
String strbase10(9999,10);
|
||||
String strbase16(9999,16);
|
||||
String strbase2(9999, 2);
|
||||
String strbase8(9999, 8);
|
||||
String strbase10(9999, 10);
|
||||
String strbase16(9999, 16);
|
||||
REQUIRE(strbase2 == "10011100001111");
|
||||
REQUIRE(strbase8 == "23417");
|
||||
REQUIRE(strbase10 == "9999");
|
||||
@ -64,7 +64,7 @@ TEST_CASE("String(value, base)", "[core][String]")
|
||||
String strnegf(-2.123, 3);
|
||||
REQUIRE(strnegi == "-9999");
|
||||
REQUIRE(strnegf == "-2.123");
|
||||
String strbase16l((long)999999,16);
|
||||
String strbase16l((long)999999, 16);
|
||||
REQUIRE(strbase16l == "f423f");
|
||||
}
|
||||
|
||||
@ -83,8 +83,8 @@ TEST_CASE("String constructors", "[core][String]")
|
||||
String s1("abcd");
|
||||
String s2(s1);
|
||||
REQUIRE(s1 == s2);
|
||||
String *s3 = new String("manos");
|
||||
s2 = *s3;
|
||||
String* s3 = new String("manos");
|
||||
s2 = *s3;
|
||||
delete s3;
|
||||
REQUIRE(s2 == "manos");
|
||||
s3 = new String("thisismuchlongerthantheother");
|
||||
@ -97,8 +97,8 @@ TEST_CASE("String constructors", "[core][String]")
|
||||
REQUIRE(ssh == "3.14159_abcd");
|
||||
String flash = (F("hello from flash"));
|
||||
REQUIRE(flash == "hello from flash");
|
||||
const char textarray[6] = {'h', 'e', 'l', 'l', 'o', 0};
|
||||
String hello(textarray);
|
||||
const char textarray[6] = { 'h', 'e', 'l', 'l', 'o', 0 };
|
||||
String hello(textarray);
|
||||
REQUIRE(hello == "hello");
|
||||
String hello2;
|
||||
hello2 = textarray;
|
||||
@ -135,13 +135,21 @@ TEST_CASE("String concantenation", "[core][String]")
|
||||
str += LLONG_MIN;
|
||||
REQUIRE(str == "abcdeabcde9872147483647-2147483648691969-123321-1.011.01-9223372036854775808");
|
||||
str += String(LLONG_MIN, 10);
|
||||
REQUIRE(str == "abcdeabcde9872147483647-2147483648691969-123321-1.011.01-9223372036854775808-9223372036854775808");
|
||||
REQUIRE(str
|
||||
== "abcdeabcde9872147483647-2147483648691969-123321-1.011.01-9223372036854775808-"
|
||||
"9223372036854775808");
|
||||
str += LLONG_MAX;
|
||||
REQUIRE(str == "abcdeabcde9872147483647-2147483648691969-123321-1.011.01-9223372036854775808-92233720368547758089223372036854775807");
|
||||
REQUIRE(str
|
||||
== "abcdeabcde9872147483647-2147483648691969-123321-1.011.01-9223372036854775808-"
|
||||
"92233720368547758089223372036854775807");
|
||||
str += ULLONG_MAX;
|
||||
REQUIRE(str == "abcdeabcde9872147483647-2147483648691969-123321-1.011.01-9223372036854775808-9223372036854775808922337203685477580718446744073709551615");
|
||||
REQUIRE(str
|
||||
== "abcdeabcde9872147483647-2147483648691969-123321-1.011.01-9223372036854775808-"
|
||||
"9223372036854775808922337203685477580718446744073709551615");
|
||||
str += String(ULLONG_MAX, 16);
|
||||
REQUIRE(str == "abcdeabcde9872147483647-2147483648691969-123321-1.011.01-9223372036854775808-9223372036854775808922337203685477580718446744073709551615ffffffffffffffff");
|
||||
REQUIRE(str
|
||||
== "abcdeabcde9872147483647-2147483648691969-123321-1.011.01-9223372036854775808-"
|
||||
"9223372036854775808922337203685477580718446744073709551615ffffffffffffffff");
|
||||
str = "clean";
|
||||
REQUIRE(str.concat(str) == true);
|
||||
REQUIRE(str == "cleanclean");
|
||||
@ -156,19 +164,19 @@ TEST_CASE("String concantenation", "[core][String]")
|
||||
REQUIRE(str == "-100");
|
||||
// Non-zero-terminated array concatenation
|
||||
const char buff[] = "abcdefg";
|
||||
String n;
|
||||
n = "1234567890"; // Make it a SSO string, fill with non-0 data
|
||||
n = "1"; // Overwrite [1] with 0, but leave old junk in SSO space still
|
||||
String n;
|
||||
n = "1234567890"; // Make it a SSO string, fill with non-0 data
|
||||
n = "1"; // Overwrite [1] with 0, but leave old junk in SSO space still
|
||||
n.concat(buff, 3);
|
||||
REQUIRE(n == "1abc"); // Ensure the trailing 0 is always present even w/this funky concat
|
||||
for (int i=0; i<20; i++)
|
||||
n.concat(buff, 1); // Add 20 'a's to go from SSO to normal string
|
||||
REQUIRE(n == "1abc"); // Ensure the trailing 0 is always present even w/this funky concat
|
||||
for (int i = 0; i < 20; i++)
|
||||
n.concat(buff, 1); // Add 20 'a's to go from SSO to normal string
|
||||
REQUIRE(n == "1abcaaaaaaaaaaaaaaaaaaaa");
|
||||
n = "";
|
||||
for (int i=0; i<=5; i++)
|
||||
for (int i = 0; i <= 5; i++)
|
||||
n.concat(buff, i);
|
||||
REQUIRE(n == "aababcabcdabcde");
|
||||
n.concat(buff, 0); // And check no add'n
|
||||
n.concat(buff, 0); // And check no add'n
|
||||
REQUIRE(n == "aababcabcdabcde");
|
||||
}
|
||||
|
||||
@ -211,7 +219,7 @@ TEST_CASE("String byte access", "[core][String]")
|
||||
TEST_CASE("String conversion", "[core][String]")
|
||||
{
|
||||
String s = "12345";
|
||||
long l = s.toInt();
|
||||
long l = s.toInt();
|
||||
REQUIRE(l == 12345);
|
||||
s = "2147483647";
|
||||
l = s.toInt();
|
||||
@ -222,9 +230,9 @@ TEST_CASE("String conversion", "[core][String]")
|
||||
s = "-2147483648";
|
||||
l = s.toInt();
|
||||
REQUIRE(l == INT_MIN);
|
||||
s = "3.14159";
|
||||
s = "3.14159";
|
||||
float f = s.toFloat();
|
||||
REQUIRE( fabs(f - 3.14159) < 0.0001 );
|
||||
REQUIRE(fabs(f - 3.14159) < 0.0001);
|
||||
}
|
||||
|
||||
TEST_CASE("String case", "[core][String]")
|
||||
@ -246,7 +254,7 @@ TEST_CASE("String nulls", "[core][String]")
|
||||
s.trim();
|
||||
s.toUpperCase();
|
||||
s.toLowerCase();
|
||||
s.remove(1,1);
|
||||
s.remove(1, 1);
|
||||
s.remove(10);
|
||||
s.replace("taco", "burrito");
|
||||
s.replace('a', 'b');
|
||||
@ -268,7 +276,7 @@ TEST_CASE("String nulls", "[core][String]")
|
||||
REQUIRE(s == "");
|
||||
REQUIRE(s.length() == 0);
|
||||
s.setCharAt(1, 't');
|
||||
REQUIRE(s.startsWith("abc",0) == false);
|
||||
REQUIRE(s.startsWith("abc", 0) == false);
|
||||
REQUIRE(s.startsWith("def") == false);
|
||||
REQUIRE(s.equalsConstantTime("def") == false);
|
||||
REQUIRE(s.equalsConstantTime("") == true);
|
||||
@ -299,125 +307,128 @@ TEST_CASE("String sizes near 8b", "[core][String]")
|
||||
String s15("12345678901234");
|
||||
String s16("123456789012345");
|
||||
String s17("1234567890123456");
|
||||
REQUIRE(!strcmp(s7.c_str(),"123456"));
|
||||
REQUIRE(!strcmp(s8.c_str(),"1234567"));
|
||||
REQUIRE(!strcmp(s9.c_str(),"12345678"));
|
||||
REQUIRE(!strcmp(s15.c_str(),"12345678901234"));
|
||||
REQUIRE(!strcmp(s16.c_str(),"123456789012345"));
|
||||
REQUIRE(!strcmp(s17.c_str(),"1234567890123456"));
|
||||
REQUIRE(!strcmp(s7.c_str(), "123456"));
|
||||
REQUIRE(!strcmp(s8.c_str(), "1234567"));
|
||||
REQUIRE(!strcmp(s9.c_str(), "12345678"));
|
||||
REQUIRE(!strcmp(s15.c_str(), "12345678901234"));
|
||||
REQUIRE(!strcmp(s16.c_str(), "123456789012345"));
|
||||
REQUIRE(!strcmp(s17.c_str(), "1234567890123456"));
|
||||
s7 += '_';
|
||||
s8 += '_';
|
||||
s9 += '_';
|
||||
s15 += '_';
|
||||
s16 += '_';
|
||||
s17 += '_';
|
||||
REQUIRE(!strcmp(s7.c_str(),"123456_"));
|
||||
REQUIRE(!strcmp(s8.c_str(),"1234567_"));
|
||||
REQUIRE(!strcmp(s9.c_str(),"12345678_"));
|
||||
REQUIRE(!strcmp(s15.c_str(),"12345678901234_"));
|
||||
REQUIRE(!strcmp(s16.c_str(),"123456789012345_"));
|
||||
REQUIRE(!strcmp(s17.c_str(),"1234567890123456_"));
|
||||
REQUIRE(!strcmp(s7.c_str(), "123456_"));
|
||||
REQUIRE(!strcmp(s8.c_str(), "1234567_"));
|
||||
REQUIRE(!strcmp(s9.c_str(), "12345678_"));
|
||||
REQUIRE(!strcmp(s15.c_str(), "12345678901234_"));
|
||||
REQUIRE(!strcmp(s16.c_str(), "123456789012345_"));
|
||||
REQUIRE(!strcmp(s17.c_str(), "1234567890123456_"));
|
||||
}
|
||||
|
||||
TEST_CASE("String SSO works", "[core][String]")
|
||||
{
|
||||
// This test assumes that SSO_SIZE==8, if that changes the test must as well
|
||||
String s;
|
||||
s += "0";
|
||||
REQUIRE(s == "0");
|
||||
REQUIRE(s.length() == 1);
|
||||
const char *savesso = s.c_str();
|
||||
s += 1;
|
||||
REQUIRE(s.c_str() == savesso);
|
||||
REQUIRE(s == "01");
|
||||
REQUIRE(s.length() == 2);
|
||||
s += "2";
|
||||
REQUIRE(s.c_str() == savesso);
|
||||
REQUIRE(s == "012");
|
||||
REQUIRE(s.length() == 3);
|
||||
s += 3;
|
||||
REQUIRE(s.c_str() == savesso);
|
||||
REQUIRE(s == "0123");
|
||||
REQUIRE(s.length() == 4);
|
||||
s += "4";
|
||||
REQUIRE(s.c_str() == savesso);
|
||||
REQUIRE(s == "01234");
|
||||
REQUIRE(s.length() == 5);
|
||||
s += "5";
|
||||
REQUIRE(s.c_str() == savesso);
|
||||
REQUIRE(s == "012345");
|
||||
REQUIRE(s.length() == 6);
|
||||
s += "6";
|
||||
REQUIRE(s.c_str() == savesso);
|
||||
REQUIRE(s == "0123456");
|
||||
REQUIRE(s.length() == 7);
|
||||
s += "7";
|
||||
REQUIRE(s.c_str() == savesso);
|
||||
REQUIRE(s == "01234567");
|
||||
REQUIRE(s.length() == 8);
|
||||
s += "8";
|
||||
REQUIRE(s.c_str() == savesso);
|
||||
REQUIRE(s == "012345678");
|
||||
REQUIRE(s.length() == 9);
|
||||
s += "9";
|
||||
REQUIRE(s.c_str() == savesso);
|
||||
REQUIRE(s == "0123456789");
|
||||
REQUIRE(s.length() == 10);
|
||||
if (sizeof(savesso) == 4) {
|
||||
s += "a";
|
||||
REQUIRE(s.c_str() != savesso);
|
||||
REQUIRE(s == "0123456789a");
|
||||
REQUIRE(s.length() == 11);
|
||||
s += "b";
|
||||
REQUIRE(s.c_str() != savesso);
|
||||
REQUIRE(s == "0123456789ab");
|
||||
REQUIRE(s.length() == 12);
|
||||
s += "c";
|
||||
REQUIRE(s.c_str() != savesso);
|
||||
REQUIRE(s == "0123456789abc");
|
||||
REQUIRE(s.length() == 13);
|
||||
} else {
|
||||
s += "a";
|
||||
// This test assumes that SSO_SIZE==8, if that changes the test must as well
|
||||
String s;
|
||||
s += "0";
|
||||
REQUIRE(s == "0");
|
||||
REQUIRE(s.length() == 1);
|
||||
const char* savesso = s.c_str();
|
||||
s += 1;
|
||||
REQUIRE(s.c_str() == savesso);
|
||||
REQUIRE(s == "0123456789a");
|
||||
REQUIRE(s.length() == 11);
|
||||
s += "bcde";
|
||||
REQUIRE(s == "01");
|
||||
REQUIRE(s.length() == 2);
|
||||
s += "2";
|
||||
REQUIRE(s.c_str() == savesso);
|
||||
REQUIRE(s == "0123456789abcde");
|
||||
REQUIRE(s.length() == 15);
|
||||
s += "fghi";
|
||||
REQUIRE(s.c_str() != savesso);
|
||||
REQUIRE(s == "0123456789abcdefghi");
|
||||
REQUIRE(s.length() == 19);
|
||||
s += "j";
|
||||
REQUIRE(s.c_str() != savesso);
|
||||
REQUIRE(s == "0123456789abcdefghij");
|
||||
REQUIRE(s.length() == 20);
|
||||
s += "k";
|
||||
REQUIRE(s.c_str() != savesso);
|
||||
REQUIRE(s == "0123456789abcdefghijk");
|
||||
REQUIRE(s.length() == 21);
|
||||
s += "l";
|
||||
REQUIRE(s.c_str() != savesso);
|
||||
REQUIRE(s == "0123456789abcdefghijkl");
|
||||
REQUIRE(s.length() == 22);
|
||||
s += "m";
|
||||
REQUIRE(s.c_str() != savesso);
|
||||
REQUIRE(s == "0123456789abcdefghijklm");
|
||||
REQUIRE(s.length() == 23);
|
||||
s += "nopq";
|
||||
REQUIRE(s.c_str() != savesso);
|
||||
REQUIRE(s == "0123456789abcdefghijklmnopq");
|
||||
REQUIRE(s.length() == 27);
|
||||
s += "rstu";
|
||||
REQUIRE(s.c_str() != savesso);
|
||||
REQUIRE(s == "0123456789abcdefghijklmnopqrstu");
|
||||
REQUIRE(s.length() == 31);
|
||||
}
|
||||
s = "0123456789abcde";
|
||||
s = s.substring(s.indexOf('a'));
|
||||
REQUIRE(s == "abcde");
|
||||
REQUIRE(s.length() == 5);
|
||||
REQUIRE(s == "012");
|
||||
REQUIRE(s.length() == 3);
|
||||
s += 3;
|
||||
REQUIRE(s.c_str() == savesso);
|
||||
REQUIRE(s == "0123");
|
||||
REQUIRE(s.length() == 4);
|
||||
s += "4";
|
||||
REQUIRE(s.c_str() == savesso);
|
||||
REQUIRE(s == "01234");
|
||||
REQUIRE(s.length() == 5);
|
||||
s += "5";
|
||||
REQUIRE(s.c_str() == savesso);
|
||||
REQUIRE(s == "012345");
|
||||
REQUIRE(s.length() == 6);
|
||||
s += "6";
|
||||
REQUIRE(s.c_str() == savesso);
|
||||
REQUIRE(s == "0123456");
|
||||
REQUIRE(s.length() == 7);
|
||||
s += "7";
|
||||
REQUIRE(s.c_str() == savesso);
|
||||
REQUIRE(s == "01234567");
|
||||
REQUIRE(s.length() == 8);
|
||||
s += "8";
|
||||
REQUIRE(s.c_str() == savesso);
|
||||
REQUIRE(s == "012345678");
|
||||
REQUIRE(s.length() == 9);
|
||||
s += "9";
|
||||
REQUIRE(s.c_str() == savesso);
|
||||
REQUIRE(s == "0123456789");
|
||||
REQUIRE(s.length() == 10);
|
||||
if (sizeof(savesso) == 4)
|
||||
{
|
||||
s += "a";
|
||||
REQUIRE(s.c_str() != savesso);
|
||||
REQUIRE(s == "0123456789a");
|
||||
REQUIRE(s.length() == 11);
|
||||
s += "b";
|
||||
REQUIRE(s.c_str() != savesso);
|
||||
REQUIRE(s == "0123456789ab");
|
||||
REQUIRE(s.length() == 12);
|
||||
s += "c";
|
||||
REQUIRE(s.c_str() != savesso);
|
||||
REQUIRE(s == "0123456789abc");
|
||||
REQUIRE(s.length() == 13);
|
||||
}
|
||||
else
|
||||
{
|
||||
s += "a";
|
||||
REQUIRE(s.c_str() == savesso);
|
||||
REQUIRE(s == "0123456789a");
|
||||
REQUIRE(s.length() == 11);
|
||||
s += "bcde";
|
||||
REQUIRE(s.c_str() == savesso);
|
||||
REQUIRE(s == "0123456789abcde");
|
||||
REQUIRE(s.length() == 15);
|
||||
s += "fghi";
|
||||
REQUIRE(s.c_str() != savesso);
|
||||
REQUIRE(s == "0123456789abcdefghi");
|
||||
REQUIRE(s.length() == 19);
|
||||
s += "j";
|
||||
REQUIRE(s.c_str() != savesso);
|
||||
REQUIRE(s == "0123456789abcdefghij");
|
||||
REQUIRE(s.length() == 20);
|
||||
s += "k";
|
||||
REQUIRE(s.c_str() != savesso);
|
||||
REQUIRE(s == "0123456789abcdefghijk");
|
||||
REQUIRE(s.length() == 21);
|
||||
s += "l";
|
||||
REQUIRE(s.c_str() != savesso);
|
||||
REQUIRE(s == "0123456789abcdefghijkl");
|
||||
REQUIRE(s.length() == 22);
|
||||
s += "m";
|
||||
REQUIRE(s.c_str() != savesso);
|
||||
REQUIRE(s == "0123456789abcdefghijklm");
|
||||
REQUIRE(s.length() == 23);
|
||||
s += "nopq";
|
||||
REQUIRE(s.c_str() != savesso);
|
||||
REQUIRE(s == "0123456789abcdefghijklmnopq");
|
||||
REQUIRE(s.length() == 27);
|
||||
s += "rstu";
|
||||
REQUIRE(s.c_str() != savesso);
|
||||
REQUIRE(s == "0123456789abcdefghijklmnopqrstu");
|
||||
REQUIRE(s.length() == 31);
|
||||
}
|
||||
s = "0123456789abcde";
|
||||
s = s.substring(s.indexOf('a'));
|
||||
REQUIRE(s == "abcde");
|
||||
REQUIRE(s.length() == 5);
|
||||
}
|
||||
|
||||
#include <new>
|
||||
@ -426,70 +437,67 @@ void repl(const String& key, const String& val, String& s, boolean useURLencode)
|
||||
s.replace(key, val);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("String SSO handles junk in memory", "[core][String]")
|
||||
{
|
||||
// We fill the SSO space with garbage then construct an object in it and check consistency
|
||||
// This is NOT how you want to use Strings outside of this testing!
|
||||
unsigned char space[64];
|
||||
String *s = (String*)space;
|
||||
memset(space, 0xff, 64);
|
||||
new(s) String;
|
||||
REQUIRE(*s == "");
|
||||
s->~String();
|
||||
// We fill the SSO space with garbage then construct an object in it and check consistency
|
||||
// This is NOT how you want to use Strings outside of this testing!
|
||||
unsigned char space[64];
|
||||
String* s = (String*)space;
|
||||
memset(space, 0xff, 64);
|
||||
new (s) String;
|
||||
REQUIRE(*s == "");
|
||||
s->~String();
|
||||
|
||||
// Tests from #5883
|
||||
bool useURLencode = false;
|
||||
const char euro[4] = {(char)0xe2, (char)0x82, (char)0xac, 0}; // Unicode euro symbol
|
||||
const char yen[3] = {(char)0xc2, (char)0xa5, 0}; // Unicode yen symbol
|
||||
// Tests from #5883
|
||||
bool useURLencode = false;
|
||||
const char euro[4] = { (char)0xe2, (char)0x82, (char)0xac, 0 }; // Unicode euro symbol
|
||||
const char yen[3] = { (char)0xc2, (char)0xa5, 0 }; // Unicode yen symbol
|
||||
|
||||
memset(space, 0xff, 64);
|
||||
new(s) String("%ssid%");
|
||||
repl(("%ssid%"), "MikroTik", *s, useURLencode);
|
||||
REQUIRE(*s == "MikroTik");
|
||||
s->~String();
|
||||
memset(space, 0xff, 64);
|
||||
new (s) String("%ssid%");
|
||||
repl(("%ssid%"), "MikroTik", *s, useURLencode);
|
||||
REQUIRE(*s == "MikroTik");
|
||||
s->~String();
|
||||
|
||||
memset(space, 0xff, 64);
|
||||
new(s) String("{E}");
|
||||
repl(("{E}"), euro, *s, useURLencode);
|
||||
REQUIRE(*s == "€");
|
||||
s->~String();
|
||||
memset(space, 0xff, 64);
|
||||
new(s) String("€");
|
||||
repl(("€"), euro, *s, useURLencode);
|
||||
REQUIRE(*s == "€");
|
||||
s->~String();
|
||||
memset(space, 0xff, 64);
|
||||
new(s) String("{Y}");
|
||||
repl(("{Y}"), yen, *s, useURLencode);
|
||||
REQUIRE(*s == "¥");
|
||||
s->~String();
|
||||
memset(space, 0xff, 64);
|
||||
new(s) String("¥");
|
||||
repl(("¥"), yen, *s, useURLencode);
|
||||
REQUIRE(*s == "¥");
|
||||
s->~String();
|
||||
memset(space, 0xff, 64);
|
||||
new (s) String("{E}");
|
||||
repl(("{E}"), euro, *s, useURLencode);
|
||||
REQUIRE(*s == "€");
|
||||
s->~String();
|
||||
memset(space, 0xff, 64);
|
||||
new (s) String("€");
|
||||
repl(("€"), euro, *s, useURLencode);
|
||||
REQUIRE(*s == "€");
|
||||
s->~String();
|
||||
memset(space, 0xff, 64);
|
||||
new (s) String("{Y}");
|
||||
repl(("{Y}"), yen, *s, useURLencode);
|
||||
REQUIRE(*s == "¥");
|
||||
s->~String();
|
||||
memset(space, 0xff, 64);
|
||||
new (s) String("¥");
|
||||
repl(("¥"), yen, *s, useURLencode);
|
||||
REQUIRE(*s == "¥");
|
||||
s->~String();
|
||||
|
||||
memset(space, 0xff, 64);
|
||||
new(s) String("%sysname%");
|
||||
repl(("%sysname%"), "CO2_defect", *s, useURLencode);
|
||||
REQUIRE(*s == "CO2_defect");
|
||||
s->~String();
|
||||
memset(space, 0xff, 64);
|
||||
new (s) String("%sysname%");
|
||||
repl(("%sysname%"), "CO2_defect", *s, useURLencode);
|
||||
REQUIRE(*s == "CO2_defect");
|
||||
s->~String();
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("Issue #5949 - Overlapping src/dest in replace", "[core][String]")
|
||||
{
|
||||
String blah = "blah";
|
||||
blah.replace("xx", "y");
|
||||
REQUIRE(blah == "blah");
|
||||
blah.replace("x", "yy");
|
||||
REQUIRE(blah == "blah");
|
||||
blah.replace(blah, blah);
|
||||
REQUIRE(blah == "blah");
|
||||
String blah = "blah";
|
||||
blah.replace("xx", "y");
|
||||
REQUIRE(blah == "blah");
|
||||
blah.replace("x", "yy");
|
||||
REQUIRE(blah == "blah");
|
||||
blah.replace(blah, blah);
|
||||
REQUIRE(blah == "blah");
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("Issue #2736 - StreamString SSO fix", "[core][StreamString]")
|
||||
{
|
||||
StreamString s;
|
||||
@ -502,102 +510,101 @@ TEST_CASE("Issue #2736 - StreamString SSO fix", "[core][StreamString]")
|
||||
|
||||
TEST_CASE("Strings with NULs", "[core][String]")
|
||||
{
|
||||
// The following should never be done in a real app! This is only to inject 0s in the middle of a string.
|
||||
// Fits in SSO...
|
||||
String str("01234567");
|
||||
REQUIRE(str.length() == 8);
|
||||
char *ptr = (char *)str.c_str();
|
||||
ptr[3] = 0;
|
||||
String str2;
|
||||
str2 = str;
|
||||
REQUIRE(str2.length() == 8);
|
||||
// Needs a buffer pointer
|
||||
str = "0123456789012345678901234567890123456789";
|
||||
ptr = (char *)str.c_str();
|
||||
ptr[3] = 0;
|
||||
str2 = str;
|
||||
REQUIRE(str2.length() == 40);
|
||||
String str3("a");
|
||||
ptr = (char *)str3.c_str();
|
||||
*ptr = 0;
|
||||
REQUIRE(str3.length() == 1);
|
||||
str3 += str3;
|
||||
REQUIRE(str3.length() == 2);
|
||||
str3 += str3;
|
||||
REQUIRE(str3.length() == 4);
|
||||
str3 += str3;
|
||||
REQUIRE(str3.length() == 8);
|
||||
str3 += str3;
|
||||
REQUIRE(str3.length() == 16);
|
||||
str3 += str3;
|
||||
REQUIRE(str3.length() == 32);
|
||||
str3 += str3;
|
||||
REQUIRE(str3.length() == 64);
|
||||
static char zeros[64] = {0};
|
||||
const char *p = str3.c_str();
|
||||
REQUIRE(!memcmp(p, zeros, 64));
|
||||
// The following should never be done in a real app! This is only to inject 0s in the middle of
|
||||
// a string. Fits in SSO...
|
||||
String str("01234567");
|
||||
REQUIRE(str.length() == 8);
|
||||
char* ptr = (char*)str.c_str();
|
||||
ptr[3] = 0;
|
||||
String str2;
|
||||
str2 = str;
|
||||
REQUIRE(str2.length() == 8);
|
||||
// Needs a buffer pointer
|
||||
str = "0123456789012345678901234567890123456789";
|
||||
ptr = (char*)str.c_str();
|
||||
ptr[3] = 0;
|
||||
str2 = str;
|
||||
REQUIRE(str2.length() == 40);
|
||||
String str3("a");
|
||||
ptr = (char*)str3.c_str();
|
||||
*ptr = 0;
|
||||
REQUIRE(str3.length() == 1);
|
||||
str3 += str3;
|
||||
REQUIRE(str3.length() == 2);
|
||||
str3 += str3;
|
||||
REQUIRE(str3.length() == 4);
|
||||
str3 += str3;
|
||||
REQUIRE(str3.length() == 8);
|
||||
str3 += str3;
|
||||
REQUIRE(str3.length() == 16);
|
||||
str3 += str3;
|
||||
REQUIRE(str3.length() == 32);
|
||||
str3 += str3;
|
||||
REQUIRE(str3.length() == 64);
|
||||
static char zeros[64] = { 0 };
|
||||
const char* p = str3.c_str();
|
||||
REQUIRE(!memcmp(p, zeros, 64));
|
||||
}
|
||||
|
||||
TEST_CASE("Replace and string expansion", "[core][String]")
|
||||
{
|
||||
String s, l;
|
||||
// Make these large enough to span SSO and non SSO
|
||||
String whole = "#123456789012345678901234567890";
|
||||
const char *res = "abcde123456789012345678901234567890";
|
||||
for (size_t i=1; i < whole.length(); i++) {
|
||||
s = whole.substring(0, i);
|
||||
l = s;
|
||||
l.replace("#", "abcde");
|
||||
char buff[64];
|
||||
strcpy(buff, res);
|
||||
buff[5 + i-1] = 0;
|
||||
REQUIRE(!strcmp(l.c_str(), buff));
|
||||
REQUIRE(l.length() == strlen(buff));
|
||||
}
|
||||
String s, l;
|
||||
// Make these large enough to span SSO and non SSO
|
||||
String whole = "#123456789012345678901234567890";
|
||||
const char* res = "abcde123456789012345678901234567890";
|
||||
for (size_t i = 1; i < whole.length(); i++)
|
||||
{
|
||||
s = whole.substring(0, i);
|
||||
l = s;
|
||||
l.replace("#", "abcde");
|
||||
char buff[64];
|
||||
strcpy(buff, res);
|
||||
buff[5 + i - 1] = 0;
|
||||
REQUIRE(!strcmp(l.c_str(), buff));
|
||||
REQUIRE(l.length() == strlen(buff));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("String chaining", "[core][String]")
|
||||
{
|
||||
const char* chunks[] {
|
||||
"~12345",
|
||||
"67890",
|
||||
"qwertyuiopasdfghjkl",
|
||||
"zxcvbnm"
|
||||
};
|
||||
const char* chunks[] { "~12345", "67890", "qwertyuiopasdfghjkl", "zxcvbnm" };
|
||||
|
||||
String all;
|
||||
for (auto* chunk : chunks) {
|
||||
all += chunk;
|
||||
}
|
||||
String all;
|
||||
for (auto* chunk : chunks)
|
||||
{
|
||||
all += chunk;
|
||||
}
|
||||
|
||||
// make sure we can chain a combination of things to form a String
|
||||
REQUIRE((String(chunks[0]) + String(chunks[1]) + String(chunks[2]) + String(chunks[3])) == all);
|
||||
REQUIRE((chunks[0] + String(chunks[1]) + F(chunks[2]) + chunks[3]) == all);
|
||||
REQUIRE((String(chunks[0]) + F(chunks[1]) + F(chunks[2]) + String(chunks[3])) == all);
|
||||
REQUIRE(('~' + String(&chunks[0][0] + 1) + chunks[1] + String(chunks[2]) + F(chunks[3])) == all);
|
||||
REQUIRE((String(chunks[0]) + '6' + (&chunks[1][0] + 1) + String(chunks[2]) + F(chunks[3])) == all);
|
||||
// make sure we can chain a combination of things to form a String
|
||||
REQUIRE((String(chunks[0]) + String(chunks[1]) + String(chunks[2]) + String(chunks[3])) == all);
|
||||
REQUIRE((chunks[0] + String(chunks[1]) + F(chunks[2]) + chunks[3]) == all);
|
||||
REQUIRE((String(chunks[0]) + F(chunks[1]) + F(chunks[2]) + String(chunks[3])) == all);
|
||||
REQUIRE(('~' + String(&chunks[0][0] + 1) + chunks[1] + String(chunks[2]) + F(chunks[3]))
|
||||
== all);
|
||||
REQUIRE((String(chunks[0]) + '6' + (&chunks[1][0] + 1) + String(chunks[2]) + F(chunks[3]))
|
||||
== all);
|
||||
|
||||
// these are still invalid (and also cannot compile at all):
|
||||
// - `F(...)` + `F(...)`
|
||||
// - `F(...)` + `const char*`
|
||||
// - `const char*` + `F(...)`
|
||||
// we need `String()` as either rhs or lhs
|
||||
// these are still invalid (and also cannot compile at all):
|
||||
// - `F(...)` + `F(...)`
|
||||
// - `F(...)` + `const char*`
|
||||
// - `const char*` + `F(...)`
|
||||
// we need `String()` as either rhs or lhs
|
||||
|
||||
// ensure chaining reuses the buffer
|
||||
// (internal details...)
|
||||
{
|
||||
String tmp(chunks[3]);
|
||||
tmp.reserve(2 * all.length());
|
||||
auto* ptr = tmp.c_str();
|
||||
String result("~1" + String(&chunks[0][0] + 2) + F(chunks[1]) + chunks[2] + std::move(tmp));
|
||||
REQUIRE(result == all);
|
||||
REQUIRE(static_cast<const void*>(result.c_str()) == static_cast<const void*>(ptr));
|
||||
}
|
||||
// ensure chaining reuses the buffer
|
||||
// (internal details...)
|
||||
{
|
||||
String tmp(chunks[3]);
|
||||
tmp.reserve(2 * all.length());
|
||||
auto* ptr = tmp.c_str();
|
||||
String result("~1" + String(&chunks[0][0] + 2) + F(chunks[1]) + chunks[2] + std::move(tmp));
|
||||
REQUIRE(result == all);
|
||||
REQUIRE(static_cast<const void*>(result.c_str()) == static_cast<const void*>(ptr));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("String concat OOB #8198", "[core][String]")
|
||||
{
|
||||
char *p = (char*)malloc(16);
|
||||
char* p = (char*)malloc(16);
|
||||
memset(p, 'x', 16);
|
||||
String s = "abcd";
|
||||
s.concat(p, 16);
|
||||
|
@ -24,8 +24,8 @@
|
||||
#include "../../../libraries/SDFS/src/SDFS.h"
|
||||
#include "../../../libraries/SD/src/SD.h"
|
||||
|
||||
|
||||
namespace spiffs_test {
|
||||
namespace spiffs_test
|
||||
{
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
|
||||
@ -47,9 +47,9 @@ namespace spiffs_test {
|
||||
TEST_CASE("SPIFFS checks the config object passed in", "[fs]")
|
||||
{
|
||||
SPIFFS_MOCK_DECLARE(64, 8, 512, "");
|
||||
FSConfig f;
|
||||
SPIFFSConfig s;
|
||||
SDFSConfig d;
|
||||
FSConfig f;
|
||||
SPIFFSConfig s;
|
||||
SDFSConfig d;
|
||||
LittleFSConfig l;
|
||||
|
||||
REQUIRE_FALSE(SPIFFS.setConfig(f));
|
||||
@ -59,14 +59,15 @@ TEST_CASE("SPIFFS checks the config object passed in", "[fs]")
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
};
|
||||
}; // namespace spiffs_test
|
||||
|
||||
|
||||
namespace littlefs_test {
|
||||
namespace littlefs_test
|
||||
{
|
||||
#define FSTYPE LittleFS
|
||||
#define TESTPRE "LittleFS - "
|
||||
#define TESTPAT "[lfs]"
|
||||
// LittleFS routines strip leading slashes before doing anything, so up to 31 char names are allowable
|
||||
// LittleFS routines strip leading slashes before doing anything, so up to 31 char names are
|
||||
// allowable
|
||||
#define TOOLONGFILENAME "/12345678901234567890123456789012"
|
||||
#define FS_MOCK_DECLARE LITTLEFS_MOCK_DECLARE
|
||||
#define FS_MOCK_RESET LITTLEFS_MOCK_RESET
|
||||
@ -82,9 +83,9 @@ namespace littlefs_test {
|
||||
TEST_CASE("LittleFS checks the config object passed in", "[fs]")
|
||||
{
|
||||
LITTLEFS_MOCK_DECLARE(64, 8, 512, "");
|
||||
FSConfig f;
|
||||
SPIFFSConfig s;
|
||||
SDFSConfig d;
|
||||
FSConfig f;
|
||||
SPIFFSConfig s;
|
||||
SDFSConfig d;
|
||||
LittleFSConfig l;
|
||||
|
||||
REQUIRE_FALSE(LittleFS.setConfig(f));
|
||||
@ -93,17 +94,21 @@ TEST_CASE("LittleFS checks the config object passed in", "[fs]")
|
||||
REQUIRE(LittleFS.setConfig(l));
|
||||
}
|
||||
|
||||
};
|
||||
}; // namespace littlefs_test
|
||||
|
||||
namespace sdfs_test {
|
||||
namespace sdfs_test
|
||||
{
|
||||
#define FSTYPE SDFS
|
||||
#define TESTPRE "SDFS - "
|
||||
#define TESTPAT "[sdfs]"
|
||||
// SDFS supports long paths (MAXPATH)
|
||||
#define TOOLONGFILENAME "/" \
|
||||
"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" \
|
||||
"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" \
|
||||
"12345678901234567890123456789012345678901234567890123456"
|
||||
#define TOOLONGFILENAME \
|
||||
"/" \
|
||||
"12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012" \
|
||||
"34567890" \
|
||||
"12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012" \
|
||||
"34567890" \
|
||||
"12345678901234567890123456789012345678901234567890123456"
|
||||
#define FS_MOCK_DECLARE SDFS_MOCK_DECLARE
|
||||
#define FS_MOCK_RESET SDFS_MOCK_RESET
|
||||
#define FS_HAS_DIRS
|
||||
@ -118,9 +123,9 @@ namespace sdfs_test {
|
||||
TEST_CASE("SDFS checks the config object passed in", "[fs]")
|
||||
{
|
||||
SDFS_MOCK_DECLARE(64, 8, 512, "");
|
||||
FSConfig f;
|
||||
SPIFFSConfig s;
|
||||
SDFSConfig d;
|
||||
FSConfig f;
|
||||
SPIFFSConfig s;
|
||||
SDFSConfig d;
|
||||
LittleFSConfig l;
|
||||
|
||||
REQUIRE_FALSE(SDFS.setConfig(f));
|
||||
@ -142,7 +147,7 @@ TEST_CASE("SD.h FILE_WRITE macro is append", "[fs]")
|
||||
f.write(65);
|
||||
f.write("bbcc");
|
||||
f.write("theend", 6);
|
||||
char block[3]={'x','y','z'};
|
||||
char block[3] = { 'x', 'y', 'z' };
|
||||
f.write(block, 3);
|
||||
uint32_t bigone = 0x40404040;
|
||||
f.write((const uint8_t*)&bigone, 4);
|
||||
@ -155,11 +160,11 @@ TEST_CASE("SD.h FILE_WRITE macro is append", "[fs]")
|
||||
File g = SD.open("/file2.txt", FILE_WRITE);
|
||||
g.write(0);
|
||||
g.close();
|
||||
g = SD.open("/file2.txt", FILE_READ);
|
||||
g = SD.open("/file2.txt", FILE_READ);
|
||||
uint8_t u = 0x66;
|
||||
g.read(&u, 1);
|
||||
g.close();
|
||||
REQUIRE(u == 0);
|
||||
}
|
||||
|
||||
};
|
||||
}; // namespace sdfs_test
|
||||
|
@ -15,11 +15,11 @@
|
||||
#endif
|
||||
|
||||
#ifndef PGM_P
|
||||
#define PGM_P const char *
|
||||
#define PGM_P const char*
|
||||
#endif
|
||||
|
||||
#ifndef PGM_VOID_P
|
||||
#define PGM_VOID_P const void *
|
||||
#define PGM_VOID_P const void*
|
||||
#endif
|
||||
|
||||
#ifndef PSTR
|
||||
@ -27,37 +27,49 @@
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define pgm_read_byte(addr) (*reinterpret_cast<const uint8_t*>(addr))
|
||||
#define pgm_read_word(addr) (*reinterpret_cast<const uint16_t*>(addr))
|
||||
#define pgm_read_dword(addr) (*reinterpret_cast<const uint32_t*>(addr))
|
||||
#define pgm_read_float(addr) (*reinterpret_cast<const float*>(addr))
|
||||
#define pgm_read_ptr(addr) (*reinterpret_cast<const void* const *>(addr))
|
||||
#define pgm_read_byte(addr) (*reinterpret_cast<const uint8_t*>(addr))
|
||||
#define pgm_read_word(addr) (*reinterpret_cast<const uint16_t*>(addr))
|
||||
#define pgm_read_dword(addr) (*reinterpret_cast<const uint32_t*>(addr))
|
||||
#define pgm_read_float(addr) (*reinterpret_cast<const float*>(addr))
|
||||
#define pgm_read_ptr(addr) (*reinterpret_cast<const void* const*>(addr))
|
||||
#else
|
||||
#define pgm_read_byte(addr) (*(const uint8_t*)(addr))
|
||||
#define pgm_read_word(addr) (*(const uint16_t*)(addr))
|
||||
#define pgm_read_dword(addr) (*(const uint32_t*)(addr))
|
||||
#define pgm_read_float(addr) (*(const float)(addr))
|
||||
#define pgm_read_ptr(addr) (*(const void* const *)(addr))
|
||||
#define pgm_read_byte(addr) (*(const uint8_t*)(addr))
|
||||
#define pgm_read_word(addr) (*(const uint16_t*)(addr))
|
||||
#define pgm_read_dword(addr) (*(const uint32_t*)(addr))
|
||||
#define pgm_read_float(addr) (*(const float)(addr))
|
||||
#define pgm_read_ptr(addr) (*(const void* const*)(addr))
|
||||
#endif
|
||||
|
||||
#define pgm_read_byte_near(addr) pgm_read_byte(addr)
|
||||
#define pgm_read_word_near(addr) pgm_read_word(addr)
|
||||
#define pgm_read_dword_near(addr) pgm_read_dword(addr)
|
||||
#define pgm_read_float_near(addr) pgm_read_float(addr)
|
||||
#define pgm_read_ptr_near(addr) pgm_read_ptr(addr)
|
||||
#define pgm_read_byte_far(addr) pgm_read_byte(addr)
|
||||
#define pgm_read_word_far(addr) pgm_read_word(addr)
|
||||
#define pgm_read_dword_far(addr) pgm_read_dword(addr)
|
||||
#define pgm_read_float_far(addr) pgm_read_float(addr)
|
||||
#define pgm_read_ptr_far(addr) pgm_read_ptr(addr)
|
||||
#define pgm_read_byte_near(addr) pgm_read_byte(addr)
|
||||
#define pgm_read_word_near(addr) pgm_read_word(addr)
|
||||
#define pgm_read_dword_near(addr) pgm_read_dword(addr)
|
||||
#define pgm_read_float_near(addr) pgm_read_float(addr)
|
||||
#define pgm_read_ptr_near(addr) pgm_read_ptr(addr)
|
||||
#define pgm_read_byte_far(addr) pgm_read_byte(addr)
|
||||
#define pgm_read_word_far(addr) pgm_read_word(addr)
|
||||
#define pgm_read_dword_far(addr) pgm_read_dword(addr)
|
||||
#define pgm_read_float_far(addr) pgm_read_float(addr)
|
||||
#define pgm_read_ptr_far(addr) pgm_read_ptr(addr)
|
||||
|
||||
// Wrapper inlines for _P functions
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
inline const char *strstr_P(const char *haystack, const char *needle) { return strstr(haystack, needle); }
|
||||
inline char *strcpy_P(char *dest, const char *src) { return strcpy(dest, src); }
|
||||
inline size_t strlen_P(const char *s) { return strlen(s); }
|
||||
inline int vsnprintf_P(char *str, size_t size, const char *format, va_list ap) { return vsnprintf(str, size, format, ap); }
|
||||
inline const char* strstr_P(const char* haystack, const char* needle)
|
||||
{
|
||||
return strstr(haystack, needle);
|
||||
}
|
||||
inline char* strcpy_P(char* dest, const char* src)
|
||||
{
|
||||
return strcpy(dest, src);
|
||||
}
|
||||
inline size_t strlen_P(const char* s)
|
||||
{
|
||||
return strlen(s);
|
||||
}
|
||||
inline int vsnprintf_P(char* str, size_t size, const char* format, va_list ap)
|
||||
{
|
||||
return vsnprintf(str, size, format, ap);
|
||||
}
|
||||
|
||||
#define memcpy_P memcpy
|
||||
#define memmove_P memmove
|
||||
|
Reference in New Issue
Block a user