Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dfde2d8a62 | ||
|
|
a3f57114da | ||
|
|
904af10914 | ||
|
|
9b5013a694 | ||
|
|
922adfd3d4 | ||
|
|
362144033b | ||
|
|
caf9a579d3 | ||
|
|
cb40fdcdbe | ||
|
|
ef15e754c9 | ||
|
|
d55568c146 | ||
|
|
e134863db1 | ||
|
|
c37ae51dd3 | ||
|
|
4fc2ff43c1 | ||
|
|
607f13d935 | ||
|
|
44c1a3f695 | ||
|
|
d30decfbc8 | ||
|
|
705b2f794e | ||
|
|
4958690d9e | ||
|
|
d7749d3a24 | ||
|
|
73e07a594f | ||
|
|
755c2ef400 | ||
|
|
3f588e970a | ||
|
|
3264807e77 | ||
|
|
01225d4648 | ||
|
|
48aa809c98 | ||
|
|
4a722d4069 | ||
|
|
07aca2a0e7 | ||
|
|
10000d9b6c | ||
|
|
f0e247f31e | ||
|
|
593dec5e88 | ||
|
|
c45b86c993 | ||
|
|
02f01f2199 | ||
|
|
88b1adc2d6 | ||
|
|
a0a0e6775b | ||
|
|
4096253694 | ||
|
|
33ba44ebda | ||
|
|
9b4cf2a92b | ||
|
|
e6b915d8e3 | ||
|
|
bb73fb5f55 | ||
|
|
10c5945afb | ||
|
|
0bd613d556 |
8
.github/workflows/docs.yml
vendored
8
.github/workflows/docs.yml
vendored
@@ -13,10 +13,16 @@ jobs:
|
||||
- name: Checkout main
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Set custom domain
|
||||
run: |
|
||||
mkdir -p site/
|
||||
echo docs.libretuya.ml > site/CNAME
|
||||
|
||||
- name: Deploy docs
|
||||
uses: mhausenblas/mkdocs-deploy-gh-pages@master
|
||||
uses: libretuya/mkdocs-deploy-gh-pages@master
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CONFIG_FILE: mkdocs.yml
|
||||
EXTRA_PACKAGES: build-base doxygen
|
||||
REQUIREMENTS: docs/requirements.txt
|
||||
CUSTOM_DOMAIN: docs.libretuya.ml
|
||||
|
||||
@@ -66,7 +66,7 @@ SPIFFS | ❌ | ❌
|
||||
BLE | - | ❌
|
||||
NTP | ❌ | ❌
|
||||
OTA | ✔️ | ✔️
|
||||
MDNS | ✔️ | BK7231T only
|
||||
MDNS | ✔️ | ✔️
|
||||
MQTT | ✅ | ❌
|
||||
SD | ❌ | ❌
|
||||
|
||||
|
||||
@@ -112,6 +112,11 @@ uint32_t LibreTuya::getMaxAllocHeap() {
|
||||
|
||||
static int8_t otaImage2Valid = -1;
|
||||
|
||||
uint8_t LibreTuya::otaGetRunning() {
|
||||
// Beken has bootloader-based OTA, running app is always index 1
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t LibreTuya::otaGetStoredIndex() {
|
||||
return otaHasImage2() ? 2 : 1;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ unsigned long micros() {
|
||||
}
|
||||
|
||||
void yield() {
|
||||
runPeriodicTasks();
|
||||
vTaskDelay(1);
|
||||
taskYIELD();
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ static GPIO_INDEX adcToGpio[] = {
|
||||
#endif
|
||||
|
||||
static uint8_t gpioToPwm(GPIO_INDEX gpio) {
|
||||
for (uint8_t i = 0; i < sizeof(pwmToGpio); i++) {
|
||||
for (uint8_t i = 0; i < sizeof(pwmToGpio) / sizeof(GPIO_INDEX); i++) {
|
||||
if (pwmToGpio[i] == gpio)
|
||||
return i;
|
||||
}
|
||||
@@ -46,7 +46,7 @@ static uint8_t gpioToPwm(GPIO_INDEX gpio) {
|
||||
}
|
||||
|
||||
static uint8_t gpioToAdc(GPIO_INDEX gpio) {
|
||||
for (uint8_t i = 0; i < sizeof(adcToGpio); i++) {
|
||||
for (uint8_t i = 0; i < sizeof(adcToGpio) / sizeof(GPIO_INDEX); i++) {
|
||||
if (adcToGpio[i] == gpio)
|
||||
return i;
|
||||
}
|
||||
@@ -94,39 +94,50 @@ void analogWrite(pin_size_t pinNumber, int value) {
|
||||
if (!pinSupported(pin, PIN_PWM))
|
||||
return;
|
||||
|
||||
float percent = value * 1.0 / (1 << _analogWriteResolution);
|
||||
uint32_t dutyCycle = percent * _analogWritePeriod * 26 - 1;
|
||||
float percent = value * 1.0 / ((1 << _analogWriteResolution) - 1);
|
||||
uint32_t frequency = 26 * _analogWritePeriod - 1;
|
||||
uint32_t dutyCycle = percent * frequency;
|
||||
pwm.channel = gpioToPwm(pin->gpio);
|
||||
#if CFG_SOC_NAME != SOC_BK7231N
|
||||
pwm.duty_cycle = dutyCycle;
|
||||
#else
|
||||
pwm.duty_cycle1 = dutyCycle;
|
||||
pwm.duty_cycle2 = dutyCycle;
|
||||
pwm.duty_cycle3 = dutyCycle;
|
||||
pwm.duty_cycle2 = 0;
|
||||
pwm.duty_cycle3 = 0;
|
||||
#endif
|
||||
|
||||
if (!pinEnabled(pin, PIN_PWM)) {
|
||||
// enable PWM and set its value
|
||||
pwm.cfg.bits.en = PWM_ENABLE;
|
||||
pwm.cfg.bits.int_en = PWM_INT_DIS;
|
||||
pwm.cfg.bits.mode = PWM_PWM_MODE;
|
||||
pwm.cfg.bits.clk = PWM_CLK_26M;
|
||||
pwm.end_value = 26 * _analogWritePeriod - 1;
|
||||
pwm.p_Int_Handler = NULL;
|
||||
__wrap_bk_printf_disable();
|
||||
sddev_control(PWM_DEV_NAME, CMD_PWM_INIT_PARAM, &pwm);
|
||||
__wrap_bk_printf_enable();
|
||||
pin->enabled &= ~PIN_GPIO;
|
||||
pin->enabled |= PIN_PWM;
|
||||
} else if (value == 0) {
|
||||
// disable PWM
|
||||
pwm.cfg.bits.en = PWM_DISABLE;
|
||||
__wrap_bk_printf_disable();
|
||||
sddev_control(PWM_DEV_NAME, CMD_PWM_DEINIT_PARAM, &pwm);
|
||||
__wrap_bk_printf_enable();
|
||||
pin->enabled &= ~PIN_PWM;
|
||||
if (value) {
|
||||
if (!pinEnabled(pin, PIN_PWM)) {
|
||||
// enable PWM and set its value
|
||||
pwm.cfg.bits.en = PWM_ENABLE;
|
||||
pwm.cfg.bits.int_en = PWM_INT_DIS;
|
||||
pwm.cfg.bits.mode = PWM_PWM_MODE;
|
||||
pwm.cfg.bits.clk = PWM_CLK_26M;
|
||||
pwm.end_value = frequency;
|
||||
pwm.p_Int_Handler = NULL;
|
||||
__wrap_bk_printf_disable();
|
||||
sddev_control(PWM_DEV_NAME, CMD_PWM_INIT_PARAM, &pwm);
|
||||
sddev_control(PWM_DEV_NAME, CMD_PWM_INIT_LEVL_SET_HIGH, &pwm.channel);
|
||||
sddev_control(PWM_DEV_NAME, CMD_PWM_UNIT_ENABLE, &pwm.channel);
|
||||
__wrap_bk_printf_enable();
|
||||
pin->enabled &= ~PIN_GPIO;
|
||||
pin->enabled |= PIN_PWM;
|
||||
} else {
|
||||
// update duty cycle
|
||||
sddev_control(PWM_DEV_NAME, CMD_PWM_SET_DUTY_CYCLE, &pwm);
|
||||
}
|
||||
} else {
|
||||
// update duty cycle
|
||||
sddev_control(PWM_DEV_NAME, CMD_PWM_SET_DUTY_CYCLE, &pwm);
|
||||
if (pinEnabled(pin, PIN_PWM)) {
|
||||
// disable PWM
|
||||
pwm.cfg.bits.en = PWM_DISABLE;
|
||||
__wrap_bk_printf_disable();
|
||||
sddev_control(PWM_DEV_NAME, CMD_PWM_SET_DUTY_CYCLE, &pwm);
|
||||
sddev_control(PWM_DEV_NAME, CMD_PWM_DEINIT_PARAM, &pwm);
|
||||
__wrap_bk_printf_enable();
|
||||
pin->enabled &= ~PIN_PWM;
|
||||
}
|
||||
// force level as LOW
|
||||
pinMode(pinNumber, OUTPUT);
|
||||
digitalWrite(pinNumber, LOW);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ PinStatus digitalRead(pin_size_t pinNumber) {
|
||||
if (!pin)
|
||||
return 0;
|
||||
// pin is not GPIO yet or not INPUT; change the mode
|
||||
if (!pinEnabled(pin, PIN_GPIO) || !pinIsOutput(pin))
|
||||
if (!pinEnabled(pin, PIN_GPIO) || !pinIsInput(pin))
|
||||
pinMode(pinNumber, INPUT);
|
||||
// read the value
|
||||
return gpio_input(pin->gpio);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "WiFiPriv.h"
|
||||
|
||||
WiFiClass::WiFiClass() {
|
||||
memset(&data, 0x00, sizeof(WiFiData));
|
||||
data.scanSem = xSemaphoreCreateBinary();
|
||||
}
|
||||
|
||||
@@ -10,6 +11,30 @@ WiFiClass::~WiFiClass() {
|
||||
vSemaphoreDelete(data.scanSem);
|
||||
}
|
||||
|
||||
void WiFiClass::dataInitialize() {
|
||||
if (data.statusIp)
|
||||
return;
|
||||
LT_DM(WIFI, "Data init");
|
||||
data.configSta = zalloc(sizeof(network_InitTypeDef_st));
|
||||
data.configAp = zalloc(sizeof(network_InitTypeDef_ap_st));
|
||||
data.statusIp = malloc(sizeof(IPStatusTypedef));
|
||||
data.statusLink = malloc(sizeof(LinkStatusTypeDef));
|
||||
STA_CFG->dhcp_mode = DHCP_CLIENT;
|
||||
LT_DM(WIFI, "Data = %p", data.configSta);
|
||||
}
|
||||
|
||||
void WiFiClass::dataFree() {
|
||||
LT_DM(WIFI, "Data free");
|
||||
free(data.configSta);
|
||||
free(data.configAp);
|
||||
free(data.statusIp);
|
||||
free(data.statusLink);
|
||||
data.configSta = NULL;
|
||||
data.configAp = NULL;
|
||||
data.statusIp = NULL;
|
||||
data.statusLink = NULL;
|
||||
}
|
||||
|
||||
WiFiStatus eventTypeToStatus(uint8_t type) {
|
||||
// rw_msg_pub.h:9
|
||||
switch (type) {
|
||||
|
||||
@@ -25,21 +25,22 @@ bool WiFiClass::softAP(const char *ssid, const char *passphrase, int channel, bo
|
||||
AP_CFG->dhcp_mode = DHCP_SERVER;
|
||||
AP_CFG->wifi_retry_interval = 100;
|
||||
|
||||
LT_I("Creating SoftAP %s", ssid);
|
||||
LT_IM(WIFI, "Creating SoftAP %s", ssid);
|
||||
|
||||
__wrap_bk_printf_disable();
|
||||
OSStatus ret = bk_wlan_start_ap_adv(AP_CFG);
|
||||
__wrap_bk_printf_enable();
|
||||
|
||||
if (ret != 0) {
|
||||
LT_E("SoftAP failed; ret=%d", ret);
|
||||
LT_EM(WIFI, "SoftAP failed; ret=%d", ret);
|
||||
return false;
|
||||
}
|
||||
LT_D_WG("Start OK");
|
||||
LT_DM(WIFI, "AP start OK");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WiFiClass::softAPConfig(IPAddress localIP, IPAddress gateway, IPAddress subnet) {
|
||||
dataInitialize();
|
||||
if (!localIP) {
|
||||
localIP = gateway = IPAddress(192, 168, 43, 1);
|
||||
subnet = IPAddress(255, 255, 255, 0);
|
||||
@@ -72,14 +73,14 @@ uint8_t WiFiClass::softAPgetStationNum() {
|
||||
}
|
||||
|
||||
IPAddress WiFiClass::softAPIP() {
|
||||
bk_wlan_get_ip_status(IP_STATUS, BK_SOFT_AP);
|
||||
AP_GET_IP_STATUS_RETURN((uint32_t)0);
|
||||
IPAddress ip;
|
||||
ip.fromString(IP_STATUS->ip);
|
||||
return ip;
|
||||
}
|
||||
|
||||
IPAddress WiFiClass::softAPSubnetMask() {
|
||||
bk_wlan_get_ip_status(IP_STATUS, BK_SOFT_AP);
|
||||
AP_GET_IP_STATUS_RETURN((uint32_t)0);
|
||||
IPAddress ip;
|
||||
ip.fromString(IP_STATUS->mask);
|
||||
return ip;
|
||||
@@ -108,5 +109,6 @@ String WiFiClass::softAPmacAddress(void) {
|
||||
}
|
||||
|
||||
const String WiFiClass::softAPSSID(void) {
|
||||
AP_GET_LINK_STATUS_RETURN("");
|
||||
return AP_CFG->wifi_ssid;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
extern "C" {
|
||||
|
||||
#include <FreeRTOS.h>
|
||||
#include <rw_msg_pub.h>
|
||||
#include <semphr.h>
|
||||
|
||||
} // extern "C"
|
||||
@@ -18,4 +19,6 @@ typedef struct {
|
||||
SemaphoreHandle_t scanSem;
|
||||
void *statusIp;
|
||||
void *statusLink;
|
||||
rw_evt_type lastStaEvent;
|
||||
rw_evt_type lastApEvent;
|
||||
} WiFiData;
|
||||
|
||||
@@ -50,7 +50,12 @@ void wifiEventHandler(rw_evt_type event) {
|
||||
if (!pWiFi)
|
||||
return; // failsafe
|
||||
|
||||
LT_D_WG("WiFi event %u", event);
|
||||
LT_DM(WIFI, "BK event %u", event);
|
||||
|
||||
if (event <= RW_EVT_STA_GOT_IP)
|
||||
pWiFi->data.lastStaEvent = event;
|
||||
else
|
||||
pWiFi->data.lastApEvent = event;
|
||||
|
||||
EventId eventId;
|
||||
EventInfo eventInfo;
|
||||
|
||||
@@ -6,35 +6,36 @@ bool WiFiClass::modePriv(WiFiMode mode, WiFiModeAction sta, WiFiModeAction ap) {
|
||||
__wrap_bk_printf_disable();
|
||||
startWifiTask();
|
||||
|
||||
if (mode && !data.statusIp) {
|
||||
data.configSta = zalloc(sizeof(network_InitTypeDef_st));
|
||||
data.configAp = zalloc(sizeof(network_InitTypeDef_ap_st));
|
||||
data.statusIp = malloc(sizeof(IPStatusTypedef));
|
||||
data.statusLink = malloc(sizeof(LinkStatusTypeDef));
|
||||
STA_CFG->dhcp_mode = DHCP_CLIENT;
|
||||
}
|
||||
|
||||
if (!__bk_rf_is_init) {
|
||||
LT_D_WG("Initializing func&app");
|
||||
LT_DM(WIFI, "Initializing func&app");
|
||||
func_init_extended();
|
||||
app_pre_start();
|
||||
// wait for the init_thread to finish its job
|
||||
while (xTaskGetHandle("init_thread")) {
|
||||
LT_V_WG("Waiting for init_thread");
|
||||
LT_VM(WIFI, "Waiting for init_thread");
|
||||
delay(10);
|
||||
}
|
||||
LT_D_WG("Success");
|
||||
LT_DM(WIFI, "Init OK");
|
||||
__bk_rf_is_init = true;
|
||||
}
|
||||
|
||||
LT_HEAP_I();
|
||||
|
||||
if (mode) {
|
||||
LT_DM(WIFI, "Wakeup RF");
|
||||
uint32_t reg = 1; // this is only checked for being true-ish
|
||||
sddev_control(SCTRL_DEV_NAME, CMD_RF_HOLD_BIT_SET, ®);
|
||||
}
|
||||
|
||||
if (sta == WLMODE_ENABLE) {
|
||||
LT_D_WG("Enabling STA");
|
||||
LT_DM(WIFI, "Enabling STA");
|
||||
bk_wlan_sta_init(NULL);
|
||||
#if CFG_WPA_CTRL_IFACE
|
||||
wlan_sta_enable();
|
||||
#endif
|
||||
wifiEventSendArduino(ARDUINO_EVENT_WIFI_STA_START);
|
||||
} else if (sta == WLMODE_DISABLE) {
|
||||
LT_D_WG("Disabling STA");
|
||||
LT_DM(WIFI, "Disabling STA");
|
||||
bk_wlan_stop(BK_STATION);
|
||||
wifiEventSendArduino(ARDUINO_EVENT_WIFI_STA_STOP);
|
||||
}
|
||||
@@ -42,25 +43,25 @@ bool WiFiClass::modePriv(WiFiMode mode, WiFiModeAction sta, WiFiModeAction ap) {
|
||||
LT_HEAP_I();
|
||||
|
||||
if (ap == WLMODE_ENABLE) {
|
||||
LT_D_WG("Enabling AP");
|
||||
LT_DM(WIFI, "Enabling AP");
|
||||
bk_wlan_ap_init(NULL);
|
||||
#if CFG_WPA_CTRL_IFACE
|
||||
wlan_ap_enable();
|
||||
wlan_ap_reload();
|
||||
uap_ip_down();
|
||||
#endif
|
||||
wifiEventSendArduino(ARDUINO_EVENT_WIFI_AP_START);
|
||||
} else if (ap == WLMODE_DISABLE) {
|
||||
LT_D_WG("Disabling AP");
|
||||
LT_DM(WIFI, "Disabling AP");
|
||||
bk_wlan_stop(BK_SOFT_AP);
|
||||
wifiEventSendArduino(ARDUINO_EVENT_WIFI_AP_STOP);
|
||||
}
|
||||
|
||||
if (!mode) {
|
||||
free(data.configSta);
|
||||
free(data.configAp);
|
||||
free(data.statusIp);
|
||||
free(data.statusLink);
|
||||
data.configSta = NULL;
|
||||
data.configAp = NULL;
|
||||
data.statusIp = NULL;
|
||||
data.statusLink = NULL;
|
||||
}
|
||||
// force checking actual mode again
|
||||
mode = getMode();
|
||||
|
||||
if (!mode)
|
||||
dataFree();
|
||||
|
||||
LT_HEAP_I();
|
||||
|
||||
@@ -69,15 +70,13 @@ bool WiFiClass::modePriv(WiFiMode mode, WiFiModeAction sta, WiFiModeAction ap) {
|
||||
}
|
||||
|
||||
WiFiMode WiFiClass::getMode() {
|
||||
if (!g_wlan_general_param)
|
||||
return WIFI_MODE_NULL;
|
||||
uint8_t role = g_wlan_general_param->role;
|
||||
// change 1->2, 2->1
|
||||
return (WiFiMode)(role + (role == 1) - (role == 2));
|
||||
uint8_t sta = !!bk_wlan_has_role(VIF_STA) * WIFI_MODE_STA;
|
||||
uint8_t ap = !!bk_wlan_has_role(VIF_AP) * WIFI_MODE_AP;
|
||||
return (WiFiMode)(sta | ap);
|
||||
}
|
||||
|
||||
WiFiStatus WiFiClass::status() {
|
||||
rw_evt_type status = mhdr_get_station_status();
|
||||
rw_evt_type status = data.lastStaEvent;
|
||||
if (status == RW_EVT_STA_CONNECTED && STA_CFG->dhcp_mode == DHCP_DISABLE)
|
||||
status = RW_EVT_STA_GOT_IP;
|
||||
return eventTypeToStatus(status);
|
||||
|
||||
@@ -20,6 +20,9 @@ extern "C" {
|
||||
#include <main_none.h>
|
||||
#include <param_config.h>
|
||||
#include <rw_msg_rx.h>
|
||||
#include <sa_ap.h>
|
||||
#include <sys_ctrl_pub.h>
|
||||
#include <vif_mgmt.h>
|
||||
#include <wlan_ui_pub.h>
|
||||
#include <wpa_supplicant_i.h>
|
||||
|
||||
@@ -54,4 +57,34 @@ extern void wifiEventHandler(rw_evt_type event);
|
||||
#define IP_STATUS ((IPStatusTypedef *)data.statusIp)
|
||||
#define LINK_STATUS ((LinkStatusTypeDef *)data.statusLink)
|
||||
|
||||
#define STA_GET_LINK_STATUS_RETURN(ret) \
|
||||
{ \
|
||||
if (!sta_ip_is_start()) \
|
||||
return ret; \
|
||||
memset(LINK_STATUS, 0x00, sizeof(LinkStatusTypeDef)); \
|
||||
bk_wlan_get_link_status(LINK_STATUS); \
|
||||
}
|
||||
|
||||
#define STA_GET_IP_STATUS_RETURN(ret) \
|
||||
{ \
|
||||
if (!sta_ip_is_start()) \
|
||||
return ret; \
|
||||
memset(IP_STATUS, 0x00, sizeof(IPStatusTypedef)); \
|
||||
bk_wlan_get_ip_status(IP_STATUS, BK_STATION); \
|
||||
}
|
||||
|
||||
#define AP_GET_LINK_STATUS_RETURN(ret) \
|
||||
{ \
|
||||
if (!uap_ip_is_start()) \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#define AP_GET_IP_STATUS_RETURN(ret) \
|
||||
{ \
|
||||
if (!uap_ip_is_start()) \
|
||||
return ret; \
|
||||
memset(IP_STATUS, 0x00, sizeof(IPStatusTypedef)); \
|
||||
bk_wlan_get_ip_status(IP_STATUS, BK_SOFT_AP); \
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
@@ -11,6 +11,8 @@ WiFiClass::begin(const char *ssid, const char *passphrase, int32_t channel, cons
|
||||
|
||||
LT_HEAP_I();
|
||||
|
||||
disconnect(false);
|
||||
|
||||
strcpy(STA_CFG->wifi_ssid, ssid);
|
||||
if (passphrase) {
|
||||
strcpy(STA_CFG->wifi_key, passphrase);
|
||||
@@ -25,8 +27,7 @@ WiFiClass::begin(const char *ssid, const char *passphrase, int32_t channel, cons
|
||||
}
|
||||
|
||||
bool WiFiClass::config(IPAddress localIP, IPAddress gateway, IPAddress subnet, IPAddress dns1, IPAddress dns2) {
|
||||
// need to initialize data struct first
|
||||
enableSTA(true);
|
||||
dataInitialize();
|
||||
|
||||
STA_CFG->dhcp_mode = localIP ? DHCP_DISABLE : DHCP_CLIENT;
|
||||
if (localIP) {
|
||||
@@ -35,8 +36,16 @@ bool WiFiClass::config(IPAddress localIP, IPAddress gateway, IPAddress subnet, I
|
||||
sprintf(STA_CFG->gateway_ip_addr, IP_FMT, gateway[0], gateway[1], gateway[2], gateway[3]);
|
||||
if (dns1) {
|
||||
sprintf(STA_CFG->dns_server_ip_addr, IP_FMT, dns1[0], dns1[1], dns1[2], dns1[3]);
|
||||
} else {
|
||||
STA_CFG->dns_server_ip_addr[0] = '\0';
|
||||
}
|
||||
} else {
|
||||
STA_CFG->local_ip_addr[0] = '\0';
|
||||
STA_CFG->net_mask[0] = '\0';
|
||||
STA_CFG->gateway_ip_addr[0] = '\0';
|
||||
STA_CFG->dns_server_ip_addr[0] = '\0';
|
||||
}
|
||||
|
||||
// from wlan_ui.c:1370
|
||||
if (sta_ip_is_start()) {
|
||||
sta_ip_down();
|
||||
@@ -54,17 +63,20 @@ bool WiFiClass::config(IPAddress localIP, IPAddress gateway, IPAddress subnet, I
|
||||
}
|
||||
|
||||
bool WiFiClass::reconnect(const uint8_t *bssid) {
|
||||
dataInitialize();
|
||||
if (!bssid && !STA_CFG->wifi_ssid[0]) {
|
||||
LT_E("(B)SSID not specified");
|
||||
LT_EM(WIFI, "(B)SSID not specified");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (bssid) {
|
||||
LT_D_WG("Connecting to " MACSTR, MAC2STR(bssid));
|
||||
LT_IM(WIFI, "Connecting to " MACSTR, MAC2STR(bssid));
|
||||
} else {
|
||||
LT_D_WG("Connecting to %s", STA_CFG->wifi_ssid);
|
||||
LT_IM(WIFI, "Connecting to %s", STA_CFG->wifi_ssid);
|
||||
}
|
||||
|
||||
LT_DM(WIFI, "Data = %p", data.configSta);
|
||||
|
||||
STA_CFG->wifi_mode = BK_STATION;
|
||||
STA_CFG->wifi_retry_interval = 100;
|
||||
if (bssid)
|
||||
@@ -73,19 +85,19 @@ bool WiFiClass::reconnect(const uint8_t *bssid) {
|
||||
memset(STA_CFG->wifi_bssid, 0x00, 6);
|
||||
|
||||
if (STA_CFG->dhcp_mode == DHCP_DISABLE) {
|
||||
LT_D_WG("Static IP: %s / %s / %s", STA_CFG->local_ip_addr, STA_CFG->net_mask, STA_CFG->gateway_ip_addr);
|
||||
LT_D_WG("Static DNS: %s", STA_CFG->dns_server_ip_addr);
|
||||
LT_DM(WIFI, "Static IP: %s / %s / %s", STA_CFG->local_ip_addr, STA_CFG->net_mask, STA_CFG->gateway_ip_addr);
|
||||
LT_DM(WIFI, "Static DNS: %s", STA_CFG->dns_server_ip_addr);
|
||||
} else {
|
||||
LT_D_WG("Using DHCP");
|
||||
LT_DM(WIFI, "Using DHCP");
|
||||
}
|
||||
|
||||
LT_D_WG("Starting WiFi...");
|
||||
LT_DM(WIFI, "Starting WiFi...");
|
||||
|
||||
__wrap_bk_printf_disable();
|
||||
bk_wlan_start_sta(STA_CFG);
|
||||
__wrap_bk_printf_enable();
|
||||
|
||||
LT_D_WG("Start OK");
|
||||
LT_DM(WIFI, "Start OK");
|
||||
return true;
|
||||
|
||||
error:
|
||||
@@ -93,6 +105,11 @@ error:
|
||||
}
|
||||
|
||||
bool WiFiClass::disconnect(bool wifiOff) {
|
||||
#if LT_DEBUG_WIFI
|
||||
memset(LINK_STATUS, 0x00, sizeof(LinkStatusTypeDef));
|
||||
bk_wlan_get_link_status(LINK_STATUS);
|
||||
LT_DM(WIFI, "Disconnecting from %s (wifiOff=%d)", LINK_STATUS ? LINK_STATUS->ssid : NULL, wifiOff);
|
||||
#endif
|
||||
bk_wlan_connection_loss();
|
||||
if (wifiOff)
|
||||
enableSTA(false);
|
||||
@@ -108,28 +125,28 @@ bool WiFiClass::getAutoReconnect() {
|
||||
}
|
||||
|
||||
IPAddress WiFiClass::localIP() {
|
||||
bk_wlan_get_ip_status(IP_STATUS, BK_STATION);
|
||||
STA_GET_IP_STATUS_RETURN((uint32_t)0);
|
||||
IPAddress ip;
|
||||
ip.fromString(IP_STATUS->ip);
|
||||
return ip;
|
||||
}
|
||||
|
||||
IPAddress WiFiClass::subnetMask() {
|
||||
bk_wlan_get_ip_status(IP_STATUS, BK_STATION);
|
||||
STA_GET_IP_STATUS_RETURN((uint32_t)0);
|
||||
IPAddress ip;
|
||||
ip.fromString(IP_STATUS->mask);
|
||||
return ip;
|
||||
}
|
||||
|
||||
IPAddress WiFiClass::gatewayIP() {
|
||||
bk_wlan_get_ip_status(IP_STATUS, BK_STATION);
|
||||
STA_GET_IP_STATUS_RETURN((uint32_t)0);
|
||||
IPAddress ip;
|
||||
ip.fromString(IP_STATUS->gate);
|
||||
return ip;
|
||||
}
|
||||
|
||||
IPAddress WiFiClass::dnsIP(uint8_t dns_no) {
|
||||
bk_wlan_get_ip_status(IP_STATUS, BK_STATION);
|
||||
STA_GET_IP_STATUS_RETURN((uint32_t)0);
|
||||
IPAddress ip;
|
||||
ip.fromString(IP_STATUS->dns);
|
||||
return ip;
|
||||
@@ -157,7 +174,7 @@ uint8_t *WiFiClass::macAddress(uint8_t *mac) {
|
||||
|
||||
bool WiFiClass::setMacAddress(const uint8_t *mac) {
|
||||
if (mac[0] & 0x01) {
|
||||
LT_E("Invalid MAC address");
|
||||
LT_EM(WIFI, "Invalid MAC address");
|
||||
return false;
|
||||
}
|
||||
// ensure "mac_inited" is true
|
||||
@@ -173,7 +190,7 @@ bool WiFiClass::setMacAddress(const uint8_t *mac) {
|
||||
}
|
||||
|
||||
const String WiFiClass::SSID() {
|
||||
bk_wlan_get_link_status(LINK_STATUS);
|
||||
STA_GET_LINK_STATUS_RETURN("");
|
||||
return (char *)LINK_STATUS->ssid;
|
||||
}
|
||||
|
||||
@@ -187,21 +204,21 @@ const String WiFiClass::psk() {
|
||||
}
|
||||
|
||||
uint8_t *WiFiClass::BSSID() {
|
||||
bk_wlan_get_link_status(LINK_STATUS);
|
||||
STA_GET_LINK_STATUS_RETURN(NULL);
|
||||
return LINK_STATUS->bssid;
|
||||
}
|
||||
|
||||
int32_t WiFiClass::channel() {
|
||||
bk_wlan_get_link_status(LINK_STATUS);
|
||||
STA_GET_LINK_STATUS_RETURN(0);
|
||||
return LINK_STATUS->channel;
|
||||
}
|
||||
|
||||
int8_t WiFiClass::RSSI() {
|
||||
bk_wlan_get_link_status(LINK_STATUS);
|
||||
STA_GET_LINK_STATUS_RETURN(0);
|
||||
return LINK_STATUS->wifi_strength;
|
||||
}
|
||||
|
||||
WiFiAuthMode WiFiClass::getEncryption() {
|
||||
bk_wlan_get_link_status(LINK_STATUS);
|
||||
STA_GET_LINK_STATUS_RETURN(WIFI_AUTH_INVALID);
|
||||
return securityTypeToAuthMode(LINK_STATUS->security);
|
||||
}
|
||||
|
||||
@@ -6,25 +6,25 @@ static void scanHandler(void *ctx, uint8_t param) {
|
||||
LT_HEAP_I();
|
||||
WiFiClass *cls = (WiFiClass *)ctx;
|
||||
if (!cls) {
|
||||
LT_W("Called without ctx");
|
||||
LT_WM(WIFI, "Called without ctx");
|
||||
return;
|
||||
}
|
||||
WiFiScanData *scan = cls->scan;
|
||||
if (!scan) {
|
||||
LT_W("Called without cls->scan");
|
||||
LT_WM(WIFI, "Called without cls->scan");
|
||||
return;
|
||||
}
|
||||
|
||||
ScanResult_adv result;
|
||||
if (wlan_sta_scan_result(&result)) {
|
||||
LT_E("Failed to get scan result");
|
||||
LT_EM(WIFI, "Failed to get scan result");
|
||||
goto end;
|
||||
}
|
||||
LT_D_WG("Found %d APs", result.ApNum);
|
||||
LT_IM(WIFI, "Found %d APs", result.ApNum);
|
||||
|
||||
cls->scanAlloc(result.ApNum);
|
||||
if (!scan->ap) {
|
||||
LT_W("scan->ap alloc failed");
|
||||
LT_WM(WIFI, "scan->ap alloc failed");
|
||||
goto end;
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ int16_t WiFiClass::scanNetworks(bool async, bool showHidden, bool passive, uint3
|
||||
scanDelete();
|
||||
scanInit();
|
||||
|
||||
LT_I("Starting WiFi scan");
|
||||
LT_IM(WIFI, "Starting WiFi scan");
|
||||
|
||||
__wrap_bk_printf_disable();
|
||||
mhdr_scanu_reg_cb(scanHandler, this);
|
||||
@@ -66,7 +66,7 @@ int16_t WiFiClass::scanNetworks(bool async, bool showHidden, bool passive, uint3
|
||||
|
||||
int16_t ret = WIFI_SCAN_RUNNING;
|
||||
if (!async) {
|
||||
LT_I("Waiting for results");
|
||||
LT_IM(WIFI, "Waiting for results");
|
||||
xSemaphoreTake(data.scanSem, 1); // reset the semaphore quickly
|
||||
xSemaphoreTake(data.scanSem, pdMS_TO_TICKS(maxMsPerChannel * 20));
|
||||
if (scan->running) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-19. */
|
||||
|
||||
#include <lt_logger.h>
|
||||
#include <sdk_extern.h>
|
||||
|
||||
#include <fal.h>
|
||||
@@ -8,10 +9,27 @@
|
||||
#define FLASH_ERASE_MIN_SIZE (4 * 1024)
|
||||
|
||||
extern uint32_t flash_ctrl(uint32_t cmd, void *param);
|
||||
extern PROTECT_TYPE get_flash_protect();
|
||||
extern void flash_protection_op(uint8_t mode, PROTECT_TYPE type);
|
||||
|
||||
static void unprotect() {
|
||||
PROTECT_TYPE type = get_flash_protect();
|
||||
if (type != FLASH_PROTECT_NONE) {
|
||||
flash_protection_op(0, FLASH_PROTECT_NONE);
|
||||
#if LT_LOGLEVEL <= LT_LEVEL_DEBUG
|
||||
LT_D("Flash protect: %u -> %u", type, get_flash_protect());
|
||||
uint16_t sr = 0;
|
||||
flash_ctrl(CMD_FLASH_READ_SR, &sr);
|
||||
LT_D("SR = %04x", sr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static int init() {
|
||||
__wrap_bk_printf_disable();
|
||||
flash_init();
|
||||
flash_ctrl(CMD_FLASH_WRITE_ENABLE, NULL);
|
||||
unprotect();
|
||||
__wrap_bk_printf_enable();
|
||||
return 0;
|
||||
}
|
||||
@@ -22,11 +40,13 @@ static int read(long offset, uint8_t *buf, size_t size) {
|
||||
}
|
||||
|
||||
static int write(long offset, const uint8_t *buf, size_t size) {
|
||||
unprotect();
|
||||
flash_write((char *)buf, size, offset);
|
||||
return size;
|
||||
}
|
||||
|
||||
static int erase(long offset, size_t size) {
|
||||
unprotect();
|
||||
size = ((size - 1) / FLASH_ERASE_MIN_SIZE) + 1;
|
||||
for (uint16_t i = 0; i < size; i++) {
|
||||
uint32_t addr = offset + i * FLASH_ERASE_MIN_SIZE;
|
||||
|
||||
@@ -12,8 +12,8 @@ void WiFiClass::printDiag(Print &dest) {
|
||||
if (getMode() & WIFI_MODE_STA) {
|
||||
dest.println("-- Station --");
|
||||
dest.print("SSID: ");
|
||||
dest.println(SSID());
|
||||
if (isConnected()) {
|
||||
dest.println(SSID());
|
||||
dest.print("Channel: ");
|
||||
dest.println(channel());
|
||||
dest.print("BSSID: ");
|
||||
@@ -28,40 +28,50 @@ void WiFiClass::printDiag(Print &dest) {
|
||||
dest.println(macAddress());
|
||||
dest.print("Hostname: ");
|
||||
dest.println(getHostname());
|
||||
} else {
|
||||
dest.println("disconnected");
|
||||
}
|
||||
}
|
||||
|
||||
if (getMode() & WIFI_MODE_AP) {
|
||||
dest.println("-- Access Point --");
|
||||
dest.print("SSID: ");
|
||||
dest.println(softAPSSID());
|
||||
dest.print("IP: ");
|
||||
dest.println(softAPIP());
|
||||
dest.print("MAC: ");
|
||||
dest.println(softAPmacAddress());
|
||||
dest.print("Hostname: ");
|
||||
dest.println(softAPgetHostname());
|
||||
if (softAPSSID().length()) {
|
||||
dest.println(softAPSSID());
|
||||
dest.print("IP: ");
|
||||
dest.println(softAPIP());
|
||||
dest.print("MAC: ");
|
||||
dest.println(softAPmacAddress());
|
||||
dest.print("Hostname: ");
|
||||
dest.println(softAPgetHostname());
|
||||
} else {
|
||||
dest.println("disconnected");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool WiFiClass::validate(const char *ssid, const char *passphrase) {
|
||||
if (!ssid || *ssid == 0x00 || strlen(ssid) > 32) {
|
||||
LT_W("SSID not specified or too long");
|
||||
LT_WM(WIFI, "SSID not specified or too long");
|
||||
return false;
|
||||
}
|
||||
if (passphrase) {
|
||||
uint16_t length = strlen(passphrase);
|
||||
if (length < 8) {
|
||||
LT_W("Passphrase too short (%u)", length);
|
||||
LT_WM(WIFI, "Passphrase too short (%u)", length);
|
||||
return false;
|
||||
}
|
||||
if (length > 63) {
|
||||
LT_W("Passphrase too long (%u)", length);
|
||||
LT_WM(WIFI, "Passphrase too long (%u)", length);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
__attribute__((weak)) void WiFiClass::dataInitialize() {}
|
||||
|
||||
__attribute__((weak)) void WiFiClass::dataFree() {}
|
||||
|
||||
WiFiClass WiFi;
|
||||
WiFiClass *pWiFi = NULL;
|
||||
|
||||
@@ -47,6 +47,8 @@ class WiFiClass {
|
||||
~WiFiClass();
|
||||
void printDiag(Print &dest);
|
||||
bool validate(const char *ssid, const char *passphrase);
|
||||
void dataInitialize();
|
||||
void dataFree();
|
||||
|
||||
public: /* WiFiGeneric.cpp */
|
||||
bool mode(WiFiMode mode);
|
||||
|
||||
@@ -7,7 +7,7 @@ bool WiFiClass::mode(WiFiMode mode) {
|
||||
pWiFi = this;
|
||||
|
||||
WiFiMode currentMode = getMode();
|
||||
LT_D_WG("Mode changing %u -> %u", currentMode, mode);
|
||||
LT_DM(WIFI, "Mode changing %u -> %u", currentMode, mode);
|
||||
if (mode == currentMode)
|
||||
return true;
|
||||
|
||||
@@ -15,11 +15,19 @@ bool WiFiClass::mode(WiFiMode mode) {
|
||||
WiFiModeAction sta = WiFiModeAction((mode & WIFI_MODE_STA) != (currentMode & WIFI_MODE_STA));
|
||||
WiFiModeAction ap = WiFiModeAction((mode & WIFI_MODE_AP) != (currentMode & WIFI_MODE_AP));
|
||||
// change 0/1 to 1/2
|
||||
sta = WiFiModeAction(sta + sta * (mode & WIFI_MODE_STA));
|
||||
ap = WiFiModeAction(ap + ap * (mode & WIFI_MODE_AP));
|
||||
sta = WiFiModeAction(sta + sta * !!(mode & WIFI_MODE_STA));
|
||||
ap = WiFiModeAction(ap + ap * !!(mode & WIFI_MODE_AP));
|
||||
// initialize data structures if wifi is enabled
|
||||
if (mode)
|
||||
dataInitialize();
|
||||
// actually change the mode
|
||||
LT_HEAP_I();
|
||||
return modePriv(mode, sta, ap);
|
||||
if (!modePriv(mode, sta, ap))
|
||||
return false;
|
||||
if (getMode() != mode) {
|
||||
LT_WM(WIFI, "Mode changed to %d (requested %d)", getMode(), mode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WiFiClass::enableSTA(bool enable) {
|
||||
|
||||
@@ -14,6 +14,7 @@ String ipToString(const IPAddress &ip) {
|
||||
* @param buf destination pointer
|
||||
* @param len how many bytes to generate
|
||||
*/
|
||||
extern "C" {
|
||||
void lt_rand_bytes(uint8_t *buf, size_t len) {
|
||||
int *data = (int *)buf;
|
||||
size_t i;
|
||||
@@ -37,7 +38,7 @@ void lt_rand_bytes(uint8_t *buf, size_t len) {
|
||||
* @param offset increment printed offset by this value
|
||||
* @param width how many bytes on a line
|
||||
*/
|
||||
void hexdump(uint8_t *buf, size_t len, uint32_t offset, uint8_t width) {
|
||||
void hexdump(const uint8_t *buf, size_t len, uint32_t offset, uint8_t width) {
|
||||
uint16_t pos = 0;
|
||||
while (pos < len) {
|
||||
// print hex offset
|
||||
@@ -61,3 +62,4 @@ void hexdump(uint8_t *buf, size_t len, uint32_t offset, uint8_t width) {
|
||||
pos += lineWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,11 +64,17 @@ extern "C" {
|
||||
"LibreTuya v" LT_VERSION_STR " on " LT_BOARD_STR ", compiled at " __DATE__ " " __TIME__ \
|
||||
)
|
||||
|
||||
void lt_rand_bytes(uint8_t *buf, size_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
String ipToString(const IPAddress &ip);
|
||||
void hexdump(uint8_t *buf, size_t len, uint32_t offset = 0, uint8_t width = 16);
|
||||
|
||||
extern "C" {
|
||||
void lt_rand_bytes(uint8_t *buf, size_t len);
|
||||
void hexdump(const uint8_t *buf, size_t len, uint32_t offset = 0, uint8_t width = 16);
|
||||
}
|
||||
|
||||
#else
|
||||
void hexdump(uint8_t *buf, size_t len, uint32_t offset, uint8_t width);
|
||||
|
||||
void lt_rand_bytes(uint8_t *buf, size_t len);
|
||||
void hexdump(const uint8_t *buf, size_t len, uint32_t offset, uint8_t width);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -74,18 +74,6 @@ __attribute__((weak)) uint32_t LibreTuya::getFlashChipSize() {
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint8_t otaRunningIndex = 0;
|
||||
|
||||
/**
|
||||
* @brief Get the currently running firmware OTA index.
|
||||
*/
|
||||
uint8_t LibreTuya::otaGetRunning() {
|
||||
if (otaRunningIndex)
|
||||
return otaRunningIndex;
|
||||
// otaRunningIndex will be correct even after switchOta()
|
||||
return otaRunningIndex = otaGetStoredIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the OTA index for updated firmware.
|
||||
*
|
||||
|
||||
@@ -33,7 +33,6 @@ class LibreTuya {
|
||||
const char *getDeviceName();
|
||||
uint32_t getCpuFreqMHz();
|
||||
uint32_t getFlashChipSize();
|
||||
uint8_t otaGetRunning();
|
||||
uint8_t otaGetTarget();
|
||||
bool otaRollback();
|
||||
bool otaCanRollback();
|
||||
@@ -109,6 +108,10 @@ class LibreTuya {
|
||||
uint32_t getMaxAllocHeap();
|
||||
|
||||
public: /* OTA-related */
|
||||
/**
|
||||
* @brief Get the currently running firmware OTA index.
|
||||
*/
|
||||
uint8_t otaGetRunning();
|
||||
/**
|
||||
* @brief Read the currently active OTA index, i.e. the one that will boot upon restart.
|
||||
*/
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#define LT_LEVEL_WARN 3
|
||||
#define LT_LEVEL_ERROR 4
|
||||
#define LT_LEVEL_FATAL 5
|
||||
#define LT_LEVEL_NONE 6
|
||||
|
||||
// Logger enabled/disabled
|
||||
#ifndef LT_LOGGER
|
||||
@@ -24,11 +25,11 @@
|
||||
#endif
|
||||
|
||||
#ifndef LT_LOGGER_CALLER
|
||||
#define LT_LOGGER_CALLER 1
|
||||
#define LT_LOGGER_CALLER 0
|
||||
#endif
|
||||
|
||||
#ifndef LT_LOGGER_TASK
|
||||
#define LT_LOGGER_TASK 1
|
||||
#define LT_LOGGER_TASK 0
|
||||
#endif
|
||||
|
||||
#ifndef LT_LOGGER_COLOR
|
||||
@@ -44,6 +45,11 @@
|
||||
#define LT_LOGLEVEL LT_LEVEL_INFO
|
||||
#endif
|
||||
|
||||
#if !LT_LOGGER
|
||||
#undef LT_LOGLEVEL
|
||||
#define LT_LOGLEVEL LT_LEVEL_NONE
|
||||
#endif
|
||||
|
||||
// Free heap size debugging
|
||||
#ifndef LT_LOG_HEAP
|
||||
#define LT_LOG_HEAP 0
|
||||
@@ -71,31 +77,48 @@
|
||||
#define LT_UART_DEFAULT_SERIAL LT_UART_DEFAULT_PORT
|
||||
#endif
|
||||
|
||||
// Per-module debugging
|
||||
// Misc options
|
||||
#ifndef LT_USE_TIME
|
||||
#define LT_USE_TIME 0
|
||||
#endif
|
||||
|
||||
// Per-module logging output - applies to all loglevels
|
||||
#ifndef LT_DEBUG_ALL
|
||||
#define LT_DEBUG_ALL 0
|
||||
#endif
|
||||
|
||||
#ifndef LT_DEBUG_WIFI
|
||||
#define LT_DEBUG_WIFI 0
|
||||
#define LT_DEBUG_WIFI 1
|
||||
#endif
|
||||
|
||||
#ifndef LT_DEBUG_WIFI_CLIENT
|
||||
#define LT_DEBUG_WIFI_CLIENT 0
|
||||
#ifndef LT_DEBUG_CLIENT
|
||||
#define LT_DEBUG_CLIENT LT_DEBUG_ALL
|
||||
#endif
|
||||
|
||||
#ifndef LT_DEBUG_WIFI_SERVER
|
||||
#define LT_DEBUG_WIFI_SERVER 0
|
||||
#endif
|
||||
|
||||
#ifndef LT_DEBUG_WIFI_STA
|
||||
#define LT_DEBUG_WIFI_STA 0
|
||||
#endif
|
||||
|
||||
#ifndef LT_DEBUG_WIFI_AP
|
||||
#define LT_DEBUG_WIFI_AP 0
|
||||
#ifndef LT_DEBUG_SERVER
|
||||
#define LT_DEBUG_SERVER LT_DEBUG_ALL
|
||||
#endif
|
||||
|
||||
#ifndef LT_DEBUG_SSL
|
||||
#define LT_DEBUG_SSL 0
|
||||
#define LT_DEBUG_SSL LT_DEBUG_ALL
|
||||
#endif
|
||||
|
||||
#ifndef LT_DEBUG_OTA
|
||||
#define LT_DEBUG_OTA 0
|
||||
#define LT_DEBUG_OTA 1
|
||||
#endif
|
||||
|
||||
#ifndef LT_DEBUG_FDB
|
||||
#define LT_DEBUG_FDB 0
|
||||
#endif
|
||||
|
||||
#ifndef LT_DEBUG_MDNS
|
||||
#define LT_DEBUG_MDNS LT_DEBUG_ALL
|
||||
#endif
|
||||
|
||||
#ifndef LT_DEBUG_LWIP
|
||||
#define LT_DEBUG_LWIP 0
|
||||
#endif
|
||||
|
||||
#ifndef LT_DEBUG_LWIP_ASSERT
|
||||
#define LT_DEBUG_LWIP_ASSERT 0
|
||||
#endif
|
||||
|
||||
@@ -21,6 +21,13 @@ extern bool startMainTask();
|
||||
*/
|
||||
extern void mainTask(const void *arg);
|
||||
|
||||
/**
|
||||
* @brief Run periodic tasks, like printing free heap or checking millis() overflow.
|
||||
*
|
||||
* This is called during delaying operations, like yield() or delay().
|
||||
*/
|
||||
extern void runPeriodicTasks();
|
||||
|
||||
#define PIN_NONE (1 << 0)
|
||||
#define PIN_GPIO (1 << 1)
|
||||
#define PIN_IRQ (1 << 2)
|
||||
|
||||
@@ -7,9 +7,21 @@
|
||||
|
||||
#if LT_LOGGER_CALLER
|
||||
#define LT_LOG(level, caller, line, ...) lt_log(level, caller, line, __VA_ARGS__)
|
||||
#define LT_LOGM(level, module, caller, line, ...) \
|
||||
do { \
|
||||
if (LT_DEBUG_##module) { \
|
||||
lt_log(level, caller, line, #module ": " __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
void lt_log(const uint8_t level, const char *caller, const unsigned short line, const char *format, ...);
|
||||
#else
|
||||
#define LT_LOG(level, caller, line, ...) lt_log(level, __VA_ARGS__)
|
||||
#define LT_LOGM(level, module, caller, line, ...) \
|
||||
do { \
|
||||
if (LT_DEBUG_##module) { \
|
||||
lt_log(level, #module ": " __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
void lt_log(const uint8_t level, const char *format, ...);
|
||||
#endif
|
||||
|
||||
@@ -26,41 +38,55 @@ void lt_log_set_port(uint8_t port);
|
||||
void lt_log_disable();
|
||||
|
||||
#if LT_LEVEL_TRACE >= LT_LOGLEVEL
|
||||
#define LT_T(...) LT_LOG(LT_LEVEL_TRACE, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#define LT_V(...) LT_LOG(LT_LEVEL_TRACE, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#define LT_T(...) LT_LOG(LT_LEVEL_TRACE, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#define LT_V(...) LT_LOG(LT_LEVEL_TRACE, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#define LT_TM(module, ...) LT_LOGM(LT_LEVEL_TRACE, module, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#define LT_VM(module, ...) LT_LOGM(LT_LEVEL_TRACE, module, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define LT_T(...)
|
||||
#define LT_V(...)
|
||||
#define LT_TM(...)
|
||||
#define LT_VM(...)
|
||||
#endif
|
||||
|
||||
#if LT_LEVEL_DEBUG >= LT_LOGLEVEL
|
||||
#define LT_D(...) LT_LOG(LT_LEVEL_DEBUG, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#define LT_D(...) LT_LOG(LT_LEVEL_DEBUG, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#define LT_DM(module, ...) LT_LOGM(LT_LEVEL_DEBUG, module, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define LT_D(...)
|
||||
#define LT_DM(...)
|
||||
#endif
|
||||
|
||||
#if LT_LEVEL_INFO >= LT_LOGLEVEL
|
||||
#define LT_I(...) LT_LOG(LT_LEVEL_INFO, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#define LT_I(...) LT_LOG(LT_LEVEL_INFO, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#define LT_IM(module, ...) LT_LOGM(LT_LEVEL_INFO, module, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define LT_I(...)
|
||||
#define LT_IM(...)
|
||||
#endif
|
||||
|
||||
#if LT_LEVEL_WARN >= LT_LOGLEVEL
|
||||
#define LT_W(...) LT_LOG(LT_LEVEL_WARN, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#define LT_W(...) LT_LOG(LT_LEVEL_WARN, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#define LT_WM(module, ...) LT_LOGM(LT_LEVEL_WARN, module, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define LT_W(...)
|
||||
#define LT_WM(...)
|
||||
#endif
|
||||
|
||||
#if LT_LEVEL_ERROR >= LT_LOGLEVEL
|
||||
#define LT_E(...) LT_LOG(LT_LEVEL_ERROR, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#define LT_E(...) LT_LOG(LT_LEVEL_ERROR, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#define LT_EM(module, ...) LT_LOGM(LT_LEVEL_ERROR, module, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define LT_E(...)
|
||||
#define LT_EM(...)
|
||||
#endif
|
||||
|
||||
#if LT_LEVEL_FATAL >= LT_LOGLEVEL
|
||||
#define LT_F(...) LT_LOG(LT_LEVEL_FATAL, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#define LT_F(...) LT_LOG(LT_LEVEL_FATAL, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#define LT_FM(module, ...) LT_LOGM(LT_LEVEL_FATAL, module, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define LT_F(...)
|
||||
#define LT_FM(...)
|
||||
#endif
|
||||
|
||||
#if LT_LOG_HEAP
|
||||
@@ -96,20 +122,6 @@ void lt_log_disable();
|
||||
#define ets_printf(...) LT_I(__VA_ARGS__)
|
||||
#define ETS_PRINTF(...) LT_I(__VA_ARGS__)
|
||||
|
||||
#define LT_T_MOD(module, ...) \
|
||||
do { \
|
||||
if (module) { \
|
||||
LT_T(__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define LT_D_MOD(module, ...) \
|
||||
do { \
|
||||
if (module) { \
|
||||
LT_D(__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define LT_RET(ret) \
|
||||
LT_E("ret=%d", ret); \
|
||||
return ret;
|
||||
@@ -155,38 +167,3 @@ void lt_log_disable();
|
||||
#else
|
||||
#define LT_ERRNO()
|
||||
#endif
|
||||
|
||||
// WiFi.cpp
|
||||
#define LT_T_WG(...) LT_T_MOD(LT_DEBUG_WIFI, __VA_ARGS__)
|
||||
#define LT_V_WG(...) LT_T_MOD(LT_DEBUG_WIFI, __VA_ARGS__)
|
||||
#define LT_D_WG(...) LT_D_MOD(LT_DEBUG_WIFI, __VA_ARGS__)
|
||||
|
||||
// WiFiClient.cpp
|
||||
#define LT_T_WC(...) LT_T_MOD(LT_DEBUG_WIFI_CLIENT, __VA_ARGS__)
|
||||
#define LT_V_WC(...) LT_T_MOD(LT_DEBUG_WIFI_CLIENT, __VA_ARGS__)
|
||||
#define LT_D_WC(...) LT_D_MOD(LT_DEBUG_WIFI_CLIENT, __VA_ARGS__)
|
||||
|
||||
// WiFiServer.cpp
|
||||
#define LT_T_WS(...) LT_T_MOD(LT_DEBUG_WIFI_SERVER, __VA_ARGS__)
|
||||
#define LT_V_WS(...) LT_T_MOD(LT_DEBUG_WIFI_SERVER, __VA_ARGS__)
|
||||
#define LT_D_WS(...) LT_D_MOD(LT_DEBUG_WIFI_SERVER, __VA_ARGS__)
|
||||
|
||||
// WiFiSTA.cpp
|
||||
#define LT_T_WSTA(...) LT_T_MOD(LT_DEBUG_WIFI_STA, __VA_ARGS__)
|
||||
#define LT_V_WSTA(...) LT_T_MOD(LT_DEBUG_WIFI_STA, __VA_ARGS__)
|
||||
#define LT_D_WSTA(...) LT_D_MOD(LT_DEBUG_WIFI_STA, __VA_ARGS__)
|
||||
|
||||
// WiFiAP.cpp
|
||||
#define LT_T_WAP(...) LT_T_MOD(LT_DEBUG_WIFI_AP, __VA_ARGS__)
|
||||
#define LT_V_WAP(...) LT_T_MOD(LT_DEBUG_WIFI_AP, __VA_ARGS__)
|
||||
#define LT_D_WAP(...) LT_D_MOD(LT_DEBUG_WIFI_AP, __VA_ARGS__)
|
||||
|
||||
// WiFiClientSecure.cpp & implementations
|
||||
#define LT_T_SSL(...) LT_T_MOD(LT_DEBUG_SSL, __VA_ARGS__)
|
||||
#define LT_V_SSL(...) LT_T_MOD(LT_DEBUG_SSL, __VA_ARGS__)
|
||||
#define LT_D_SSL(...) LT_D_MOD(LT_DEBUG_SSL, __VA_ARGS__)
|
||||
|
||||
// Update.cpp
|
||||
#define LT_T_OTA(...) LT_T_MOD(LT_DEBUG_OTA, __VA_ARGS__)
|
||||
#define LT_V_OTA(...) LT_T_MOD(LT_DEBUG_OTA, __VA_ARGS__)
|
||||
#define LT_D_OTA(...) LT_D_MOD(LT_DEBUG_OTA, __VA_ARGS__)
|
||||
|
||||
@@ -32,6 +32,23 @@ void mainTask(const void *arg) {
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned long periodicTasks[] = {0, 0};
|
||||
|
||||
void runPeriodicTasks() {
|
||||
#if LT_LOG_HEAP
|
||||
if (millis() - periodicTasks[0] > 1000) {
|
||||
LT_HEAP_I();
|
||||
periodicTasks[0] = millis();
|
||||
}
|
||||
#endif
|
||||
#if LT_USE_TIME
|
||||
if (millis() - periodicTasks[1] > 10000) {
|
||||
gettimeofday(NULL, NULL);
|
||||
periodicTasks[1] = millis();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
// print a startup banner
|
||||
LT_BANNER();
|
||||
@@ -47,7 +64,7 @@ int main(void) {
|
||||
fal_root_part = (fal_partition_t)fal_partition_find("root");
|
||||
// start the main task and OS kernel
|
||||
if (!startMainTask()) {
|
||||
LT_E("Couldn't start the main task");
|
||||
LT_F("Couldn't start the main task");
|
||||
}
|
||||
|
||||
while (1) {}
|
||||
@@ -37,7 +37,7 @@ class SocketHandle {
|
||||
};
|
||||
|
||||
LwIPClient::LwIPClient() {
|
||||
LT_V_WC("LwIPClient()");
|
||||
LT_VM(CLIENT, "LwIPClient()");
|
||||
_connected = false;
|
||||
_sock = NULL;
|
||||
_rxBuffer = NULL;
|
||||
@@ -45,7 +45,7 @@ LwIPClient::LwIPClient() {
|
||||
}
|
||||
|
||||
LwIPClient::LwIPClient(int sock) {
|
||||
LT_V_WC("LwIPClient(%d)", sock);
|
||||
LT_VM(CLIENT, "LwIPClient(%d)", sock);
|
||||
_connected = true;
|
||||
_sock = std::make_shared<SocketHandle>(sock);
|
||||
_rxBuffer = std::make_shared<LwIPRxBuffer>(sock);
|
||||
@@ -53,7 +53,7 @@ LwIPClient::LwIPClient(int sock) {
|
||||
}
|
||||
|
||||
LwIPClient::~LwIPClient() {
|
||||
LT_V_WC("~LwIPClient()");
|
||||
LT_VM(CLIENT, "~LwIPClient()");
|
||||
stop();
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ int LwIPClient::connect(IPAddress ip, uint16_t port, int32_t timeout) {
|
||||
stop();
|
||||
int sock = lwip_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (sock < 0) {
|
||||
LT_D_WC("socket failed");
|
||||
LT_DM(CLIENT, "socket failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -114,19 +114,19 @@ int LwIPClient::connect(IPAddress ip, uint16_t port, int32_t timeout) {
|
||||
|
||||
int res = lwip_connect(sock, (struct sockaddr *)&addr, sizeof(addr));
|
||||
if (res < 0 && errno != EINPROGRESS) {
|
||||
LT_E("Connect failed; errno=%d", errno);
|
||||
LT_EM(CLIENT, "Connect failed; errno=%d", errno);
|
||||
lwip_close(sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = lwip_select(sock + 1, NULL, &fdset, NULL, timeout < 0 ? NULL : &tv);
|
||||
if (res < 0) {
|
||||
LT_E("Select failed; errno=%d", errno);
|
||||
LT_EM(CLIENT, "Select failed; errno=%d", errno);
|
||||
lwip_close(sock);
|
||||
return 0;
|
||||
}
|
||||
if (res == 0) {
|
||||
LT_E("Select timeout; errno=%d", errno);
|
||||
LT_EM(CLIENT, "Select timeout; errno=%d", errno);
|
||||
lwip_close(sock);
|
||||
return 0;
|
||||
}
|
||||
@@ -136,7 +136,7 @@ int LwIPClient::connect(IPAddress ip, uint16_t port, int32_t timeout) {
|
||||
res = lwip_getsockopt(sock, SOL_SOCKET, SO_ERROR, &sockerr, &len);
|
||||
|
||||
if (res < 0 || sockerr != 0) {
|
||||
LT_E("Socket error; res=%d, sockerr=%d", res, sockerr);
|
||||
LT_EM(CLIENT, "Socket error; res=%d, sockerr=%d", res, sockerr);
|
||||
lwip_close(sock);
|
||||
return 0;
|
||||
}
|
||||
@@ -198,7 +198,7 @@ size_t LwIPClient::write(const uint8_t *buf, size_t size) {
|
||||
retry--;
|
||||
|
||||
if (lwip_select(fd() + 1, NULL, &fdset, NULL, &tv) < 0) {
|
||||
LT_W("Select failed; errno=%d", errno);
|
||||
LT_WM(CLIENT, "Select failed; errno=%d", errno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -214,7 +214,7 @@ size_t LwIPClient::write(const uint8_t *buf, size_t size) {
|
||||
retry = WIFI_CLIENT_WRITE_RETRY;
|
||||
}
|
||||
} else if (res < 0 && errno != EAGAIN) {
|
||||
LT_W("Send failed; errno=%d", errno);
|
||||
LT_WM(CLIENT, "Send failed; errno=%d", errno);
|
||||
setWriteError(res);
|
||||
_connected = false;
|
||||
retry = 0;
|
||||
@@ -223,7 +223,7 @@ size_t LwIPClient::write(const uint8_t *buf, size_t size) {
|
||||
}
|
||||
}
|
||||
}
|
||||
LT_D_WC("wrote %d bytes", written);
|
||||
LT_DM(CLIENT, "wrote %d bytes", written);
|
||||
return written;
|
||||
}
|
||||
|
||||
@@ -306,7 +306,7 @@ void LwIPClient::flush() {
|
||||
}
|
||||
|
||||
void LwIPClient::stop() {
|
||||
LT_V_WC("Stopping TCP");
|
||||
LT_VM(CLIENT, "Stopping TCP");
|
||||
_connected = false;
|
||||
_sock = NULL;
|
||||
_rxBuffer = NULL;
|
||||
@@ -327,11 +327,11 @@ uint8_t LwIPClient::connected() {
|
||||
case ECONNRESET:
|
||||
case ECONNREFUSED:
|
||||
case ECONNABORTED:
|
||||
LT_W("Connection closed; errno=%d", errno);
|
||||
LT_IM(CLIENT, "Connection closed; errno=%d", errno);
|
||||
_connected = false;
|
||||
break;
|
||||
default:
|
||||
LT_I("Connection status unknown; errno=%d", errno);
|
||||
LT_WM(CLIENT, "Connection status unknown; errno=%d", errno);
|
||||
_connected = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -14,13 +14,13 @@ extern "C" {
|
||||
|
||||
size_t LwIPRxBuffer::r_available() {
|
||||
if (_sock < 0) {
|
||||
LT_D_WC("_sock < 0");
|
||||
LT_DM(CLIENT, "_sock < 0");
|
||||
return 0;
|
||||
}
|
||||
int count = 0; // must be of same size as in lwip_ioctl()
|
||||
int res = lwip_ioctl(_sock, FIONREAD, &count);
|
||||
if (res < 0) {
|
||||
LT_D_WC("lwip_ioctl()=%d, errno=%d", res, errno);
|
||||
LT_DM(CLIENT, "lwip_ioctl()=%d, errno=%d", res, errno);
|
||||
_failed = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ bool LwIPServer::begin(uint16_t port, bool reuseAddr) {
|
||||
|
||||
_sock = lwip_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (_sock < 0) {
|
||||
LT_E("Socket failed; errno=%d", errno);
|
||||
LT_EM(SERVER, "Socket failed; errno=%d", errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -45,17 +45,17 @@ bool LwIPServer::begin(uint16_t port, bool reuseAddr) {
|
||||
addr.sin_port = htons(_port);
|
||||
|
||||
if (lwip_bind(_sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
LT_E("Bind failed; errno=%d", errno);
|
||||
LT_EM(SERVER, "Bind failed; errno=%d", errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lwip_listen(_sock, _maxClients) < 0) {
|
||||
LT_E("Bind failed; errno=%d", errno);
|
||||
LT_EM(SERVER, "Bind failed; errno=%d", errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t *addrB = (uint8_t *)&_addr;
|
||||
LT_I("Server running on %hhu.%hhu.%hhu.%hhu:%hu", addrB[0], addrB[1], addrB[2], addrB[3], _port);
|
||||
LT_IM(SERVER, "Server running on %hhu.%hhu.%hhu.%hhu:%hu", addrB[0], addrB[1], addrB[2], addrB[3], _port);
|
||||
|
||||
lwip_fcntl(_sock, F_SETFL, O_NONBLOCK);
|
||||
_active = true;
|
||||
@@ -99,7 +99,7 @@ WiFiClient LwIPServer::accept() {
|
||||
// and receive data, so LwIP still sees a connected client that sends nothing. At least
|
||||
// that's what I understand. And any loop that doesn't call delay() seems to block the TCP
|
||||
// stack completely and prevents it from even being pinged.
|
||||
LT_D_WS("Got client");
|
||||
LT_DM(SERVER, "Got client");
|
||||
delay(5);
|
||||
return WiFiClient(sock);
|
||||
}
|
||||
|
||||
@@ -22,12 +22,12 @@ MbedTLSClient::MbedTLSClient(int sock) : WiFiClient(sock) {
|
||||
}
|
||||
|
||||
MbedTLSClient::~MbedTLSClient() {
|
||||
LT_V_WC("~MbedTLSClient()");
|
||||
LT_VM(CLIENT, "~MbedTLSClient()");
|
||||
stop();
|
||||
}
|
||||
|
||||
void MbedTLSClient::stop() {
|
||||
LT_V_SSL("Stopping SSL");
|
||||
LT_VM(SSL, "Stopping SSL");
|
||||
|
||||
if (_sslCfg.ca_chain) {
|
||||
mbedtls_x509_crt_free(&_caCert);
|
||||
@@ -88,7 +88,7 @@ void debug_cb(void *ctx, int level, const char *file, int line, const char *str)
|
||||
uint16_t len = strlen(str);
|
||||
char *msg = (char *)str;
|
||||
msg[len - 1] = '\0';
|
||||
LT_I("%04d: |%d| %s", line, level, msg);
|
||||
LT_IM(SSL, "%04d: |%d| %s", line, level, msg);
|
||||
}
|
||||
|
||||
int MbedTLSClient::connect(
|
||||
@@ -115,13 +115,13 @@ int MbedTLSClient::connect(
|
||||
|
||||
int ret = WiFiClient::connect(addr, port, timeout);
|
||||
if (ret < 0) {
|
||||
LT_E("SSL socket failed");
|
||||
LT_EM(SSL, "SSL socket failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *uid = "lt-ssl"; // TODO
|
||||
|
||||
LT_V_SSL("Init SSL");
|
||||
LT_VM(SSL, "Init SSL");
|
||||
init();
|
||||
LT_HEAP_I();
|
||||
|
||||
@@ -160,7 +160,7 @@ int MbedTLSClient::connect(
|
||||
#ifdef MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED
|
||||
uint16_t len = strlen(psk);
|
||||
if ((len & 1) != 0 || len > 2 * MBEDTLS_PSK_MAX_LEN) {
|
||||
LT_E("PSK length invalid");
|
||||
LT_EM(SSL, "PSK length invalid");
|
||||
return -1;
|
||||
}
|
||||
unsigned char pskBin[MBEDTLS_PSK_MAX_LEN] = {};
|
||||
@@ -185,13 +185,13 @@ int MbedTLSClient::connect(
|
||||
if (!_insecure && clientCert && clientKey) {
|
||||
mbedtls_x509_crt_init(&_clientCert);
|
||||
mbedtls_pk_init(&_clientKey);
|
||||
LT_V_SSL("Loading client cert");
|
||||
LT_VM(SSL, "Loading client cert");
|
||||
ret = mbedtls_x509_crt_parse(&_clientCert, (const unsigned char *)clientCert, strlen(clientCert) + 1);
|
||||
if (ret < 0) {
|
||||
mbedtls_x509_crt_free(&_clientCert);
|
||||
LT_RET(ret);
|
||||
}
|
||||
LT_V_SSL("Loading private key");
|
||||
LT_VM(SSL, "Loading private key");
|
||||
ret = mbedtls_pk_parse_key(&_clientKey, (const unsigned char *)clientKey, strlen(clientKey) + 1, NULL, 0);
|
||||
if (ret < 0) {
|
||||
mbedtls_x509_crt_free(&_clientCert);
|
||||
@@ -200,7 +200,7 @@ int MbedTLSClient::connect(
|
||||
mbedtls_ssl_conf_own_cert(&_sslCfg, &_clientCert, &_clientKey);
|
||||
}
|
||||
|
||||
LT_V_SSL("Setting TLS hostname");
|
||||
LT_VM(SSL, "Setting TLS hostname");
|
||||
ret = mbedtls_ssl_set_hostname(&_sslCtx, host);
|
||||
LT_RET_NZ(ret);
|
||||
|
||||
@@ -214,7 +214,7 @@ int MbedTLSClient::connect(
|
||||
|
||||
LT_HEAP_I();
|
||||
|
||||
LT_V_SSL("SSL handshake");
|
||||
LT_VM(SSL, "SSL handshake");
|
||||
if (_handshakeTimeout == 0)
|
||||
_handshakeTimeout = timeout;
|
||||
unsigned long start = millis();
|
||||
@@ -223,7 +223,7 @@ int MbedTLSClient::connect(
|
||||
LT_RET(ret);
|
||||
}
|
||||
if ((millis() - start) > _handshakeTimeout) {
|
||||
LT_E("SSL handshake timeout");
|
||||
LT_EM(SSL, "SSL handshake timeout");
|
||||
return -1;
|
||||
}
|
||||
delay(2);
|
||||
@@ -232,26 +232,27 @@ int MbedTLSClient::connect(
|
||||
LT_HEAP_I();
|
||||
|
||||
if (clientCert && clientKey) {
|
||||
LT_D_SSL(
|
||||
LT_DM(
|
||||
SSL,
|
||||
"Protocol %s, ciphersuite %s",
|
||||
mbedtls_ssl_get_version(&_sslCtx),
|
||||
mbedtls_ssl_get_ciphersuite(&_sslCtx)
|
||||
);
|
||||
ret = mbedtls_ssl_get_record_expansion(&_sslCtx);
|
||||
if (ret >= 0)
|
||||
LT_D_SSL("Record expansion: %d", ret);
|
||||
LT_DM(SSL, "Record expansion: %d", ret);
|
||||
else {
|
||||
LT_W("Record expansion unknown");
|
||||
LT_WM(SSL, "Record expansion unknown");
|
||||
}
|
||||
}
|
||||
|
||||
LT_V_SSL("Verifying certificate");
|
||||
LT_VM(SSL, "Verifying certificate");
|
||||
ret = mbedtls_ssl_get_verify_result(&_sslCtx);
|
||||
if (ret) {
|
||||
char buf[512];
|
||||
memset(buf, 0, sizeof(buf));
|
||||
mbedtls_x509_crt_verify_info(buf, sizeof(buf), " ! ", ret);
|
||||
LT_E("Failed to verify peer certificate! Verification info: %s", buf);
|
||||
LT_EM(SSL, "Failed to verify peer certificate! Verification info: %s", buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -417,7 +418,7 @@ bool MbedTLSClient::verify(const char *fingerprint, const char *domainName) {
|
||||
return false;
|
||||
|
||||
if (memcmp(fpLocal, fpRemote, 32)) {
|
||||
LT_D_SSL("Fingerprints don't match");
|
||||
LT_DM(SSL, "Fingerprints don't match");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -438,7 +439,7 @@ void MbedTLSClient::setAlpnProtocols(const char **alpnProtocols) {
|
||||
bool MbedTLSClient::getFingerprintSHA256(uint8_t result[32]) {
|
||||
const mbedtls_x509_crt *cert = mbedtls_ssl_get_peer_cert(&_sslCtx);
|
||||
if (!cert) {
|
||||
LT_E("Failed to get peer certificate");
|
||||
LT_EM(SSL, "Failed to get peer certificate");
|
||||
return false;
|
||||
}
|
||||
mbedtls_sha256_context shaCtx;
|
||||
|
||||
@@ -25,13 +25,8 @@
|
||||
|
||||
size_t StreamString::write(const uint8_t *data, size_t size) {
|
||||
if(size && data) {
|
||||
const unsigned int newlen = len + size;
|
||||
if(reserve(newlen + 1)) {
|
||||
memcpy((void *) (buffer + len), (const void *) data, size);
|
||||
changeBuffer(newlen);
|
||||
*(buffer + newlen) = 0x00; // add null for string end
|
||||
return size;
|
||||
}
|
||||
concat(data, size);
|
||||
return size;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -18,16 +18,20 @@ bool UpdateClass::begin(size_t size, int command, int unused2, uint8_t unused3,
|
||||
return false;
|
||||
cleanup();
|
||||
|
||||
LT_D_OTA("begin(%u, ...) / OTA curr: %u, trgt: %u", size, LT.otaGetRunning(), LT.otaGetTarget());
|
||||
LT_DM(OTA, "begin(%u, ...) / OTA curr: %u, trgt: %u", size, LT.otaGetRunning(), LT.otaGetTarget());
|
||||
|
||||
ctx = uf2_ctx_init(LT.otaGetTarget(), FAMILY);
|
||||
info = uf2_info_init();
|
||||
|
||||
if (!size)
|
||||
return errorArd(UPDATE_ERROR_SIZE);
|
||||
if (!size) {
|
||||
cleanup(UPDATE_ERROR_SIZE);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (command != U_FLASH)
|
||||
return errorArd(UPDATE_ERROR_BAD_ARGUMENT);
|
||||
if (command != U_FLASH) {
|
||||
cleanup(UPDATE_ERROR_BAD_ARGUMENT);
|
||||
return false;
|
||||
}
|
||||
|
||||
bytesTotal = size;
|
||||
return true;
|
||||
@@ -46,12 +50,15 @@ bool UpdateClass::end(bool evenIfRemaining) {
|
||||
|
||||
if (!isFinished() && !evenIfRemaining) {
|
||||
// abort if not finished
|
||||
return errorArd(UPDATE_ERROR_ABORT);
|
||||
cleanup(UPDATE_ERROR_ABORT);
|
||||
return false;
|
||||
}
|
||||
// TODO what is evenIfRemaining for?
|
||||
if (!LT.otaSwitch())
|
||||
if (!LT.otaSwitch()) {
|
||||
// try to activate the second OTA
|
||||
return errorArd(UPDATE_ERROR_ACTIVATE);
|
||||
cleanup(UPDATE_ERROR_ACTIVATE);
|
||||
return false;
|
||||
}
|
||||
|
||||
cleanup();
|
||||
return true;
|
||||
@@ -72,7 +79,7 @@ size_t UpdateClass::write(uint8_t *data, size_t len) {
|
||||
// 0 if not running
|
||||
return 0;
|
||||
|
||||
LT_D_OTA("write(%u) / buf %u/512", len, bufSize());
|
||||
LT_VM(OTA, "write(%u) / buf %u/512", len, bufSize());
|
||||
|
||||
/* while (buf == bufPos && len >= UF2_BLOCK_SIZE) {
|
||||
// buffer empty and entire block is in data
|
||||
@@ -89,9 +96,11 @@ size_t UpdateClass::write(uint8_t *data, size_t len) {
|
||||
uint16_t toWrite; // 1..512
|
||||
while (len && (toWrite = min(len, bufLeft()))) {
|
||||
tryWriteData(data, toWrite);
|
||||
if (hasError())
|
||||
if (hasError()) {
|
||||
// return on errors
|
||||
printErrorContext2(data, toWrite);
|
||||
return written;
|
||||
}
|
||||
data += toWrite;
|
||||
len -= toWrite;
|
||||
written += toWrite;
|
||||
@@ -113,7 +122,7 @@ size_t UpdateClass::writeStream(Stream &data) {
|
||||
if (available <= 0) {
|
||||
if (millis() - lastData > UPDATE_TIMEOUT_MS) {
|
||||
// waited for data too long; abort with error
|
||||
errorArd(UPDATE_ERROR_STREAM);
|
||||
cleanup(UPDATE_ERROR_STREAM);
|
||||
return written;
|
||||
}
|
||||
continue;
|
||||
@@ -127,9 +136,11 @@ size_t UpdateClass::writeStream(Stream &data) {
|
||||
bufPos += read;
|
||||
written += read;
|
||||
tryWriteData();
|
||||
if (hasError())
|
||||
if (hasError()) {
|
||||
// return on errors
|
||||
printErrorContext2(NULL, read); // buf is not valid anymore
|
||||
return written;
|
||||
}
|
||||
}
|
||||
return written;
|
||||
}
|
||||
@@ -145,7 +156,7 @@ size_t UpdateClass::writeStream(Stream &data) {
|
||||
size_t UpdateClass::tryWriteData(uint8_t *data, size_t len) {
|
||||
uf2_block_t *block = NULL;
|
||||
|
||||
LT_V_OTA("Writing %u to buffer (%u/512)", len, bufSize());
|
||||
LT_VM(OTA, "Writing %u to buffer (%u/512)", len, bufSize());
|
||||
|
||||
if (len == UF2_BLOCK_SIZE) {
|
||||
// data has a complete block
|
||||
@@ -164,7 +175,7 @@ size_t UpdateClass::tryWriteData(uint8_t *data, size_t len) {
|
||||
|
||||
// a complete block has been found
|
||||
if (block) {
|
||||
if (errorUf2(uf2_check_block(ctx, block)))
|
||||
if (checkUf2Error(uf2_check_block(ctx, block)))
|
||||
// block is invalid
|
||||
return 0;
|
||||
|
||||
@@ -174,23 +185,24 @@ size_t UpdateClass::tryWriteData(uint8_t *data, size_t len) {
|
||||
|
||||
if (!bytesWritten) {
|
||||
// parse header block to allow retrieving firmware info
|
||||
if (errorUf2(uf2_parse_header(ctx, block, info)))
|
||||
if (checkUf2Error(uf2_parse_header(ctx, block, info)))
|
||||
// header is invalid
|
||||
return 0;
|
||||
|
||||
LT_I("OTA: %s v%s - LT v%s @ %s", info->fw_name, info->fw_version, info->lt_version, info->board);
|
||||
LT_IM(OTA, "%s v%s - LT v%s @ %s", info->fw_name, info->fw_version, info->lt_version, info->board);
|
||||
|
||||
if (bytesTotal == UPDATE_SIZE_UNKNOWN) {
|
||||
// set total update size from block count info
|
||||
bytesTotal = block->block_count * UF2_BLOCK_SIZE;
|
||||
} else if (bytesTotal != block->block_count * UF2_BLOCK_SIZE) {
|
||||
// given update size does not match the block count
|
||||
LT_D_OTA("Image size wrong; got %u, calculated %u", bytesTotal, block->block_count * UF2_BLOCK_SIZE);
|
||||
return errorArd(UPDATE_ERROR_SIZE);
|
||||
LT_EM(OTA, "Image size wrong; got %u, calculated %u", bytesTotal, block->block_count * UF2_BLOCK_SIZE);
|
||||
cleanup(UPDATE_ERROR_SIZE);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
// write data blocks normally
|
||||
if (errorUf2(uf2_write(ctx, block)))
|
||||
if (checkUf2Error(uf2_write(ctx, block)))
|
||||
// block writing failed
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -75,10 +75,11 @@ class UpdateClass {
|
||||
const char *getBoardName();
|
||||
|
||||
private: /* UpdateUtil.cpp */
|
||||
void cleanup();
|
||||
bool errorUf2(uf2_err_t err);
|
||||
bool errorArd(uint8_t err);
|
||||
void cleanup(uint8_t ardErr = UPDATE_ERROR_OK, uf2_err_t uf2Err = UF2_ERR_OK);
|
||||
bool checkUf2Error(uf2_err_t err);
|
||||
void bufAlloc();
|
||||
void printErrorContext1();
|
||||
void printErrorContext2(const uint8_t *data, size_t len);
|
||||
uint16_t bufLeft();
|
||||
uint16_t bufSize();
|
||||
|
||||
@@ -117,8 +118,12 @@ class UpdateClass {
|
||||
return errUf2;
|
||||
}
|
||||
|
||||
uint16_t getErrorCode() {
|
||||
return (errArd << 8) | errUf2;
|
||||
}
|
||||
|
||||
void clearError() {
|
||||
errorArd(UPDATE_ERROR_OK);
|
||||
cleanup(UPDATE_ERROR_OK);
|
||||
}
|
||||
|
||||
bool hasError() {
|
||||
|
||||
@@ -30,7 +30,15 @@ UpdateClass &UpdateClass::onProgress(THandlerFunction_Progress callback) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
void UpdateClass::cleanup() {
|
||||
void UpdateClass::cleanup(uint8_t ardErr, uf2_err_t uf2Err) {
|
||||
errUf2 = uf2Err;
|
||||
errArd = ardErr;
|
||||
|
||||
#if LT_DEBUG_OTA
|
||||
if (hasError())
|
||||
printErrorContext1();
|
||||
#endif
|
||||
|
||||
free(ctx); // NULL in constructor
|
||||
ctx = NULL;
|
||||
uf2_info_free(info); // NULL in constructor
|
||||
@@ -40,8 +48,6 @@ void UpdateClass::cleanup() {
|
||||
|
||||
bytesWritten = 0;
|
||||
bytesTotal = 0;
|
||||
errUf2 = UF2_ERR_OK;
|
||||
errArd = UPDATE_ERROR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,38 +57,19 @@ void UpdateClass::cleanup() {
|
||||
* Use like: "if (errorUf2(...)) return false;"
|
||||
* @return true if err is not OK, false otherwise
|
||||
*/
|
||||
bool UpdateClass::errorUf2(uf2_err_t err) {
|
||||
if (err)
|
||||
LT_D_OTA("[%4d] errorUf2(%d)", ctx ? ctx->seq : 0, err);
|
||||
bool UpdateClass::checkUf2Error(uf2_err_t err) {
|
||||
if (err <= UF2_ERR_IGNORE)
|
||||
return false;
|
||||
cleanup();
|
||||
errUf2 = err;
|
||||
errArd = errorMap[err];
|
||||
cleanup(errorMap[err], err);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set errUf2 and errArd according to given Arduino error code.
|
||||
* Abort the update.
|
||||
* Use like: "return errorArd(...);"
|
||||
* @return false - always
|
||||
*/
|
||||
bool UpdateClass::errorArd(uint8_t err) {
|
||||
if (err)
|
||||
LT_D_OTA("[%4d] errorArd(%d)", ctx ? ctx->seq : 0, err);
|
||||
cleanup();
|
||||
errUf2 = UF2_ERR_OK;
|
||||
errArd = err;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort the update with UPDATE_ERROR_ABORT reason.
|
||||
*/
|
||||
void UpdateClass::abort() {
|
||||
LT_D_OTA("Aborting update");
|
||||
errorArd(UPDATE_ERROR_ABORT);
|
||||
LT_DM(OTA, "Aborting update");
|
||||
cleanup(UPDATE_ERROR_ABORT);
|
||||
}
|
||||
|
||||
void UpdateClass::bufAlloc() {
|
||||
@@ -105,6 +92,42 @@ void UpdateClass::printError(Print &out) {
|
||||
out.println(errorString());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Print details about the error and current OTA state.
|
||||
*/
|
||||
void UpdateClass::printErrorContext1() {
|
||||
#if LT_DEBUG_OTA
|
||||
LT_EM(OTA, "Error: %s", errorString());
|
||||
if (errArd == UPDATE_ERROR_ABORT)
|
||||
return;
|
||||
|
||||
LT_EM(OTA, "- written: %u of %u", bytesWritten, bytesTotal);
|
||||
LT_EM(OTA, "- buf: size=%u, left=%u", bufSize(), bufLeft());
|
||||
hexdump(buf, bufSize());
|
||||
|
||||
if (ctx)
|
||||
LT_EM(
|
||||
OTA,
|
||||
"- ctx: seq=%u, part1=%s, part2=%s",
|
||||
ctx->seq - 1, // print last parsed block seq
|
||||
ctx->part1 ? ctx->part1->name : NULL,
|
||||
ctx->part2 ? ctx->part2->name : NULL
|
||||
);
|
||||
|
||||
uf2_block_t *block = (uf2_block_t *)buf;
|
||||
if (buf)
|
||||
LT_EM(OTA, "- buf: seq=%u/%u, addr=%u, len=%u", block->block_seq, block->block_count, block->addr, block->len);
|
||||
#endif
|
||||
}
|
||||
|
||||
void UpdateClass::printErrorContext2(const uint8_t *data, size_t len) {
|
||||
#if LT_DEBUG_OTA
|
||||
LT_EM(OTA, "- while writing %u bytes", len);
|
||||
if (data)
|
||||
hexdump(data, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get string representation of the error in format
|
||||
* "ard=..,uf2=..". Returns "" if no error.
|
||||
|
||||
@@ -50,27 +50,27 @@ bool WiFiMulti::addAP(const char *ssid, const char *passphrase) {
|
||||
|
||||
if (!ssid || *ssid == 0x00 || strlen(ssid) > 31) {
|
||||
// fail SSID too long or missing!
|
||||
LT_E("SSID missing or too long");
|
||||
LT_EM(WIFI, "SSID missing or too long");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (passphrase && strlen(passphrase) > 64) {
|
||||
// fail passphrase too long!
|
||||
LT_E("Passphrase too long");
|
||||
LT_EM(WIFI, "Passphrase too long");
|
||||
return false;
|
||||
}
|
||||
|
||||
newAP.ssid = strdup(ssid);
|
||||
|
||||
if (!newAP.ssid) {
|
||||
LT_E("Fail newAP.ssid == 0");
|
||||
LT_EM(WIFI, "Fail newAP.ssid == 0");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (passphrase && *passphrase != 0x00) {
|
||||
newAP.passphrase = strdup(passphrase);
|
||||
if (!newAP.passphrase) {
|
||||
LT_E("Fail newAP.passphrase == 0");
|
||||
LT_EM(WIFI, "Fail newAP.passphrase == 0");
|
||||
free(newAP.ssid);
|
||||
return false;
|
||||
}
|
||||
@@ -79,7 +79,7 @@ bool WiFiMulti::addAP(const char *ssid, const char *passphrase) {
|
||||
}
|
||||
|
||||
APlist.push_back(newAP);
|
||||
LT_V("Add SSID: %s", newAP.ssid);
|
||||
LT_VM(WIFI, "Add SSID: %s", newAP.ssid);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -108,12 +108,12 @@ uint8_t WiFiMulti::run(uint32_t connectTimeout) {
|
||||
uint8_t bestBSSID[6];
|
||||
int32_t bestChannel = 0;
|
||||
|
||||
LT_I("Scan finished");
|
||||
LT_IM(WIFI, "Scan finished");
|
||||
|
||||
if (scanResult == 0) {
|
||||
LT_I("No networks found");
|
||||
LT_IM(WIFI, "No networks found");
|
||||
} else {
|
||||
LT_I("%d networks found", scanResult);
|
||||
LT_IM(WIFI, "%d networks found", scanResult);
|
||||
for (int8_t i = 0; i < scanResult; ++i) {
|
||||
|
||||
String ssid_scan;
|
||||
@@ -144,7 +144,8 @@ uint8_t WiFiMulti::run(uint32_t connectTimeout) {
|
||||
}
|
||||
|
||||
if (known) {
|
||||
LT_D(
|
||||
LT_DM(
|
||||
WIFI,
|
||||
" ---> %d: [%d][%02X:%02X:%02X:%02X:%02X:%02X] %s (%d) %c",
|
||||
i,
|
||||
chan_scan,
|
||||
@@ -159,7 +160,8 @@ uint8_t WiFiMulti::run(uint32_t connectTimeout) {
|
||||
(sec_scan == WIFI_AUTH_OPEN) ? ' ' : '*'
|
||||
);
|
||||
} else {
|
||||
LT_D(
|
||||
LT_DM(
|
||||
WIFI,
|
||||
" %d: [%d][%02X:%02X:%02X:%02X:%02X:%02X] %s (%d) %c",
|
||||
i,
|
||||
chan_scan,
|
||||
@@ -181,7 +183,8 @@ uint8_t WiFiMulti::run(uint32_t connectTimeout) {
|
||||
WiFi.scanDelete();
|
||||
|
||||
if (bestNetwork.ssid) {
|
||||
LT_I(
|
||||
LT_IM(
|
||||
WIFI,
|
||||
"Connecting to BSSID: %02X:%02X:%02X:%02X:%02X:%02X SSID: %s Channel: %d (%d)",
|
||||
bestBSSID[0],
|
||||
bestBSSID[1],
|
||||
@@ -208,33 +211,33 @@ uint8_t WiFiMulti::run(uint32_t connectTimeout) {
|
||||
IPAddress ip;
|
||||
switch (status) {
|
||||
case WL_CONNECTED:
|
||||
LT_I("Connecting done");
|
||||
LT_D("SSID: %s", WiFi.SSID().c_str());
|
||||
LT_IM(WIFI, "Connecting done");
|
||||
LT_DM(WIFI, "SSID: %s", WiFi.SSID().c_str());
|
||||
// TODO fix this after implementing IP format for printf()
|
||||
ip = WiFi.localIP();
|
||||
LT_D("IP: %u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
|
||||
LT_D("MAC: %s", WiFi.BSSIDstr().c_str());
|
||||
LT_D("Channel: %d", WiFi.channel());
|
||||
LT_DM(WIFI, "IP: %u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
|
||||
LT_DM(WIFI, "MAC: %s", WiFi.BSSIDstr().c_str());
|
||||
LT_DM(WIFI, "Channel: %d", WiFi.channel());
|
||||
break;
|
||||
case WL_NO_SSID_AVAIL:
|
||||
LT_E("Connecting failed; AP not found");
|
||||
LT_EM(WIFI, "Connecting failed; AP not found");
|
||||
break;
|
||||
case WL_CONNECT_FAILED:
|
||||
LT_E("Connecting failed");
|
||||
LT_EM(WIFI, "Connecting failed");
|
||||
break;
|
||||
default:
|
||||
LT_E("Connecting failed (%d)", status);
|
||||
LT_EM(WIFI, "Connecting failed (%d)", status);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
LT_E("No matching network found!");
|
||||
LT_EM(WIFI, "No matching network found!");
|
||||
}
|
||||
} else {
|
||||
// start scan
|
||||
LT_V("Delete old wifi config...");
|
||||
LT_VM(WIFI, "Delete old wifi config...");
|
||||
WiFi.disconnect();
|
||||
|
||||
LT_D("Start scan");
|
||||
LT_DM(WIFI, "Start scan");
|
||||
// scan wifi async mode
|
||||
WiFi.scanNetworks(true);
|
||||
}
|
||||
|
||||
@@ -3,71 +3,65 @@
|
||||
#ifdef LT_HAS_LWIP2
|
||||
|
||||
#include "mDNS.h"
|
||||
#include <vector>
|
||||
|
||||
extern "C" {
|
||||
#include <errno.h>
|
||||
#include <lwip/apps/mdns.h>
|
||||
#include <lwip/igmp.h>
|
||||
#include <lwip/init.h>
|
||||
#include <lwip/netif.h>
|
||||
}
|
||||
|
||||
static u8_t mdns_netif_client_id = 0; // TODO fix this
|
||||
|
||||
struct mdns_domain {
|
||||
/* Encoded domain name */
|
||||
u8_t name[256];
|
||||
/* Total length of domain name, including zero */
|
||||
u16_t length;
|
||||
/* Set if compression of this domain is not allowed */
|
||||
u8_t skip_compression;
|
||||
};
|
||||
|
||||
/** Description of a service */
|
||||
struct mdns_service {
|
||||
/** TXT record to answer with */
|
||||
struct mdns_domain txtdata;
|
||||
/** Name of service, like 'myweb' */
|
||||
char name[MDNS_LABEL_MAXLEN + 1];
|
||||
/** Type of service, like '_http' */
|
||||
char service[MDNS_LABEL_MAXLEN + 1];
|
||||
/** Callback function and userdata
|
||||
* to update txtdata buffer */
|
||||
service_get_txt_fn_t txt_fn;
|
||||
void *txt_userdata;
|
||||
/** TTL in seconds of SRV/TXT replies */
|
||||
u32_t dns_ttl;
|
||||
/** Protocol, TCP or UDP */
|
||||
u16_t proto;
|
||||
/** Port of the service */
|
||||
u16_t port;
|
||||
};
|
||||
|
||||
/** Description of a host/netif */
|
||||
struct mdns_host {
|
||||
/** Hostname */
|
||||
char name[MDNS_LABEL_MAXLEN + 1];
|
||||
/** Pointer to services */
|
||||
struct mdns_service *services[MDNS_MAX_SERVICES];
|
||||
/** TTL in seconds of A/AAAA/PTR replies */
|
||||
u32_t dns_ttl;
|
||||
};
|
||||
|
||||
static String mdnsInstanceName = "default_instance";
|
||||
static std::vector<char *> services;
|
||||
static std::vector<uint8_t> protos;
|
||||
static std::vector<std::vector<char *>> records;
|
||||
|
||||
mDNS::mDNS() {}
|
||||
|
||||
mDNS::~mDNS() {}
|
||||
|
||||
static void mdnsTxtCallback(struct mdns_service *service, void *userdata) {
|
||||
size_t index = (size_t)userdata;
|
||||
if (index >= records.size())
|
||||
return;
|
||||
|
||||
for (const auto record : records[index]) {
|
||||
err_t err = mdns_resp_add_service_txtitem(service, record, strlen(record));
|
||||
if (err != ERR_OK)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void mdnsStatusCallback(struct netif *netif, uint8_t result) {
|
||||
LT_DM(MDNS, "Status: netif %u, status %u", netif->num, result);
|
||||
}
|
||||
|
||||
bool mDNS::begin(const char *hostname) {
|
||||
LT_DM(MDNS, "Starting (%s)", hostname);
|
||||
#if LWIP_VERSION_MAJOR >= 2 && LWIP_VERSION_MINOR >= 1
|
||||
mdns_resp_register_name_result_cb(mdnsStatusCallback);
|
||||
#endif
|
||||
mdns_resp_init();
|
||||
struct netif *netif = netif_list;
|
||||
uint8_t enabled = 0;
|
||||
while (netif != NULL) {
|
||||
netif->flags |= NETIF_FLAG_IGMP;
|
||||
// TODO: detect mdns_netif_client_id by checking netif_get_client_data()
|
||||
// and finding the requested hostname in struct mdns_host
|
||||
if (netif_is_up(netif) && mdns_resp_add_netif(netif, hostname, 255) == ERR_OK) {
|
||||
enabled++;
|
||||
uint8_t enabled = 0;
|
||||
|
||||
struct netif *netif;
|
||||
for (netif = netif_list; netif != NULL; netif = netif->next) {
|
||||
if (!netif_is_up(netif))
|
||||
continue;
|
||||
|
||||
LT_DM(MDNS, "Adding netif %u", netif->num);
|
||||
if ((netif->flags & NETIF_FLAG_IGMP) == 0) {
|
||||
LT_DM(MDNS, "Enabling IGMP");
|
||||
netif->flags |= NETIF_FLAG_IGMP;
|
||||
igmp_start(netif);
|
||||
}
|
||||
netif = netif->next;
|
||||
|
||||
err_t ret = mdns_resp_add_netif(netif, hostname, 255);
|
||||
if (ret == ERR_OK)
|
||||
enabled++;
|
||||
else
|
||||
LT_DM(MDNS, "Cannot add netif %u; ret=%d, errno=%d", netif->num, ret, errno);
|
||||
}
|
||||
return enabled > 0;
|
||||
}
|
||||
@@ -81,72 +75,53 @@ void mDNS::end() {
|
||||
}
|
||||
}
|
||||
|
||||
void mDNS::setInstanceName(String name) {
|
||||
mdnsInstanceName = name;
|
||||
}
|
||||
|
||||
bool mDNS::addService(char *service, char *proto, uint16_t port) {
|
||||
char _service[strlen(service) + 2];
|
||||
char _proto[strlen(proto) + 2];
|
||||
_service[0] = '_';
|
||||
_proto[0] = '_';
|
||||
// prepend names with _
|
||||
strcpy(_service + 1, service + (service[0] == '_'));
|
||||
strcpy(_proto + 1, proto + (proto[0] == '_'));
|
||||
|
||||
mdns_sd_proto protocol = DNSSD_PROTO_UDP;
|
||||
if (strncmp(_proto + 1, "tcp", 3) == 0)
|
||||
protocol = DNSSD_PROTO_TCP;
|
||||
|
||||
bool mDNS::addServiceImpl(const char *name, const char *service, uint8_t proto, uint16_t port) {
|
||||
bool added = false;
|
||||
struct netif *netif = netif_list;
|
||||
while (netif != NULL) {
|
||||
if (netif_is_up(netif)) {
|
||||
mdns_resp_add_service(netif, mdnsInstanceName.c_str(), _service, protocol, port, 255, NULL, NULL);
|
||||
// register TXT callback;
|
||||
// pass service index as userdata parameter
|
||||
LT_DM(MDNS, "Add service: netif %u / %s / %s / %u / %u", netif->num, name, service, proto, port);
|
||||
mdns_resp_add_service(
|
||||
netif,
|
||||
name,
|
||||
service,
|
||||
(mdns_sd_proto)proto,
|
||||
port,
|
||||
255,
|
||||
mdnsTxtCallback,
|
||||
(void *)services.size() // index of newly added service
|
||||
);
|
||||
added = true;
|
||||
}
|
||||
netif = netif->next;
|
||||
}
|
||||
|
||||
if (!added)
|
||||
return false;
|
||||
|
||||
// add the service to TXT record arrays
|
||||
services.push_back(strdup(service));
|
||||
protos.push_back(proto);
|
||||
records.emplace_back();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mDNS::addServiceTxt(char *name, char *proto, char *key, char *value) {
|
||||
char _name[strlen(name) + 2];
|
||||
char _proto[strlen(proto) + 2];
|
||||
_name[0] = '_';
|
||||
_proto[0] = '_';
|
||||
// prepend names with _
|
||||
strcpy(_name + 1, name + (name[0] == '_'));
|
||||
strcpy(_proto + 1, proto + (proto[0] == '_'));
|
||||
|
||||
mdns_sd_proto protocol = DNSSD_PROTO_UDP;
|
||||
if (strncmp(_proto + 1, "tcp", 3) == 0)
|
||||
protocol = DNSSD_PROTO_TCP;
|
||||
|
||||
struct netif *netif = netif_list;
|
||||
struct mdns_host *mdns;
|
||||
struct mdns_service *service;
|
||||
|
||||
uint8_t txt_len = strlen(key) + strlen(value) + 1;
|
||||
char *txt = (char *)malloc(txt_len + 1);
|
||||
sprintf(txt, "%s=%s", key, value);
|
||||
|
||||
while (netif != NULL) {
|
||||
if (netif_is_up(netif)) {
|
||||
mdns = (struct mdns_host *)netif_get_client_data(netif, mdns_netif_client_id);
|
||||
|
||||
for (uint8_t i = 0; i < MDNS_MAX_SERVICES; i++) {
|
||||
service = mdns->services[i];
|
||||
if (service == NULL)
|
||||
continue;
|
||||
if (strcmp(service->service, _name) || service->proto != protocol)
|
||||
continue;
|
||||
if (mdns_resp_add_service_txtitem(service, txt, txt_len) != ERR_OK) {
|
||||
free(txt);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool mDNS::addServiceTxtImpl(const char *service, uint8_t proto, const char *item) {
|
||||
int8_t index = -1;
|
||||
for (uint8_t i = 0; i < services.size(); i++) {
|
||||
// find a matching service
|
||||
if (strcmp(services[i], service) == 0 && protos[i] == proto) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
netif = netif->next;
|
||||
}
|
||||
free(txt);
|
||||
if (index == -1)
|
||||
return false;
|
||||
|
||||
records[index].push_back(strdup(item));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
40
arduino/libretuya/libraries/mDNS/mDNS.cpp
Normal file
40
arduino/libretuya/libraries/mDNS/mDNS.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-08-26. */
|
||||
|
||||
#include "mDNS.h"
|
||||
|
||||
static char *ensureUnderscore(const char *value) {
|
||||
uint8_t len = strlen(value) + 1;
|
||||
char *result = (char *)malloc(len);
|
||||
result[0] = '_';
|
||||
strcpy(result + 1, value + (value[0] == '_'));
|
||||
return result;
|
||||
}
|
||||
|
||||
void mDNS::setInstanceName(const char *name) {
|
||||
if (instanceName)
|
||||
free(instanceName);
|
||||
instanceName = strdup(name);
|
||||
}
|
||||
|
||||
bool mDNS::addService(char *service, char *proto, uint16_t port) {
|
||||
char *_service = ensureUnderscore(service);
|
||||
uint8_t _proto = strncmp(proto + (proto[0] == '_'), "tcp", 3) == 0 ? MDNS_TCP : MDNS_UDP;
|
||||
|
||||
bool result = addServiceImpl(instanceName ? instanceName : "LT mDNS", _service, _proto, port);
|
||||
free(_service);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool mDNS::addServiceTxt(char *service, char *proto, char *key, char *value) {
|
||||
char *_service = ensureUnderscore(service);
|
||||
uint8_t _proto = strncmp(proto + (proto[0] == '_'), "tcp", 3) == 0 ? MDNS_TCP : MDNS_UDP;
|
||||
|
||||
uint8_t txt_len = strlen(key) + strlen(value) + 1;
|
||||
char *txt = (char *)malloc(txt_len + 1);
|
||||
sprintf(txt, "%s=%s", key, value);
|
||||
|
||||
bool result = addServiceTxtImpl(_service, _proto, txt);
|
||||
free(_service);
|
||||
free(txt);
|
||||
return result;
|
||||
}
|
||||
@@ -44,7 +44,16 @@ License (MIT license):
|
||||
#include <Arduino.h>
|
||||
#include <api/IPv6Address.h>
|
||||
|
||||
#define MDNS_UDP 0
|
||||
#define MDNS_TCP 1
|
||||
|
||||
class mDNS {
|
||||
private:
|
||||
bool addServiceImpl(const char *name, const char *service, uint8_t proto, uint16_t port);
|
||||
bool addServiceTxtImpl(const char *service, uint8_t proto, const char *item);
|
||||
|
||||
char *instanceName = NULL;
|
||||
|
||||
public:
|
||||
mDNS();
|
||||
~mDNS();
|
||||
@@ -52,9 +61,9 @@ class mDNS {
|
||||
bool begin(const char *hostname);
|
||||
void end();
|
||||
|
||||
void setInstanceName(String name);
|
||||
void setInstanceName(const char *name);
|
||||
bool addService(char *service, char *proto, uint16_t port);
|
||||
bool addServiceTxt(char *name, char *proto, char *key, char *value);
|
||||
bool addServiceTxt(char *service, char *proto, char *key, char *value);
|
||||
// void enableArduino(uint16_t port = 3232, bool auth = false);
|
||||
// void disableArduino();
|
||||
// void enableWorkstation(esp_interface_t interface = ESP_IF_WIFI_STA);
|
||||
@@ -73,12 +82,12 @@ class mDNS {
|
||||
String txt(int idx, int txtIdx);
|
||||
String txtKey(int idx, int txtIdx);
|
||||
|
||||
void setInstanceName(const char *name) {
|
||||
setInstanceName(String(name));
|
||||
void setInstanceName(String name) {
|
||||
setInstanceName(name.c_str());
|
||||
}
|
||||
|
||||
void setInstanceName(char *name) {
|
||||
setInstanceName(String(name));
|
||||
setInstanceName((const char *)name);
|
||||
}
|
||||
|
||||
bool addService(const char *service, const char *proto, uint16_t port) {
|
||||
@@ -89,12 +98,12 @@ class mDNS {
|
||||
return addService(service.c_str(), proto.c_str(), port);
|
||||
}
|
||||
|
||||
void addServiceTxt(const char *name, const char *proto, const char *key, const char *value) {
|
||||
addServiceTxt((char *)name, (char *)proto, (char *)key, (char *)value);
|
||||
void addServiceTxt(const char *service, const char *proto, const char *key, const char *value) {
|
||||
addServiceTxt((char *)service, (char *)proto, (char *)key, (char *)value);
|
||||
}
|
||||
|
||||
void addServiceTxt(String name, String proto, String key, String value) {
|
||||
addServiceTxt(name.c_str(), proto.c_str(), key.c_str(), value.c_str());
|
||||
void addServiceTxt(String service, String proto, String key, String value) {
|
||||
addServiceTxt(service.c_str(), proto.c_str(), key.c_str(), value.c_str());
|
||||
}
|
||||
|
||||
IPAddress queryHost(const char *host, uint32_t timeout = 2000) {
|
||||
|
||||
@@ -36,10 +36,14 @@
|
||||
/* MCU Endian Configuration, default is Little Endian Order. */
|
||||
// #define FDB_BIG_ENDIAN
|
||||
|
||||
/* log print macro. default EF_PRINT macro is printf() */
|
||||
#define FDB_PRINT(...)
|
||||
#include <printf_config.h>
|
||||
|
||||
/* print debug information */
|
||||
// #define FDB_DEBUG_ENABLE
|
||||
#if LT_DEBUG_FDB
|
||||
#include <printf/printf.h>
|
||||
#define FDB_PRINT(...) __wrap_printf(__VA_ARGS__)
|
||||
#define FDB_DEBUG_ENABLE
|
||||
#else
|
||||
#define FDB_PRINT(...)
|
||||
#endif
|
||||
|
||||
#endif /* _FDB_CFG_H_ */
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-05-16. */
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
extern char *strdup(const char *);
|
||||
extern int strcasecmp(const char *s1, const char *s2);
|
||||
extern int strncasecmp(const char *s1, const char *s2, size_t n);
|
||||
|
||||
50
arduino/libretuya/posix/time.c
Normal file
50
arduino/libretuya/posix/time.c
Normal file
@@ -0,0 +1,50 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-09-03. */
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <errno.h>
|
||||
|
||||
static uint32_t reset_epoch = 0; // epoch corresponding to millis() == 0
|
||||
static uint32_t reset_millis = 0; // millis() when epoch reset was performed
|
||||
|
||||
int __wrap_gettimeofday(struct timeval *tv, void *tz) {
|
||||
if (millis() < reset_millis) {
|
||||
// the clock overflowed
|
||||
reset_epoch += UINT32_MAX / 1000;
|
||||
reset_millis = millis();
|
||||
}
|
||||
if (!tv) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
unsigned long m = millis();
|
||||
tv->tv_sec = reset_epoch + (m / 1000);
|
||||
tv->tv_usec = (m % 1000) * 1000;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __wrap_settimeofday(const struct timeval *tv, const struct timezone *tz) {
|
||||
if (!tv) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
unsigned long m = millis();
|
||||
reset_epoch = tv->tv_sec - (m / 1000);
|
||||
reset_millis = m;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gettimeofday(struct timeval *tv, void *tz) {
|
||||
return __wrap_gettimeofday(tv, tz);
|
||||
}
|
||||
|
||||
int settimeofday(const struct timeval *tv, const struct timezone *tz) {
|
||||
return __wrap_settimeofday(tv, tz);
|
||||
}
|
||||
|
||||
int _gettimeofday(struct timeval *tv, void *tz) {
|
||||
return __wrap_gettimeofday(tv, tz);
|
||||
}
|
||||
|
||||
int _settimeofday(const struct timeval *tv, const struct timezone *tz) {
|
||||
return __wrap_settimeofday(tv, tz);
|
||||
}
|
||||
@@ -99,6 +99,13 @@ uint32_t LibreTuya::getMaxAllocHeap() {
|
||||
|
||||
/* OTA-related */
|
||||
|
||||
uint8_t LibreTuya::otaGetRunning() {
|
||||
// RTL8710B is XIP, so check the code offset in flash
|
||||
uint32_t addr = (uint32_t)lt_log;
|
||||
uint32_t offs = addr - SPI_FLASH_BASE;
|
||||
return offs > FLASH_OTA2_OFFSET ? 2 : 1;
|
||||
}
|
||||
|
||||
uint8_t LibreTuya::otaGetStoredIndex() {
|
||||
uint32_t *otaAddress = (uint32_t *)0x8009000;
|
||||
if (*otaAddress == 0xFFFFFFFF)
|
||||
|
||||
@@ -34,7 +34,7 @@ bool WiFiClass::softAP(const char *ssid, const char *passphrase, int channel, bo
|
||||
|
||||
dhcps_deinit();
|
||||
|
||||
LT_I("Creating SoftAP %s", ssid);
|
||||
LT_IM(WIFI, "Creating SoftAP %s", ssid);
|
||||
|
||||
int ret;
|
||||
if (!ssidHidden) {
|
||||
@@ -60,7 +60,7 @@ bool WiFiClass::softAP(const char *ssid, const char *passphrase, int channel, bo
|
||||
wifi_indication(WIFI_EVENT_CONNECT, NULL, ARDUINO_EVENT_WIFI_AP_START, -2);
|
||||
|
||||
if (ret < 0) {
|
||||
LT_E("SoftAP failed; ret=%d", ret);
|
||||
LT_EM(WIFI, "SoftAP failed; ret=%d", ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ bool WiFiClass::modePriv(WiFiMode mode, WiFiModeAction sta, WiFiModeAction ap) {
|
||||
|
||||
if (!data.initialized) {
|
||||
// initialize wifi first
|
||||
LT_I("Initializing LwIP");
|
||||
LT_IM(WIFI, "Initializing LwIP");
|
||||
LwIP_Init();
|
||||
reset_wifi_struct();
|
||||
data.initialized = true;
|
||||
@@ -23,7 +23,7 @@ bool WiFiClass::modePriv(WiFiMode mode, WiFiModeAction sta, WiFiModeAction ap) {
|
||||
LT_HEAP_I();
|
||||
if (getMode()) {
|
||||
// stop wifi to change mode
|
||||
LT_D_WG("Stopping WiFi to change mode");
|
||||
LT_DM(WIFI, "Stopping WiFi to change mode");
|
||||
if (wifi_off() != RTW_SUCCESS)
|
||||
goto error;
|
||||
vTaskDelay(20);
|
||||
@@ -32,7 +32,7 @@ bool WiFiClass::modePriv(WiFiMode mode, WiFiModeAction sta, WiFiModeAction ap) {
|
||||
}
|
||||
|
||||
if (wifi_on((rtw_mode_t)mode) != RTW_SUCCESS) {
|
||||
LT_E("Error while changing mode(%u)", mode);
|
||||
LT_EM(WIFI, "Error while changing mode(%u)", mode);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -72,12 +72,14 @@ WiFiStatus WiFiClass::status() {
|
||||
}
|
||||
|
||||
bool WiFiClass::setSleep(bool enable) {
|
||||
LT_D_WG("WiFi sleep mode %u", enable);
|
||||
if (enable)
|
||||
LT_DM(WIFI, "WiFi sleep mode %u", enable);
|
||||
if (enable) {
|
||||
if (wifi_enable_powersave() != RTW_SUCCESS)
|
||||
return false;
|
||||
else if (wifi_disable_powersave() != RTW_SUCCESS)
|
||||
} else {
|
||||
if (wifi_disable_powersave() != RTW_SUCCESS)
|
||||
return false;
|
||||
}
|
||||
data.sleep = enable;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ bool WiFiClass::reconnect(const uint8_t *bssid) {
|
||||
int ret;
|
||||
uint8_t dhcpRet;
|
||||
|
||||
LT_I("Connecting to %s", wifi.ssid.val);
|
||||
LT_IM(WIFI, "Connecting to %s", wifi.ssid.val);
|
||||
__wrap_rtl_printf_disable();
|
||||
__wrap_DiagPrintf_disable();
|
||||
|
||||
@@ -110,11 +110,11 @@ bool WiFiClass::reconnect(const uint8_t *bssid) {
|
||||
__wrap_DiagPrintf_enable();
|
||||
return true;
|
||||
}
|
||||
LT_E("DHCP failed; dhcpRet=%d", dhcpRet);
|
||||
LT_EM(WIFI, "DHCP failed; dhcpRet=%d", dhcpRet);
|
||||
wifi_disconnect();
|
||||
goto error;
|
||||
}
|
||||
LT_E("Connection failed; ret=%d", ret);
|
||||
LT_EM(WIFI, "Connection failed; ret=%d", ret);
|
||||
error:
|
||||
__wrap_rtl_printf_enable();
|
||||
__wrap_DiagPrintf_enable();
|
||||
|
||||
@@ -39,7 +39,7 @@ int16_t WiFiClass::scanNetworks(bool async, bool showHidden, bool passive, uint3
|
||||
scanDelete();
|
||||
scanInit();
|
||||
|
||||
LT_I("Starting WiFi scan");
|
||||
LT_IM(WIFI, "Starting WiFi scan");
|
||||
|
||||
if (wifi_scan_networks(scanHandler, this) != RTW_SUCCESS)
|
||||
return WIFI_SCAN_FAILED;
|
||||
@@ -47,7 +47,7 @@ int16_t WiFiClass::scanNetworks(bool async, bool showHidden, bool passive, uint3
|
||||
scan->running = true;
|
||||
|
||||
if (!async) {
|
||||
LT_I("Waiting for results");
|
||||
LT_IM(WIFI, "Waiting for results");
|
||||
xSemaphoreTake(data.scanSem, 1); // reset the semaphore quickly
|
||||
xSemaphoreTake(data.scanSem, pdMS_TO_TICKS(maxMsPerChannel * 20));
|
||||
return scan->count;
|
||||
|
||||
@@ -30,6 +30,9 @@ env.Append(
|
||||
# wrappers from port/printf/
|
||||
"-Wl,-wrap,putchar",
|
||||
"-Wl,-wrap,puts",
|
||||
# wrappers from posix/time.c
|
||||
"-Wl,-wrap,gettimeofday",
|
||||
"-Wl,-wrap,settimeofday",
|
||||
],
|
||||
)
|
||||
# Arduino core uses __libc_init_array
|
||||
|
||||
@@ -249,6 +249,7 @@ env.AddLibrary(
|
||||
"+<usb>",
|
||||
"+<../ip/**>",
|
||||
],
|
||||
options=dict(CCFLAGS=["-Wno-unused-variable"]),
|
||||
)
|
||||
|
||||
# Sources - functional components
|
||||
@@ -263,6 +264,7 @@ env.AddLibrary(
|
||||
"+<camera_intf/*.c>",
|
||||
"+<hostapd_intf/*.c>",
|
||||
"+<joint_up/*.c>",
|
||||
"+<lwip_intf/dhcpd/*.c>",
|
||||
"+<misc/*.c>",
|
||||
"+<net_param_intf/*.c>",
|
||||
"+<power_save/*.c>",
|
||||
@@ -288,6 +290,7 @@ env.AddLibrary(
|
||||
"+<ethernet_intf>",
|
||||
"+<include>",
|
||||
"+<joint_up>",
|
||||
"+<lwip_intf>", # for config/lwipopts.h
|
||||
"+<power_save>",
|
||||
"+<rf_test>",
|
||||
"+<rf_use>",
|
||||
@@ -342,28 +345,8 @@ env.AddLibrary(
|
||||
),
|
||||
)
|
||||
|
||||
# Sources - lwIP 2.0.2
|
||||
env.AddLibrary(
|
||||
name="bdk_lwip",
|
||||
base_dir=join(FUNC_DIR, "lwip_intf"),
|
||||
srcs=[
|
||||
"+<lwip-2.0.2/port/*.c>",
|
||||
"+<lwip-2.0.2/src/api/*.c>",
|
||||
"+<lwip-2.0.2/src/apps/ping/*.c>",
|
||||
"+<lwip-2.0.2/src/apps/mdns/*.c>",
|
||||
"+<lwip-2.0.2/src/core/*.c>",
|
||||
"+<lwip-2.0.2/src/core/ipv4/*.c>",
|
||||
"+<lwip-2.0.2/src/core/ipv6/*.c>",
|
||||
"+<lwip-2.0.2/src/netif/ethernet.c>",
|
||||
"+<dhcpd/*.c>",
|
||||
],
|
||||
includes=[
|
||||
"+<lwip-2.0.2/port>",
|
||||
"+<lwip-2.0.2/src/include>",
|
||||
"+<lwip-2.0.2/src/include/netif>",
|
||||
],
|
||||
options=dict(CCFLAGS=["-Wno-missing-braces"]),
|
||||
)
|
||||
# Sources - lwIP 2.1.3
|
||||
env.AddLibraryLwIP(version="2.1.3", port="bdk")
|
||||
|
||||
# Sources - mbedTLS 2.6.0
|
||||
env.AddLibrary(
|
||||
|
||||
@@ -25,6 +25,13 @@ def env_add_lwip(
|
||||
"+<port/realtek>",
|
||||
"+<port/realtek/freertos>",
|
||||
]
|
||||
elif port in ["bdk"]:
|
||||
port_srcs = [
|
||||
"+<port/*.c>",
|
||||
]
|
||||
port_includes = [
|
||||
"+<port>",
|
||||
]
|
||||
|
||||
env.AddLibrary(
|
||||
name=f"lwip{version}_{port}",
|
||||
|
||||
@@ -47,6 +47,7 @@ def env_add_defaults(env, platform, board):
|
||||
# Default build options
|
||||
env.Prepend(
|
||||
CPPPATH=[
|
||||
"$LT_DIR/platform/common/config",
|
||||
"$LT_DIR/platform/common/fixups",
|
||||
"$LT_DIR/platform/common/fixups/lib_inc",
|
||||
"$BOARD_DIR",
|
||||
|
||||
@@ -30,7 +30,10 @@ def env_uf2ota(env, *args, **kwargs):
|
||||
"${FAMILY}",
|
||||
f"lt{lt_version}",
|
||||
]
|
||||
output = join("${BUILD_DIR}", "_".join(output)) + ".uf2"
|
||||
output = "_".join(output) + ".uf2"
|
||||
if platform.custom("fw_output"):
|
||||
output = platform.custom("fw_output")
|
||||
output = join("${BUILD_DIR}", output)
|
||||
env["UF2OUT"] = output
|
||||
env["UF2OUT_BASE"] = basename(output)
|
||||
|
||||
@@ -56,7 +59,7 @@ def env_uf2upload(env, target):
|
||||
# from platform-espressif32/builder/main.py
|
||||
if protocol == "uart":
|
||||
# upload via UART
|
||||
env["UPLOADERFLAGS"] = [
|
||||
env["UPLOADERFLAGS_UF2"] = [
|
||||
"${UF2OUT}",
|
||||
"uart",
|
||||
"${UPLOAD_PORT}",
|
||||
@@ -77,7 +80,7 @@ def env_uf2upload(env, target):
|
||||
# add main upload target
|
||||
env.Replace(
|
||||
UPLOADER="${LTCHIPTOOL} uf2 upload",
|
||||
UPLOADCMD="${UPLOADER} ${UPLOADERFLAGS}",
|
||||
UPLOADCMD="${UPLOADER} ${UPLOADERFLAGS_UF2} ${UPLOADERFLAGS}",
|
||||
)
|
||||
actions.append(env.VerboseAction("${UPLOADCMD}", "Uploading ${UF2OUT_BASE}"))
|
||||
env.AddPlatformTarget("upload", target, actions, "Upload")
|
||||
|
||||
@@ -29,34 +29,51 @@ build_flags =
|
||||
|
||||
### Logger
|
||||
|
||||
- `LT_LOGGER` (1) - enable/disable LibreTuya logger globally. Enabled by default.
|
||||
- `LT_LOGGER` (1) - enable/disable LibreTuya logger globally; disabling this sets the loglevel to `LT_LEVEL_NONE` - the logger can't be enabled even by using `lt_log_set_port()`
|
||||
- `LT_LOGLEVEL` - global LT loglevel:
|
||||
- `LT_LEVEL_TRACE` (same as LT_LEVEL_VERBOSE)
|
||||
- `LT_LEVEL_VERBOSE`
|
||||
- `LT_LEVEL_TRACE` - same as `LT_LEVEL_VERBOSE`
|
||||
- `LT_LEVEL_DEBUG`
|
||||
- `LT_LEVEL_INFO` - default
|
||||
- `LT_LEVEL_WARN`
|
||||
- `LT_LEVEL_ERROR`
|
||||
- `LT_LEVEL_FATAL`
|
||||
- `LT_LEVEL_NONE` - disables everything
|
||||
- `LT_LOGGER_TIMESTAMP` (1) - print program runtime in printk-like format
|
||||
- `LT_LOGGER_CALLER` (1) - print calling method name
|
||||
- `LT_LOGGER_TASK` (1) - print calling FreeRTOS task (if available)
|
||||
- `LT_LOGGER_COLOR` (0) - output ANSI terminal colors
|
||||
- `LT_PRINTF_BROKEN` (0) - whether printf outputs "0." for floats with value 0
|
||||
- `LT_LOG_HEAP` (0) - print free heap size using `LT_HEAP_I()`
|
||||
- `LT_LOG_HEAP` (0) - print free heap size using `LT_HEAP_I()`, and periodically every 1000 ms
|
||||
- `LT_LOG_ERRNO` (0) - print and clear errno value (if set) using `LT_ERRNO()`
|
||||
|
||||
#### Debug logging
|
||||
#### Per-module logging & debugging
|
||||
|
||||
The following options enable library-specific debugging messages. They are only effective if `LT_LOGLEVEL` is set below INFO. All of them are disabled by default.
|
||||
The following options enable library-specific logging output. They are effective **for all loglevels** - i.e. disabling `LT_DEBUG_WIFI` will disable WiFi debug messages, as well as errors.
|
||||
|
||||
Families should generally call i.e. WiFiClient debugging for client-related code, even if the `WiFiClient.cpp` file is physically absent.
|
||||
To see debug messages from i.e. OTA, loglevel must also be changed.
|
||||
|
||||
- `LT_DEBUG_WIFI` - WiFi
|
||||
- `LT_DEBUG_WIFI_CLIENT` - WiFiClient
|
||||
- `LT_DEBUG_WIFI_SERVER` - WiFiServer
|
||||
- `LT_DEBUG_WIFI_STA` - WiFiSTA
|
||||
- `LT_DEBUG_WIFI_AP` - WiFiAP
|
||||
- `LT_DEBUG_SSL` - WiFiClientSecure
|
||||
- `LT_DEBUG_ALL` (0) - enable all following options by default (except for FDB and LWIP)
|
||||
- `LT_DEBUG_WIFI` (1) - WiFi (generic, STA, AP, scan, events, etc.)
|
||||
- `LT_DEBUG_CLIENT` (0) - TCP client
|
||||
- `LT_DEBUG_SERVER` (0) - TCP server
|
||||
- `LT_DEBUG_SSL` (0) - SSL clients
|
||||
- `LT_DEBUG_OTA` (1) - OTA updates (`Update` library)
|
||||
- `LT_DEBUG_FDB` (0) - FlashDB debugging (macros within the library)
|
||||
- `LT_DEBUG_MDNS` (0) - mDNS client library
|
||||
- `LT_DEBUG_LWIP` (0) - enables `LWIP_DEBUG`, provides `LWIP_PLATFORM_DIAG`; per-module options (i.e. `TCP_DEBUG`) are off by default and need to be enabled separately
|
||||
- `LT_DEBUG_LWIP_ASSERT` (0) - enables assertions within lwIP (doesn't need `LT_DEBUG_LWIP`)
|
||||
|
||||
!!! hint
|
||||
Enabling `LT_DEBUG_ALL` doesn't mean that *every* debugging message will be printed. If loglevel is i.e. `WARN`, debug messages won't be visible anyway.
|
||||
|
||||
This can be used, for example, to enable only "important" messages:
|
||||
```ini
|
||||
[env:my_board]
|
||||
build_flags =
|
||||
-D LT_LOGLEVEL=LT_LEVEL_WARN
|
||||
-D LT_DEBUG_ALL=1 # will print only warnings and errors from all modules
|
||||
```
|
||||
|
||||
### Serial output
|
||||
|
||||
@@ -90,3 +107,7 @@ The meaning of most flags is as follows:
|
||||
- `LT_ARD_HAS_MD5` - MD5 library implemented, `MD5Impl.h` available
|
||||
- `LT_ARD_HAS_WIFI` - WiFi library implemented, `WiFiData.h` available
|
||||
- `LT_HEAP_FUNC` - function name used to get available heap size (for `LT_HEAP_I()`)
|
||||
|
||||
### Misc options
|
||||
|
||||
- `LT_USE_TIME` - enables implementation of `gettimeofday()` and `settimeofday()`; checks for `millis()` overflows periodically
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/kuba2k2/platformio-libretuya"
|
||||
},
|
||||
"version": "0.9.0",
|
||||
"version": "0.10.0",
|
||||
"frameworks": {
|
||||
"arduino": {
|
||||
"title": "Generic Arduino framework",
|
||||
@@ -42,7 +42,7 @@
|
||||
"framework-realtek-amb1": {
|
||||
"type": "framework",
|
||||
"optional": true,
|
||||
"version": "https://github.com/ambiot/amb1_sdk",
|
||||
"version": "https://github.com/ambiot/amb1_sdk#750b0bc",
|
||||
"manifest": {
|
||||
"description": "SDK for Ameba1"
|
||||
},
|
||||
@@ -56,7 +56,7 @@
|
||||
"framework-realtek-ambz2": {
|
||||
"type": "framework",
|
||||
"optional": true,
|
||||
"version": "https://github.com/ambiot/ambz2_sdk",
|
||||
"version": "https://github.com/ambiot/ambz2_sdk#f009272",
|
||||
"manifest": {
|
||||
"description": "SDK for AmebaZ2"
|
||||
},
|
||||
@@ -65,16 +65,21 @@
|
||||
"framework-beken-bdk": {
|
||||
"type": "framework",
|
||||
"optional": true,
|
||||
"version": "https://github.com/bekencorp/bdk_freertos",
|
||||
"version": "https://github.com/bekencorp/bdk_freertos#c3533e8",
|
||||
"manifest": {
|
||||
"description": "Beken Development Kit for FreeRTOS"
|
||||
},
|
||||
"toolchain": "gccarmnoneeabi@~1.40804.0"
|
||||
"toolchain": "gccarmnoneeabi@~1.40804.0",
|
||||
"libraries": {
|
||||
"lwip": [
|
||||
"v2.1.3-bdk"
|
||||
]
|
||||
}
|
||||
},
|
||||
"framework-arduino-api": {
|
||||
"type": "framework",
|
||||
"optional": true,
|
||||
"version": "https://github.com/arduino/ArduinoCore-API",
|
||||
"version": "https://github.com/arduino/ArduinoCore-API#ee040ed",
|
||||
"manifest": {
|
||||
"description": "Hardware independent layer of the Arduino cores"
|
||||
},
|
||||
@@ -122,7 +127,7 @@
|
||||
},
|
||||
"tool-ltchiptool": {
|
||||
"type": "uploader",
|
||||
"version": "https://github.com/libretuya/ltchiptool#v1.4.0",
|
||||
"version": "https://github.com/libretuya/ltchiptool#v1.5.2",
|
||||
"note": "This is used only for C/C++ code from ltchiptool."
|
||||
},
|
||||
"tool-openocd": {
|
||||
@@ -134,7 +139,7 @@
|
||||
"tool-bk7231tools": {
|
||||
"type": "uploader",
|
||||
"optional": true,
|
||||
"version": "https://github.com/libretuya/bk7231tools"
|
||||
"version": "https://github.com/notkmhn/bk7231tools#1eea4c3"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ def check_ltchiptool():
|
||||
import ltchiptool
|
||||
|
||||
importlib.reload(ltchiptool)
|
||||
if Version(ltchiptool.get_version()) < Version("1.4.0"):
|
||||
if Version(ltchiptool.get_version()) < Version("1.5.1"):
|
||||
raise ImportError("Version too old")
|
||||
|
||||
|
||||
|
||||
@@ -2,11 +2,18 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include_next "lwipopts.h"
|
||||
#include "lwip-2.0.2/port/lwipopts.h"
|
||||
|
||||
#define LWIP_MDNS_RESPONDER 1
|
||||
#define LWIP_NUM_NETIF_CLIENT_DATA 1
|
||||
#define LWIP_SO_RCVBUF 1 // for ioctl(FIONREAD)
|
||||
#include <sys/time.h>
|
||||
|
||||
// mDNS support
|
||||
#undef MEMP_NUM_UDP_PCB
|
||||
#define LWIP_NUM_NETIF_CLIENT_DATA 2
|
||||
#define MEMP_NUM_UDP_PCB (MAX_SOCKETS_UDP + 2 + 1)
|
||||
|
||||
#define ip_addr ip4_addr
|
||||
#define ip_addr_t ip4_addr_t
|
||||
|
||||
// increase TCP/IP thread stack size (was 512)
|
||||
#undef TCPIP_THREAD_STACKSIZE
|
||||
#define TCPIP_THREAD_STACKSIZE 1024
|
||||
|
||||
65
platform/common/config/lwipopts.h
Normal file
65
platform/common/config/lwipopts.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-08-26. */
|
||||
|
||||
#define LWIP_TIMEVAL_PRIVATE 0
|
||||
#define LWIP_NETIF_HOSTNAME 1 // to support hostname changing
|
||||
#define LWIP_SO_RCVBUF 1 // for ioctl(FIONREAD)
|
||||
|
||||
#define LWIP_MDNS_RESPONDER 1
|
||||
#define MDNS_MAX_SERVICES 10
|
||||
|
||||
#include_next "lwipopts.h"
|
||||
|
||||
// set lwIP debugging options according to LT config
|
||||
#if LT_DEBUG_LWIP
|
||||
#undef LWIP_DEBUG
|
||||
#define LWIP_DEBUG 1
|
||||
// make lwIP use printf() library
|
||||
#include <stdio.h>
|
||||
#undef LWIP_PLATFORM_DIAG
|
||||
// clang-format off
|
||||
#define LWIP_PLATFORM_DIAG(x) do { printf x; } while (0)
|
||||
// clang-format on
|
||||
#endif
|
||||
|
||||
#if LT_DEBUG_LWIP_ASSERT
|
||||
#undef LWIP_NOASSERT
|
||||
#undef LWIP_PLATFORM_ASSERT
|
||||
// clang-format off
|
||||
#define LWIP_PLATFORM_ASSERT(x) do { printf("ASSERT \"%s\" - %s:%d\n", x, __FILE__, __LINE__); while (1) {}; } while (0)
|
||||
// clang-format on
|
||||
#endif
|
||||
|
||||
// remove family-defined debugging options (use lwIP defaults, or user-defined)
|
||||
#undef ETHARP_DEBUG
|
||||
#undef NETIF_DEBUG
|
||||
#undef PBUF_DEBUG
|
||||
#undef API_LIB_DEBUG
|
||||
#undef API_MSG_DEBUG
|
||||
#undef SOCKETS_DEBUG
|
||||
#undef ICMP_DEBUG
|
||||
#undef IGMP_DEBUG
|
||||
#undef INET_DEBUG
|
||||
#undef IP_DEBUG
|
||||
#undef IP_REASS_DEBUG
|
||||
#undef RAW_DEBUG
|
||||
#undef MEM_DEBUG
|
||||
#undef MEMP_DEBUG
|
||||
#undef SYS_DEBUG
|
||||
#undef TIMERS_DEBUG
|
||||
#undef TCP_DEBUG
|
||||
#undef TCP_INPUT_DEBUG
|
||||
#undef TCP_FR_DEBUG
|
||||
#undef TCP_RTO_DEBUG
|
||||
#undef TCP_CWND_DEBUG
|
||||
#undef TCP_WND_DEBUG
|
||||
#undef TCP_OUTPUT_DEBUG
|
||||
#undef TCP_RST_DEBUG
|
||||
#undef TCP_QLEN_DEBUG
|
||||
#undef UDP_DEBUG
|
||||
#undef TCPIP_DEBUG
|
||||
#undef SLIP_DEBUG
|
||||
#undef DHCP_DEBUG
|
||||
#undef AUTOIP_DEBUG
|
||||
#undef DNS_DEBUG
|
||||
#undef IP6_DEBUG
|
||||
#undef MDNS_DEBUG
|
||||
@@ -2,10 +2,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define LWIP_TIMEVAL_PRIVATE 0
|
||||
#define LWIP_NETIF_HOSTNAME 1 // to support hostname changing
|
||||
#define LWIP_SO_RCVBUF 1 // for ioctl(FIONREAD)
|
||||
|
||||
#include_next "lwipopts.h"
|
||||
|
||||
#define ip_addr ip4_addr // LwIP 2.0.x compatibility
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
# Copyright (c) Kuba Szczodrzyński 2022-06-12.
|
||||
@@ -1,69 +0,0 @@
|
||||
# Copyright 2022-04-24 kuba2k2
|
||||
|
||||
import sys
|
||||
from os.path import dirname, join
|
||||
|
||||
sys.path.append(join(dirname(__file__), ".."))
|
||||
|
||||
from argparse import ArgumentParser, FileType
|
||||
from binascii import crc32
|
||||
from os import makedirs
|
||||
from os.path import basename, dirname, join
|
||||
|
||||
from tools.util.crc16 import CRC16
|
||||
from tools.util.platform import get_board_manifest
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = ArgumentParser("dumptool", description="Convert flash dump images")
|
||||
parser.add_argument("action", choices=["split"])
|
||||
parser.add_argument("board", help="Board name or board.json file", type=str)
|
||||
parser.add_argument("file", help="Input file", type=FileType("rb"))
|
||||
parser.add_argument("--output", "-o", help="Output directory", type=str)
|
||||
parser.add_argument("--no-trim", "-n", help="Don't trim output binaries")
|
||||
parser.add_argument("--no-checksum", "-c", help="Don't append checksum to filename")
|
||||
args = parser.parse_args()
|
||||
|
||||
board = get_board_manifest(args.board)
|
||||
|
||||
if "flash" not in board:
|
||||
print("Flash layout not defined")
|
||||
exit()
|
||||
flash_layout = board["flash"]
|
||||
|
||||
output = join(dirname(args.file.name), basename(args.file.name) + ".split")
|
||||
output = args.output or output
|
||||
makedirs(output, exist_ok=True)
|
||||
|
||||
with args.file as f:
|
||||
dump = f.read()
|
||||
|
||||
for name, layout in flash_layout.items():
|
||||
(offset, _, length) = layout.partition("+")
|
||||
offset = int(offset, 16)
|
||||
length = int(length, 16)
|
||||
|
||||
if offset + length > len(dump):
|
||||
print(f"Partition '{name}' is out of bounds!")
|
||||
print(f" - Dump size: {hex(len(dump))}")
|
||||
print(f" - Partition start: {hex(offset)}")
|
||||
print(f" - Partition length: {hex(length)}")
|
||||
print(f" - Partition end: {hex(offset+length)}")
|
||||
exit()
|
||||
|
||||
part = dump[offset : offset + length]
|
||||
offset = offset.to_bytes(length=3, byteorder="big").hex().upper()
|
||||
filename = f"{offset}_{name}.bin"
|
||||
|
||||
if not args.no_trim:
|
||||
part = part.rstrip(b"\xff")
|
||||
if not args.no_checksum:
|
||||
if length > 0x10000: # 64 KiB
|
||||
cs = crc32(part)
|
||||
cs = cs.to_bytes(length=4, byteorder="big")
|
||||
else:
|
||||
cs = CRC16.ARC.calc(part)
|
||||
cs = cs.to_bytes(length=2, byteorder="big")
|
||||
filename = f"{offset}_{name}_{cs.hex().upper()}.bin"
|
||||
print(f"Writing {filename}")
|
||||
with open(join(output, filename), "wb") as f:
|
||||
f.write(part)
|
||||
Reference in New Issue
Block a user